Strip down further TCC (removing unused function, unused parameter...). Split source in multiple files (WIP)

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-02-08 15:45:16 +01:00
parent f08ef63153
commit 6318a909ff
65 changed files with 892 additions and 10358 deletions

View file

@ -1,3 +1 @@
AM_CFLAGS =
SUBDIRS = libtcc tcc
SUBDIRS = libtcc tcc libtcc1

View file

@ -1,3 +1,4 @@
-I.
-DHAVE_CONFIG_H
-Ilibtcc/include
-Ilibtcc

View file

@ -10,7 +10,8 @@ AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
libtcc/Makefile
tcc/Makefile])
tcc/Makefile
libtcc1/Makefile])
AC_LANG([C])
AC_PROG_CC
@ -18,6 +19,7 @@ AC_PROG_CPP
AC_PROG_CC_C_O
AC_PROG_RANLIB
AM_PROG_AR
AM_PROG_AS
AC_CHECK_INCLUDES_DEFAULT
AC_C_CONST

View file

@ -3,4 +3,4 @@ libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c \
tccasm.c tccelf.c \
i386/gen.c i386/link.c \
i386/asm.c tcccoff.c
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/libtcc
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include

View file

@ -21,6 +21,7 @@
#define USING_GLOBALS
#include "tcc.h"
#include "token.h"
#define MAX_OPERANDS 3
@ -201,7 +202,7 @@ static const ASMInstr asm_instrs[] = {
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
#include "asm.h"
#include "asm.inc"
/* last operation */
{ 0, },
};
@ -213,7 +214,7 @@ static const uint16_t op0_codes[] = {
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
#include "asm.h"
#include "asm.inc"
};
static inline int get_reg_shift(TCCState *s1)
@ -382,7 +383,7 @@ static void parse_operand(TCCState *s1, Operand *op)
}
/* XXX: unify with C code output ? */
ST_FUNC void gen_expr32(ExprValue *pe)
void gen_expr32(ExprValue *pe)
{
if (pe->pcrel)
/* If PC-relative, always set VT_SYM, even without symbol,
@ -501,7 +502,7 @@ static void maybe_print_stats (void)
}
}
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
void asm_opcode(TCCState *s1, int opcode)
{
const ASMInstr *pa;
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc, p;
@ -962,7 +963,7 @@ static const char *skip_constraint_modifiers(const char *p)
/* If T (a token) is of the form "%reg" returns the register
number and type, otherwise return -1. */
ST_FUNC int asm_parse_regvar (int t)
int asm_parse_regvar (int t)
{
const char *s;
Operand op;
@ -987,7 +988,7 @@ ST_FUNC int asm_parse_regvar (int t)
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
void asm_compute_constraints(ASMOperand *operands,
int nb_operands, int nb_outputs,
const uint8_t *clobber_regs,
int *pout_reg)
@ -1239,7 +1240,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
#endif
}
ST_FUNC void subst_asm_operand(CString *add_str,
void subst_asm_operand(CString *add_str,
SValue *sv, int modifier)
{
int r, reg, size, val;
@ -1328,7 +1329,7 @@ ST_FUNC void subst_asm_operand(CString *add_str,
}
/* generate prolog and epilog code for asm statement */
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
void asm_gen_code(ASMOperand *operands, int nb_operands,
int nb_outputs, int is_output,
uint8_t *clobber_regs,
int out_reg)
@ -1425,7 +1426,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
}
}
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
void asm_clobber(uint8_t *clobber_regs, const char *str)
{
int reg;

View file

@ -18,70 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef TARGET_DEFS_ONLY
/* number of available registers */
#define NB_REGS 5
#define NB_ASM_REGS 8
#define CONFIG_TCC_ASM
/* a register can belong to several classes. The classes must be
sorted from more general to more precise (see gv2() code which does
assumptions on it). */
#define RC_INT 0x0001 /* generic integer register */
#define RC_FLOAT 0x0002 /* generic float register */
#define RC_EAX 0x0004
#define RC_EDX 0x0008
#define RC_ECX 0x0010
#define RC_EBX 0x0020
#define RC_ST0 0x0040
#define RC_IRET RC_EAX /* function return: integer register */
#define RC_IRE2 RC_EDX /* function return: second integer register */
#define RC_FRET RC_ST0 /* function return: float register */
/* pretty names for the registers */
enum {
TREG_EAX = 0,
TREG_ECX,
TREG_EDX,
TREG_EBX,
TREG_ST0,
TREG_ESP = 4
};
/* return registers for function */
#define REG_IRET TREG_EAX /* single word int return register */
#define REG_IRE2 TREG_EDX /* second word return register (for long long) */
#define REG_FRET TREG_ST0 /* float return register */
/* defined if function parameters must be evaluated in reverse order */
#define INVERT_FUNC_PARAMS
/* defined if structures are passed as pointers. Otherwise structures
are directly pushed on stack. */
/* #define FUNC_STRUCT_PARAM_AS_PTR */
/* pointer size, in bytes */
#define PTR_SIZE 4
/* long double size and alignment, in bytes */
#define LDOUBLE_SIZE 12
#define LDOUBLE_ALIGN 4
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8
/* define if return values need to be extended explicitely
at caller side (for interfacing with non-TCC compilers) */
#define PROMOTE_RET
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#define USING_GLOBALS
#include "tcc.h"
#include <tcc.h>
#include "token.h"
ST_DATA const char * const target_machine_defs =
const char * const target_machine_defs =
"__i386__\0"
"__i386\0"
;
@ -89,7 +30,7 @@ ST_DATA const char * const target_machine_defs =
/* define to 1/0 to [not] have EBX as 4th register */
#define USE_EBX 0
ST_DATA const int reg_classes[NB_REGS] = {
const int reg_classes[NB_REGS] = {
/* eax */ RC_INT | RC_EAX,
/* ecx */ RC_INT | RC_ECX,
/* edx */ RC_INT | RC_EDX,
@ -101,7 +42,7 @@ static unsigned long func_sub_sp_offset;
static int func_ret_sub;
/* XXX: make it faster ? */
ST_FUNC void g(int c)
void g(int c)
{
int ind1;
if (nocode_wanted)
@ -113,7 +54,7 @@ ST_FUNC void g(int c)
ind = ind1;
}
ST_FUNC void o(unsigned int c)
void o(unsigned int c)
{
while (c) {
g(c);
@ -121,13 +62,13 @@ ST_FUNC void o(unsigned int c)
}
}
ST_FUNC void gen_le16(int v)
void gen_le16(int v)
{
g(v);
g(v >> 8);
}
ST_FUNC void gen_le32(int c)
void gen_le32(int c)
{
g(c);
g(c >> 8);
@ -136,7 +77,7 @@ ST_FUNC void gen_le32(int c)
}
/* output a symbol and patch all calls to it */
ST_FUNC void gsym_addr(int t, int a)
void gsym_addr(int t, int a)
{
while (t) {
unsigned char *ptr = cur_text_section->data + t;
@ -158,7 +99,7 @@ static int oad(int c, int s)
return t;
}
ST_FUNC void gen_fill_nops(int bytes)
void gen_fill_nops(int bytes)
{
while (bytes--)
g(0x90);
@ -168,14 +109,14 @@ ST_FUNC void gen_fill_nops(int bytes)
#define gjmp2(instr,lbl) oad(instr,lbl)
/* output constant with relocation if 'r & VT_SYM' is true */
ST_FUNC void gen_addr32(int r, Sym *sym, int c)
void gen_addr32(int r, Sym *sym, int c)
{
if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_386_32);
gen_le32(c);
}
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
void gen_addrpc32(int r, Sym *sym, int c)
{
if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_386_PC32);
@ -206,7 +147,7 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c)
}
/* load 'r' from value 'sv' */
ST_FUNC void load(int r, SValue *sv)
void load(int r, SValue *sv)
{
int v, t, ft, fc, fr;
SValue v1;
@ -281,7 +222,7 @@ ST_FUNC void load(int r, SValue *sv)
}
/* store register 'r' in lvalue 'v' */
ST_FUNC void store(int r, SValue *v)
void store(int r, SValue *v)
{
int fr, bt, ft, fc;
@ -349,7 +290,7 @@ static const uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
{
#if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD
int size, align, nregs;
@ -370,6 +311,10 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
ret->ref = NULL;
return nregs;
#else
(void)vt;
(void)variadic;
(void)ret;
(void)regsize;
*ret_align = 1; // Never have to re-align return values for x86
return 0;
#endif
@ -378,7 +323,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
/* Generate function call. The function address is pushed first, then
all the parameters in call order. This functions pops all the
parameters and the function address. */
ST_FUNC void gfunc_call(int nb_args)
void gfunc_call(int nb_args)
{
int size, align, r, args_size, i, func_call;
Sym *func_sym;
@ -488,7 +433,7 @@ ST_FUNC void gfunc_call(int nb_args)
#endif
/* generate function prolog of type 't' */
ST_FUNC void gfunc_prolog(Sym *func_sym)
void gfunc_prolog(Sym *func_sym)
{
CType *func_type = &func_sym->type;
int addr, align, size, func_call, fastcall_nb_regs;
@ -571,7 +516,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
}
/* generate function epilog */
ST_FUNC void gfunc_epilog(void)
void gfunc_epilog(void)
{
addr_t v, saved_ind;
@ -612,13 +557,13 @@ ST_FUNC void gfunc_epilog(void)
}
/* generate a jump to a label */
ST_FUNC int gjmp(int t)
int gjmp(int t)
{
return gjmp2(0xe9, t);
}
/* generate a jump to a fixed address */
ST_FUNC void gjmp_addr(int a)
void gjmp_addr(int a)
{
int r;
r = a - ind - 2;
@ -632,7 +577,7 @@ ST_FUNC void gjmp_addr(int a)
#if 0
/* generate a jump to a fixed address */
ST_FUNC void gjmp_cond_addr(int a, int op)
void gjmp_cond_addr(int a, int op)
{
int r = a - ind - 2;
if (r == (char)r)
@ -642,7 +587,7 @@ ST_FUNC void gjmp_cond_addr(int a, int op)
}
#endif
ST_FUNC int gjmp_append(int n, int t)
int gjmp_append(int n, int t)
{
void *p;
/* insert vtop->c jump list in t */
@ -656,14 +601,14 @@ ST_FUNC int gjmp_append(int n, int t)
return t;
}
ST_FUNC int gjmp_cond(int op, int t)
int gjmp_cond(int op, int t)
{
g(0x0f);
t = gjmp2(op - 16, t);
return t;
}
ST_FUNC void gen_opi(int op)
void gen_opi(int op)
{
int r, fr, opc, c;
@ -802,7 +747,7 @@ ST_FUNC void gen_opi(int op)
/* generate a floating point operation 'v = t1 op t2' instruction. The
two operands are guaranteed to have the same floating point type */
/* XXX: need to use ST1 too */
ST_FUNC void gen_opf(int op)
void gen_opf(int op)
{
int a, ft, fc, swapped, r;
@ -923,7 +868,7 @@ ST_FUNC void gen_opf(int op)
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
and 'long long' cases. */
ST_FUNC void gen_cvt_itof(int t)
void gen_cvt_itof(void)
{
save_reg(TREG_ST0);
gv(RC_INT);
@ -954,7 +899,7 @@ ST_FUNC void gen_cvt_itof(int t)
}
/* convert fp to int 't' type */
ST_FUNC void gen_cvt_ftoi(int t)
void gen_cvt_ftoi(int t)
{
int bt = vtop->type.t & VT_BTYPE;
if (bt == VT_FLOAT)
@ -972,14 +917,14 @@ ST_FUNC void gen_cvt_ftoi(int t)
}
/* convert from one floating point type to another */
ST_FUNC void gen_cvt_ftof(int t)
void gen_cvt_ftof(void)
{
/* all we have to do on i386 is to put the float in a register */
gv(RC_FLOAT);
}
/* char/short to int conversion */
ST_FUNC void gen_cvt_csti(int t)
void gen_cvt_csti(int t)
{
int r, sz, xl;
r = gv(RC_INT);
@ -992,7 +937,7 @@ ST_FUNC void gen_cvt_csti(int t)
}
/* increment tcov counter */
ST_FUNC void gen_increment_tcov (SValue *sv)
void gen_increment_tcov (SValue *sv)
{
o(0x0583); /* addl $1, xxx */
greloc(cur_text_section, sv->sym, ind, R_386_32);
@ -1005,27 +950,27 @@ ST_FUNC void gen_increment_tcov (SValue *sv)
}
/* computed goto support */
ST_FUNC void ggoto(void)
void ggoto(void)
{
gcall_or_jmp(1);
vtop--;
}
/* Save the stack pointer onto the stack */
ST_FUNC void gen_vla_sp_save(int addr) {
void gen_vla_sp_save(int addr) {
/* mov %esp,addr(%ebp)*/
o(0x89);
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
}
/* Restore the SP from a location on the stack */
ST_FUNC void gen_vla_sp_restore(int addr) {
void gen_vla_sp_restore(int addr) {
o(0x8b);
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
}
/* Subtract from the stack pointer, and push the resulting value onto the stack */
ST_FUNC void gen_vla_alloc(CType *type, int align) {
void gen_vla_alloc(CType *type, int align) {
int use_call = 0;
#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
@ -1051,6 +996,3 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
}
/* end of X86 code generator */
/*************************************************************/
#endif
/*************************************************************/

View file

@ -1,31 +1,9 @@
#ifdef TARGET_DEFS_ONLY
#define EM_TCC_TARGET EM_386
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_386_32
#define R_DATA_PTR R_386_32
#define R_JMP_SLOT R_386_JMP_SLOT
#define R_GLOB_DAT R_386_GLOB_DAT
#define R_COPY R_386_COPY
#define R_RELATIVE R_386_RELATIVE
#define R_NUM R_386_NUM
#define ELF_START_ADDR 0x08048000
#define ELF_PAGE_SIZE 0x1000
#define PCRELATIVE_DLLPLT 0
#define RELOCATE_DLLPLT 1
#else /* !TARGET_DEFS_ONLY */
#include "tcc.h"
#include <tcc.h>
#ifdef NEED_RELOC_TYPE
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */
ST_FUNC int code_reloc (int reloc_type)
int code_reloc (int reloc_type)
{
switch (reloc_type) {
case R_386_RELATIVE:
@ -55,7 +33,7 @@ ST_FUNC int code_reloc (int reloc_type)
/* Returns an enumerator to describe whether and when the relocation needs a
GOT and/or PLT entry to be created. See tcc.h for a description of the
different values. */
ST_FUNC int gotplt_entry_type (int reloc_type)
int gotplt_entry_type (int reloc_type)
{
switch (reloc_type) {
case R_386_RELATIVE:
@ -92,7 +70,7 @@ ST_FUNC int gotplt_entry_type (int reloc_type)
}
#ifdef NEED_BUILD_GOT
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = s1->plt;
uint8_t *p;
@ -134,7 +112,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *s1)
void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
@ -167,9 +145,9 @@ ST_FUNC void relocate_plt(TCCState *s1)
#endif
#endif
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
int sym_index, esym_index;
int sym_index;
sym_index = ELFW(R_SYM)(rel->r_info);
@ -295,5 +273,3 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
return;
}
}
#endif /* !TARGET_DEFS_ONLY */

View file

@ -266,7 +266,7 @@
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
#include "asm.h"
#include "asm.inc"
#define ALT(x)
#define DEF_ASM_OP0(name, opcode)
@ -274,4 +274,4 @@
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
#include "asm.h"
#include "asm.inc"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
#ifndef TCC_I386_GEN_H
# define TCC_I386_GEN_H 1
/* number of available registers */
# define NB_REGS 5
# define NB_ASM_REGS 8
/* a register can belong to several classes. The classes must be
sorted from more general to more precise (see gv2() code which does
assumptions on it). */
# define RC_INT 0x0001 /* generic integer register */
# define RC_FLOAT 0x0002 /* generic float register */
# define RC_EAX 0x0004
# define RC_EDX 0x0008
# define RC_ECX 0x0010
# define RC_EBX 0x0020
# define RC_ST0 0x0040
# define RC_IRET RC_EAX /* function return: integer register */
# define RC_IRE2 RC_EDX /* function return: second integer register */
# define RC_FRET RC_ST0 /* function return: float register */
/* pretty names for the registers */
enum {
TREG_EAX = 0,
TREG_ECX,
TREG_EDX,
TREG_EBX,
TREG_ST0,
TREG_ESP = 4
};
/* return registers for function */
# define REG_IRET TREG_EAX /* single word int return register */
# define REG_IRE2 TREG_EDX /* second word return register (for long long) */
# define REG_FRET TREG_ST0 /* float return register */
/* defined if function parameters must be evaluated in reverse order */
# define INVERT_FUNC_PARAMS
/* defined if structures are passed as pointers. Otherwise structures
are directly pushed on stack. */
/* #define FUNC_STRUCT_PARAM_AS_PTR */
/* pointer size, in bytes */
# define PTR_SIZE 4
/* long double size and alignment, in bytes */
# define LDOUBLE_SIZE 12
# define LDOUBLE_ALIGN 4
/* maximum alignment (for aligned attribute support) */
# define MAX_ALIGN 8
/* define if return values need to be extended explicitely
at caller side (for interfacing with non-TCC compilers) */
# define PROMOTE_RET
#endif /* !TCC_I386_GEN_H */

View file

@ -0,0 +1,20 @@
#ifndef TCC_I386_LINK_H
# define TCC_I386_LINK_H 1
/* relocation type for 32 bit data relocation */
# define R_DATA_32 R_386_32
# define R_DATA_PTR R_386_32
# define R_JMP_SLOT R_386_JMP_SLOT
# define R_GLOB_DAT R_386_GLOB_DAT
# define R_COPY R_386_COPY
# define R_RELATIVE R_386_RELATIVE
# define R_NUM R_386_NUM
# define ELF_START_ADDR 0x08048000
# define ELF_PAGE_SIZE 0x1000
# define PCRELATIVE_DLLPLT 0
# define RELOCATE_DLLPLT 1
#endif /* !TCC_I386_LINK_H */

View file

@ -0,0 +1,25 @@
#ifndef LIBTCC_OPTION_H
# define LIBTCC_OPTION_H 1
# include <stdint.h>
# define TCC_OPTION_HAS_ARG 0x0001
# define TCC_OPTION_NOSEP 0x0002 /** cannot have space before option and arg */
# define TCC_OPT_HELP 'h'
# define TCC_OPT_HELP_MORE 'm'
# define TCC_OPT_ARCHIVE 'a'
# define TCC_OPT_VERSION 'V'
typedef struct TCCOption {
const char *name;
uint16_t index;
uint16_t flags;
} TCCOption;
typedef struct TCCState TCCState;
int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
void tcc_add_options(TCCOption *opts);
#endif /* LIBTCC_OPTION_H */

View file

@ -25,15 +25,15 @@
/* global variables */
/* XXX: get rid of this ASAP (or maybe not) */
ST_DATA struct TCCState *tcc_state;
struct TCCState *tcc_state;
TCC_SEM(static tcc_compile_sem);
/* an array of pointers to memory to be free'd after errors */
ST_DATA void** stk_data;
ST_DATA int nb_stk_data;
void** stk_data;
int nb_stk_data;
/********************************************************/
#ifdef _WIN32
ST_FUNC char *normalize_slashes(char *path)
char *normalize_slashes(char *path)
{
char *p;
for (p = path; *p; ++p)
@ -99,7 +99,7 @@ PUB_FUNC char *tcc_fileextension (const char *name)
return e ? e : strchr(b, 0);
}
ST_FUNC char *tcc_load_text(int fd)
char *tcc_load_text(int fd)
{
int len = lseek(fd, 0, SEEK_END);
char *buf = load_data(fd, 0, len + 1);
@ -111,10 +111,6 @@ ST_FUNC char *tcc_load_text(int fd)
/********************************************************/
/* memory management */
/* we'll need the actual versions for a minute */
#undef free
#undef realloc
static void *default_reallocator(void *ptr, unsigned long size)
{
void *ptr1;
@ -132,14 +128,6 @@ static void *default_reallocator(void *ptr, unsigned long size)
return ptr1;
}
ST_FUNC void libc_free(void *ptr)
{
free(ptr);
}
#define free(p) use_tcc_free(p)
#define realloc(p, s) use_tcc_realloc(p, s)
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
@ -208,7 +196,7 @@ struct mem_debug_header {
int line_num;
char file_name[MEM_DEBUG_FILE_LEN + 1];
unsigned magic2;
ALIGNED(16) unsigned char magic3[4];
__attribute__((aligned(16))) unsigned char magic3[4];
};
typedef struct mem_debug_header mem_debug_header_t;
@ -369,16 +357,16 @@ PUB_FUNC void tcc_memcheck(int d)
#endif
/* for #pragma once */
ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2)
int normalized_PATHCMP(const char *f1, const char *f2)
{
char *p1, *p2;
int ret = 1;
if (!!(p1 = realpath(f1, NULL))) {
if (!!(p2 = realpath(f2, NULL))) {
ret = PATHCMP(p1, p2);
libc_free(p2); /* realpath() requirement */
free(p2); /* realpath() requirement */
}
libc_free(p1);
free(p1);
}
return ret;
}
@ -386,7 +374,7 @@ ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2)
/********************************************************/
/* dynarrays */
ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
void dynarray_add(void *ptab, int *nb_ptr, void *data)
{
int nb, nb_alloc;
void **pp;
@ -406,7 +394,7 @@ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
*nb_ptr = nb;
}
ST_FUNC void dynarray_reset(void *pp, int *n)
void dynarray_reset(void *pp, int *n)
{
void **p;
for (p = *(void***)pp; *n; ++p, --*n)
@ -575,7 +563,7 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
/********************************************************/
/* I/O layer */
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
{
BufferedFile *bf;
int buflen = initlen ? initlen : IO_BUF_SIZE;
@ -598,7 +586,7 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
}
ST_FUNC void tcc_close(void)
void tcc_close(void)
{
TCCState *s1 = tcc_state;
BufferedFile *bf = file;
@ -626,7 +614,7 @@ static int _tcc_open(TCCState *s1, const char *filename)
return fd;
}
ST_FUNC int tcc_open(TCCState *s1, const char *filename)
int tcc_open(TCCState *s1, const char *filename)
{
int fd = _tcc_open(s1, filename);
if (fd < 0)
@ -755,8 +743,7 @@ void tcc_delete(TCCState *s1)
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
tcc_free(s1->tcc_lib_path);
tcc_free(s1->soname);
tcc_free(s1->tcc_lib_path);;
tcc_free(s1->rpath);
tcc_free(s1->elf_entryname);
tcc_free(s1->init_symbol);
@ -771,8 +758,6 @@ void tcc_delete(TCCState *s1)
cstr_free(&s1->cmdline_defs);
cstr_free(&s1->cmdline_incl);
cstr_free(&s1->linker_arg);
/* free loaded dlls array */
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
tcc_free(s1);
#ifdef MEM_DEBUG
tcc_memcheck(-1);
@ -823,35 +808,9 @@ int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
return 0;
}
/* add/update a 'DLLReference', Just find if level == -1 */
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level)
{
DLLReference *ref = NULL;
int i;
for (i = 0; i < s1->nb_loaded_dlls; i++)
if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) {
ref = s1->loaded_dlls[i];
break;
}
if (level == -1)
return ref;
if (ref) {
if (level < ref->level)
ref->level = level;
ref->found = 1;
return ref;
}
ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
strcpy(ref->name, dllname);
dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref);
ref->level = level;
ref->index = s1->nb_loaded_dlls;
return ref;
}
static int guess_filetype(const char *filename);
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
{
int fd, ret = -1;
@ -893,12 +852,6 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
ret = coff_load_file(s1, fd, filename);
break;
case AFF_BINTYPE_DYN:
if (s1->output_type == TCC_OUTPUT_MEMORY) {
} else
ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
break;
default:
/* as GNU ld, consider it is an ld script if not recognized */
ret = tcc_load_ldscript(s1, fd);
@ -970,14 +923,14 @@ static int tcc_add_library_internal(TCCState *s1, const char *fmt,
}
/* find and load a dll. Return non zero if not found */
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
int tcc_add_dll(TCCState *s, const char *filename, int flags)
{
return tcc_add_library_internal(s, "%s/%s", filename, flags,
s->library_paths, s->nb_library_paths);
}
/* find [cross-]libtcc1.a and tcc helper objects in library path */
ST_FUNC int tcc_add_support(TCCState *s1, const char *filename)
int tcc_add_support(TCCState *s1, const char *filename)
{
char buf[100];
if (CONFIG_TCC_CROSSPREFIX[0])
@ -985,13 +938,11 @@ ST_FUNC int tcc_add_support(TCCState *s1, const char *filename)
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
}
#if !defined TCC_TARGET_PE
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
int tcc_add_crt(TCCState *s1, const char *filename)
{
return tcc_add_library_internal(s1, "%s/%s",
filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths);
}
#endif
/* the library name is the same as the argument of the '-l' option */
int tcc_add_library(TCCState *s, const char *libraryname)
@ -1010,7 +961,7 @@ int tcc_add_library(TCCState *s, const char *libraryname)
}
/* handle #pragma comment(lib,) */
ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
void tcc_add_pragma_libs(TCCState *s1)
{
int i;
for (i = 0; i < s1->nb_pragma_libs; i++)
@ -1184,20 +1135,12 @@ static int tcc_set_linker(TCCState *s, const char *option)
ignoring = 1;
} else if (link_option(option, "O", &p)) {
ignoring = 1;
} else if (link_option(option, "export-all-symbols", &p)) {
s->rdynamic = 1;
} else if (link_option(option, "export-dynamic", &p)) {
s->rdynamic = 1;
} else if (link_option(option, "rpath=", &p)) {
copy_linker_arg(&s->rpath, p, ':');
} else if (link_option(option, "enable-new-dtags", &p)) {
s->enable_new_dtags = 1;
} else if (link_option(option, "section-alignment=", &p)) {
s->section_align = strtoul(p, &end, 16);
} else if (link_option(option, "soname=", &p)) {
copy_linker_arg(&s->soname, p, 0);
} else if (link_option(option, "install_name=", &p)) {
copy_linker_arg(&s->soname, p, 0);
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
if (ret > 0)
s->filetype |= AFF_WHOLE_ARCHIVE;
@ -1308,10 +1251,7 @@ static const TCCOption tcc_options[] = {
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
{ "dumpversion", TCC_OPTION_dumpversion, 0},
{ "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "static", TCC_OPTION_static, 0 },
{ "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "shared", TCC_OPTION_shared, 0 },
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
{ "pthread", TCC_OPTION_pthread, 0},
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
@ -1346,6 +1286,9 @@ static const TCCOption tcc_options[] = {
{ "pipe", 0, 0 },
{ "s", 0, 0 },
{ "traditional", 0, 0 },
{ "static", 0, 0},
{ "shared", 0, 0},
{ "soname", 0, 0},
{ NULL, 0, 0 },
};
@ -1591,21 +1534,13 @@ dorun:
s->dflag = 3;
else if (*optarg == 'M')
s->dflag = 7;
else if (isnum(*optarg))
s->g_debug |= atoi(optarg);
else
goto unsupported_option;
break;
case TCC_OPTION_static:
s->static_link = 1;
break;
case TCC_OPTION_std:
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
s->cversion = 201112;
break;
case TCC_OPTION_soname:
s->soname = tcc_strdup(optarg);
break;
case TCC_OPTION_o:
if (s->outfile) {
tcc_warning("multiple -o option");
@ -1655,9 +1590,6 @@ dorun:
case TCC_OPTION_w:
s->warn_none = 1;
break;
case TCC_OPTION_rdynamic:
s->rdynamic = 1;
break;
case TCC_OPTION_Wl:
if (s->linker_arg.size)
((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
@ -1789,9 +1721,3 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
#endif
}
#if ONE_SOURCE
# undef malloc
# undef realloc
# undef free
#endif

View file

@ -1,2 +1,113 @@
#include "tcc.h"
#include <stdlib.h>
#include <tcc/option.h>
#include "utils/cstr.h"
enum {
OPTION_ignored = 0,
OPTION_I,
OPTION_D,
OPTION_U,
OPTION_P,
OPTION_L,
OPTION_B,
OPTION_l,
OPTION_bench,
OPTION_c,
OPTION_dumpmachine,
OPTION_dumpversion,
OPTION_d,
OPTION_std,
OPTION_o,
OPTION_pthread,
OPTION_r,
OPTION_Wl,
OPTION_Wp,
OPTION_W,
OPTION_O,
OPTION_m,
OPTION_f,
OPTION_isystem,
OPTION_include,
OPTION_nostdinc,
OPTION_nostdlib,
OPTION_print_search_dirs,
OPTION_w,
OPTION_E,
OPTION_M,
OPTION_MF,
OPTION_MD,
OPTION_MM,
OPTION_MMD,
OPTION_MP,
OPTION_x,
};
static const TCCOption options[] = {
{"I", OPTION_I, TCC_OPTION_HAS_ARG},
{"D", OPTION_D, TCC_OPTION_HAS_ARG},
{"U", OPTION_U, TCC_OPTION_HAS_ARG},
{"P", OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"L", OPTION_L, TCC_OPTION_HAS_ARG},
{"B", OPTION_B, TCC_OPTION_HAS_ARG},
{"l", OPTION_l, TCC_OPTION_HAS_ARG},
{"bench", OPTION_bench, 0},
{"c", OPTION_c, 0},
{"dumpmachine", OPTION_dumpmachine, 0},
{"dumpversion", OPTION_dumpversion, 0},
{"d", OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"std", OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"o", OPTION_o, TCC_OPTION_HAS_ARG},
{"pthread", OPTION_pthread, 0},
{"r", OPTION_r, 0},
{"Wl", OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"Wp", OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"W", OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"O", OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"m", OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"f", OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"isystem", OPTION_isystem, TCC_OPTION_HAS_ARG},
{"include", OPTION_include, TCC_OPTION_HAS_ARG},
{"nostdinc", OPTION_nostdinc, 0},
{"nostdlib", OPTION_nostdlib, 0},
{"print-search-dirs", OPTION_print_search_dirs, 0},
{"w", OPTION_w, 0},
{"E", OPTION_E, 0},
{"M", OPTION_M, 0},
{"MD", OPTION_MD, 0},
{"MF", OPTION_MF, TCC_OPTION_HAS_ARG},
{"MM", OPTION_MM, 0},
{"MMD", OPTION_MMD, 0},
{"MP", OPTION_MP, 0},
{"x", OPTION_x, 0},
/* ignored (silently, except after -Wunsupported) */
{"arch", 0, TCC_OPTION_HAS_ARG},
{"g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{"C", 0, 0},
{"-param", 0, 0},
{"pedantic", 0, 0},
{"pipe", 0, 0},
{"s", 0, 0},
{"traditional", 0, 0},
{"shared", 0, 0},
{NULL, 0, 0}
};
static TCCOption *options_ext = NULL;
static const char dumpmachine_str[] = "i386-pc-stupidos";
void
tcc_add_options(TCCOption *opt)
{
options_ext = opt;
}
int
tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
{
return (0);
}

View file

@ -1,6 +0,0 @@
#ifndef LIBTCC_OPTION_H
# define LIBTCC_OPTION_H 1
int tcc_parse_args(void *s, int *argc, char ***argv, int optind);
#endif /* LIBTCC_OPTION_H */

4
libtcc/tcc_internal.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef TCC_INTERNAL_H
# define TCC_INTERNAL_H 1
#endif /* !TCC_INTERNAL_H */

View file

@ -21,7 +21,7 @@
#define USING_GLOBALS
#include "tcc.h"
#include "utils/string.h"
#ifdef CONFIG_TCC_ASM
#include "token.h"
static Section *last_text_section; /* to handle .previous asm directive */
static int asmgoto_n;
@ -33,7 +33,7 @@ static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n)
return tok_alloc_const(buf);
}
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
int asm_get_local_label_name(TCCState *s1, unsigned int n)
{
return asm_get_prefix_name(s1, "L..", n);
}
@ -101,7 +101,7 @@ static Sym *asm_label_push(int v)
are anonymous in C, in this case CSYM can be used to transfer
all information from that symbol to the (possibly newly created)
asm symbol. */
ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
Sym* get_asm_sym(int name, Sym *csym)
{
Sym *sym = asm_label_find(name);
if (!sym) {
@ -388,12 +388,12 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
}
}
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
void asm_expr(TCCState *s1, ExprValue *pe)
{
asm_expr_cmp(s1, pe);
}
ST_FUNC int asm_int_expr(TCCState *s1)
int asm_int_expr(TCCState *s1)
{
ExprValue e;
asm_expr(s1, &e);
@ -1006,7 +1006,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
}
/* Assemble the current file */
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
int tcc_assemble(TCCState *s1, int do_preprocess)
{
int ret;
/* default section is text */
@ -1043,7 +1043,7 @@ static void tcc_assemble_inline(TCCState *s1, const char *str, int len, int glob
/* find a constraint by its number or id (gcc 3 extended
syntax). return -1 if not found. Return in *pp in char after the
constraint */
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
int find_constraint(ASMOperand *operands, int nb_operands,
const char *name, const char **pp)
{
int index;
@ -1182,7 +1182,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
}
/* parse the GCC asm() instruction */
ST_FUNC void asm_instr(void)
void asm_instr(void)
{
CString astr, *astr1;
@ -1330,7 +1330,7 @@ ST_FUNC void asm_instr(void)
}
ST_FUNC void asm_global_instr(void)
void asm_global_instr(void)
{
CString *astr;
int saved_nocode_wanted = nocode_wanted;
@ -1361,21 +1361,3 @@ ST_FUNC void asm_global_instr(void)
nocode_wanted = saved_nocode_wanted;
}
/********************************************************/
#else
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
{
tcc_error("asm not supported");
}
ST_FUNC void asm_instr(void)
{
tcc_error("inline asm() not supported");
}
ST_FUNC void asm_global_instr(void)
{
tcc_error("inline asm() not supported");
}
#endif /* CONFIG_TCC_ASM */

View file

@ -1,4 +1,4 @@
#include "coff.h"
#include "tcc/coff.h"
#include "tcc.h"

View file

@ -1,951 +0,0 @@
/*
* COFF file handling for TCC
*
* Copyright (c) 2003, 2004 TK
* Copyright (c) 2004 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tcc.h"
/* XXX: this file uses tcc_error() to the effect of exit(1) */
#undef _tcc_error
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
SCNHDR section_header[MAXNSCNS];
#define MAX_FUNCS 1000
#define MAX_FUNC_NAME_LENGTH 128
int nFuncs;
char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
int LineNoFilePtr[MAX_FUNCS];
int EndAddress[MAX_FUNCS];
int LastLineNo[MAX_FUNCS];
int FuncEntries[MAX_FUNCS];
int OutputTheSection(Section * sect);
short int GetCoffFlags(const char *s);
void SortSymbolTable(TCCState *s1);
Section *FindSection(TCCState * s1, const char *sname);
int C67_main_entry_point;
int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
int nb_syms;
typedef struct {
long tag;
long size;
long fileptr;
long nextsym;
short int dummy;
} AUXFUNC;
typedef struct {
long regmask;
unsigned short lineno;
unsigned short nentries;
int localframe;
int nextentry;
short int dummy;
} AUXBF;
typedef struct {
long dummy;
unsigned short lineno;
unsigned short dummy1;
int dummy2;
int dummy3;
unsigned short dummy4;
} AUXEF;
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
{
Section *tcc_sect;
SCNHDR *coff_sec;
int file_pointer;
char *Coff_str_table, *pCoff_str_table;
int CoffTextSectionNo, coff_nb_syms;
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
Section *stext, *sdata, *sbss;
int i, NSectionsToOutput = 0;
Coff_str_table = pCoff_str_table = NULL;
stext = FindSection(s1, ".text");
sdata = FindSection(s1, ".data");
sbss = FindSection(s1, ".bss");
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
file_hdr.f_timdat = 0; /* time & date stamp */
file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
o_filehdr.magic = 0x0108; /* see magic.h */
o_filehdr.vstamp = 0x0190; /* version stamp */
o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */
o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
// create all the section headers
file_pointer = FILHSZ + sizeof(AOUTHDR);
CoffTextSectionNo = -1;
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
NSectionsToOutput++;
if (CoffTextSectionNo == -1 && tcc_sect == stext)
CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is
strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
coff_sec->s_size = tcc_sect->data_offset; /* section size */
coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
coff_sec->s_relptr = 0; /* file ptr to relocation */
coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
coff_sec->s_nreloc = 0; /* number of relocation entries */
coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
coff_sec->s_reserved = 0; /* reserved byte */
coff_sec->s_page = 0; /* memory page id */
file_pointer += sizeof(SCNHDR);
}
}
file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
// now loop through and determine file pointer locations
// for the raw data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put raw data
coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */
file_pointer += coff_sec->s_size;
}
}
// now loop through and determine file pointer locations
// for the relocation data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put relocations data
if (coff_sec->s_nreloc > 0) {
coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
}
}
}
// now loop through and determine file pointer locations
// for the line number data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
coff_sec->s_nlnno = 0;
coff_sec->s_lnnoptr = 0;
if (s1->do_debug && tcc_sect == stext) {
// count how many line nos data
// also find association between source file name and function
// so we can sort the symbol table
Stab_Sym *sym, *sym_end;
char func_name[MAX_FUNC_NAME_LENGTH],
last_func_name[MAX_FUNC_NAME_LENGTH];
unsigned long func_addr, last_pc, pc;
const char *incl_files[INCLUDE_STACK_SIZE];
int incl_index, len, last_line_num;
const char *str, *p;
coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
func_name[0] = '\0';
func_addr = 0;
incl_index = 0;
last_func_name[0] = '\0';
last_pc = 0xffffffff;
last_line_num = 1;
sym = (Stab_Sym *) stab_section->data + 1;
sym_end =
(Stab_Sym *) (stab_section->data +
stab_section->data_offset);
nFuncs = 0;
while (sym < sym_end) {
switch (sym->n_type) {
/* function start or end */
case N_FUN:
if (sym->n_strx == 0) {
// end of function
coff_sec->s_nlnno++;
file_pointer += LINESZ;
pc = sym->n_value + func_addr;
func_name[0] = '\0';
func_addr = 0;
EndAddress[nFuncs] = pc;
FuncEntries[nFuncs] =
(file_pointer -
LineNoFilePtr[nFuncs]) / LINESZ - 1;
LastLineNo[nFuncs++] = last_line_num + 1;
} else {
// beginning of function
LineNoFilePtr[nFuncs] = file_pointer;
coff_sec->s_nlnno++;
file_pointer += LINESZ;
str =
(const char *) stabstr_section->data +
sym->n_strx;
p = strchr(str, ':');
if (!p) {
pstrcpy(func_name, sizeof(func_name), str);
pstrcpy(Func[nFuncs], sizeof(func_name), str);
} else {
len = p - str;
if (len > sizeof(func_name) - 1)
len = sizeof(func_name) - 1;
memcpy(func_name, str, len);
memcpy(Func[nFuncs], str, len);
func_name[len] = '\0';
}
// save the file that it came in so we can sort later
pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
incl_files[incl_index - 1]);
func_addr = sym->n_value;
}
break;
/* line number info */
case N_SLINE:
pc = sym->n_value + func_addr;
last_pc = pc;
last_line_num = sym->n_desc;
/* XXX: slow! */
strcpy(last_func_name, func_name);
coff_sec->s_nlnno++;
file_pointer += LINESZ;
break;
/* include files */
case N_BINCL:
str =
(const char *) stabstr_section->data + sym->n_strx;
add_incl:
if (incl_index < INCLUDE_STACK_SIZE) {
incl_files[incl_index++] = str;
}
break;
case N_EINCL:
if (incl_index > 1)
incl_index--;
break;
case N_SO:
if (sym->n_strx == 0) {
incl_index = 0; /* end of translation unit */
} else {
str =
(const char *) stabstr_section->data +
sym->n_strx;
/* do not add path */
len = strlen(str);
if (len > 0 && str[len - 1] != '/')
goto add_incl;
}
break;
}
sym++;
}
}
}
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
if (s1->do_debug)
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
else
file_hdr.f_nsyms = 0;
file_pointer += file_hdr.f_nsyms * SYMNMLEN;
// OK now we are all set to write the file
fwrite(&file_hdr, FILHSZ, 1, f);
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
// write section headers
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
}
}
// write raw data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
}
}
// write relocation data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put relocations data
if (coff_sec->s_nreloc > 0) {
fwrite(tcc_sect->reloc,
coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
}
}
}
// group the symbols in order of filename, func1, func2, etc
// finally global symbols
if (s1->do_debug)
SortSymbolTable(s1);
// write line no data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (s1->do_debug && tcc_sect == stext) {
// count how many line nos data
Stab_Sym *sym, *sym_end;
char func_name[128], last_func_name[128];
unsigned long func_addr, last_pc, pc;
const char *incl_files[INCLUDE_STACK_SIZE];
int incl_index, len, last_line_num;
const char *str, *p;
LINENO CoffLineNo;
func_name[0] = '\0';
func_addr = 0;
incl_index = 0;
last_func_name[0] = '\0';
last_pc = 0;
last_line_num = 1;
sym = (Stab_Sym *) stab_section->data + 1;
sym_end =
(Stab_Sym *) (stab_section->data +
stab_section->data_offset);
while (sym < sym_end) {
switch (sym->n_type) {
/* function start or end */
case N_FUN:
if (sym->n_strx == 0) {
// end of function
CoffLineNo.l_addr.l_paddr = last_pc;
CoffLineNo.l_lnno = last_line_num + 1;
fwrite(&CoffLineNo, 6, 1, f);
pc = sym->n_value + func_addr;
func_name[0] = '\0';
func_addr = 0;
} else {
// beginning of function
str =
(const char *) stabstr_section->data +
sym->n_strx;
p = strchr(str, ':');
if (!p) {
pstrcpy(func_name, sizeof(func_name), str);
} else {
len = p - str;
if (len > sizeof(func_name) - 1)
len = sizeof(func_name) - 1;
memcpy(func_name, str, len);
func_name[len] = '\0';
}
func_addr = sym->n_value;
last_pc = func_addr;
last_line_num = -1;
// output a function begin
CoffLineNo.l_addr.l_symndx =
FindCoffSymbolIndex(s1, func_name);
CoffLineNo.l_lnno = 0;
fwrite(&CoffLineNo, 6, 1, f);
}
break;
/* line number info */
case N_SLINE:
pc = sym->n_value + func_addr;
/* XXX: slow! */
strcpy(last_func_name, func_name);
// output a line reference
CoffLineNo.l_addr.l_paddr = last_pc;
if (last_line_num == -1) {
CoffLineNo.l_lnno = sym->n_desc;
} else {
CoffLineNo.l_lnno = last_line_num + 1;
}
fwrite(&CoffLineNo, 6, 1, f);
last_pc = pc;
last_line_num = sym->n_desc;
break;
/* include files */
case N_BINCL:
str =
(const char *) stabstr_section->data + sym->n_strx;
add_incl2:
if (incl_index < INCLUDE_STACK_SIZE) {
incl_files[incl_index++] = str;
}
break;
case N_EINCL:
if (incl_index > 1)
incl_index--;
break;
case N_SO:
if (sym->n_strx == 0) {
incl_index = 0; /* end of translation unit */
} else {
str =
(const char *) stabstr_section->data +
sym->n_strx;
/* do not add path */
len = strlen(str);
if (len > 0 && str[len - 1] != '/')
goto add_incl2;
}
break;
}
sym++;
}
}
}
// write symbol table
if (s1->do_debug) {
int k;
struct syment csym;
AUXFUNC auxfunc;
AUXBF auxbf;
AUXEF auxef;
int i;
Elf32_Sym *p;
const char *name;
int nstr;
int n = 0;
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
pCoff_str_table = Coff_str_table;
nstr = 0;
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
name = symtab_section->link->data + p->st_name;
for (k = 0; k < 8; k++)
csym._n._n_name[k] = 0;
if (strlen(name) <= 8) {
strcpy(csym._n._n_name, name);
} else {
if (pCoff_str_table - Coff_str_table + strlen(name) >
MAX_STR_TABLE - 1)
tcc_error("String table too large");
csym._n._n_n._n_zeroes = 0;
csym._n._n_n._n_offset =
pCoff_str_table - Coff_str_table + 4;
strcpy(pCoff_str_table, name);
pCoff_str_table += strlen(name) + 1; // skip over null
nstr++;
}
if (p->st_info == 4) {
// put a filename symbol
csym.n_value = 33; // ?????
csym.n_scnum = N_DEBUG;
csym.n_type = 0;
csym.n_sclass = C_FILE;
csym.n_numaux = 0;
fwrite(&csym, 18, 1, f);
n++;
} else if (p->st_info == 0x12) {
// find the function data
for (k = 0; k < nFuncs; k++) {
if (strcmp(name, Func[k]) == 0)
break;
}
if (k >= nFuncs) {
tcc_error("debug info can't find function: %s", name);
}
// put a Function Name
csym.n_value = p->st_value; // physical address
csym.n_scnum = CoffTextSectionNo;
csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
csym.n_sclass = C_EXT;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
// now put aux info
auxfunc.tag = 0;
auxfunc.size = EndAddress[k] - p->st_value;
auxfunc.fileptr = LineNoFilePtr[k];
auxfunc.nextsym = n + 6; // tktk
auxfunc.dummy = 0;
fwrite(&auxfunc, 18, 1, f);
// put a .bf
strcpy(csym._n._n_name, ".bf");
csym.n_value = p->st_value; // physical address
csym.n_scnum = CoffTextSectionNo;
csym.n_type = 0;
csym.n_sclass = C_FCN;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
// now put aux info
auxbf.regmask = 0;
auxbf.lineno = 0;
auxbf.nentries = FuncEntries[k];
auxbf.localframe = 0;
auxbf.nextentry = n + 6;
auxbf.dummy = 0;
fwrite(&auxbf, 18, 1, f);
// put a .ef
strcpy(csym._n._n_name, ".ef");
csym.n_value = EndAddress[k]; // physical address
csym.n_scnum = CoffTextSectionNo;
csym.n_type = 0;
csym.n_sclass = C_FCN;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
// now put aux info
auxef.dummy = 0;
auxef.lineno = LastLineNo[k];
auxef.dummy1 = 0;
auxef.dummy2 = 0;
auxef.dummy3 = 0;
auxef.dummy4 = 0;
fwrite(&auxef, 18, 1, f);
n += 6;
} else {
// try an put some type info
if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
csym.n_type = T_DOUBLE; // int
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
csym.n_type = T_FLOAT;
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_INT) {
csym.n_type = T_INT; // int
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
csym.n_type = T_SHORT;
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
csym.n_type = T_CHAR;
csym.n_sclass = C_EXT;
} else {
csym.n_type = T_INT; // just mark as a label
csym.n_sclass = C_LABEL;
}
csym.n_value = p->st_value;
csym.n_scnum = 2;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
auxfunc.tag = 0;
auxfunc.size = 0x20;
auxfunc.fileptr = 0;
auxfunc.nextsym = 0;
auxfunc.dummy = 0;
fwrite(&auxfunc, 18, 1, f);
n++;
n++;
}
p++;
}
}
if (s1->do_debug) {
// write string table
// first write the size
i = pCoff_str_table - Coff_str_table;
fwrite(&i, 4, 1, f);
// then write the strings
fwrite(Coff_str_table, i, 1, f);
tcc_free(Coff_str_table);
}
return 0;
}
// group the symbols in order of filename, func1, func2, etc
// finally global symbols
void SortSymbolTable(TCCState *s1)
{
int i, j, k, n = 0;
Elf32_Sym *p, *p2, *NewTable;
char *name, *name2;
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
p = (Elf32_Sym *) symtab_section->data;
// find a file symbol, copy it over
// then scan the whole symbol list and copy any function
// symbols that match the file association
for (i = 0; i < nb_syms; i++) {
if (p->st_info == 4) {
name = (char *) symtab_section->link->data + p->st_name;
// this is a file symbol, copy it over
NewTable[n++] = *p;
p2 = (Elf32_Sym *) symtab_section->data;
for (j = 0; j < nb_syms; j++) {
if (p2->st_info == 0x12) {
// this is a func symbol
name2 =
(char *) symtab_section->link->data + p2->st_name;
// find the function data index
for (k = 0; k < nFuncs; k++) {
if (strcmp(name2, Func[k]) == 0)
break;
}
if (k >= nFuncs) {
tcc_error("debug (sort) info can't find function: %s", name2);
}
if (strcmp(AssociatedFile[k], name) == 0) {
// yes they match copy it over
NewTable[n++] = *p2;
}
}
p2++;
}
}
p++;
}
// now all the filename and func symbols should have been copied over
// copy all the rest over (all except file and funcs)
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
if (p->st_info != 4 && p->st_info != 0x12) {
NewTable[n++] = *p;
}
p++;
}
if (n != nb_syms)
tcc_error("Internal Compiler error, debug info");
// copy it all back
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
*p++ = NewTable[i];
}
tcc_free(NewTable);
}
int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
{
int i, n = 0;
Elf32_Sym *p;
char *name;
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
name = (char *) symtab_section->link->data + p->st_name;
if (p->st_info == 4) {
// put a filename symbol
n++;
} else if (p->st_info == 0x12) {
if (strcmp(func_name, name) == 0)
return n;
n += 6;
// put a Function Name
// now put aux info
// put a .bf
// now put aux info
// put a .ef
// now put aux info
} else {
n += 2;
}
p++;
}
return n; // total number of symbols
}
int OutputTheSection(Section * sect)
{
const char *s = sect->name;
if (!strcmp(s, ".text"))
return 1;
else if (!strcmp(s, ".data"))
return 1;
else
return 0;
}
short int GetCoffFlags(const char *s)
{
if (!strcmp(s, ".text"))
return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
else if (!strcmp(s, ".data"))
return STYP_DATA;
else if (!strcmp(s, ".bss"))
return STYP_BSS;
else if (!strcmp(s, ".stack"))
return STYP_BSS | STYP_ALIGN | 0x200;
else if (!strcmp(s, ".cinit"))
return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
else
return 0;
}
Section *FindSection(TCCState * s1, const char *sname)
{
Section *s;
int i;
for (i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (!strcmp(sname, s->name))
return s;
}
tcc_error("could not find section %s", sname);
return 0;
}
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
{
// tktk TokenSym *ts;
FILE *f;
unsigned int str_size;
char *Coff_str_table, *name;
int i, k;
struct syment csym;
char name2[9];
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
f = fdopen(fd, "rb");
if (!f) {
tcc_error("Unable to open .out file for input");
}
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
tcc_error("error reading .out file for input");
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
tcc_error("error reading .out file for input");
// first read the string table
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
tcc_error("error reading .out file for input");
if (fread(&str_size, sizeof(int), 1, f) != 1)
tcc_error("error reading .out file for input");
Coff_str_table = (char *) tcc_malloc(str_size);
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
tcc_error("error reading .out file for input");
// read/process all the symbols
// seek back to symbols
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
tcc_error("error reading .out file for input");
for (i = 0; i < file_hdr.f_nsyms; i++) {
if (fread(&csym, SYMESZ, 1, f) != 1)
tcc_error("error reading .out file for input");
if (csym._n._n_n._n_zeroes == 0) {
name = Coff_str_table + csym._n._n_n._n_offset - 4;
} else {
name = csym._n._n_name;
if (name[7] != 0) {
for (k = 0; k < 8; k++)
name2[k] = name[k];
name2[8] = 0;
name = name2;
}
}
// if (strcmp("_DAC_Buffer",name)==0) // tktk
// name[0]=0;
if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
(csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure
(csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
(csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
{
// strip off any leading underscore (except for other main routine)
if (name[0] == '_' && strcmp(name, "_main") != 0)
name++;
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
}
// skip any aux records
if (csym.n_numaux == 1) {
if (fread(&csym, SYMESZ, 1, f) != 1)
tcc_error("error reading .out file for input");
i++;
}
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,7 @@
#define USING_GLOBALS
#include "tcc.h"
#include "utils/string.h"
#include "token.h"
/********************************************************/
/* global variables */
@ -30,13 +31,13 @@
rsym: return symbol
anon_sym: anonymous symbol index
*/
ST_DATA int rsym, anon_sym, ind, loc;
int rsym, anon_sym, ind, loc;
ST_DATA Sym *global_stack;
ST_DATA Sym *local_stack;
ST_DATA Sym *define_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *local_label_stack;
Sym *global_stack;
Sym *local_stack;
Sym *define_stack;
Sym *global_label_stack;
Sym *local_label_stack;
static Sym *sym_free_first;
static void **sym_pools;
@ -45,11 +46,11 @@ static int nb_sym_pools;
static Sym *all_cleanups, *pending_gotos;
static int local_scope;
ST_DATA SValue *vtop;
SValue *vtop;
static SValue _vstack[1 + VSTACK_SIZE];
#define vstack (_vstack + 1)
ST_DATA int nocode_wanted; /* no code generation wanted */
int nocode_wanted; /* no code generation wanted */
#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
#define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
@ -67,13 +68,13 @@ ST_DATA int nocode_wanted; /* no code generation wanted */
#define CONST_WANTED_MASK 0x0FFF0000
#define CONST_WANTED (nocode_wanted & CONST_WANTED_MASK)
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
ST_DATA int func_vc;
ST_DATA int func_ind;
ST_DATA const char *funcname;
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
CType func_vt; /* current function return type (used by return instruction) */
int func_var; /* true if current function is variadic (used by return instruction) */
int func_vc;
int func_ind;
const char *funcname;
CType int_type, func_old_type, char_type, char_pointer_type;
static CString initstr;
#if PTR_SIZE == 4
@ -163,7 +164,7 @@ static void do_Static_assert(void);
/* Automagical code suppression */
/* Clear 'nocode_wanted' at forward label if it was used */
ST_FUNC void gsym(int t)
void gsym(int t)
{
if (t) {
gsym_addr(t, ind);
@ -199,7 +200,7 @@ static int gjmp_acs(int t)
#define gjmp gjmp_acs
/* ------------------------------------------------------------------------- */
ST_INLN int is_float(int t)
int is_float(int t)
{
int bt = t & VT_BTYPE;
return bt == VT_LDOUBLE
@ -289,7 +290,7 @@ static int RC2_TYPE(int t, int rc)
/* we use our own 'finite' function to avoid potential problems with
non standard math libs */
/* XXX: endianness dependent */
ST_FUNC int ieee_finite(double d)
int ieee_finite(double d)
{
int p[4];
memcpy(p, &d, sizeof(double));
@ -299,13 +300,13 @@ ST_FUNC int ieee_finite(double d)
/* compiling intel long double natively */
# define TCC_IS_NATIVE_387
ST_FUNC void test_lvalue(void)
void test_lvalue(void)
{
if (!(vtop->r & VT_LVAL))
expect("lvalue");
}
ST_FUNC void check_vstack(void)
void check_vstack(void)
{
if (vtop != vstack - 1)
tcc_error("internal compiler error: vstack leak (%d)",
@ -327,7 +328,7 @@ void pv (const char *lbl, int a, int b)
/* ------------------------------------------------------------------------- */
/* initialize vstack and types. This must be done also for tcc -E */
ST_FUNC void tccgen_init(TCCState *s1)
void tccgen_init(TCCState *s1)
{
vtop = vstack - 1;
memset(vtop, 0, sizeof *vtop);
@ -351,7 +352,7 @@ ST_FUNC void tccgen_init(TCCState *s1)
cstr_new(&initstr);
}
ST_FUNC int tccgen_compile(TCCState *s1)
int tccgen_compile(TCCState *s1)
{
funcname = "";
func_ind = -1;
@ -371,7 +372,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
return 0;
}
ST_FUNC void tccgen_finish(TCCState *s1)
void tccgen_finish(TCCState *s1)
{
free_inline_functions(s1);
sym_pop(&global_stack, NULL, 0);
@ -396,7 +397,7 @@ ST_FUNC void tccgen_finish(TCCState *s1)
}
/* ------------------------------------------------------------------------- */
ST_FUNC ElfSym *elfsym(Sym *s)
ElfSym *elfsym(Sym *s)
{
if (!s || !s->c)
return NULL;
@ -404,7 +405,7 @@ ST_FUNC ElfSym *elfsym(Sym *s)
}
/* apply storage attributes to Elf symbol */
ST_FUNC void update_storage(Sym *sym)
void update_storage(Sym *sym)
{
ElfSym *esym;
int sym_bind, old_sym_bind;
@ -450,7 +451,7 @@ ST_FUNC void update_storage(Sym *sym)
/* update sym->c so that it points to an external symbol in section
'section' with value 'value' */
ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
void put_extern_sym2(Sym *sym, int sh_num,
addr_t value, unsigned long size,
int can_add_underscore)
{
@ -515,7 +516,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
update_storage(sym);
}
ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size)
void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size)
{
if (nocode_wanted && (NODATA_WANTED || (s && s == cur_text_section)))
return;
@ -523,7 +524,7 @@ ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long si
}
/* add a new relocation entry to symbol 'sym' in section 's' */
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
void greloca(Section *s, Sym *sym, unsigned long offset, int type,
addr_t addend)
{
int c = 0;
@ -542,7 +543,7 @@ ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
}
#if PTR_SIZE == 4
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
void greloc(Section *s, Sym *sym, unsigned long offset, int type)
{
greloca(s, sym, offset, type, 0);
}
@ -584,7 +585,7 @@ static inline Sym *sym_malloc(void)
#endif
}
ST_INLN void sym_free(Sym *sym)
void sym_free(Sym *sym)
{
#ifndef SYM_DEBUG
sym->next = sym_free_first;
@ -595,7 +596,7 @@ ST_INLN void sym_free(Sym *sym)
}
/* push, without hashing */
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c)
Sym *sym_push2(Sym **ps, int v, int t, int c)
{
Sym *s;
@ -612,7 +613,7 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c)
/* find a symbol and return its associated structure. 's' is the top
of the symbol stack */
ST_FUNC Sym *sym_find2(Sym *s, int v)
Sym *sym_find2(Sym *s, int v)
{
while (s) {
if (s->v == v)
@ -623,7 +624,7 @@ ST_FUNC Sym *sym_find2(Sym *s, int v)
}
/* structure lookup */
ST_INLN Sym *struct_find(int v)
Sym *struct_find(int v)
{
v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
@ -632,7 +633,7 @@ ST_INLN Sym *struct_find(int v)
}
/* find an identifier */
ST_INLN Sym *sym_find(int v)
Sym *sym_find(int v)
{
v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
@ -649,7 +650,7 @@ static int sym_scope(Sym *s)
}
/* push a given symbol on the symbol stack */
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
Sym *sym_push(int v, CType *type, int r, int c)
{
Sym *s, **ps;
TokenSym *ts;
@ -681,7 +682,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
}
/* push a global identifier */
ST_FUNC Sym *global_identifier_push(int v, int t, int c)
Sym *global_identifier_push(int v, int t, int c)
{
Sym *s, **ps;
s = sym_push2(&global_stack, v, t, c);
@ -701,7 +702,7 @@ ST_FUNC Sym *global_identifier_push(int v, int t, int c)
/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
pop them yet from the list, but do remove them from the token array. */
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
void sym_pop(Sym **ptop, Sym *b, int keep)
{
Sym *s, *ss, **ps;
TokenSym *ts;
@ -730,7 +731,7 @@ ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
}
/* label lookup */
ST_FUNC Sym *label_find(int v)
Sym *label_find(int v)
{
v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
@ -738,7 +739,7 @@ ST_FUNC Sym *label_find(int v)
return table_ident[v]->sym_label;
}
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
Sym *label_push(Sym **ptop, int v, int flags)
{
Sym *s, **ps;
s = sym_push2(ptop, v, VT_STATIC, 0);
@ -757,7 +758,7 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
/* pop labels until element last is reached. Look if any labels are
undefined. Define symbols if '&&label' was used. */
ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
void label_pop(Sym **ptop, Sym *slast, int keep)
{
Sym *s, *s1;
for(s = *ptop; s != slast; s = s1) {
@ -824,7 +825,7 @@ static void vsetc(CType *type, int r, CValue *vc)
vtop->sym = NULL;
}
ST_FUNC void vswap(void)
void vswap(void)
{
SValue tmp;
@ -835,7 +836,7 @@ ST_FUNC void vswap(void)
}
/* pop stack value */
ST_FUNC void vpop(void)
void vpop(void)
{
int v;
v = vtop->r & VT_VALMASK;
@ -868,7 +869,7 @@ static void vpush64(int ty, unsigned long long v)
}
/* push integer constant */
ST_FUNC void vpushi(int v)
void vpushi(int v)
{
vpush64(VT_INT, v);
}
@ -885,7 +886,7 @@ static inline void vpushll(long long v)
vpush64(VT_LLONG, v);
}
ST_FUNC void vset(CType *type, int r, int v)
void vset(CType *type, int r, int v)
{
CValue cval;
cval.i = v;
@ -900,7 +901,7 @@ static void vseti(int r, int v)
vset(&type, r, v);
}
ST_FUNC void vpushv(SValue *v)
void vpushv(SValue *v)
{
if (vtop >= vstack + (VSTACK_SIZE - 1))
tcc_error("memory full (vstack)");
@ -914,7 +915,7 @@ static void vdup(void)
}
/* rotate the stack element at position n-1 to the top */
ST_FUNC void vrotb(int n)
void vrotb(int n)
{
SValue tmp;
if (--n < 1)
@ -926,7 +927,7 @@ ST_FUNC void vrotb(int n)
}
/* rotate the top stack element into position n-1 */
ST_FUNC void vrott(int n)
void vrott(int n)
{
SValue tmp;
if (--n < 1)
@ -938,7 +939,7 @@ ST_FUNC void vrott(int n)
}
/* reverse order of the the first n stack elements */
ST_FUNC void vrev(int n)
void vrev(int n)
{
int i;
SValue tmp;
@ -951,7 +952,7 @@ ST_FUNC void vrev(int n)
/* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */
/* called from generators to set the result from relational ops */
ST_FUNC void vset_VT_CMP(int op)
void vset_VT_CMP(int op)
{
vtop->r = VT_CMP;
vtop->cmp_op = op;
@ -1038,7 +1039,7 @@ static void gen_test_zero(int op)
/* ------------------------------------------------------------------------- */
/* push a symbol value of TYPE */
ST_FUNC void vpushsym(CType *type, Sym *sym)
void vpushsym(CType *type, Sym *sym)
{
CValue cval;
cval.i = 0;
@ -1047,7 +1048,7 @@ ST_FUNC void vpushsym(CType *type, Sym *sym)
}
/* Return a static symbol pointing to a section */
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
{
int v;
Sym *sym;
@ -1066,7 +1067,7 @@ static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned
}
/* define a new external reference to a symbol 'v' of type 'u' */
ST_FUNC Sym *external_global_sym(int v, CType *type)
Sym *external_global_sym(int v, CType *type)
{
Sym *s;
@ -1085,14 +1086,14 @@ ST_FUNC Sym *external_global_sym(int v, CType *type)
/* create an external reference with no specific type similar to asm labels.
This avoids type conflicts if the symbol is used from C too */
ST_FUNC Sym *external_helper_sym(int v)
Sym *external_helper_sym(int v)
{
CType ct = { VT_ASM_FUNC, NULL };
return external_global_sym(v, &ct);
}
/* push a reference to an helper function (such as memmove) */
ST_FUNC void vpush_helper_func(int v)
void vpush_helper_func(int v)
{
vpushsym(&func_old_type, external_helper_sym(v));
}
@ -1289,7 +1290,7 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
}
/* save registers up to (vtop - n) stack entry */
ST_FUNC void save_regs(int n)
void save_regs(int n)
{
SValue *p, *p1;
for(p = vstack, p1 = vtop - n; p <= p1; p++)
@ -1297,14 +1298,14 @@ ST_FUNC void save_regs(int n)
}
/* save r to the memory stack, and mark it as being free */
ST_FUNC void save_reg(int r)
void save_reg(int r)
{
save_reg_upstack(r, 0);
}
/* save r to the memory stack, and mark it as being free,
if seen up to (vtop - n) stack entry */
ST_FUNC void save_reg_upstack(int r, int n)
void save_reg_upstack(int r, int n)
{
int l, size, align, bt, r2;
SValue *p, *p1, sv;
@ -1357,7 +1358,7 @@ ST_FUNC void save_reg_upstack(int r, int n)
}
/* find a free register of class 'rc'. If none, save one register */
ST_FUNC int get_reg(int rc)
int get_reg(int rc)
{
int r;
SValue *p;
@ -1455,7 +1456,7 @@ static void move_reg(int r, int s, int t)
}
/* get address of vtop (vtop MUST BE an lvalue) */
ST_FUNC void gaddrof(void)
void gaddrof(void)
{
vtop->r &= ~VT_LVAL;
/* tricky: if saved lvalue, then we can go back to lvalue */
@ -1555,7 +1556,7 @@ static void store_packed_bf(int bit_pos, int bit_size)
vpop(), vpop();
}
static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
static int adjust_bf(SValue *sv)
{
int t;
if (0 == sv->type.ref)
@ -1571,7 +1572,7 @@ static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
/* store vtop a register belonging to class 'rc'. lvalues are
converted to values. Cannot be used if cannot be converted to
register value (such as structures). */
ST_FUNC int gv(int rc)
int gv(int rc)
{
int r, r2, r_ok, r2_ok, rc2, bt;
int bit_pos, bit_size, size, align;
@ -1590,7 +1591,7 @@ ST_FUNC int gv(int rc)
if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
type.t |= VT_UNSIGNED;
r = adjust_bf(vtop, bit_pos, bit_size);
r = adjust_bf(vtop);
if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
type.t |= VT_LLONG;
@ -1616,7 +1617,7 @@ ST_FUNC int gv(int rc)
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
/* CPUs usually cannot use float constants, so we store them
generically in data segment */
init_params p = { rodata_section };
init_params p = { rodata_section, 0, NULL };
unsigned long offset;
size = type_size(&vtop->type, &align);
if (NODATA_WANTED)
@ -1709,7 +1710,7 @@ ST_FUNC int gv(int rc)
}
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
ST_FUNC void gv2(int rc1, int rc2)
void gv2(int rc1, int rc2)
{
/* generate more generic register first. But VT_JMP or VT_CMP
values must be generated first in all cases to avoid possible
@ -1739,7 +1740,7 @@ ST_FUNC void gv2(int rc1, int rc2)
#if PTR_SIZE == 4
/* expand 64bit on stack in two ints */
ST_FUNC void lexpand(void)
void lexpand(void)
{
int u, v;
u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
@ -2031,10 +2032,6 @@ static void gen_opl(int op)
else if (op1 == TOK_GE)
op1 = TOK_UGE;
gen_op(op1);
#if 0//def TCC_TARGET_I386
if (op == TOK_NE) { gsym(b); break; }
if (op == TOK_EQ) { gsym(a); break; }
#endif
gvtst_set(1, a);
gvtst_set(0, b);
break;
@ -2216,10 +2213,6 @@ static void gen_opif(int op)
{
int c1, c2, i, bt;
SValue *v1, *v2;
#if defined _MSC_VER && defined __x86_64__
/* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */
volatile
#endif
long double f1, f2;
v1 = vtop - 1;
@ -2389,6 +2382,7 @@ static void type_to_str(char *buf, int buf_size,
tstr = "double";
if (!(t & VT_LONG))
goto add_tstr;
// fall through
case VT_LDOUBLE:
tstr = "long double";
add_tstr:
@ -2703,7 +2697,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
}
/* generic gen_op: handles types problems */
ST_FUNC void gen_op(int op)
void gen_op(int op)
{
int t1, t2, bt1, bt2, t;
CType type1, combtype;
@ -2845,7 +2839,7 @@ static void gen_cvt_itof1(int t)
vpushi(0);
PUT_R_RET(vtop, t);
} else {
gen_cvt_itof(t);
gen_cvt_itof();
}
}
@ -3012,7 +3006,7 @@ error:
if (sf || df) {
if (sf && df) {
/* convert from fp to fp */
gen_cvt_ftof(dbt);
gen_cvt_ftof();
} else if (df) {
/* convert int to fp */
gen_cvt_itof1(dbt);
@ -3122,7 +3116,7 @@ done:
}
/* return type size as known at compile time. Put alignment at 'a' */
ST_FUNC int type_size(CType *type, int *a)
int type_size(CType *type, int *a)
{
Sym *s;
int bt;
@ -3152,11 +3146,7 @@ ST_FUNC int type_size(CType *type, int *a)
*a = LDOUBLE_ALIGN;
return LDOUBLE_SIZE;
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE)
*a = 4;
#else
*a = 8;
#endif
return 8;
} else if (bt == VT_INT || bt == VT_FLOAT) {
*a = 4;
@ -3196,7 +3186,7 @@ static inline CType *pointed_type(CType *type)
}
/* modify type so that its it is a pointer to type. */
ST_FUNC void mk_pointer(CType *type)
void mk_pointer(CType *type)
{
Sym *s;
s = sym_push(SYM_FIELD, type, 0, -1);
@ -3317,7 +3307,7 @@ static void gen_assign_cast(CType *dt)
}
/* store vtop in lvalue pushed on stack */
ST_FUNC void vstore(void)
void vstore(void)
{
int sbt, dbt, ft, r, size, align, bit_size, bit_pos, delayed_cast;
@ -3369,7 +3359,7 @@ ST_FUNC void vstore(void)
gen_cast(&vtop[-1].type);
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
}
r = adjust_bf(vtop - 1, bit_pos, bit_size);
r = adjust_bf(vtop - 1);
if (dbt != VT_BOOL) {
gen_cast(&vtop[-1].type);
dbt = vtop[-1].type.t & VT_BTYPE;
@ -3463,7 +3453,7 @@ ST_FUNC void vstore(void)
}
/* post defines POST/PRE add. c is the token ++ or -- */
ST_FUNC void inc(int post, int c)
void inc(int post, int c)
{
test_lvalue();
vdup(); /* save lvalue */
@ -3480,7 +3470,7 @@ ST_FUNC void inc(int post, int c)
vpop(); /* if post op, return saved value */
}
ST_FUNC CString* parse_mult_str (const char *msg)
CString* parse_mult_str (const char *msg)
{
/* read the string */
if (tok != TOK_STR)
@ -3497,7 +3487,7 @@ ST_FUNC CString* parse_mult_str (const char *msg)
/* If I is >= 1 and a power of two, returns log2(i)+1.
If I is 0 returns 0. */
ST_FUNC int exact_log2p1(int i)
int exact_log2p1(int i)
{
int ret;
if (!i)
@ -3638,7 +3628,6 @@ redo:
case TOK_STDCALL3:
ad->f.func_call = FUNC_STDCALL;
break;
#ifdef TCC_TARGET_I386
case TOK_REGPARM1:
case TOK_REGPARM2:
skip('(');
@ -3661,7 +3650,6 @@ redo:
case TOK_THISCALL3:
ad->f.func_call = FUNC_THISCALL;
break;
#endif
case TOK_MODE:
skip('(');
switch(tok) {
@ -4553,7 +4541,7 @@ static inline void convert_parameter_type(CType *pt)
}
}
ST_FUNC CString* parse_asm_str(void)
CString* parse_asm_str(void)
{
skip('(');
return parse_mult_str("string constant");
@ -4865,7 +4853,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
}
/* indirection with full error checking and bound check */
ST_FUNC void indir(void)
void indir(void)
{
if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
@ -4972,12 +4960,14 @@ static void parse_builtin_params(int nc, const char *args)
continue;
case 'V':
type.t = VT_CONSTANT;
// fall through
case 'v':
type.t |= VT_VOID;
mk_pointer (&type);
break;
case 'S':
type.t = VT_CONSTANT;
// fall through
case 's':
type.t |= char_type.t;
mk_pointer (&type);
@ -5132,7 +5122,7 @@ static void parse_atomic(int atok)
}
}
ST_FUNC void unary(void)
void unary(void)
{
int n, t, align, size, r;
CType type;
@ -6176,7 +6166,7 @@ static void expr_eq(void)
}
}
ST_FUNC void gexpr(void)
void gexpr(void)
{
expr_eq();
if (tok == ',') {
@ -6217,7 +6207,7 @@ static inline int64_t expr_const64(void)
/* parse an integer constant and return its value.
Complain if it doesn't fit 32bit (signed or unsigned). */
ST_FUNC int expr_const(void)
int expr_const(void)
{
int c;
int64_t wc = expr_const64();
@ -7680,13 +7670,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
p.local_offset = addr + size;
if (v) {
/* local variable */
#ifdef CONFIG_TCC_ASM
if (ad->asm_label) {
int reg = asm_parse_regvar(ad->asm_label);
if (reg >= 0)
r = (r & ~VT_VALMASK) | reg;
}
#endif
sym = sym_push(v, type, r, addr);
if (ad->cleanup_func) {
Sym *cls = sym_push2(&all_cleanups,
@ -7733,8 +7721,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
sec = rodata_section;
} else if (has_init) {
sec = data_section;
/*if (tcc_state->g_debug & 4)
tcc_warning("rw data: %s", get_tok_str(v, 0));*/
} else if (tcc_state->nocommon)
sec = bss_section;
}

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,9 @@
#define USING_GLOBALS
#include "tcc.h"
#include "utils/string.h"
#include "token.h"
#include <math.h>
#include <errno.h>
/* #define to 1 to enable (see parse_pp_string()) */
#define ACCEPT_LF_IN_STRINGS 0
@ -28,19 +31,19 @@
/********************************************************/
/* global variables */
ST_DATA int tok_flags;
ST_DATA int parse_flags;
int tok_flags;
int parse_flags;
ST_DATA struct BufferedFile *file;
ST_DATA int tok;
ST_DATA CValue tokc;
ST_DATA const int *macro_ptr;
ST_DATA CString tokcstr; /* current parsed string, if any */
struct BufferedFile *file;
int tok;
CValue tokc;
const int *macro_ptr;
CString tokcstr; /* current parsed string, if any */
/* display benchmark infos */
ST_DATA int tok_ident;
ST_DATA TokenSym **table_ident;
ST_DATA int pp_expr;
int tok_ident;
TokenSym **table_ident;
int pp_expr;
/* ------------------------------------------------------------------------- */
@ -64,7 +67,7 @@ static TokenString *macro_stack;
static const char tcc_keywords[] =
#define DEF(id, str) str "\0"
#include "tcctok.h"
#include "token.inc"
#undef DEF
;
@ -98,7 +101,7 @@ static const unsigned char tok_two_chars[] =
0
};
ST_FUNC void skip(int c)
void skip(int c)
{
if (tok != c) {
char tmp[40];
@ -108,7 +111,7 @@ ST_FUNC void skip(int c)
next();
}
ST_FUNC void expect(const char *msg)
void expect(const char *msg)
{
tcc_error("%s expected", msg);
}
@ -339,7 +342,7 @@ static void cstr_realloc(CString *cstr, int new_size)
}
/* add a byte */
ST_INLN void cstr_ccat(CString *cstr, int ch)
void cstr_ccat(CString *cstr, int ch)
{
int size;
size = cstr->size + 1;
@ -349,7 +352,7 @@ ST_INLN void cstr_ccat(CString *cstr, int ch)
cstr->size = size;
}
ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc)
char *unicode_to_utf8 (char *b, uint32_t Uc)
{
if (Uc<0x80) *b++=Uc;
else if (Uc<0x800) *b++=192+Uc/64, *b++=128+Uc%64;
@ -361,7 +364,7 @@ ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc)
}
/* add a unicode character expanded into utf8 */
ST_INLN void cstr_u8cat(CString *cstr, int ch)
void cstr_u8cat(CString *cstr, int ch)
{
char buf[4], *e;
e = unicode_to_utf8(buf, (uint32_t)ch);
@ -369,7 +372,7 @@ ST_INLN void cstr_u8cat(CString *cstr, int ch)
}
/* add string of 'len', or of its len/len+1 when 'len' == -1/0 */
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
void cstr_cat(CString *cstr, const char *str, int len)
{
int size;
if (len <= 0)
@ -382,7 +385,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
}
/* add a wide char */
ST_FUNC void cstr_wccat(CString *cstr, int ch)
void cstr_wccat(CString *cstr, int ch)
{
int size;
size = cstr->size + sizeof(nwchar_t);
@ -392,24 +395,24 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch)
cstr->size = size;
}
ST_FUNC void cstr_new(CString *cstr)
void cstr_new(CString *cstr)
{
memset(cstr, 0, sizeof(CString));
}
/* free string and reset it to NULL */
ST_FUNC void cstr_free(CString *cstr)
void cstr_free(CString *cstr)
{
tcc_free(cstr->data);
}
/* reset string to empty */
ST_FUNC void cstr_reset(CString *cstr)
void cstr_reset(CString *cstr)
{
cstr->size = 0;
}
ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
{
va_list v;
int len, size = 80;
@ -429,7 +432,7 @@ ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
return len;
}
ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...)
int cstr_printf(CString *cstr, const char *fmt, ...)
{
va_list ap; int len;
va_start(ap, fmt);
@ -496,7 +499,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
/* find a token and add it if not found */
ST_FUNC TokenSym *tok_alloc(const char *str, int len)
TokenSym *tok_alloc(const char *str, int len)
{
TokenSym *ts, **pts;
int i;
@ -519,7 +522,7 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int len)
return tok_alloc_new(pts, str, len);
}
ST_FUNC int tok_alloc_const(const char *str)
int tok_alloc_const(const char *str)
{
return tok_alloc(str, strlen(str))->tok;
}
@ -527,7 +530,7 @@ ST_FUNC int tok_alloc_const(const char *str)
/* XXX: buffer overflow */
/* XXX: float tokens */
ST_FUNC const char *get_tok_str(int v, CValue *cv)
const char *get_tok_str(int v, CValue *cv)
{
char *p;
int i, len;
@ -551,6 +554,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
break;
case TOK_LCHAR:
cstr_ccat(&cstr_buf, 'L');
// fall through
case TOK_CCHAR:
cstr_ccat(&cstr_buf, '\'');
add_char(&cstr_buf, cv->i);
@ -562,6 +566,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
return (char*)cv->str.data;
case TOK_LSTR:
cstr_ccat(&cstr_buf, 'L');
// fall through
case TOK_STR:
cstr_ccat(&cstr_buf, '\"');
if (v == TOK_STR) {
@ -1000,7 +1005,7 @@ static inline int tok_size(const int *p)
#endif
/* token string handling */
ST_INLN void tok_str_new(TokenString *s)
void tok_str_new(TokenString *s)
{
s->str = NULL;
s->len = s->need_spc = 0;
@ -1008,25 +1013,25 @@ ST_INLN void tok_str_new(TokenString *s)
s->last_line_num = -1;
}
ST_FUNC TokenString *tok_str_alloc(void)
TokenString *tok_str_alloc(void)
{
TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str);
tok_str_new(str);
return str;
}
ST_FUNC void tok_str_free_str(int *str)
void tok_str_free_str(int *str)
{
tal_free(tokstr_alloc, str);
}
ST_FUNC void tok_str_free(TokenString *str)
void tok_str_free(TokenString *str)
{
tok_str_free_str(str->str);
tal_free(tokstr_alloc, str);
}
ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
int *tok_str_realloc(TokenString *s, int new_size)
{
int *str, size;
@ -1043,7 +1048,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
return s->str;
}
ST_FUNC void tok_str_add(TokenString *s, int t)
void tok_str_add(TokenString *s, int t)
{
int len, *str;
@ -1055,7 +1060,7 @@ ST_FUNC void tok_str_add(TokenString *s, int t)
s->len = len;
}
ST_FUNC void begin_macro(TokenString *str, int alloc)
void begin_macro(TokenString *str, int alloc)
{
str->alloc = alloc;
str->prev = macro_stack;
@ -1065,7 +1070,7 @@ ST_FUNC void begin_macro(TokenString *str, int alloc)
macro_stack = str;
}
ST_FUNC void end_macro(void)
void end_macro(void)
{
TokenString *str = macro_stack;
macro_stack = str->prev;
@ -1154,7 +1159,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
}
/* add the current parse token in token string 's' */
ST_FUNC void tok_str_add_tok(TokenString *s)
void tok_str_add_tok(TokenString *s)
{
CValue cval;
@ -1272,7 +1277,7 @@ static int macro_is_equal(const int *a, const int *b)
}
/* defines handling */
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
void define_push(int v, int macro_type, int *str, Sym *first_arg)
{
Sym *s, *o;
@ -1287,14 +1292,14 @@ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
}
/* undefined a define symbol. Its name is just set to zero */
ST_FUNC void define_undef(Sym *s)
void define_undef(Sym *s)
{
int v = s->v;
if (v >= TOK_IDENT && v < tok_ident)
table_ident[v - TOK_IDENT]->sym_define = NULL;
}
ST_INLN Sym *define_find(int v)
Sym *define_find(int v)
{
v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
@ -1303,7 +1308,7 @@ ST_INLN Sym *define_find(int v)
}
/* free define stack until top reaches 'b' */
ST_FUNC void free_defines(Sym *b)
void free_defines(Sym *b)
{
while (define_stack != b) {
Sym *top = define_stack;
@ -1314,22 +1319,7 @@ ST_FUNC void free_defines(Sym *b)
}
}
/* fake the nth "#if defined test_..." for tcc -dt -run */
static void maybe_run_test(TCCState *s)
{
const char *p;
if (s->include_stack_ptr != s->include_stack)
return;
p = get_tok_str(tok, NULL);
if (0 != memcmp(p, "test_", 5))
return;
/*if (0 != --s->run_test)
return;*/
fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
define_push(tok, MACRO_OBJ, NULL, NULL);
}
ST_FUNC void skip_to_eol(int warn)
void skip_to_eol(int warn)
{
if (tok == TOK_LINEFEED)
return;
@ -1521,7 +1511,7 @@ static int expr_preprocess(TCCState *s1)
return c != 0;
}
ST_FUNC void pp_error(CString *cs)
void pp_error(CString *cs)
{
cstr_printf(cs, "bad preprocessor expression: #%s", get_tok_str(pp_expr, 0));
macro_ptr = macro_stack->str;
@ -1530,7 +1520,7 @@ ST_FUNC void pp_error(CString *cs)
}
/* parse after #define */
ST_FUNC void parse_define(void)
void parse_define(void)
{
Sym *s, *first, **ps;
int v, t, varg, is_vaargs, t0;
@ -1780,7 +1770,7 @@ pragma_err:
}
/* put alternative filename */
ST_FUNC void tccpp_putfile(const char *filename)
void tccpp_putfile(const char *filename)
{
char buf[1024];
buf[0] = 0;
@ -1802,7 +1792,7 @@ ST_FUNC void tccpp_putfile(const char *filename)
}
/* is_bof is true if first non space token at beginning of file */
ST_FUNC void preprocess(int is_bof)
void preprocess(int is_bof)
{
TCCState *s1 = tcc_state;
int c, n, saved_parse_flags;
@ -2659,7 +2649,7 @@ maybe_newline:
if (!(isidnum_table['$' - CH_EOF] & IS_ID)
|| (parse_flags & PARSE_FLAG_ASM_FILE))
goto parse_simple;
// fall through
case 'a': case 'b': case 'c': case 'd':
case 'e': case 'f': case 'g': case 'h':
case 'i': case 'j': case 'k': case 'l':
@ -3465,7 +3455,7 @@ static int macro_subst(
}
/* return next token with macro substitution */
ST_FUNC void next(void)
void next(void)
{
int t;
while (macro_ptr) {
@ -3524,7 +3514,7 @@ convert:
/* push back current token and set current token to 'last_tok'. Only
identifier case handled for labels. */
ST_INLN void unget_tok(int last_tok)
void unget_tok(int last_tok)
{
TokenString *str = &unget_buf;
int alloc = 0;
@ -3595,7 +3585,7 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
cstr_printf(cs, "#define __BASE_FILE__ \"%s\"\n", file->filename);
}
ST_FUNC void preprocess_start(TCCState *s1, int filetype)
void preprocess_start(TCCState *s1, int filetype)
{
int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
@ -3631,7 +3621,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype)
}
/* cleanup from error/setjmp */
ST_FUNC void preprocess_end(TCCState *s1)
void preprocess_end(TCCState *s1)
{
while (macro_stack)
end_macro();
@ -3641,14 +3631,14 @@ ST_FUNC void preprocess_end(TCCState *s1)
tccpp_delete(s1);
}
ST_FUNC int set_idnum(int c, int val)
int set_idnum(int c, int val)
{
int prev = isidnum_table[c - CH_EOF];
isidnum_table[c - CH_EOF] = val;
return prev;
}
ST_FUNC void tccpp_new(TCCState *s)
void tccpp_new(TCCState *s)
{
int i, c;
const char *p, *r;
@ -3700,7 +3690,7 @@ ST_FUNC void tccpp_new(TCCState *s)
define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
}
ST_FUNC void tccpp_delete(TCCState *s)
void tccpp_delete(TCCState *s)
{
int i, n;
@ -3852,7 +3842,7 @@ static int pp_check_he0xE(int t, const char *p)
}
/* Preprocess the current file */
ST_FUNC int tcc_preprocess(TCCState *s1)
int tcc_preprocess(TCCState *s1)
{
BufferedFile **iptr;
int token_seen, spcs, level;

98
libtcc/token.h Normal file
View file

@ -0,0 +1,98 @@
#ifndef TCC_TOKEN_H
# define TCC_TOKEN_H 1
/* conditional ops */
# define TOK_LAND 0x90
# define TOK_LOR 0x91
/* warning: the following compare tokens depend on i386 asm code */
# define TOK_ULT 0x92
# define TOK_UGE 0x93
# define TOK_EQ 0x94
# define TOK_NE 0x95
# define TOK_ULE 0x96
# define TOK_UGT 0x97
# define TOK_Nset 0x98
# define TOK_Nclear 0x99
# define TOK_LT 0x9c
# define TOK_GE 0x9d
# define TOK_LE 0x9e
# define TOK_GT 0x9f
# define TOK_ISCOND(t) (t >= TOK_LAND && t <= TOK_GT)
# define TOK_DEC 0x80 /* -- */
# define TOK_MID 0x81 /* inc/dec, to void constant */
# define TOK_INC 0x82 /* ++ */
# define TOK_UDIV 0x83 /* unsigned division */
# define TOK_UMOD 0x84 /* unsigned modulo */
# define TOK_PDIV 0x85 /* fast division with undefined rounding for pointers */
# define TOK_UMULL 0x86 /* unsigned 32x32 -> 64 mul */
# define TOK_ADDC1 0x87 /* add with carry generation */
# define TOK_ADDC2 0x88 /* add with carry use */
# define TOK_SUBC1 0x89 /* add with carry generation */
# define TOK_SUBC2 0x8a /* add with carry use */
# define TOK_SHL '<' /* shift left */
# define TOK_SAR '>' /* signed shift right */
# define TOK_SHR 0x8b /* unsigned shift right */
# define TOK_NEG TOK_MID /* unary minus operation (for floats) */
# define TOK_ARROW 0xa0 /* -> */
# define TOK_DOTS 0xa1 /* three dots */
# define TOK_TWODOTS 0xa2 /* C++ token ? */
# define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */
# define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
# define TOK_PPJOIN (TOK_TWOSHARPS | SYM_FIELD) /* A '##' in a macro to mean pasting */
# define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */
/* assignment operators */
# define TOK_A_ADD 0xb0
# define TOK_A_SUB 0xb1
# define TOK_A_MUL 0xb2
# define TOK_A_DIV 0xb3
# define TOK_A_MOD 0xb4
# define TOK_A_AND 0xb5
# define TOK_A_OR 0xb6
# define TOK_A_XOR 0xb7
# define TOK_A_SHL 0xb8
# define TOK_A_SAR 0xb9
# define TOK_ASSIGN(t) (t >= TOK_A_ADD && t <= TOK_A_SAR)
# define TOK_ASSIGN_OP(t) ("+-*/%&|^<>"[t - TOK_A_ADD])
/* tokens that carry values (in additional token string space / tokc) --> */
# define TOK_CCHAR 0xc0 /* char constant in tokc */
# define TOK_LCHAR 0xc1
# define TOK_CINT 0xc2 /* number in tokc */
# define TOK_CUINT 0xc3 /* unsigned int constant */
# define TOK_CLLONG 0xc4 /* long long constant */
# define TOK_CULLONG 0xc5 /* unsigned long long constant */
# define TOK_CLONG 0xc6 /* long constant */
# define TOK_CULONG 0xc7 /* unsigned long constant */
# define TOK_STR 0xc8 /* pointer to string in tokc */
# define TOK_LSTR 0xc9
# define TOK_CFLOAT 0xca /* float constant */
# define TOK_CDOUBLE 0xcb /* double constant */
# define TOK_CLDOUBLE 0xcc /* long double constant */
# define TOK_PPNUM 0xcd /* preprocessor number */
# define TOK_PPSTR 0xce /* preprocessor string */
# define TOK_LINENUM 0xcf /* line number info */
# define TOK_HAS_VALUE(t) (t >= TOK_CCHAR && t <= TOK_LINENUM)
# define TOK_EOF (-1) /* end of file */
# define TOK_LINEFEED 10 /* line feed */
/* all identifiers and strings have token above that */
# define TOK_IDENT 256
enum tcc_token {
TOK_LAST = TOK_IDENT - 1
# define DEF(id, str) ,id
# include "token.inc"
# undef DEF
};
/* keywords: tok >= TOK_IDENT && tok < TOK_UIDENT */
# define TOK_UIDENT TOK_DEFINE
#endif /* !TCC_TOKEN_H */

View file

@ -265,4 +265,4 @@
DEF_ASMDIR(symver)
DEF_ASMDIR(section) /* must be last directive */
#include "i386/tok.h"
#include "i386/token.inc"

21
libtcc/utils/cstr.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef LIBTCC_UTILS_CSTR_H
# define LIBTCC_UTILS_CSTR_H 1
# include <stdarg.h>
typedef struct CString {
int size;
int size_allocated;
char *data;
} CString;
void cstr_ccat(CString *cstr, int ch);
void cstr_cat(CString *cstr, const char *str, int len);
void cstr_wccat(CString *cstr, int ch);
void cstr_new(CString *cstr);
void cstr_free(CString *cstr);
int cstr_printf(CString *cs, const char *fmt, ...) __attribute__ ((format (printf, (2), (3))));
int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
void cstr_reset(CString *cstr);
#endif /* !LIBTCC_UTILS_CSTR_H */

20
libtcc1/Makefile.am Normal file
View file

@ -0,0 +1,20 @@
COMPILE = ../tcc/tcc
noinst_LIBRARIES = libtcc1.a
libtcc1_a_SOURCES = alloca.S atomic.S builtin.c libtcc1.c stdatomic.c
alloca.o: alloca.S
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
atomic.o: atomic.S
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
builtin.o: builtin.c
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
libtcc1.o: libtcc1.c
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
stdatomic.o: stdatomic.c
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include

View file

@ -1,96 +0,0 @@
/* ---------------------------------------------- */
/* alloca-bt.S */
#ifdef __leading_underscore
# define _(s) _##s
#else
# define _(s) s
#endif
/* ---------------------------------------------- */
#if defined __i386__
.globl _(__bound_alloca)
_(__bound_alloca):
pop %edx
pop %eax
mov %eax, %ecx
add $3+1,%eax
and $-4,%eax
jz p6
#ifdef _WIN32
p4:
cmp $4096,%eax
jbe p5
test %eax,-4096(%esp)
sub $4096,%esp
sub $4096,%eax
jmp p4
p5:
#endif
sub %eax,%esp
mov %esp,%eax
push %edx
push %eax
push %ecx
push %eax
call _(__bound_new_region)
add $8, %esp
pop %eax
pop %edx
p6:
push %edx
push %edx
ret
/* ---------------------------------------------- */
#elif defined __x86_64__
.globl _(__bound_alloca)
_(__bound_alloca):
#ifdef _WIN32
inc %rcx # add one extra to separate regions
jmp _(alloca)
.globl _(__bound_alloca_nr)
_(__bound_alloca_nr):
dec %rcx
push %rax
mov %rcx,%rdx
mov %rax,%rcx
sub $32,%rsp
call _(__bound_new_region)
add $32,%rsp
pop %rax
ret
#else
pop %rdx
mov %rdi,%rax
mov %rax,%rsi # size, a second parm to the __bound_new_region
add $15 + 1,%rax # add one extra to separate regions
and $-16,%rax
jz p3
sub %rax,%rsp
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
mov %rsp,%rax
push %rdx
push %rax
call _(__bound_new_region)
pop %rax
pop %rdx
p3:
push %rdx
ret
#endif
/* ---------------------------------------------- */
#endif

View file

@ -7,9 +7,6 @@
# define _(s) s
#endif
/* ---------------------------------------------- */
#if defined __i386__
.globl _(alloca), _(__alloca)
_(alloca):
_(__alloca):
@ -35,51 +32,3 @@ p2:
push %eax
lea 8(%esp),%eax
ret
/* ---------------------------------------------- */
#elif defined __x86_64__
.globl _(alloca)
_(alloca):
pop %rdx
#ifdef _WIN32
mov %rcx,%rax
#else
mov %rdi,%rax
#endif
add $15,%rax
and $-16,%rax
jz p3
#ifdef _WIN32
p1:
cmp $4096,%rax
jbe p2
test %rax,-4096(%rsp)
sub $4096,%rsp
sub $4096,%rax
jmp p1
p2:
#endif
sub %rax,%rsp
mov %rsp,%rax
p3:
push %rdx
ret
/* ---------------------------------------------- */
#elif defined __arm__
.text
.align 2
.global alloca
.type alloca, %function
alloca:
rsb sp, r0, sp
bic sp, sp, #7
mov r0, sp
mov pc, lr
.size alloca, .-alloca
/* ---------------------------------------------- */
#endif

View file

@ -1,544 +0,0 @@
/* TCC ARM runtime EABI
Copyright (C) 2013 Thomas Preud'homme
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
#ifdef __TINYC__
#define INT_MIN (-2147483647 - 1)
#define INT_MAX 2147483647
#define UINT_MAX 0xffffffff
#define LONG_MIN (-2147483647L - 1)
#define LONG_MAX 2147483647L
#define ULONG_MAX 0xffffffffUL
#define LLONG_MAX 9223372036854775807LL
#define LLONG_MIN (-9223372036854775807LL - 1)
#define ULLONG_MAX 0xffffffffffffffffULL
#else
#include <limits.h>
#endif
/* We rely on the little endianness and EABI calling convention for this to
work */
typedef struct double_unsigned_struct {
unsigned low;
unsigned high;
} double_unsigned_struct;
typedef struct unsigned_int_struct {
unsigned low;
int high;
} unsigned_int_struct;
#define REGS_RETURN(name, type) \
void name ## _return(type ret) {}
/* Float helper functions */
#define FLOAT_EXP_BITS 8
#define FLOAT_FRAC_BITS 23
#define DOUBLE_EXP_BITS 11
#define DOUBLE_FRAC_BITS 52
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
/* float to [unsigned] long long conversion */
#define DEFINE__AEABI_F2XLZ(name, with_sign) \
void __aeabi_ ## name(unsigned val) \
{ \
int exp, high_shift, sign; \
double_unsigned_struct ret; \
\
/* compute sign */ \
sign = val >> 31; \
\
/* compute real exponent */ \
exp = val >> FLOAT_FRAC_BITS; \
exp &= (1 << FLOAT_EXP_BITS) - 1; \
exp -= ONE_EXP(FLOAT); \
\
/* undefined behavior if truncated value cannot be represented */ \
if (with_sign) { \
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
return; \
} else { \
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
return; \
} \
\
val &= (1 << FLOAT_FRAC_BITS) - 1; \
if (exp >= 32) { \
ret.high = 1 << (exp - 32); \
if (exp - 32 >= FLOAT_FRAC_BITS) { \
ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
ret.low = 0; \
} else { \
high_shift = FLOAT_FRAC_BITS - (exp - 32); \
ret.high |= val >> high_shift; \
ret.low = val << (32 - high_shift); \
} \
} else { \
ret.high = 0; \
ret.low = 1 << exp; \
if (exp > FLOAT_FRAC_BITS) \
ret.low |= val << (exp - FLOAT_FRAC_BITS); \
else \
ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
} \
\
/* encode negative integer using 2's complement */ \
if (with_sign && sign) { \
ret.low = ~ret.low; \
ret.high = ~ret.high; \
if (ret.low == UINT_MAX) { \
ret.low = 0; \
ret.high++; \
} else \
ret.low++; \
} \
\
double_unsigned_struct_return(ret); \
}
/* float to unsigned long long conversion */
DEFINE__AEABI_F2XLZ(f2ulz, 0)
/* float to long long conversion */
DEFINE__AEABI_F2XLZ(f2lz, 1)
/* double to [unsigned] long long conversion */
#define DEFINE__AEABI_D2XLZ(name, with_sign) \
void __aeabi_ ## name(double_unsigned_struct val) \
{ \
int exp, high_shift, sign; \
double_unsigned_struct ret; \
\
if ((val.high & ~0x80000000) == 0 && val.low == 0) { \
ret.low = ret.high = 0; \
goto _ret_; \
} \
\
/* compute sign */ \
sign = val.high >> 31; \
\
/* compute real exponent */ \
exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
exp &= (1 << DOUBLE_EXP_BITS) - 1; \
exp -= ONE_EXP(DOUBLE); \
\
/* undefined behavior if truncated value cannot be represented */ \
if (with_sign) { \
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
return; \
} else { \
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
return; \
} \
\
val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
if (exp >= 32) { \
ret.high = 1 << (exp - 32); \
if (exp >= DOUBLE_FRAC_BITS) { \
high_shift = exp - DOUBLE_FRAC_BITS; \
ret.high |= val.high << high_shift; \
ret.high |= val.low >> (32 - high_shift); \
ret.low = val.low << high_shift; \
} else { \
high_shift = DOUBLE_FRAC_BITS - exp; \
ret.high |= val.high >> high_shift; \
ret.low = val.high << (32 - high_shift); \
ret.low |= val.low >> high_shift; \
} \
} else { \
ret.high = 0; \
ret.low = 1 << exp; \
if (exp > DOUBLE_FRAC_BITS - 32) { \
high_shift = exp - DOUBLE_FRAC_BITS - 32; \
ret.low |= val.high << high_shift; \
ret.low |= val.low >> (32 - high_shift); \
} else \
ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
} \
\
/* encode negative integer using 2's complement */ \
if (with_sign && sign) { \
ret.low = ~ret.low; \
ret.high = ~ret.high; \
if (ret.low == UINT_MAX) { \
ret.low = 0; \
ret.high++; \
} else \
ret.low++; \
} \
\
_ret_: \
double_unsigned_struct_return(ret); \
}
/* double to unsigned long long conversion */
DEFINE__AEABI_D2XLZ(d2ulz, 0)
/* double to long long conversion */
DEFINE__AEABI_D2XLZ(d2lz, 1)
/* long long to float conversion */
#define DEFINE__AEABI_XL2F(name, with_sign) \
unsigned __aeabi_ ## name(unsigned long long v) \
{ \
int s /* shift */, flb /* first lost bit */, sign = 0; \
unsigned p = 0 /* power */, ret; \
double_unsigned_struct val; \
\
/* fraction in negative float is encoded in 1's complement */ \
if (with_sign && (v & (1ULL << 63))) { \
sign = 1; \
v = ~v + 1; \
} \
val.low = v; \
val.high = v >> 32; \
/* fill fraction bits */ \
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
if (p) { \
ret = val.high & (p - 1); \
if (s < FLOAT_FRAC_BITS) { \
ret <<= FLOAT_FRAC_BITS - s; \
ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
} else { \
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
ret >>= s - FLOAT_FRAC_BITS; \
} \
s += 32; \
} else { \
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
if (p) { \
ret = val.low & (p - 1); \
if (s <= FLOAT_FRAC_BITS) { \
ret <<= FLOAT_FRAC_BITS - s; \
flb = 0; \
} else { \
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
ret >>= s - FLOAT_FRAC_BITS; \
} \
} else \
return 0; \
} \
if (flb) \
ret++; \
\
/* fill exponent bits */ \
ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
\
/* fill sign bit */ \
ret |= sign << 31; \
\
return ret; \
}
/* unsigned long long to float conversion */
DEFINE__AEABI_XL2F(ul2f, 0)
/* long long to float conversion */
DEFINE__AEABI_XL2F(l2f, 1)
/* long long to double conversion */
#define __AEABI_XL2D(name, with_sign) \
void __aeabi_ ## name(unsigned long long v) \
{ \
int s /* shift */, high_shift, sign = 0; \
unsigned tmp, p = 0; \
double_unsigned_struct val, ret; \
\
/* fraction in negative float is encoded in 1's complement */ \
if (with_sign && (v & (1ULL << 63))) { \
sign = 1; \
v = ~v + 1; \
} \
val.low = v; \
val.high = v >> 32; \
\
/* fill fraction bits */ \
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
if (p) { \
tmp = val.high & (p - 1); \
if (s < DOUBLE_FRAC_BITS - 32) { \
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
ret.high = tmp << high_shift; \
ret.high |= val.low >> (32 - high_shift); \
ret.low = val.low << high_shift; \
} else { \
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
ret.high = tmp >> high_shift; \
ret.low = tmp << (32 - high_shift); \
ret.low |= val.low >> high_shift; \
if ((val.low >> (high_shift - 1)) & 1) { \
if (ret.low == UINT_MAX) { \
ret.high++; \
ret.low = 0; \
} else \
ret.low++; \
} \
} \
s += 32; \
} else { \
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
if (p) { \
tmp = val.low & (p - 1); \
if (s <= DOUBLE_FRAC_BITS - 32) { \
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
ret.high = tmp << high_shift; \
ret.low = 0; \
} else { \
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
ret.high = tmp >> high_shift; \
ret.low = tmp << (32 - high_shift); \
} \
} else { \
ret.high = ret.low = 0; \
goto _ret_; \
} \
} \
\
/* fill exponent bits */ \
ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
\
/* fill sign bit */ \
ret.high |= sign << 31; \
\
_ret_: \
double_unsigned_struct_return(ret); \
}
/* unsigned long long to double conversion */
__AEABI_XL2D(ul2d, 0)
/* long long to double conversion */
__AEABI_XL2D(l2d, 1)
/* Long long helper functions */
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
#define define_aeabi_xdivmod_signed_type(basetype, type) \
typedef struct type { \
basetype quot; \
unsigned basetype rem; \
} type
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
typedef struct type { \
basetype quot; \
basetype rem; \
} type
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
static inline rettype aeabi_ ## name (type num, type den) \
{ \
rettype ret; \
type quot = 0; \
\
/* Increase quotient while it is less than numerator */ \
while (num >= den) { \
type q = 1; \
\
/* Find closest power of two */ \
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
q <<= 1; \
\
/* Compute difference between current quotient and numerator */ \
num -= q * den; \
quot += q; \
} \
ret.quot = quot; \
ret.rem = num; \
return ret; \
}
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
void __aeabi_ ## name(type numerator, type denominator) \
{ \
unsigned type num, den; \
urettype uxdiv_ret; \
rettype ret; \
\
if (numerator >= 0) \
num = numerator; \
else \
num = 0 - numerator; \
if (denominator >= 0) \
den = denominator; \
else \
den = 0 - denominator; \
uxdiv_ret = aeabi_ ## uiname(num, den); \
/* signs differ */ \
if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
ret.quot = 0 - uxdiv_ret.quot; \
else \
ret.quot = uxdiv_ret.quot; \
if (numerator < 0) \
ret.rem = 0 - uxdiv_ret.rem; \
else \
ret.rem = uxdiv_ret.rem; \
\
rettype ## _return(ret); \
}
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
define_aeabi_xdivmod_signed_type(int, idiv_t);
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
REGS_RETURN(lldiv_t, lldiv_t)
REGS_RETURN(ulldiv_t, ulldiv_t)
REGS_RETURN(idiv_t, idiv_t)
REGS_RETURN(uidiv_t, uidiv_t)
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULLONG)
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
{
ulldiv_t_return(aeabi_uldivmod(num, den));
}
void __aeabi_llsl(double_unsigned_struct val, int shift)
{
double_unsigned_struct ret;
if (shift >= 32) {
val.high = val.low;
val.low = 0;
shift -= 32;
}
if (shift > 0) {
ret.low = val.low << shift;
ret.high = (val.high << shift) | (val.low >> (32 - shift));
double_unsigned_struct_return(ret);
return;
}
double_unsigned_struct_return(val);
}
#define aeabi_lsr(val, shift, fill, type) \
type ## _struct ret; \
\
if (shift >= 32) { \
val.low = val.high; \
val.high = fill; \
shift -= 32; \
} \
if (shift > 0) { \
ret.high = val.high >> shift; \
ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
type ## _struct_return(ret); \
return; \
} \
type ## _struct_return(val);
void __aeabi_llsr(double_unsigned_struct val, int shift)
{
aeabi_lsr(val, shift, 0, double_unsigned);
}
void __aeabi_lasr(unsigned_int_struct val, int shift)
{
aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
}
/* Integer division functions */
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
int __aeabi_idiv(int numerator, int denominator)
{
unsigned num, den;
uidiv_t ret;
if (numerator >= 0)
num = numerator;
else
num = 0 - numerator;
if (denominator >= 0)
den = denominator;
else
den = 0 - denominator;
ret = aeabi_uidivmod(num, den);
if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
ret.quot *= -1;
return ret.quot;
}
unsigned __aeabi_uidiv(unsigned num, unsigned den)
{
return aeabi_uidivmod(num, den).quot;
}
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
void __aeabi_uidivmod(unsigned num, unsigned den)
{
uidiv_t_return(aeabi_uidivmod(num, den));
}
/* Some targets do not have all eabi calls (OpenBSD) */
typedef __SIZE_TYPE__ size_t;
extern void *memcpy(void *dest, const void *src, size_t n);
extern void *memmove(void *dest, const void *src, size_t n);
extern void *memset(void *s, int c, size_t n);
void *
__aeabi_memcpy (void *dest, const void *src, size_t n)
{
return memcpy (dest, src, n);
}
void *
__aeabi_memmove (void *dest, const void *src, size_t n)
{
return memmove (dest, src, n);
}
void *
__aeabi_memmove4 (void *dest, const void *src, size_t n)
{
return memmove (dest, src, n);
}
void *
__aeabi_memmove8 (void *dest, const void *src, size_t n)
{
return memmove (dest, src, n);
}
void *
__aeabi_memset (void *s, size_t n, int c)
{
return memset (s, c, n);
}

View file

@ -1,51 +0,0 @@
/* armflush.c - flush the instruction cache
__clear_cache is used in tccrun.c, It is a built-in
intrinsic with gcc. However tcc in order to compile
itself needs this function */
#ifdef __TINYC__
/* syscall wrapper */
unsigned _tccsyscall(unsigned syscall_nr, ...);
/* arm-tcc supports only fake asm currently */
__asm__(
".global _tccsyscall\n"
"_tccsyscall:\n"
"push {r7, lr}\n\t"
"mov r7, r0\n\t"
"mov r0, r1\n\t"
"mov r1, r2\n\t"
"mov r2, r3\n\t"
"svc #0\n\t"
"pop {r7, pc}"
);
/* from unistd.h: */
#if defined(__thumb__) || defined(__ARM_EABI__)
# define __NR_SYSCALL_BASE 0x0
#else
# define __NR_SYSCALL_BASE 0x900000
#endif
#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
#define syscall _tccsyscall
#else
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#endif
/* Flushing for tccrun */
void __clear_cache(void *beginning, void *end)
{
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
* However, there is no ARM asm parser in tcc so we use it for now */
syscall(__ARM_NR_cacheflush, beginning, end, 0);
}

View file

@ -12,7 +12,6 @@
# define _(s) s
#endif
#if defined __i386__
.text
.align 2
@ -33,826 +32,3 @@ _(__atomic_clear):
xchgb (%edx), %al
ret
.size _(__atomic_clear), .-_(__atomic_clear)
#elif defined __x86_64__
.text
.align 2
.global _(__atomic_test_and_set)
.type _(__atomic_test_and_set), %function
_(__atomic_test_and_set):
movl $1, %eax
xchgb (%rdi), %al
ret
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
.global _(__atomic_clear)
.type _(__atomic_clear), %function
_(__atomic_clear):
xorl %eax, %eax
xchgb (%rdi), %al
ret
.size _(__atomic_clear), .-_(__atomic_clear)
#elif defined __arm__
#ifndef __TINYC__
.arch armv6k
.syntax unified
#endif
.text
.align 2
.global _(fetch_and_add_arm)
.type _(fetch_and_add_arm), %function
_(fetch_and_add_arm):
mcr p15, #0, r0, c7, c10, #5
.L0:
ldrex r3, [r0]
add r3, r3, r1
strex r2, r3, [r0]
cmp r2, #0
bne .L0
mcr p15, #0, r0, c7, c10, #5
bx lr
.size _(fetch_and_add_arm), .-_(fetch_and_add_arm)
.global _(__atomic_test_and_set)
.type _(__atomic_test_and_set), %function
_(__atomic_test_and_set):
#ifdef __TINYC__
.int 0xe92d4030
.int 0xee070fba
.int 0xe5d03000
.int 0xe24dd014
.int 0xe1a05000
.int 0xe2533000
.int 0xe1a04001
.int 0x13a03001
.int 0xee070fba
.int 0xe5cd300f
.int 0xe3a03001
.int 0xe1a02003
.int 0xe28d100f
.int 0xe1a00005
.int 0xe58d4004
.int 0xe58d4000
.int 0xeb000009
.int 0xe3500000
.int 0x0afffff6
.int 0xe5dd000f
.int 0xe28dd014
.int 0xe8bd8030
#else
push {r4, r5, lr}
mcr p15, 0, r0, c7, c10, 5
ldrb r3, [r0]
sub sp, sp, #20
mov r5, r0
subs r3, r3, #0
mov r4, r1
movne r3, #1
mcr p15, 0, r0, c7, c10, 5
strb r3, [sp, #15]
.L20:
mov r3, #1
mov r2, r3
add r1, sp, #15
mov r0, r5
str r4, [sp, #4]
str r4, [sp]
bl __atomic_compare_exchange_1
cmp r0, #0
beq .L20
ldrb r0, [sp, #15]
add sp, sp, #20
pop {r4, r5, pc}
#endif
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
.global _(__atomic_clear)
.type _(__atomic_clear), %function
_(__atomic_clear):
#ifdef __TINYC__
.int 0xe3a03000
.int 0xee070fba
.int 0xe5c03000
.int 0xee070fba
.int 0xe12fff1e
#else
mov r3, #0
mcr p15, 0, r0, c7, c10, 5
strb r3, [r0]
mcr p15, 0, r0, c7, c10, 5
bx lr
#endif
.size _(__atomic_clear), .-_(__atomic_clear)
.global _(__atomic_compare_exchange_1)
.type _(__atomic_compare_exchange_1), %function
_(__atomic_compare_exchange_1):
#ifdef __TINYC__
.int 0xe52de004
.int 0xe5d13000
.int 0xf57ff05b
.int 0xe1d0cf9f
.int 0xe15c0003
.int 0x1a000002
.int 0xe1c0ef92
.int 0xe35e0000
.int 0x1afffff9
.int 0x03a00001
.int 0x13a00000
.int 0xf57ff05b
.int 0x15c1c000
.int 0xe49df004
#else
str lr, [sp, #-4]!
ldrb r3, [r1]
mcr p15, 0, r0, c7, c10, 5
.L1:
ldrexb ip, [r0]
cmp ip, r3
bne .L2
strexb lr, r2, [r0]
cmp lr, #0
bne .L1
.L2:
mcr p15, 0, r0, c7, c10, 5
moveq r0, #1
movne r0, #0
strbne ip, [r1]
ldr pc, [sp], #4
#endif
.size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
.global _(__atomic_compare_exchange_2)
.type _(__atomic_compare_exchange_2), %function
_(__atomic_compare_exchange_2):
#ifdef __TINYC__
.int 0xe52de004
.int 0xe1d130b0
.int 0xf57ff05b
.int 0xe1f0cf9f
.int 0xe15c0003
.int 0x1a000002
.int 0xe1e0ef92
.int 0xe35e0000
.int 0x1afffff9
.int 0x03a00001
.int 0x13a00000
.int 0xf57ff05b
.int 0x11c1c0b0
.int 0xe49df004
#else
str lr, [sp, #-4]!
ldrh r3, [r1]
mcr p15, 0, r0, c7, c10, 5
.L3:
ldrexh ip, [r0]
cmp ip, r3
bne .L4
strexh lr, r2, [r0]
cmp lr, #0
bne .L3
.L4:
mcr p15, 0, r0, c7, c10, 5
moveq r0, #1
movne r0, #0
strhne ip, [r1]
ldr pc, [sp], #4
#endif
.size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
.global _(__atomic_compare_exchange_4)
.type _(__atomic_compare_exchange_4), %function
_(__atomic_compare_exchange_4):
#ifdef __TINYC__
.int 0xe52de004
.int 0xe5913000
.int 0xf57ff05b
.int 0xe190cf9f
.int 0xe15c0003
.int 0x1a000002
.int 0xe180ef92
.int 0xe35e0000
.int 0x1afffff9
.int 0x03a00001
.int 0x13a00000
.int 0xf57ff05b
.int 0x1581c000
.int 0xe49df004
#else
str lr, [sp, #-4]!
ldr r3, [r1]
mcr p15, 0, r0, c7, c10, 5
.L5:
ldrex ip, [r0]
cmp ip, r3
bne .L6
strex lr, r2, [r0]
cmp lr, #0
bne .L5
.L6:
mcr p15, 0, r0, c7, c10, 5
moveq r0, #1
movne r0, #0
strne ip, [r1]
ldr pc, [sp], #4
#endif
.size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
/* ---------------------------------------------- */
#elif defined __aarch64__
.text
.align 2
.global _(fetch_and_add_arm64)
.type _(fetch_and_add_arm64), %function
_(fetch_and_add_arm64):
#ifdef __TINYC__
.int 0x885f7c02
.int 0x0b010042
.int 0x8803fc02
.int 0x35ffffa3
.int 0xd5033bbf
.int 0xd65f03c0
#else
ldxr w2, [x0]
add w2, w2, w1
stlxr w3, w2, [x0]
cbnz w3, _(fetch_and_add_arm64)
dmb ish
ret
#endif
.size _(fetch_and_add_arm64), .-_(fetch_and_add_arm64)
.global _(__atomic_test_and_set)
.type _(__atomic_test_and_set), %function
_(__atomic_test_and_set):
#ifdef __TINYC__
.int 0xa9bf7bfd
.int 0xaa0003e1
.int 0x52800020
.int 0x910003fd
.int 0x2a0003f0
.int 0x085ffc20
.int 0x0811fc30
.int 0x35ffffd1
.int 0xa8c17bfd
.int 0xd65f03c0
#else
stp x29, x30, [sp, -16]!
mov x1, x0
mov w0, 1
mov x29, sp
mov w16, w0
.L20:
ldaxrb w0, [x1]
stlxrb w17, w16, [x1]
cbnz w17, .L20
ldp x29, x30, [sp], 16
ret
#endif
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
.global _(__atomic_clear)
.type _(__atomic_clear), %function
_(__atomic_clear):
#ifdef __TINYC__
.int 0x089ffc1f
.int 0xd65f03c0
#else
stlrb wzr, [x0]
ret
#endif
.size _(__atomic_clear), .-_(__atomic_clear)
.global _(__atomic_compare_exchange_1)
.type _(__atomic_compare_exchange_1), %function
_(__atomic_compare_exchange_1):
#ifdef __TINYC__
.int 0xa9be7bfd
.int 0x910003fd
.int 0xa90153f3
.int 0xaa0103f3
.int 0x12001c41
.int 0xaa0003e2
.int 0x39400274
.int 0x2a1403e0
.int 0x53001c10
.int 0x085ffc40
.int 0x6b10001f
.int 0x54000061
.int 0x0811fc41
.int 0x35ffff91
.int 0x6b34001f
.int 0x1a9f17e1
.int 0x54000040
.int 0x39000260
.int 0x2a0103e0
.int 0xa94153f3
.int 0xa8c27bfd
.int 0xd65f03c0
#else
stp x29, x30, [sp, -32]!
mov x29, sp
stp x19, x20, [sp, 16]
mov x19, x1
and w1, w2, 255
mov x2, x0
ldrb w20, [x19]
mov w0, w20
uxtb w16, w0
.L1:
ldaxrb w0, [x2]
cmp w0, w16
b.ne .L2
stlxrb w17, w1, [x2]
cbnz w17, .L1
.L2:
cmp w0, w20, uxtb
cset w1, eq
beq .L3
strb w0, [x19]
.L3:
mov w0, w1
ldp x19, x20, [sp, 16]
ldp x29, x30, [sp], 32
ret
#endif
.size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
.global _(__atomic_compare_exchange_2)
.type _(__atomic_compare_exchange_2), %function
_(__atomic_compare_exchange_2):
#ifdef __TINYC__
.int 0xa9be7bfd
.int 0x910003fd
.int 0xa90153f3
.int 0xaa0103f3
.int 0x12003c41
.int 0xaa0003e2
.int 0x79400274
.int 0x2a1403e0
.int 0x53003c10
.int 0x485ffc40
.int 0x6b10001f
.int 0x54000061
.int 0x4811fc41
.int 0x35ffff91
.int 0x6b34201f
.int 0x1a9f17e1
.int 0x54000040
.int 0x79000260
.int 0x2a0103e0
.int 0xa94153f3
.int 0xa8c27bfd
.int 0xd65f03c0
#else
stp x29, x30, [sp, -32]!
mov x29, sp
stp x19, x20, [sp, 16]
mov x19, x1
and w1, w2, 65535
mov x2, x0
ldrh w20, [x19]
mov w0, w20
uxth w16, w0
.L4:
ldaxrh w0, [x2]
cmp w0, w16
b.ne .L5
stlxrh w17, w1, [x2]
cbnz w17, .L4
.L5:
cmp w0, w20, uxth
cset w1, eq
beq .L6
strh w0, [x19]
.L6:
mov w0, w1
ldp x19, x20, [sp, 16]
ldp x29, x30, [sp], 32
ret
#endif
.size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
.global _(__atomic_compare_exchange_4)
.type _(__atomic_compare_exchange_4), %function
_(__atomic_compare_exchange_4):
#ifdef __TINYC__
.int 0xa9be7bfd
.int 0x910003fd
.int 0xa90153f3
.int 0xaa0103f3
.int 0x2a0203e1
.int 0xaa0003e2
.int 0xb9400274
.int 0x2a1403e0
.int 0x2a0003f0
.int 0x885ffc40
.int 0x6b10001f
.int 0x54000061
.int 0x8811fc41
.int 0x35ffff91
.int 0x6b14001f
.int 0x1a9f17e1
.int 0x54000040
.int 0xb9000260
.int 0x2a0103e0
.int 0xa94153f3
.int 0xa8c27bfd
.int 0xd65f03c0
#else
stp x29, x30, [sp, -32]!
mov x29, sp
stp x19, x20, [sp, 16]
mov x19, x1
mov w1, w2
mov x2, x0
ldr w20, [x19]
mov w0, w20
mov w16, w0
.L7:
ldaxr w0, [x2]
cmp w0, w16
b.ne .L8
stlxr w17, w1, [x2]
cbnz w17, .L7
.L8:
cmp w0, w20
cset w1, eq
beq .L9
str w0, [x19]
.L9:
mov w0, w1
ldp x19, x20, [sp, 16]
ldp x29, x30, [sp], 32
ret
#endif
.size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
.global _(__atomic_compare_exchange_8)
.type _(__atomic_compare_exchange_8), %function
_(__atomic_compare_exchange_8):
#ifdef __TINYC__
.int 0xa9be7bfd
.int 0x910003fd
.int 0xa90153f3
.int 0xaa0103f3
.int 0xaa0203e1
.int 0xaa0003e2
.int 0xf9400274
.int 0xaa1403e0
.int 0xaa0003f0
.int 0xc85ffc40
.int 0xeb10001f
.int 0x54000061
.int 0xc811fc41
.int 0x35ffff91
.int 0xeb14001f
.int 0x1a9f17e1
.int 0x54000040
.int 0xf9000260
.int 0x2a0103e0
.int 0xa94153f3
.int 0xa8c27bfd
.int 0xd65f03c0
#else
stp x29, x30, [sp, -32]!
mov x29, sp
stp x19, x20, [sp, 16]
mov x19, x1
mov x1, x2
mov x2, x0
ldr x20, [x19]
mov x0, x20
mov x16, x0
.L10:
ldaxr x0, [x2]
cmp x0, x16
b.ne .L11
stlxr w17, x1, [x2]
cbnz w17, .L10
.L11:
cmp x0, x20
cset w1, eq
beq .L12
str x0, [x19]
.L12:
mov w0, w1
ldp x19, x20, [sp, 16]
ldp x29, x30, [sp], 32
ret
#endif
.size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8)
/* ---------------------------------------------- */
#elif defined __riscv
.text
.align 2
.global _(fetch_and_add_riscv64)
.type _(fetch_and_add_riscv64), %function
_(fetch_and_add_riscv64):
#ifdef __TINYC__
.int 0x0f50000f
.int 0x004b5202f
.short 0x8082
#else
fence iorw,ow
amoadd.w.aq zero,a1,0(a0)
ret
#endif
.size _(fetch_and_add_riscv64), .-_(fetch_and_add_riscv64)
.global _(__atomic_test_and_set)
.type _(__atomic_test_and_set), %function
_(__atomic_test_and_set):
#ifdef __TINYC__
.int 0x00357793
.int 0x0037979b
.short 0x4685
.short 0x9971
.int 0x00f696bb
.int 0x0f50000f
.int 0x44d5272f
.int 0x00f7553b
.int 0x0ff57513
.short 0x8082
#else
andi a5,a0,3
slliw a5,a5,3
li a3,1
andi a0,a0,-4
sllw a3,a3,a5
fence iorw,ow; amoor.w.aq a4,a3,0(a0)
srlw a0,a4,a5
andi a0,a0,0xff
ret
#endif
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
.global _(__atomic_clear)
.type _(__atomic_clear), %function
_(__atomic_clear):
#ifdef __TINYC__
.int 0x0ff0000f
.int 0x00050023
.int 0x0ff0000f
.short 0x8082
#else
fence iorw,iorw
sb zero,0(a0)
fence iorw,iorw
ret
#endif
.size _(__atomic_clear), .-_(__atomic_clear)
.global _(__atomic_compare_exchange_1)
.type _(__atomic_compare_exchange_1), %function
_(__atomic_compare_exchange_1):
#ifdef __TINYC__
.short 0x1141
.short 0x86ba
.short 0x873e
.short 0xe406
.int 0x0ff0000f
.int 0x0005c803
.int 0xff857893
.int 0x0008b783
.short 0x891d
.short 0x050e
.int 0x0ff00693
.int 0x00a696b3
.int 0x00a81833
.int 0x00a61633
.int 0xfff6c713
.short 0x8f7d
.int 0x00f6f333
.short 0x8f51
.int 0x03031263
.int 0x1008b32f
.int 0x00f31663
.int 0x18e8be2f
.int 0xfe0e1ae3
.int 0x40f30733
.short 0x879a
.short 0xff69
.int 0x0ff0000f
.short 0x4505
.short 0xa801
.int 0x00a7d7b3
.int 0x00f58023
.int 0x0ff0000f
.short 0x4501
.short 0x60a2
.short 0x0141
.short 0x8082
#else
addi sp,sp,-16
mv a3,a4
mv a4,a5
sd ra,8(sp)
fence
lbu a6,0(a1)
andi a7,a0,-8
ld a5,0(a7)
andi a0,a0,7
slli a0,a0,0x3
li a3,255
sll a3,a3,a0
sll a6,a6,a0
sll a2,a2,a0
.L1:
not a4,a3
and a4,a4,a5
and t1,a3,a5
or a4,a4,a2
bne t1,a6,.L4
.L2:
lr.d t1,(a7)
bne t1,a5,.L3
sc.d t3,a4,(a7)
bnez t3,.L2
.L3:
sub a4,t1,a5
mv a5,t1
bnez a4,.L1
fence
li a0,1
j .L5
.L4:
srl a5,a5,a0
sb a5,0(a1)
fence
li a0,0
.L5:
ld ra,8(sp)
addi sp,sp,16
jr ra
#endif
.size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
.global _(__atomic_compare_exchange_2)
.type _(__atomic_compare_exchange_2), %function
_(__atomic_compare_exchange_2):
#ifdef __TINYC__
.short 0x1141
.short 0x86ba
.short 0x873e
.short 0xe406
.int 0x0ff0000f
.int 0x0005d803
.int 0xff857893
.short 0x67c1
.short 0x891d
.int 0x0008b703
.short 0x050e
.short 0x17fd
.int 0x00a797b3
.int 0x00a81833
.int 0x00a61633
.int 0xfff7c693
.short 0x8ef9
.int 0x00e7f333
.short 0x8ed1
.int 0x03031263
.int 0x1008b32f
.int 0x00e31663
.int 0x18d8be2f
.int 0xfe0e1ae3
.int 0x40e306b3
.short 0x871a
.short 0xfee9
.int 0x0ff0000f
.short 0x4505
.short 0xa801
.int 0x00a75733
.int 0x00e59023
.int 0x0ff0000f
.short 0x4501
.short 0x60a2
.short 0x0141
.short 0x8082
#else
addi sp,sp,-16
mv a3,a4
mv a4,a5
sd ra,8(sp)
fence
lhu a6,0(a1)
andi a7,a0,-8
lui a5,0x10
andi a0,a0,7
ld a4,0(a7)
slli a0,a0,0x3
addi a5,a5,-1
sll a5,a5,a0
sll a6,a6,a0
sll a2,a2,a0
.L6:
not a3,a5
and a3,a3,a4
and t1,a5,a4
or a3,a3,a2
bne t1,a6,.L9
.L7:
lr.d t1,(a7)
bne t1,a4,.L8
sc.d t3,a3,(a7)
bnez t3,.L7
.L8:
sub a3,t1,a4
mv a4,t1
bnez a3,.L6
fence
li a0,1
j .L10
.L9:
srl a4,a4,a0
sh a4,0(a1)
fence
li a0,0
.L10:
ld ra,8(sp)
addi sp,sp,16
jr ra
#endif
.size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
.global _(__atomic_compare_exchange_4)
.type _(__atomic_compare_exchange_4), %function
_(__atomic_compare_exchange_4):
#ifdef __TINYC__
.short 0x419c
.int 0x0f50000f
.int 0x1405272f
.int 0x00f71663
.int 0x1cc5282f
.int 0xfe081ae3
.int 0x40f707bb
.int 0x0017b513
.short 0xc391
.short 0xc198
.short 0x8905
.short 0x8082
#else
lw a5,0(a1)
fence iorw,ow;
.L11:
lr.w.aq a4,0(a0)
bne a4,a5,.L12
sc.w.aq a6,a2,0(a0)
bnez a6,.L11
.L12:
subw a5,a4,a5
seqz a0,a5
beq a5,zero,.L13
sw a4,0(a1)
.L13:
andi a0,a0,1
ret
#endif
.size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
.global _(__atomic_compare_exchange_8)
.type _(__atomic_compare_exchange_8), %function
_(__atomic_compare_exchange_8):
#ifdef __TINYC__
.short 0x619c
.int 0x0f50000f
.int 0x1405372f
.int 0x00f71563
.int 0x1cc536af
.short 0xfaf5
.int 0x40f707b3
.int 0x0017b513
.short 0xc391
.short 0xe198
.short 0x8905
.short 0x8082
#else
ld a5,0(a1)
fence iorw,ow;
.L14:
lr.d.aq a4,0(a0)
bne a4,a5,.L15
sc.d.aq a3,a2,0(a0)
bnez a3,.L14
.L15:
sub a5,a4,a5
seqz a0,a5
beq a5,zero,.L16
sd a4,0(a1)
.L16:
andi a0,a0,1
ret
#endif
.size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8)
/* ---------------------------------------------- */
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,74 +0,0 @@
/* ------------------------------------------------------------- */
/* stubs for calling bcheck functions from a dll. */
#include <windows.h>
#include <stdio.h>
#define REDIR_ALL \
REDIR(__bt_init) \
REDIR(__bt_exit) \
REDIR(tcc_backtrace) \
\
REDIR(__bound_ptr_add) \
REDIR(__bound_ptr_indir1) \
REDIR(__bound_ptr_indir2) \
REDIR(__bound_ptr_indir4) \
REDIR(__bound_ptr_indir8) \
REDIR(__bound_ptr_indir12) \
REDIR(__bound_ptr_indir16) \
REDIR(__bound_local_new) \
REDIR(__bound_local_delete) \
REDIR(__bound_new_region) \
\
REDIR(__bound_free) \
REDIR(__bound_malloc) \
REDIR(__bound_realloc) \
REDIR(__bound_memcpy) \
REDIR(__bound_memcmp) \
REDIR(__bound_memmove) \
REDIR(__bound_memset) \
REDIR(__bound_strlen) \
REDIR(__bound_strcpy) \
REDIR(__bound_strncpy) \
REDIR(__bound_strcmp) \
REDIR(__bound_strncmp) \
REDIR(__bound_strcat) \
REDIR(__bound_strchr) \
REDIR(__bound_strdup)
#ifdef __leading_underscore
#define _(s) "_"#s
#else
#define _(s) #s
#endif
#define REDIR(s) void *s;
static struct { REDIR_ALL } all_ptrs;
#undef REDIR
#define REDIR(s) #s"\0"
static const char all_names[] = REDIR_ALL;
#undef REDIR
#define REDIR(s) __asm__(".global " _(s) ";" _(s) ": jmp *%0" : : "m" (all_ptrs.s) );
static void all_jmps() { REDIR_ALL }
#undef REDIR
void __bt_init_dll(int bcheck)
{
const char *s = all_names;
void **p = (void**)&all_ptrs;
do {
*p = (void*)GetProcAddress(GetModuleHandle(NULL), (char*)s);
if (NULL == *p) {
char buf[100];
sprintf(buf,
"Error: function '%s()' not found in executable. "
"(Need -bt or -b for linking the exe.)", s);
if (GetStdHandle(STD_ERROR_HANDLE))
fprintf(stderr, "TCC/BCHECK: %s\n", buf), fflush(stderr);
else
MessageBox(NULL, buf, "TCC/BCHECK", MB_ICONERROR);
ExitProcess(1);
}
s = strchr(s,'\0') + 1, ++p;
} while (*s && (bcheck || p < &all_ptrs.__bound_ptr_add));
}

View file

@ -1,68 +0,0 @@
/* ------------------------------------------------------------- */
/* for linking rt_printline and the signal/exception handler
from tccrun.c into executables. */
#define CONFIG_TCC_BACKTRACE_ONLY
#define ONE_SOURCE 1
#define pstrcpy tcc_pstrcpy
#include "../tccrun.c"
#ifndef _WIN32
# define __declspec(n)
#endif
__declspec(dllexport)
void __bt_init(rt_context *p, int is_exe)
{
__attribute__((weak)) int main();
__attribute__((weak)) void __bound_init(void*, int);
//fprintf(stderr, "__bt_init %d %p %p %p\n", is_exe, p, p->stab_sym, p->bounds_start), fflush(stderr);
/* call __bound_init here due to redirection of sigaction */
/* needed to add global symbols */
if (p->bounds_start)
__bound_init(p->bounds_start, -1);
/* add to chain */
rt_wait_sem();
p->next = g_rc, g_rc = p;
rt_post_sem();
if (is_exe) {
/* we are the executable (not a dll) */
p->top_func = main;
set_exception_handler();
}
}
__declspec(dllexport)
void __bt_exit(rt_context *p)
{
struct rt_context *rc, **pp;
__attribute__((weak)) void __bound_exit_dll(void*);
//fprintf(stderr, "__bt_exit %d %p\n", !!p->top_func, p);
if (p->bounds_start)
__bound_exit_dll(p->bounds_start);
/* remove from chain */
rt_wait_sem();
for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
if (rc == p) {
*pp = rc->next;
break;
}
rt_post_sem();
}
/* copy a string and truncate it. */
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
{
int l = strlen(s);
if (l >= buf_size)
l = buf_size - 1;
memcpy(buf, s, l);
buf[l] = 0;
return buf;
}

View file

@ -1,56 +0,0 @@
/* ------------------------------------------------------------- */
/* function to get a stack backtrace on demand with a message */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#undef __attribute__
#ifdef _WIN32
# define DLL_EXPORT __declspec(dllexport)
#else
# define DLL_EXPORT
#endif
/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */
#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wframe-address"
#endif
typedef struct rt_frame {
void *ip, *fp, *sp;
} rt_frame;
__attribute__((weak))
int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
{
va_list ap;
int ret;
if (_tcc_backtrace) {
rt_frame f;
f.fp = __builtin_frame_address(1);
f.ip = __builtin_return_address(0);
va_start(ap, fmt);
ret = _tcc_backtrace(&f, fmt, ap);
va_end(ap);
} else {
const char *p, *nl = "\n";
if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0])))
fmt = p + 1;
if (fmt[0] == '\001')
++fmt, nl = "";
va_start(ap, fmt);
ret = vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "%s", nl), fflush(stderr);
}
return ret;
}
#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
#pragma GCC diagnostic pop
#endif

View file

@ -1 +0,0 @@
void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle;

View file

@ -57,102 +57,34 @@
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __ORDER_BIG_ENDIAN__ 4321
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#if defined _WIN32
#define __WCHAR_TYPE__ unsigned short
#define __WINT_TYPE__ unsigned short
#elif defined __linux__
#define __WCHAR_TYPE__ int
#define __WINT_TYPE__ unsigned int
#else
#define __WCHAR_TYPE__ int
#define __WINT_TYPE__ int
#endif
#if __STDC_VERSION__ >= 201112L
#if __STDC_VERSION__ >= 201112L
# define __STDC_NO_ATOMICS__ 1
# define __STDC_NO_COMPLEX__ 1
# define __STDC_NO_THREADS__ 1
#if !defined _WIN32
# define __STDC_UTF_16__ 1
# define __STDC_UTF_32__ 1
#endif
#endif
#if defined _WIN32
#define __declspec(x) __attribute__((x))
#define __cdecl
#elif defined __FreeBSD__
#define __GNUC__ 9
#define __GNUC_MINOR__ 3
#define __GNUC_PATCHLEVEL__ 0
#define __GNUC_STDC_INLINE__ 1
#define __NO_TLS 1
#define __RUNETYPE_INTERNAL 1
# if __SIZEOF_POINTER__ == 8
/* FIXME, __int128_t is used by setjump */
#define __int128_t struct { unsigned char _dummy[16] __attribute((aligned(16))); }
#define __SIZEOF_SIZE_T__ 8
#define __SIZEOF_PTRDIFF_T__ 8
#else
#define __SIZEOF_SIZE_T__ 4
#define __SIZEOF_PTRDIFF_T__ 4
# endif
#elif defined __FreeBSD_kernel__
#elif defined __NetBSD__
#define __GNUC__ 4
#define __GNUC_MINOR__ 1
#define __GNUC_PATCHLEVEL__ 0
#define _Pragma(x)
#define __ELF__ 1
#if defined __aarch64__
#define _LOCORE /* avoids usage of __asm */
#endif
#elif defined __OpenBSD__
#define __GNUC__ 4
#define _ANSI_LIBRARY 1
#elif defined __APPLE__
/* emulate APPLE-GCC to make libc's headerfiles compile: */
#define __GNUC__ 4 /* darwin emits warning on GCC<4 */
#define __APPLE_CC__ 1 /* for <TargetConditionals.h> */
#define __LITTLE_ENDIAN__ 1
#define _DONT_USE_CTYPE_INLINE_ 1
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
#define __FINITE_MATH_ONLY__ 1
#define _FORTIFY_SOURCE 0
//#define __has_builtin(x) 0
#elif defined __ANDROID__
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
#else
/* Linux */
#endif
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
#ifndef __NetBSD__
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
#define __INTPTR_TYPE__ __PTRDIFF_TYPE__
#endif
#define __INT32_TYPE__ int
#if !defined _WIN32
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
#define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
#endif
/* not implemented */
#define __PRETTY_FUNCTION__ __FUNCTION__
#define __has_builtin(x) 0
#define __has_feature(x) 0
#define __has_attribute(x) 0
/* C23 Keywords */
#define _Nonnull
#define _Nullable
@ -181,67 +113,10 @@
#endif
/* __builtin_va_list */
#if defined __x86_64__
#if !defined _WIN32
/* GCC compatible definition of va_list. */
/* This should be in sync with the declaration in our lib/libtcc1.c */
typedef struct {
unsigned gp_offset, fp_offset;
union {
unsigned overflow_offset;
char *overflow_arg_area;
};
char *reg_save_area;
} __builtin_va_list[1];
void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
#define __builtin_va_start(ap, last) \
(*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
#define __builtin_va_arg(ap, t) \
(*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
#define __builtin_va_copy(dest, src) (*(dest) = *(src))
#else /* _WIN64 */
typedef char *__builtin_va_list;
#define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
#endif
#elif defined __arm__
typedef char *__builtin_va_list;
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
& ~(_tcc_alignof(type) - 1))
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
#define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
#elif defined __aarch64__
#if defined __APPLE__
typedef struct {
void *__stack;
} __builtin_va_list;
#else
typedef struct {
void *__stack, *__gr_top, *__vr_top;
int __gr_offs, __vr_offs;
} __builtin_va_list;
#endif
#elif defined __riscv
typedef char *__builtin_va_list;
#define __va_reg_size (__riscv_xlen >> 3)
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
& -(__alignof__(type)))
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
#else /* __i386__ */
typedef char *__builtin_va_list;
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
#endif
#define __builtin_va_end(ap) (void)(ap)
#ifndef __builtin_va_copy
# define __builtin_va_copy(dest, src) (dest) = (src)
@ -283,13 +158,6 @@
__BOTH(char*, strchr, (const char*, int))
__BOTH(char*, strrchr, (const char*, int))
__BOTH(char*, strdup, (const char*))
#if defined __ARM_EABI__
__BOUND(void*,__aeabi_memcpy,(void*,const void*,__SIZE_TYPE__))
__BOUND(void*,__aeabi_memmove,(void*,const void*,__SIZE_TYPE__))
__BOUND(void*,__aeabi_memmove4,(void*,const void*,__SIZE_TYPE__))
__BOUND(void*,__aeabi_memmove8,(void*,const void*,__SIZE_TYPE__))
__BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__))
#endif
#if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR
#define __MAYBE_REDIR __BUILTIN

View file

@ -1,677 +0,0 @@
/*
* TCC runtime library for arm64.
*
* Copyright (c) 2015 Edmund Grimley Evans
*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved. This file is offered as-is,
* without any warranty.
*/
#ifdef __TINYC__
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
void *memcpy(void*,void*,__SIZE_TYPE__);
#else
#include <stdint.h>
#include <string.h>
#endif
#if !defined __riscv && !defined __APPLE__
void __clear_cache(void *beg, void *end)
{
__arm64_clear_cache(beg, end);
}
#endif
typedef struct {
uint64_t x0, x1;
} u128_t;
static long double f3_zero(int sgn)
{
long double f;
u128_t x = { 0, (uint64_t)sgn << 63 };
memcpy(&f, &x, 16);
return f;
}
static long double f3_infinity(int sgn)
{
long double f;
u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
memcpy(&f, &x, 16);
return f;
}
static long double f3_NaN(void)
{
long double f;
#if 0
// ARM's default NaN usually has just the top fraction bit set:
u128_t x = { 0, 0x7fff800000000000 };
#else
// GCC's library sets all fraction bits:
u128_t x = { -1, 0x7fffffffffffffff };
#endif
memcpy(&f, &x, 16);
return f;
}
static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt)
{
u128_t x = { mnt.x0,
mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
memcpy(f, &x, 16);
return 1;
}
static int fp3_detect_NaNs(long double *f,
int a_sgn, int a_exp, u128_t a,
int b_sgn, int b_exp, u128_t b)
{
// Detect signalling NaNs:
if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
return fp3_convert_NaN(f, a_sgn, a);
if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
return fp3_convert_NaN(f, b_sgn, b);
// Detect quiet NaNs:
if (a_exp == 32767 && (a.x0 | a.x1 << 16))
return fp3_convert_NaN(f, a_sgn, a);
if (b_exp == 32767 && (b.x0 | b.x1 << 16))
return fp3_convert_NaN(f, b_sgn, b);
return 0;
}
static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
{
u128_t x;
memcpy(&x, &f, 16);
*sgn = x.x1 >> 63;
*exp = x.x1 >> 48 & 32767;
x.x1 = x.x1 << 16 >> 16;
if (*exp)
x.x1 |= (uint64_t)1 << 48;
else
*exp = 1;
*mnt = x;
}
static u128_t f3_normalise(int32_t *exp, u128_t mnt)
{
int sh;
if (!(mnt.x0 | mnt.x1))
return mnt;
if (!mnt.x1) {
mnt.x1 = mnt.x0;
mnt.x0 = 0;
*exp -= 64;
}
for (sh = 32; sh; sh >>= 1) {
if (!(mnt.x1 >> (64 - sh))) {
mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh);
mnt.x0 = mnt.x0 << sh;
*exp -= sh;
}
}
return mnt;
}
static u128_t f3_sticky_shift(int32_t sh, u128_t x)
{
if (sh >= 128) {
x.x0 = !!(x.x0 | x.x1);
x.x1 = 0;
return x;
}
if (sh >= 64) {
x.x0 = x.x1 | !!x.x0;
x.x1 = 0;
sh -= 64;
}
if (sh > 0) {
x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh));
x.x1 = x.x1 >> sh;
}
return x;
}
static long double f3_round(int sgn, int32_t exp, u128_t x)
{
long double f;
int error;
if (exp > 0) {
x = f3_sticky_shift(13, x);
}
else {
x = f3_sticky_shift(14 - exp, x);
exp = 0;
}
error = x.x0 & 3;
x.x0 = x.x0 >> 2 | x.x1 << 62;
x.x1 = x.x1 >> 2;
if (error == 3 || ((error == 2) & (x.x0 & 1))) {
if (!++x.x0) {
++x.x1;
if (x.x1 == (uint64_t)1 << 48)
exp = 1;
else if (x.x1 == (uint64_t)1 << 49) {
++exp;
x.x0 = x.x0 >> 1 | x.x1 << 63;
x.x1 = x.x1 >> 1;
}
}
}
if (exp >= 32767)
return f3_infinity(sgn);
x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
memcpy(&f, &x, 16);
return f;
}
static long double f3_add(long double fa, long double fb, int neg)
{
u128_t a, b, x;
int32_t a_exp, b_exp, x_exp;
int a_sgn, b_sgn, x_sgn;
long double fx;
f3_unpack(&a_sgn, &a_exp, &a, fa);
f3_unpack(&b_sgn, &b_exp, &b, fb);
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
return fx;
b_sgn ^= neg;
// Handle infinities and zeroes:
if (a_exp == 32767 && b_exp == 32767 && a_sgn != b_sgn)
return f3_NaN();
if (a_exp == 32767)
return f3_infinity(a_sgn);
if (b_exp == 32767)
return f3_infinity(b_sgn);
if (!(a.x0 | a.x1 | b.x0 | b.x1))
return f3_zero(a_sgn & b_sgn);
a.x1 = a.x1 << 3 | a.x0 >> 61;
a.x0 = a.x0 << 3;
b.x1 = b.x1 << 3 | b.x0 >> 61;
b.x0 = b.x0 << 3;
if (a_exp <= b_exp) {
a = f3_sticky_shift(b_exp - a_exp, a);
a_exp = b_exp;
}
else {
b = f3_sticky_shift(a_exp - b_exp, b);
b_exp = a_exp;
}
x_sgn = a_sgn;
x_exp = a_exp;
if (a_sgn == b_sgn) {
x.x0 = a.x0 + b.x0;
x.x1 = a.x1 + b.x1 + (x.x0 < a.x0);
}
else {
x.x0 = a.x0 - b.x0;
x.x1 = a.x1 - b.x1 - (x.x0 > a.x0);
if (x.x1 >> 63) {
x_sgn ^= 1;
x.x0 = -x.x0;
x.x1 = -x.x1 - !!x.x0;
}
}
if (!(x.x0 | x.x1))
return f3_zero(0);
x = f3_normalise(&x_exp, x);
return f3_round(x_sgn, x_exp + 12, x);
}
long double __addtf3(long double a, long double b)
{
return f3_add(a, b, 0);
}
long double __subtf3(long double a, long double b)
{
return f3_add(a, b, 1);
}
long double __multf3(long double fa, long double fb)
{
u128_t a, b, x;
int32_t a_exp, b_exp, x_exp;
int a_sgn, b_sgn, x_sgn;
long double fx;
f3_unpack(&a_sgn, &a_exp, &a, fa);
f3_unpack(&b_sgn, &b_exp, &b, fb);
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
return fx;
// Handle infinities and zeroes:
if ((a_exp == 32767 && !(b.x0 | b.x1)) ||
(b_exp == 32767 && !(a.x0 | a.x1)))
return f3_NaN();
if (a_exp == 32767 || b_exp == 32767)
return f3_infinity(a_sgn ^ b_sgn);
if (!(a.x0 | a.x1) || !(b.x0 | b.x1))
return f3_zero(a_sgn ^ b_sgn);
a = f3_normalise(&a_exp, a);
b = f3_normalise(&b_exp, b);
x_sgn = a_sgn ^ b_sgn;
x_exp = a_exp + b_exp - 16352;
{
// Convert to base (1 << 30), discarding bottom 6 bits, which are zero,
// so there are (32, 30, 30, 30) bits in (a3, a2, a1, a0):
uint64_t a0 = a.x0 << 28 >> 34;
uint64_t b0 = b.x0 << 28 >> 34;
uint64_t a1 = a.x0 >> 36 | a.x1 << 62 >> 34;
uint64_t b1 = b.x0 >> 36 | b.x1 << 62 >> 34;
uint64_t a2 = a.x1 << 32 >> 34;
uint64_t b2 = b.x1 << 32 >> 34;
uint64_t a3 = a.x1 >> 32;
uint64_t b3 = b.x1 >> 32;
// Use 16 small multiplications and additions that do not overflow:
uint64_t x0 = a0 * b0;
uint64_t x1 = (x0 >> 30) + a0 * b1 + a1 * b0;
uint64_t x2 = (x1 >> 30) + a0 * b2 + a1 * b1 + a2 * b0;
uint64_t x3 = (x2 >> 30) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
uint64_t x4 = (x3 >> 30) + a1 * b3 + a2 * b2 + a3 * b1;
uint64_t x5 = (x4 >> 30) + a2 * b3 + a3 * b2;
uint64_t x6 = (x5 >> 30) + a3 * b3;
// We now have (64, 30, 30, ...) bits in (x6, x5, x4, ...).
// Take the top 128 bits, setting bottom bit if any lower bits were set:
uint64_t y0 = (x5 << 34 | x4 << 34 >> 30 | x3 << 34 >> 60 |
!!(x3 << 38 | (x2 | x1 | x0) << 34));
uint64_t y1 = x6;
// Top bit may be zero. Renormalise:
if (!(y1 >> 63)) {
y1 = y1 << 1 | y0 >> 63;
y0 = y0 << 1;
--x_exp;
}
x.x0 = y0;
x.x1 = y1;
}
return f3_round(x_sgn, x_exp, x);
}
long double __divtf3(long double fa, long double fb)
{
u128_t a, b, x;
int32_t a_exp, b_exp, x_exp;
int a_sgn, b_sgn, x_sgn, i;
long double fx;
f3_unpack(&a_sgn, &a_exp, &a, fa);
f3_unpack(&b_sgn, &b_exp, &b, fb);
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
return fx;
// Handle infinities and zeroes:
if ((a_exp == 32767 && b_exp == 32767) ||
(!(a.x0 | a.x1) && !(b.x0 | b.x1)))
return f3_NaN();
if (a_exp == 32767 || !(b.x0 | b.x1))
return f3_infinity(a_sgn ^ b_sgn);
if (!(a.x0 | a.x1) || b_exp == 32767)
return f3_zero(a_sgn ^ b_sgn);
a = f3_normalise(&a_exp, a);
b = f3_normalise(&b_exp, b);
x_sgn = a_sgn ^ b_sgn;
x_exp = a_exp - b_exp + 16395;
a.x0 = a.x0 >> 1 | a.x1 << 63;
a.x1 = a.x1 >> 1;
b.x0 = b.x0 >> 1 | b.x1 << 63;
b.x1 = b.x1 >> 1;
x.x0 = 0;
x.x1 = 0;
for (i = 0; i < 116; i++) {
x.x1 = x.x1 << 1 | x.x0 >> 63;
x.x0 = x.x0 << 1;
if (a.x1 > b.x1 || (a.x1 == b.x1 && a.x0 >= b.x0)) {
a.x1 = a.x1 - b.x1 - (a.x0 < b.x0);
a.x0 = a.x0 - b.x0;
x.x0 |= 1;
}
a.x1 = a.x1 << 1 | a.x0 >> 63;
a.x0 = a.x0 << 1;
}
x.x0 |= !!(a.x0 | a.x1);
x = f3_normalise(&x_exp, x);
return f3_round(x_sgn, x_exp, x);
}
long double __extendsftf2(float f)
{
long double fx;
u128_t x;
uint32_t a;
uint64_t aa;
memcpy(&a, &f, 4);
aa = a;
x.x0 = 0;
if (!(a << 1))
x.x1 = aa << 32;
else if (a << 1 >> 24 == 255)
x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 |
(uint64_t)!!(a << 9) << 47);
else if (a << 1 >> 24 == 0) {
uint64_t adj = 0;
while (!(a << 1 >> 1 >> (23 - adj)))
adj++;
x.x1 = aa >> 31 << 63 | (16256 - adj + 1) << 48 | aa << adj << 41 >> 16;
} else
x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
aa << 41 >> 16);
memcpy(&fx, &x, 16);
return fx;
}
long double __extenddftf2(double f)
{
long double fx;
u128_t x;
uint64_t a;
memcpy(&a, &f, 8);
x.x0 = a << 60;
if (!(a << 1))
x.x1 = a;
else if (a << 1 >> 53 == 2047)
x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 |
(uint64_t)!!(a << 12) << 47);
else if (a << 1 >> 53 == 0) {
uint64_t adj = 0;
while (!(a << 1 >> 1 >> (52 - adj)))
adj++;
x.x0 <<= adj;
x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16;
} else
x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
memcpy(&fx, &x, 16);
return fx;
}
float __trunctfsf2(long double f)
{
u128_t mnt;
int32_t exp;
int sgn;
uint32_t x;
float fx;
f3_unpack(&sgn, &exp, &mnt, f);
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
else if (exp > 16510)
x = 0x7f800000 | (uint32_t)sgn << 31;
else if (exp < 16233)
x = (uint32_t)sgn << 31;
else {
exp -= 16257;
x = mnt.x1 >> 23 | !!(mnt.x0 | mnt.x1 << 41);
if (exp < 0) {
x = x >> -exp | !!(x << (32 + exp));
exp = 0;
}
if ((x & 3) == 3 || (x & 7) == 6)
x += 4;
x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
}
memcpy(&fx, &x, 4);
return fx;
}
double __trunctfdf2(long double f)
{
u128_t mnt;
int32_t exp;
int sgn;
uint64_t x;
double fx;
f3_unpack(&sgn, &exp, &mnt, f);
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
else if (exp > 17406)
x = 0x7ff0000000000000 | (uint64_t)sgn << 63;
else if (exp < 15308)
x = (uint64_t)sgn << 63;
else {
exp -= 15361;
x = mnt.x1 << 6 | mnt.x0 >> 58 | !!(mnt.x0 << 6);
if (exp < 0) {
x = x >> -exp | !!(x << (64 + exp));
exp = 0;
}
if ((x & 3) == 3 || (x & 7) == 6)
x += 4;
x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
}
memcpy(&fx, &x, 8);
return fx;
}
int32_t __fixtfsi(long double fa)
{
u128_t a;
int32_t a_exp;
int a_sgn;
int32_t x;
f3_unpack(&a_sgn, &a_exp, &a, fa);
if (a_exp < 16369)
return 0;
if (a_exp > 16413)
return a_sgn ? -0x80000000 : 0x7fffffff;
x = a.x1 >> (16431 - a_exp);
return a_sgn ? -x : x;
}
int64_t __fixtfdi(long double fa)
{
u128_t a;
int32_t a_exp;
int a_sgn;
int64_t x;
f3_unpack(&a_sgn, &a_exp, &a, fa);
if (a_exp < 16383)
return 0;
if (a_exp > 16445)
return a_sgn ? -0x8000000000000000 : 0x7fffffffffffffff;
x = (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
return a_sgn ? -x : x;
}
uint32_t __fixunstfsi(long double fa)
{
u128_t a;
int32_t a_exp;
int a_sgn;
f3_unpack(&a_sgn, &a_exp, &a, fa);
if (a_sgn || a_exp < 16369)
return 0;
if (a_exp > 16414)
return -1;
return a.x1 >> (16431 - a_exp);
}
uint64_t __fixunstfdi(long double fa)
{
u128_t a;
int32_t a_exp;
int a_sgn;
f3_unpack(&a_sgn, &a_exp, &a, fa);
if (a_sgn || a_exp < 16383)
return 0;
if (a_exp > 16446)
return -1;
return (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
}
long double __floatsitf(int32_t a)
{
int sgn = 0;
int exp = 16414;
uint32_t mnt = a;
u128_t x = { 0, 0 };
long double f;
int i;
if (a) {
if (a < 0) {
sgn = 1;
mnt = -mnt;
}
for (i = 16; i; i >>= 1)
if (!(mnt >> (32 - i))) {
mnt <<= i;
exp -= i;
}
x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
(uint64_t)(mnt << 1) << 16);
}
memcpy(&f, &x, 16);
return f;
}
long double __floatditf(int64_t a)
{
int sgn = 0;
int exp = 16446;
uint64_t mnt = a;
u128_t x = { 0, 0 };
long double f;
int i;
if (a) {
if (a < 0) {
sgn = 1;
mnt = -mnt;
}
for (i = 32; i; i >>= 1)
if (!(mnt >> (64 - i))) {
mnt <<= i;
exp -= i;
}
x.x0 = mnt << 49;
x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
}
memcpy(&f, &x, 16);
return f;
}
long double __floatunsitf(uint32_t a)
{
int exp = 16414;
uint32_t mnt = a;
u128_t x = { 0, 0 };
long double f;
int i;
if (a) {
for (i = 16; i; i >>= 1)
if (!(mnt >> (32 - i))) {
mnt <<= i;
exp -= i;
}
x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
}
memcpy(&f, &x, 16);
return f;
}
long double __floatunditf(uint64_t a)
{
int exp = 16446;
uint64_t mnt = a;
u128_t x = { 0, 0 };
long double f;
int i;
if (a) {
for (i = 32; i; i >>= 1)
if (!(mnt >> (64 - i))) {
mnt <<= i;
exp -= i;
}
x.x0 = mnt << 49;
x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
}
memcpy(&f, &x, 16);
return f;
}
static int f3_cmp(long double fa, long double fb)
{
u128_t a, b;
memcpy(&a, &fa, 16);
memcpy(&b, &fb, 16);
return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
(b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
a.x1 >> 63 != b.x1 >> 63 ? (int)(b.x1 >> 63) - (int)(a.x1 >> 63) :
a.x1 < b.x1 ? (int)(a.x1 >> 63 << 1) - 1 :
a.x1 > b.x1 ? 1 - (int)(a.x1 >> 63 << 1) :
a.x0 < b.x0 ? (int)(a.x1 >> 63 << 1) - 1 :
b.x0 < a.x0 ? 1 - (int)(a.x1 >> 63 << 1) : 0);
}
int __eqtf2(long double a, long double b)
{
return !!f3_cmp(a, b);
}
int __netf2(long double a, long double b)
{
return !!f3_cmp(a, b);
}
int __lttf2(long double a, long double b)
{
return f3_cmp(a, b);
}
int __letf2(long double a, long double b)
{
return f3_cmp(a, b);
}
int __gttf2(long double a, long double b)
{
return -f3_cmp(b, a);
}
int __getf2(long double a, long double b)
{
return -f3_cmp(b, a);
}

View file

@ -106,11 +106,7 @@ union float_long {
unsigned int l;
};
/* XXX: we don't support several builtin supports for now */
#if !defined __x86_64__ && !defined __arm__ && !defined __riscv
/* XXX: use gcc/tcc intrinsic ? */
#if defined __i386__
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
: "=r" ((USItype) (sh)), \
@ -139,9 +135,6 @@ union float_long {
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
(count) = __cbtmp ^ 31; \
} while (0)
#else
#error unsupported CPU type
#endif
/* most of this code is taken from libgcc2.c from gcc */
@ -478,7 +471,6 @@ long long __ashldi3(long long a, int b)
#endif
}
#endif /* !__x86_64__ */
/* XXX: fix tcc's code generator to do this instead */
float __floatundisf(unsigned long long a)
@ -594,7 +586,6 @@ long long __fixdfdi (double a1)
return s ? ret : -ret;
}
#ifndef __arm__
unsigned long long __fixunsxfdi (long double a1)
{
register union ldouble_long dl1;
@ -624,18 +615,6 @@ long long __fixxfdi (long double a1)
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret;
}
#endif /* !ARM */
#if defined __x86_64__
/* float constants used for unary minus operation */
const float __mzerosf = -0.0;
const double __mzerodf = -0.0;
#endif
#if defined _WIN64
/* MSVC x64 intrinsic */
void __faststorefence(void)
{
__asm__("lock; orl $0,(%rsp)");
}
#endif

View file

@ -1,86 +0,0 @@
/* ------------------------------------------------------------- */
/* support for tcc_run() */
#ifdef __leading_underscore
# define _(s) s
#else
# define _(s) _##s
#endif
#ifndef _WIN32
extern void (*_(_init_array_start)[]) (int argc, char **argv, char **envp);
extern void (*_(_init_array_end)[]) (int argc, char **argv, char **envp);
static void run_ctors(int argc, char **argv, char **env)
{
int i = 0;
while (&_(_init_array_start)[i] != _(_init_array_end))
(*_(_init_array_start)[i++])(argc, argv, env);
}
#endif
extern void (*_(_fini_array_start)[]) (void);
extern void (*_(_fini_array_end)[]) (void);
static void run_dtors(void)
{
int i = 0;
while (&_(_fini_array_end)[i] != _(_fini_array_start))
(*_(_fini_array_end)[--i])();
}
static void *rt_exitfunc[32];
static void *rt_exitarg[32];
static int __rt_nr_exit;
void __run_on_exit(int ret)
{
int n = __rt_nr_exit;
while (n)
--n, ((void(*)(int,void*))rt_exitfunc[n])(ret, rt_exitarg[n]);
}
int on_exit(void *function, void *arg)
{
int n = __rt_nr_exit;
if (n < 32) {
rt_exitfunc[n] = function;
rt_exitarg[n] = arg;
__rt_nr_exit = n + 1;
return 0;
}
return 1;
}
int atexit(void (*function)(void))
{
return on_exit(function, 0);
}
typedef struct rt_frame {
void *ip, *fp, *sp;
} rt_frame;
__attribute__((noreturn)) void __rt_exit(rt_frame *, int);
void exit(int code)
{
rt_frame f;
run_dtors();
__run_on_exit(code);
f.fp = 0;
f.ip = exit;
__rt_exit(&f, code);
}
#ifndef _WIN32
int main(int, char**, char**);
int _runmain(int argc, char **argv, char **envp)
{
int ret;
run_ctors(argc, argv, envp);
ret = main(argc, argv, envp);
run_dtors();
__run_on_exit(ret);
return ret;
}
#endif

View file

@ -18,7 +18,6 @@ typedef __SIZE_TYPE__ size_t;
void __atomic_thread_fence(int memorder);
#define MemoryBarrier(memorder) __atomic_thread_fence(memorder)
#if defined __i386__ || defined __x86_64__
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
bool __atomic_compare_exchange_##MODE \
(volatile void *atom, void *ref, TYPE xchg, \
@ -35,12 +34,7 @@ void __atomic_thread_fence(int memorder);
*(TYPE *)ref = rv; \
return (rv == cmp); \
}
#else
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
extern bool __atomic_compare_exchange_##MODE \
(volatile void *atom, void *ref, TYPE xchg, \
bool weak, int success_memorder, int failure_memorder);
#endif
#define ATOMIC_LOAD(TYPE, MODE) \
TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
@ -116,9 +110,6 @@ void __atomic_thread_fence(int memorder);
ATOMIC_GEN(uint8_t, 1, "b")
ATOMIC_GEN(uint16_t, 2, "w")
ATOMIC_GEN(uint32_t, 4, "l")
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
ATOMIC_GEN(uint64_t, 8, "q")
#endif
/* uses alias to allow building with gcc/clang */
#ifdef __TINYC__
@ -133,17 +124,7 @@ void ATOMIC(signal_fence) (int memorder)
void ATOMIC(thread_fence) (int memorder)
{
#if defined __i386__
__asm__ volatile("lock orl $0, (%esp)");
#elif defined __x86_64__
__asm__ volatile("lock orq $0, (%rsp)");
#elif defined __arm__
__asm__ volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5
#elif defined __aarch64__
__asm__ volatile(".int 0xd5033bbf"); // dmb ish
#elif defined __riscv
__asm__ volatile(".int 0x0ff0000f"); // fence iorw,iorw
#endif
}
bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
@ -154,11 +135,7 @@ bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
case 1: ret = true; break;
case 2: ret = true; break;
case 4: ret = true; break;
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
case 8: ret = true; break;
#else
case 8: ret = false; break;
#endif
default: ret = false; break;
}
return ret;

View file

@ -1,80 +0,0 @@
/* Simple libc header for TCC
*
* Add any function you want from the libc there. This file is here
* only for your convenience so that you do not need to put the whole
* glibc include files on your floppy disk
*/
#ifndef _TCCLIB_H
#define _TCCLIB_H
#include <stddef.h>
#include <stdarg.h>
/* stdlib.h */
void *calloc(size_t nmemb, size_t size);
void *malloc(size_t size);
void free(void *ptr);
void *realloc(void *ptr, size_t size);
int atoi(const char *nptr);
long int strtol(const char *nptr, char **endptr, int base);
unsigned long int strtoul(const char *nptr, char **endptr, int base);
void exit(int);
/* stdio.h */
typedef struct __FILE FILE;
#define EOF (-1)
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fildes, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
int fclose(FILE *stream);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int ungetc(int c, FILE *stream);
int fflush(FILE *stream);
int putchar (int c);
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int asprintf(char **strp, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
int vasprintf(char **strp, const char *format, va_list ap);
int vdprintf(int fd, const char *format, va_list ap);
void perror(const char *s);
/* string.h */
char *strcat(char *dest, const char *src);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
char *strcpy(char *dest, const char *src);
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
char *strdup(const char *s);
size_t strlen(const char *s);
/* dlfcn.h */
#define RTLD_LAZY 0x001
#define RTLD_NOW 0x002
#define RTLD_GLOBAL 0x100
void *dlopen(const char *filename, int flag);
const char *dlerror(void);
void *dlsym(void *handle, char *symbol);
int dlclose(void *handle);
#endif /* _TCCLIB_H */

View file

@ -1,428 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#ifndef _WIN32
#include <unistd.h>
#include <errno.h>
#else
#include <windows.h>
#include <io.h>
#endif
/* section layout (all little endian):
32bit offset to executable/so file name
filename \0
function name \0
align to 64 bits
64bit function start line
64bits end_line(28bits) / start_line(28bits) / flag=0xff(8bits)
64bits counter
\0
\0
\0
executable/so file name \0
*/
typedef struct tcov_line {
unsigned int fline;
unsigned int lline;
unsigned long long count;
} tcov_line;
typedef struct tcov_function {
char *function;
unsigned int first_line;
unsigned int n_line;
unsigned int m_line;
tcov_line *line;
} tcov_function;
typedef struct tcov_file {
char *filename;
unsigned int n_func;
unsigned int m_func;
tcov_function *func;
struct tcov_file *next;
} tcov_file;
static FILE *open_tcov_file (char *cov_filename)
{
int fd;
#ifndef _WIN32
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; /* Until EOF. */
lock.l_pid = getpid ();
#endif
fd = open (cov_filename, O_RDWR | O_CREAT, 0666);
if (fd < 0)
return NULL;
#ifndef _WIN32
while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR)
continue;
#else
{
OVERLAPPED overlapped = { 0 };
LockFileEx((HANDLE)_get_osfhandle(fd), LOCKFILE_EXCLUSIVE_LOCK,
0, 1, 0, &overlapped);
}
#endif
return fdopen (fd, "r+");
}
static unsigned long long get_value(unsigned char *p, int size)
{
unsigned long long value = 0;
p += size;
while (size--)
value = (value << 8) | *--p;
return value;
}
static int sort_func (const void *p, const void *q)
{
const tcov_function *pp = (const tcov_function *) p;
const tcov_function *pq = (const tcov_function *) q;
return pp->first_line > pq->first_line ? 1 :
pp->first_line < pq->first_line ? -1 : 0;
}
static int sort_line (const void *p, const void *q)
{
const tcov_line *pp = (const tcov_line *) p;
const tcov_line *pq = (const tcov_line *) q;
return pp->fline > pq->fline ? 1 :
pp->fline < pq->fline ? -1 :
pp->count < pq->count ? 1 :
pp->count > pq->count ? -1 : 0;
}
/* sort to let inline functions work */
static tcov_file *sort_test_coverage (unsigned char *p)
{
int i, j, k;
unsigned char *start = p;
tcov_file *file = NULL;
tcov_file *nfile;
p += 4;
while (*p) {
char *filename = (char *)p;
size_t len = strlen (filename);
nfile = file;
while (nfile) {
if (strcmp (nfile->filename, filename) == 0)
break;
nfile = nfile->next;
}
if (nfile == NULL) {
nfile = malloc (sizeof(tcov_file));
if (nfile == NULL) {
fprintf (stderr, "Malloc error test_coverage\n");
return file;
}
nfile->filename = filename;
nfile->n_func = 0;
nfile->m_func = 0;
nfile->func = NULL;
nfile->next = NULL;
if (file == NULL)
file = nfile;
else {
tcov_file *lfile = file;
while (lfile->next)
lfile = lfile->next;
lfile->next = nfile;
}
}
p += len + 1;
while (*p) {
int i;
char *function = (char *)p;
tcov_function *func;
p += strlen (function) + 1;
p += -(p - start) & 7;
for (i = 0; i < nfile->n_func; i++) {
func = &nfile->func[i];
if (strcmp (func->function, function) == 0)
break;
}
if (i == nfile->n_func) {
if (nfile->n_func >= nfile->m_func) {
nfile->m_func = nfile->m_func == 0 ? 4 : nfile->m_func * 2;
nfile->func = realloc (nfile->func,
nfile->m_func *
sizeof (tcov_function));
if (nfile->func == NULL) {
fprintf (stderr, "Realloc error test_coverage\n");
return file;
}
}
func = &nfile->func[nfile->n_func++];
func->function = function;
func->first_line = get_value (p, 8);
func->n_line = 0;
func->m_line = 0;
func->line = NULL;
}
p += 8;
while (*p) {
tcov_line *line;
unsigned long long val;
if (func->n_line >= func->m_line) {
func->m_line = func->m_line == 0 ? 4 : func->m_line * 2;
func->line = realloc (func->line,
func->m_line * sizeof (tcov_line));
if (func->line == NULL) {
fprintf (stderr, "Realloc error test_coverage\n");
return file;
}
}
line = &func->line[func->n_line++];
val = get_value (p, 8);
line->fline = (val >> 8) & 0xfffffffULL;
line->lline = val >> 36;
line->count = get_value (p + 8, 8);
p += 16;
}
p++;
}
p++;
}
nfile = file;
while (nfile) {
qsort (nfile->func, nfile->n_func, sizeof (tcov_function), sort_func);
for (i = 0; i < nfile->n_func; i++) {
tcov_function *func = &nfile->func[i];
qsort (func->line, func->n_line, sizeof (tcov_line), sort_line);
}
nfile = nfile->next;
}
return file;
}
/* merge with previous tcov file */
static void merge_test_coverage (tcov_file *file, FILE *fp,
unsigned int *pruns)
{
unsigned int runs;
char *p;
char str[10000];
*pruns = 1;
if (fp == NULL)
return;
if (fgets(str, sizeof(str), fp) &&
(p = strrchr (str, ':')) &&
(sscanf (p + 1, "%u", &runs) == 1))
*pruns = runs + 1;
while (file) {
int i;
size_t len = strlen (file->filename);
while (fgets(str, sizeof(str), fp) &&
(p = strstr(str, "0:File:")) == NULL) {}
if ((p = strstr(str, "0:File:")) == NULL ||
strncmp (p + strlen("0:File:"), file->filename, len) != 0 ||
p[strlen("0:File:") + len] != ' ')
break;
for (i = 0; i < file->n_func; i++) {
int j;
tcov_function *func = &file->func[i];
unsigned int next_zero = 0;
unsigned int curline = 0;
for (j = 0; j < func->n_line; j++) {
tcov_line *line = &func->line[j];
unsigned int fline = line->fline;
unsigned long long count;
unsigned int tmp;
char c;
while (curline < fline &&
fgets(str, sizeof(str), fp))
if ((p = strchr(str, ':')) &&
sscanf (p + 1, "%u", &tmp) == 1)
curline = tmp;
if (sscanf (str, "%llu%c\n", &count, &c) == 2) {
if (next_zero == 0)
line->count += count;
next_zero = c == '*';
}
}
}
file = file->next;
}
}
/* store tcov data in file */
void __store_test_coverage (unsigned char * p)
{
int i, j;
unsigned int files;
unsigned int funcs;
unsigned int blocks;
unsigned int blocks_run;
unsigned int runs;
char *cov_filename = (char *)p + get_value (p, 4);
FILE *fp;
char *q;
tcov_file *file;
tcov_file *nfile;
tcov_function *func;
fp = open_tcov_file (cov_filename);
if (fp == NULL) {
fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename);
return;
}
file = sort_test_coverage (p);
merge_test_coverage (file, fp, &runs);
fseek (fp, 0, SEEK_SET);
fprintf (fp, " -: 0:Runs:%u\n", runs);
files = 0;
funcs = 0;
blocks = 0;
blocks_run = 0;
nfile = file;
while (nfile) {
files++;
for (i = 0; i < nfile->n_func; i++) {
func = &nfile->func[i];
funcs++;
for (j = 0; j < func->n_line; j++) {
blocks++;
blocks_run += func->line[j].count != 0;
}
}
nfile = nfile->next;
}
if (blocks == 0)
blocks = 1;
fprintf (fp, " -: 0:All:%s Files:%u Functions:%u %.02f%%\n",
cov_filename, files, funcs, 100.0 * (double) blocks_run / blocks);
nfile = file;
while (nfile) {
FILE *src = fopen (nfile->filename, "r");
unsigned int curline = 1;
char str[10000];
if (src == NULL)
goto next;
funcs = 0;
blocks = 0;
blocks_run = 0;
for (i = 0; i < nfile->n_func; i++) {
func = &nfile->func[i];
funcs++;
for (j = 0; j < func->n_line; j++) {
blocks++;
blocks_run += func->line[j].count != 0;
}
}
if (blocks == 0)
blocks = 1;
fprintf (fp, " -: 0:File:%s Functions:%u %.02f%%\n",
nfile->filename, funcs, 100.0 * (double) blocks_run / blocks);
for (i = 0; i < nfile->n_func; i++) {
func = &nfile->func[i];
while (curline < func->first_line &&
fgets(str, sizeof(str), src))
fprintf (fp, " -:%5u:%s", curline++, str);
blocks = 0;
blocks_run = 0;
for (j = 0; j < func->n_line; j++) {
blocks++;
blocks_run += func->line[j].count != 0;
}
if (blocks == 0)
blocks = 1;
fprintf (fp, " -: 0:Function:%s %.02f%%\n",
func->function, 100.0 * (double) blocks_run / blocks);
#if 0
for (j = 0; j < func->n_line; j++) {
unsigned int fline = func->line[j].fline;
unsigned int lline = func->line[j].lline;
unsigned long long count = func->line[j].count;
fprintf (fp, "%u %u %llu\n", fline, lline, count);
}
#endif
for (j = 0; j < func->n_line;) {
unsigned int fline = func->line[j].fline;
unsigned int lline = func->line[j].lline;
unsigned long long count = func->line[j].count;
unsigned int has_zero = 0;
unsigned int same_line = fline == lline;
j++;
while (j < func->n_line) {
unsigned int nfline = func->line[j].fline;
unsigned int nlline = func->line[j].lline;
unsigned long long ncount = func->line[j].count;
if (fline == nfline) {
if (ncount == 0)
has_zero = 1;
else if (ncount > count)
count = ncount;
same_line = nfline == nlline;
lline = nlline;
j++;
}
else
break;
}
if (same_line)
lline++;
while (curline < fline &&
fgets(str, sizeof(str), src))
fprintf (fp, " -:%5u:%s", curline++, str);
while (curline < lline &&
fgets(str, sizeof(str), src)) {
if (count == 0)
fprintf (fp, " #####:%5u:%s",
curline, str);
else if (has_zero)
fprintf (fp, "%8llu*:%5u:%s",
count, curline, str);
else
fprintf (fp, "%9llu:%5u:%s",
count, curline, str);
curline++;
}
}
}
while (fgets(str, sizeof(str), src))
fprintf (fp, " -:%5u:%s", curline++, str);
fclose (src);
next:
nfile = nfile->next;
}
while (file) {
for (i = 0; i < file->n_func; i++) {
func = &file->func[i];
free (func->line);
}
free (file->func);
nfile = file;
file = file->next;
free (nfile);
}
fclose (fp);
}

View file

@ -1,67 +0,0 @@
/* va_list.c - tinycc support for va_list on X86_64 */
#if defined __x86_64__
/* Avoid include files, they may not be available when cross compiling */
extern void abort(void);
/* This should be in sync with our include/stdarg.h */
enum __va_arg_type {
__va_gen_reg, __va_float_reg, __va_stack
};
/* GCC compatible definition of va_list. */
/*predefined by TCC (tcc_predefs.h):
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
union {
unsigned int overflow_offset;
char *overflow_arg_area;
};
char *reg_save_area;
} __builtin_va_list[1];
*/
extern void *memcpy(void *dest, const void *src, unsigned long n);
void *__va_arg(__builtin_va_list ap,
int arg_type,
int size, int align)
{
size = (size + 7) & ~7;
align = (align + 7) & ~7;
switch ((enum __va_arg_type)arg_type) {
case __va_gen_reg:
if (ap->gp_offset + size <= 48) {
ap->gp_offset += size;
return ap->reg_save_area + ap->gp_offset - size;
}
goto use_overflow_area;
case __va_float_reg:
if (ap->fp_offset < 128 + 48) {
ap->fp_offset += 16;
if (size == 8)
return ap->reg_save_area + ap->fp_offset - 16;
if (ap->fp_offset < 128 + 48) {
memcpy(ap->reg_save_area + ap->fp_offset - 8,
ap->reg_save_area + ap->fp_offset, 8);
ap->fp_offset += 16;
return ap->reg_save_area + ap->fp_offset - 32;
}
}
goto use_overflow_area;
case __va_stack:
use_overflow_area:
ap->overflow_arg_area += size;
ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
return ap->overflow_arg_area - size;
default: /* should never happen */
abort();
return 0;
}
}
#endif

View file

@ -2,4 +2,4 @@ bin_PROGRAMS = tcc
tcc_SOURCES = tcc.c tcctools.c
tcc_LDADD = ../libtcc/libtcc.a
tcc_CPPFLAGS = -I$(top_srcdir)
tcc_CPPFLAGS = -I$(top_srcdir)/libtcc/include -I$(top_srcdir)/libtcc

View file

@ -19,7 +19,7 @@
*/
#include "config.h"
#include "libtcc/tcc.h"
#include <tcc.h>
#include "tcctools.h"
static const char HELP_STR[] =
@ -136,7 +136,6 @@ static void print_search_dirs(TCCState *s)
print_dirs("libraries", s->library_paths, s->nb_library_paths);
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
}
static void set_environment(TCCState *s)
@ -215,8 +214,6 @@ redo:
fputs(HELP_MORE_STR, stdout);
return 0;
}
if (opt == OPT_M32 || opt == OPT_M64)
return tcc_tool_cross(s, argv, opt);
if (s->verbose)
printf("%s", VERSION_STR);
if (opt == OPT_AR)

View file

@ -33,7 +33,6 @@ static const char help_str[] =
"General options:\n"
" -c compile only - generate an object file\n"
" -o outfile set output filename\n"
" -run run compiled source\n"
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
" -w disable all warnings\n"
@ -52,12 +51,7 @@ static const char help_str[] =
" -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n"
" -r generate (relocatable) object file\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -soname set name for shared library to be used at runtime\n"
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
"Debugger options:\n"
" -g generate stab runtime debug info\n"
" -gdwarf[-x] generate dwarf runtime debug info\n"
"Misc. options:\n"
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
@ -81,12 +75,10 @@ static const char help_more_str[] =
" -Wp,-opt same as -opt\n"
" -include file include 'file' above each input file\n"
" -isystem dir add 'dir' to system include path\n"
" -static link to static libraries (not recommended)\n"
" -dumpversion print version\n"
" -print-search-dirs print search paths\n"
" -dt with -run/-E: auto-define 'test_...' macros\n"
"Ignored options:\n"
" -arch -C --param -pedantic -pipe -s -traditional\n"
" -arch -C --param -pedantic -pipe -s -traditional -g -static -shared\n"
"-W[no-]... warnings:\n"
" all turn on some (*) warnings\n"
" error[=warning] stop after warning (any or specified)\n"
@ -104,20 +96,14 @@ static const char help_more_str[] =
" reverse-funcargs evaluate function arguments right to left\n"
" gnu89-inline 'extern inline' is like 'static inline'\n"
" asynchronous-unwind-tables create eh_frame section [on]\n"
" test-coverage create code coverage code\n"
"-m... target specific options:\n"
" ms-bitfields use MSVC bitfield layout\n"
"-Wl,... linker options:\n"
" -nostdlib do not link with standard crt/libs\n"
" -[no-]whole-archive load lib(s) fully/only as needed\n"
" -export-all-symbols same as -rdynamic\n"
" -export-dynamic same as -rdynamic\n"
" -image-base= -Ttext= set base address of executable\n"
" -section-alignment= set section alignment in executable\n"
" -rpath= set dynamic library search path\n"
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
" -soname= set DT_SONAME elf tag\n"
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
" -oformat=[coff,binary] set executable output format\n"
" -init= -fini= -Map= -as-needed -O (ignored)\n"
"Predefined macros:\n"

View file

@ -28,7 +28,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "libtcc/tcc.h"
#include "tcc.h"
//#define ARMAG "!<arch>\n"
#define ARFMAG "`\n"
@ -54,7 +54,7 @@ static int ar_usage(int ret) {
return ret;
}
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
int tcc_tool_ar(TCCState *s1, int argc, char **argv)
{
static const ArHdr arhdr_init = {
"/ ",
@ -357,93 +357,6 @@ the_end:
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option)
{
tcc_error_noabort("-m%d not implemented.", option);
return 1;
}
#else
#ifdef _WIN32
#include <process.h>
/* - Empty argument or with space/tab (not newline) requires quoting.
* - Double-quotes at the value require '\'-escape, regardless of quoting.
* - Consecutive (or 1) backslashes at the value all need '\'-escape only if
* followed by [escaped] double quote, else taken literally, e.g. <x\\y\>
* remains literal without quoting or esc, but <x\\"y\> becomes <x\\\\\"y\>.
* - This "before double quote" rule applies also before delimiting quoting,
* e.g. <x\y \"z\> becomes <"x\y \\\"z\\"> (quoting required because space).
*
* https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
*/
static char *quote_win32(const char *s)
{
char *o, *r = tcc_malloc(2 * strlen(s) + 3); /* max-esc, quotes, \0 */
int cbs = 0, quoted = !*s; /* consecutive backslashes before current */
for (o = r; *s; *o++ = *s++) {
quoted |= *s == ' ' || *s == '\t';
if (*s == '\\' || *s == '"')
*o++ = '\\';
else
o -= cbs; /* undo cbs escapes, if any (not followed by DQ) */
cbs = *s == '\\' ? cbs + 1 : 0;
}
if (quoted) {
memmove(r + 1, r, o++ - r);
*r = *o++ = '"';
} else {
o -= cbs;
}
*o = 0;
return r; /* don't bother with realloc(r, o-r+1) */
}
static int execvp_win32(const char *prog, char **argv)
{
int ret; char **p;
/* replace all " by \" */
for (p = argv; *p; ++p)
*p = quote_win32(*p);
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
if (-1 == ret)
return ret;
_cwait(&ret, ret, WAIT_CHILD);
exit(ret);
}
#define execvp execvp_win32
#endif /* _WIN32 */
ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
{
char program[4096];
char *a0 = argv[0];
int prefix = tcc_basename(a0) - a0;
snprintf(program, sizeof program,
"%.*s%s"
#ifdef TCC_TARGET_PE
"-win32"
#endif
"-tcc"
#ifdef _WIN32
".exe"
#endif
, prefix, a0, target == 64 ? "x86_64" : "i386");
if (strcmp(a0, program))
execvp(argv[0] = program, argv);
tcc_error_noabort("could not run '%s'", program);
return 1;
}
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
/* -------------------------------------------------------------- */
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
@ -470,7 +383,7 @@ static char *escape_target_dep(const char *s) {
return res;
}
ST_FUNC int gen_makedeps(TCCState *s1, const char *target, const char *filename)
int gen_makedeps(TCCState *s1, const char *target, const char *filename)
{
FILE *depout;
char buf[1024];

View file

@ -1,10 +1,9 @@
#ifndef TCC_TCCTOOLS_H
# define TCC_TCCTOOLS_H 1
# include "libtcc/libtcc.h"
# include "libtcc.h"
int tcc_tool_ar(TCCState *s1, int argc, char **argv);
int tcc_tool_cross(TCCState *s1, char **argv, int target);
int gen_makedeps(TCCState *s1, const char *target, const char *filename);
#endif /* !TCC_TCCTOOLS_H */