From 88a3ccab9f3c877e2ffb8fecc3303006e0640907 Mon Sep 17 00:00:00 2001 From: grischka Date: Sun, 20 Dec 2009 01:53:49 +0100 Subject: [PATCH] allow tcc be build from separate objects If you want that, run: make NOTALLINONE=1 --- Makefile | 41 ++- arm-gen.c | 70 ++--- c67-gen.c | 95 +++---- i386-asm.c | 20 +- i386-gen.c | 78 +++--- libtcc.c | 734 ++++++++------------------------------------------- tcc.c | 32 +-- tcc.h | 440 +++++++++++++++++++++++++++--- tccasm.c | 18 +- tcccoff.c | 4 +- tccelf.c | 62 ++--- tccgen.c | 342 ++++++++++++++++++++---- tccpe.c | 129 +++++---- tccpp.c | 221 +++++++++++++--- tccrun.c | 43 +-- x86_64-gen.c | 38 ++- 16 files changed, 1322 insertions(+), 1045 deletions(-) diff --git a/Makefile b/Makefile index 08ef48a..b27e5fa 100644 --- a/Makefile +++ b/Makefile @@ -113,11 +113,13 @@ ifdef CONFIG_CROSS PROGS+=$(PROGS_CROSS) endif +# NOTALLINONE = 1 + all: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc-doc.html tcc.1 libtcc_test$(EXESUF) # Host Tiny C Compiler -tcc$(EXESUF): $(NATIVE_FILES) - $(CC) -o $@ $< $(NATIVE_TARGET) $(CFLAGS) $(LIBS) +tcc$(EXESUF): tcc.o libtcc.a + $(CC) -o $@ $^ $(LIBS) # Cross Tiny C Compilers i386-tcc$(EXESUF): $(I386_FILES) @@ -151,10 +153,22 @@ arm-tcc-vfp-eabi$(EXESUF): $(ARM_FILES) $(CC) -o $@ $< -DTCC_TARGET_ARM -DTCC_ARM_EABI $(CFLAGS) $(LIBS) # libtcc generation and test -libtcc.o: $(NATIVE_FILES) - $(CC) -o $@ -c libtcc.c $(NATIVE_TARGET) $(CFLAGS) -libtcc.a: libtcc.o +ifdef NOTALLINONE +LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) +LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES)) +$(LIBTCC_OBJ) : DEFINES += -DNOTALLINONE +else +LIBTCC_OBJ = libtcc.o +LIBTCC_INC = $(NATIVE_FILES) +endif + +tcc.o : DEFINES += -DNOTALLINONE + +$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) + $(CC) -o $@ -c $< $(NATIVE_TARGET) $(CFLAGS) $(DEFINES) + +libtcc.a: $(LIBTCC_OBJ) $(AR) rcs $@ $^ libtcc_test$(EXESUF): tests/libtcc_test.c libtcc.a @@ -260,19 +274,18 @@ tar: rm -rf /tmp/$(TCC-VERSION) # in tests subdir -test clean: +%est: $(MAKE) -C tests $@ +clean: + rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.out libtcc_test$(EXESUF) + $(MAKE) -C tests $@ + +distclean: clean + rm -vf config.h config.mak config.texi tcc.1 + config.mak: @echo Running configure ... @./configure -# clean -clean: local_clean -local_clean: - rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.out libtcc_test$(EXESUF) - -distclean: clean - rm -vf config.h config.mak config.texi tcc.1 - endif # ifeq ($(TOP),.) diff --git a/arm-gen.c b/arm-gen.c index e0866ff..e9bc3a0 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -20,11 +20,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef TARGET_DEFS_ONLY + #ifdef TCC_ARM_EABI #define TCC_ARM_VFP #endif - /* number of available registers */ #ifdef TCC_ARM_VFP #define NB_REGS 13 @@ -75,32 +76,6 @@ enum { #endif }; -const int reg_classes[NB_REGS] = { - /* r0 */ RC_INT | RC_R0, - /* r1 */ RC_INT | RC_R1, - /* r2 */ RC_INT | RC_R2, - /* r3 */ RC_INT | RC_R3, - /* r12 */ RC_INT | RC_R12, - /* f0 */ RC_FLOAT | RC_F0, - /* f1 */ RC_FLOAT | RC_F1, - /* f2 */ RC_FLOAT | RC_F2, - /* f3 */ RC_FLOAT | RC_F3, -#ifdef TCC_ARM_VFP - /* d4/s8 */ RC_FLOAT | RC_F4, -/* d5/s10 */ RC_FLOAT | RC_F5, -/* d6/s12 */ RC_FLOAT | RC_F6, -/* d7/s14 */ RC_FLOAT | RC_F7, -#endif -}; - -static int two2mask(int a,int b) { - return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); -} - -static int regmask(int r) { - return reg_classes[r]&~(RC_INT|RC_FLOAT); -} - #ifdef TCC_ARM_VFP #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0) #endif @@ -171,10 +146,42 @@ static CType float_type, double_type, func_float_type, func_double_type; #define ELF_PAGE_SIZE 0x1000 /******************************************************/ +#else /* ! TARGET_DEFS_ONLY */ +/******************************************************/ +#include "tcc.h" + +ST_DATA const int reg_classes[NB_REGS] = { + /* r0 */ RC_INT | RC_R0, + /* r1 */ RC_INT | RC_R1, + /* r2 */ RC_INT | RC_R2, + /* r3 */ RC_INT | RC_R3, + /* r12 */ RC_INT | RC_R12, + /* f0 */ RC_FLOAT | RC_F0, + /* f1 */ RC_FLOAT | RC_F1, + /* f2 */ RC_FLOAT | RC_F2, + /* f3 */ RC_FLOAT | RC_F3, +#ifdef TCC_ARM_VFP + /* d4/s8 */ RC_FLOAT | RC_F4, +/* d5/s10 */ RC_FLOAT | RC_F5, +/* d6/s12 */ RC_FLOAT | RC_F6, +/* d7/s14 */ RC_FLOAT | RC_F7, +#endif +}; + static unsigned long func_sub_sp_offset,last_itod_magic; static int leaffunc; -void o(unsigned long i) +static int two2mask(int a,int b) { + return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); +} + +static int regmask(int r) { + return reg_classes[r]&~(RC_INT|RC_FLOAT); +} + +/******************************************************/ + +void o(unsigned int i) { /* this is a good place to start adding big-endian support*/ int ind1; @@ -304,7 +311,7 @@ void stuff_const_harder(unsigned long op,unsigned long v) { } } -unsigned long encbranch(int pos,int addr,int fail) +ST_FUNC unsigned long encbranch(int pos,int addr,int fail) { addr-=pos+8; addr/=4; @@ -1571,7 +1578,7 @@ void gen_opf(int op) /* convert integers to fp 't' type. Must handle 'int', 'unsigned int' and 'long long' cases. */ -void gen_cvt_itof1(int t) +ST_FUNC void gen_cvt_itof1(int t) { int r,r2,bt; bt=vtop->type.t & VT_BTYPE; @@ -1732,4 +1739,5 @@ void ggoto(void) /* end of ARM code generator */ /*************************************************************/ - +#endif +/*************************************************************/ diff --git a/c67-gen.c b/c67-gen.c index 88224fd..b353194 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef TARGET_DEFS_ONLY + //#define ASSEMBLY_LISTING_C67 /* number of available registers */ @@ -85,62 +87,18 @@ enum { TREG_C67_B13, }; -const int reg_classes[NB_REGS] = { - /* eax */ RC_INT | RC_FLOAT | RC_EAX, - // only allow even regs for floats (allow for doubles) - /* ecx */ RC_INT | RC_ECX, - /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX, - // only allow even regs for floats (allow for doubles) - /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0, - /* A4 */ RC_C67_A4, - /* A5 */ RC_C67_A5, - /* B4 */ RC_C67_B4, - /* B5 */ RC_C67_B5, - /* A6 */ RC_C67_A6, - /* A7 */ RC_C67_A7, - /* B6 */ RC_C67_B6, - /* B7 */ RC_C67_B7, - /* A8 */ RC_C67_A8, - /* A9 */ RC_C67_A9, - /* B8 */ RC_C67_B8, - /* B9 */ RC_C67_B9, - /* A10 */ RC_C67_A10, - /* A11 */ RC_C67_A11, - /* B10 */ RC_C67_B10, - /* B11 */ RC_C67_B11, - /* A12 */ RC_C67_A10, - /* A13 */ RC_C67_A11, - /* B12 */ RC_C67_B10, - /* B13 */ RC_C67_B11 -}; - /* return registers for function */ #define REG_IRET TREG_C67_A4 /* single word int return register */ #define REG_LRET TREG_C67_A5 /* second word return register (for long long) */ #define REG_FRET TREG_C67_A4 /* float return register */ - #define ALWAYS_ASSERT(x) \ do {\ if (!(x))\ error("internal compiler error file at %s:%d", __FILE__, __LINE__);\ } while (0) -// although tcc thinks it is passing parameters on the stack, -// the C67 really passes up to the first 10 params in special -// regs or regs pairs (for 64 bit params). So keep track of -// the stack offsets so we can translate to the appropriate -// reg (pair) - - -#define NoCallArgsPassedOnStack 10 -int NoOfCurFuncArgs; -int TranslateStackToReg[NoCallArgsPassedOnStack]; -int ParamLocOnStack[NoCallArgsPassedOnStack]; -int TotalBytesPushedOnStack; - /* defined if function parameters must be evaluated in reverse order */ - //#define INVERT_FUNC_PARAMS /* defined if structures are passed as pointers. Otherwise structures @@ -171,7 +129,52 @@ int TotalBytesPushedOnStack; #define ELF_PAGE_SIZE 0x1000 /******************************************************/ +#else /* ! TARGET_DEFS_ONLY */ +/******************************************************/ +#include "tcc.h" +ST_DATA const int reg_classes[NB_REGS] = { + /* eax */ RC_INT | RC_FLOAT | RC_EAX, + // only allow even regs for floats (allow for doubles) + /* ecx */ RC_INT | RC_ECX, + /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX, + // only allow even regs for floats (allow for doubles) + /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0, + /* A4 */ RC_C67_A4, + /* A5 */ RC_C67_A5, + /* B4 */ RC_C67_B4, + /* B5 */ RC_C67_B5, + /* A6 */ RC_C67_A6, + /* A7 */ RC_C67_A7, + /* B6 */ RC_C67_B6, + /* B7 */ RC_C67_B7, + /* A8 */ RC_C67_A8, + /* A9 */ RC_C67_A9, + /* B8 */ RC_C67_B8, + /* B9 */ RC_C67_B9, + /* A10 */ RC_C67_A10, + /* A11 */ RC_C67_A11, + /* B10 */ RC_C67_B10, + /* B11 */ RC_C67_B11, + /* A12 */ RC_C67_A10, + /* A13 */ RC_C67_A11, + /* B12 */ RC_C67_B10, + /* B13 */ RC_C67_B11 +}; + +// although tcc thinks it is passing parameters on the stack, +// the C67 really passes up to the first 10 params in special +// regs or regs pairs (for 64 bit params). So keep track of +// the stack offsets so we can translate to the appropriate +// reg (pair) + +#define NoCallArgsPassedOnStack 10 +int NoOfCurFuncArgs; +int TranslateStackToReg[NoCallArgsPassedOnStack]; +int ParamLocOnStack[NoCallArgsPassedOnStack]; +int TotalBytesPushedOnStack; + +/******************************************************/ static unsigned long func_sub_sp_offset; static int func_ret_sub; @@ -2545,5 +2548,7 @@ void ggoto(void) vtop--; } -/* end of X86 code generator */ +/* end of C67 code generator */ +/*************************************************************/ +#endif /*************************************************************/ diff --git a/i386-asm.c b/i386-asm.c index 6e1314c..a378191 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -19,7 +19,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "tcc.h" + +// #define NB_ASM_REGS 8 #define MAX_OPERANDS 3 +#define NB_SAVED_REGS 3 #define TOK_ASM_first TOK_ASM_clc #define TOK_ASM_last TOK_ASM_emms @@ -398,7 +402,8 @@ static void parse_operand(TCCState *s1, Operand *op) op->type |= indir; } -static void gen_expr32(ExprValue *pe) +/* XXX: unify with C code output ? */ +ST_FUNC void gen_expr32(ExprValue *pe) { gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v); } @@ -554,7 +559,7 @@ static inline void asm_modrm(int reg, Operand *op) } } -static void asm_opcode(TCCState *s1, int opcode) +ST_FUNC void asm_opcode(TCCState *s1, int opcode) { const ASMInstr *pa; int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix; @@ -966,9 +971,6 @@ static void asm_opcode(TCCState *s1, int opcode) #endif } -#define NB_SAVED_REGS 3 -#define NB_ASM_REGS 8 - /* return the constraint priority (we allocate first the lowest numbered constraints) */ static inline int constraint_priority(const char *str) @@ -1030,7 +1032,7 @@ static const char *skip_constraint_modifiers(const char *p) #define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask) -static void asm_compute_constraints(ASMOperand *operands, +ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg) @@ -1262,7 +1264,7 @@ static void asm_compute_constraints(ASMOperand *operands, #endif } -static void subst_asm_operand(CString *add_str, +ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) { int r, reg, size, val; @@ -1356,7 +1358,7 @@ static void subst_asm_operand(CString *add_str, } /* generate prolog and epilog code for asm statment */ -static void asm_gen_code(ASMOperand *operands, int nb_operands, +ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg) @@ -1450,7 +1452,7 @@ static void asm_gen_code(ASMOperand *operands, int nb_operands, } } -static void asm_clobber(uint8_t *clobber_regs, const char *str) +ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str) { int reg; TokenSym *ts; diff --git a/i386-gen.c b/i386-gen.c index 161be93..9a8ceee 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -18,8 +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 4 +#define NB_REGS 4 +#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 @@ -42,13 +45,6 @@ enum { TREG_ST0, }; -const int reg_classes[NB_REGS] = { - /* eax */ RC_INT | RC_EAX, - /* ecx */ RC_INT | RC_ECX, - /* edx */ RC_INT | RC_EDX, - /* st0 */ RC_FLOAT | RC_ST0, -}; - /* return registers for function */ #define REG_IRET TREG_EAX /* single word int return register */ #define REG_LRET TREG_EDX /* second word return register (for long long) */ @@ -70,6 +66,9 @@ const int reg_classes[NB_REGS] = { /* maximum alignment (for aligned attribute support) */ #define MAX_ALIGN 8 + +#define psym oad + /******************************************************/ /* ELF defines */ @@ -85,6 +84,16 @@ const int reg_classes[NB_REGS] = { #define ELF_PAGE_SIZE 0x1000 /******************************************************/ +#else /* ! TARGET_DEFS_ONLY */ +/******************************************************/ +#include "tcc.h" + +ST_DATA const int reg_classes[NB_REGS] = { + /* eax */ RC_INT | RC_EAX, + /* ecx */ RC_INT | RC_ECX, + /* edx */ RC_INT | RC_EDX, + /* st0 */ RC_FLOAT | RC_ST0, +}; static unsigned long func_sub_sp_offset; static int func_ret_sub; @@ -93,7 +102,7 @@ static unsigned long func_bound_offset; #endif /* XXX: make it faster ? */ -void g(int c) +ST_FUNC void g(int c) { int ind1; ind1 = ind + 1; @@ -103,7 +112,7 @@ void g(int c) ind = ind1; } -void o(unsigned int c) +ST_FUNC void o(unsigned int c) { while (c) { g(c); @@ -111,13 +120,13 @@ void o(unsigned int c) } } -void gen_le16(int v) +ST_FUNC void gen_le16(int v) { g(v); g(v >> 8); } -void gen_le32(int c) +ST_FUNC void gen_le32(int c) { g(c); g(c >> 8); @@ -126,7 +135,7 @@ void gen_le32(int c) } /* output a symbol and patch all calls to it */ -void gsym_addr(int t, int a) +ST_FUNC void gsym_addr(int t, int a) { int n, *ptr; while (t) { @@ -137,7 +146,7 @@ void gsym_addr(int t, int a) } } -void gsym(int t) +ST_FUNC void gsym(int t) { gsym_addr(t, ind); } @@ -147,7 +156,7 @@ void gsym(int t) #define psym oad /* instruction + 4 bytes data. Return the address of the data */ -static int oad(int c, int s) +ST_FUNC int oad(int c, int s) { int ind1; @@ -162,14 +171,14 @@ static int oad(int c, int s) } /* output constant with relocation if 'r & VT_SYM' is true */ -static void gen_addr32(int r, Sym *sym, int c) +ST_FUNC 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); } -static void gen_addrpc32(int r, Sym *sym, int c) +ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) { if (r & VT_SYM) greloc(cur_text_section, sym, ind, R_386_PC32); @@ -200,7 +209,7 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c) } /* load 'r' from value 'sv' */ -void load(int r, SValue *sv) +ST_FUNC void load(int r, SValue *sv) { int v, t, ft, fc, fr; SValue v1; @@ -269,7 +278,7 @@ void load(int r, SValue *sv) } /* store register 'r' in lvalue 'v' */ -void store(int r, SValue *v) +ST_FUNC void store(int r, SValue *v) { int fr, bt, ft, fc; @@ -349,7 +358,7 @@ static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; /* 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. */ -void gfunc_call(int nb_args) +ST_FUNC void gfunc_call(int nb_args) { int size, align, r, args_size, i, func_call; Sym *func_sym; @@ -442,7 +451,7 @@ void gfunc_call(int nb_args) #endif /* generate function prolog of type 't' */ -void gfunc_prolog(CType *func_type) +ST_FUNC void gfunc_prolog(CType *func_type) { int addr, align, size, func_call, fastcall_nb_regs; int param_index, param_addr; @@ -524,7 +533,7 @@ void gfunc_prolog(CType *func_type) } /* generate function epilog */ -void gfunc_epilog(void) +ST_FUNC void gfunc_epilog(void) { int v, saved_ind; @@ -595,13 +604,13 @@ void gfunc_epilog(void) } /* generate a jump to a label */ -int gjmp(int t) +ST_FUNC int gjmp(int t) { return psym(0xe9, t); } /* generate a jump to a fixed address */ -void gjmp_addr(int a) +ST_FUNC void gjmp_addr(int a) { int r; r = a - ind - 2; @@ -614,7 +623,7 @@ void gjmp_addr(int a) } /* generate a test. set 'inv' to invert test. Stack entry is popped */ -int gtst(int inv, int t) +ST_FUNC int gtst(int inv, int t) { int v, *p; @@ -659,7 +668,7 @@ int gtst(int inv, int t) } /* generate an integer binary operation */ -void gen_opi(int op) +ST_FUNC void gen_opi(int op) { int r, fr, opc, c; @@ -793,7 +802,7 @@ void gen_opi(int op) /* generate a floating point operation 'v = t1 op t2' instruction. The two operands are guaranted to have the same floating point type */ /* XXX: need to use ST1 too */ -void gen_opf(int op) +ST_FUNC void gen_opf(int op) { int a, ft, fc, swapped, r; @@ -905,7 +914,7 @@ void gen_opf(int op) /* convert integers to fp 't' type. Must handle 'int', 'unsigned int' and 'long long' cases. */ -void gen_cvt_itof(int t) +ST_FUNC void gen_cvt_itof(int t) { save_reg(TREG_ST0); gv(RC_INT); @@ -935,7 +944,7 @@ void gen_cvt_itof(int t) /* convert fp to int 't' type */ /* XXX: handle long long case */ -void gen_cvt_ftoi(int t) +ST_FUNC void gen_cvt_ftoi(int t) { int r, r2, size; Sym *sym; @@ -986,14 +995,14 @@ void gen_cvt_ftoi(int t) } /* convert from one floating point type to another */ -void gen_cvt_ftof(int t) +ST_FUNC void gen_cvt_ftof(int t) { /* all we have to do on i386 is to put the float in a register */ gv(RC_FLOAT); } /* computed goto support */ -void ggoto(void) +ST_FUNC void ggoto(void) { gcall_or_jmp(1); vtop--; @@ -1003,7 +1012,7 @@ void ggoto(void) #ifdef CONFIG_TCC_BCHECK /* generate a bounded pointer addition */ -void gen_bounded_ptr_add(void) +ST_FUNC void gen_bounded_ptr_add(void) { Sym *sym; @@ -1026,7 +1035,7 @@ void gen_bounded_ptr_add(void) /* patch pointer addition in vtop so that pointer dereferencing is also tested */ -void gen_bounded_ptr_deref(void) +ST_FUNC void gen_bounded_ptr_deref(void) { int func; int size, align; @@ -1068,4 +1077,5 @@ void gen_bounded_ptr_deref(void) /* end of X86 code generator */ /*************************************************************/ - +#endif +/*************************************************************/ diff --git a/libtcc.c b/libtcc.c index 7ef1f0b..9be8c1c 100644 --- a/libtcc.c +++ b/libtcc.c @@ -23,344 +23,70 @@ /********************************************************/ /* global variables */ -/* display benchmark infos */ -int total_lines; -int total_bytes; - -/* parser */ -static struct BufferedFile *file; -static int ch, tok; -static CValue tokc; -static CString tokcstr; /* current parsed string, if any */ -/* additional informations about token */ -static int tok_flags; -#define TOK_FLAG_BOL 0x0001 /* beginning of line before */ -#define TOK_FLAG_BOF 0x0002 /* beginning of file before */ -#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */ -#define TOK_FLAG_EOF 0x0008 /* end of file */ - -static int *macro_ptr, *macro_ptr_allocated; -static int *unget_saved_macro_ptr; -static int unget_saved_buffer[TOK_MAX_SIZE + 1]; -static int unget_buffer_enabled; -static int parse_flags; -#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */ -#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */ -#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a - token. line feed is also - returned at eof */ -#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ -#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ - -static Section *text_section, *data_section, *bss_section; /* predefined sections */ -static Section *cur_text_section; /* current section where function code is - generated */ -#ifdef CONFIG_TCC_ASM -static Section *last_text_section; /* to handle .previous asm directive */ -#endif - -#ifdef CONFIG_TCC_BCHECK -/* bound check related sections */ -static Section *bounds_section; /* contains global data bound description */ -static Section *lbounds_section; /* contains local data bound description */ -#endif - -/* symbol sections */ -static Section *symtab_section, *strtab_section; - -/* debug sections */ -static Section *stab_section, *stabstr_section; - -/* loc : local variable index - ind : output code index - rsym: return symbol - anon_sym: anonymous symbol index -*/ -static int rsym, anon_sym, ind, loc; -/* expression generation modifiers */ -static int const_wanted; /* true if constant wanted */ -static int nocode_wanted; /* true if no code generation wanted for an expression */ -static int global_expr; /* true if compound literals must be allocated - globally (used during initializers parsing */ -static CType func_vt; /* current function return type (used by return - instruction) */ -static int func_vc; -static int last_line_num, last_ind, func_ind; /* debug last line number and pc */ -static int tok_ident; -static TokenSym **table_ident; -static TokenSym *hash_ident[TOK_HASH_SIZE]; -static char token_buf[STRING_MAX_SIZE + 1]; -static char *funcname; -static Sym *global_stack, *local_stack; -static Sym *define_stack; -static Sym *global_label_stack, *local_label_stack; -/* symbol allocator */ -#define SYM_POOL_NB (8192 / sizeof(Sym)) -static Sym *sym_free_first; -static void **sym_pools; -static int nb_sym_pools; - -static SValue vstack[VSTACK_SIZE], *vtop; -/* some predefined types */ -static CType char_pointer_type, func_old_type, int_type; - /* use GNU C extensions */ -static int gnu_ext = 1; +ST_DATA int gnu_ext = 1; -/* use Tiny C extensions */ -static int tcc_ext = 1; - -/* max number of callers shown if error */ -#ifdef CONFIG_TCC_BACKTRACE -int num_callers = 6; -void *rt_prog_main; -const char **rt_bound_error_msg; -#endif +/* use TinyCC extensions */ +ST_DATA int tcc_ext = 1; /* XXX: get rid of this ASAP */ -static struct TCCState *tcc_state; +ST_DATA struct TCCState *tcc_state; -/********************************************************/ -/* function prototypes */ - -/* tccpp.c */ -static void next(void); -char *get_tok_str(int v, CValue *cv); - -/* tccgen.c */ -static void parse_expr_type(CType *type); -static void expr_type(CType *type); -static void unary_type(CType *type); -static void block(int *bsym, int *csym, int *case_sym, int *def_sym, - int case_reg, int is_expr); -static int expr_const(void); -static void expr_eq(void); -static void gexpr(void); -static void gen_inline_functions(void); -static void decl(int l); -static void decl_initializer(CType *type, Section *sec, unsigned long c, - int first, int size_only); -static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, - int has_init, int v, int scope); -int gv(int rc); -void gv2(int rc1, int rc2); -void move_reg(int r, int s); -void save_regs(int n); -void save_reg(int r); -void vpop(void); -void vswap(void); -void vdup(void); -int get_reg(int rc); -int get_reg_ex(int rc,int rc2); - -void gen_op(int op); -void force_charshort_cast(int t); -static void gen_cast(CType *type); -void vstore(void); -static Sym *sym_find(int v); -static Sym *sym_push(int v, CType *type, int r, int c); - -/* type handling */ -static int type_size(CType *type, int *a); -static inline CType *pointed_type(CType *type); -static int pointed_size(CType *type); -static int lvalue_type(int t); -static int parse_btype(CType *type, AttributeDef *ad); -static void type_decl(CType *type, AttributeDef *ad, int *v, int td); -static int compare_types(CType *type1, CType *type2, int unqualified); -static int is_compatible_types(CType *type1, CType *type2); -static int is_compatible_parameter_types(CType *type1, CType *type2); - -int ieee_finite(double d); -void vpushi(int v); -void vpushll(long long v); -void vrott(int n); -void vnrott(int n); -void lexpand_nr(void); -static void vpush_global_sym(CType *type, int v); -void vset(CType *type, int r, int v); -void type_to_str(char *buf, int buf_size, - CType *type, const char *varstr); -static Sym *get_sym_ref(CType *type, Section *sec, - unsigned long offset, unsigned long size); -static Sym *external_global_sym(int v, CType *type, int r); - -/* section generation */ -static void section_realloc(Section *sec, unsigned long new_size); -static void *section_ptr_add(Section *sec, unsigned long size); -static void put_extern_sym(Sym *sym, Section *section, - unsigned long value, unsigned long size); -static void greloc(Section *s, Sym *sym, unsigned long addr, int type); -static int put_elf_str(Section *s, const char *sym); -static int put_elf_sym(Section *s, - unsigned long value, unsigned long size, - int info, int other, int shndx, const char *name); -static int add_elf_sym(Section *s, uplong value, unsigned long size, - int info, int other, int sh_num, const char *name); -static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, - int type, int symbol); -static void put_stabs(const char *str, int type, int other, int desc, - unsigned long value); -static void put_stabs_r(const char *str, int type, int other, int desc, - unsigned long value, Section *sec, int sym_index); -static void put_stabn(int type, int other, int desc, int value); -static void put_stabd(int type, int other, int desc); -static int tcc_add_dll(TCCState *s, const char *filename, int flags); - -#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */ -#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */ -#define AFF_PREPROCESS 0x0004 /* preprocess file */ -static int tcc_add_file_internal(TCCState *s, const char *filename, int flags); - -/* tcccoff.c */ -int tcc_output_coff(TCCState *s1, FILE *f); - -/* tccpe.c */ -int pe_load_file(struct TCCState *s1, const char *filename, int fd); -int pe_output_file(struct TCCState *s1, const char *filename); -int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)); - -/* tccasm.c */ -#ifdef CONFIG_TCC_ASM -static void asm_expr(TCCState *s1, ExprValue *pe); -static int asm_int_expr(TCCState *s1); -static int find_constraint(ASMOperand *operands, int nb_operands, - const char *name, const char **pp); - -static int tcc_assemble(TCCState *s1, int do_preprocess); +#ifdef CONFIG_TCC_BACKTRACE +ST_DATA int num_callers = 6; +ST_DATA const char **rt_bound_error_msg; +ST_DATA void *rt_prog_main; #endif -static void asm_instr(void); -static void asm_global_instr(void); - -/********************************************************/ -/* libtcc.c */ - -static Sym *__sym_malloc(void); -static inline Sym *sym_malloc(void); -static inline void sym_free(Sym *sym); -Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags); -static void free_section(Section *s); -static void section_realloc(Section *sec, unsigned long new_size); -static void *section_ptr_add(Section *sec, unsigned long size); -Section *find_section(TCCState *s1, const char *name); -static void put_extern_sym2( - Sym *sym, Section *section, - unsigned long value, unsigned long size, int can_add_underscore); -static void put_extern_sym( - Sym *sym, Section *section, - unsigned long value, unsigned long size); -static void greloc(Section *s, Sym *sym, unsigned long offset, int type); - -static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap); -static void strcat_printf(char *buf, int buf_size, const char *fmt, ...); - -/* CString handling */ -static void cstr_realloc(CString *cstr, int new_size); -static inline void cstr_ccat(CString *cstr, int ch); -static void cstr_cat(CString *cstr, const char *str); -static void cstr_wccat(CString *cstr, int ch); -static void cstr_new(CString *cstr); -static void cstr_free(CString *cstr); -#define cstr_reset(cstr) cstr_free(cstr) -static void add_char(CString *cstr, int c); - -static Sym *sym_push2(Sym **ps, int v, int t, long c); -static Sym *sym_find2(Sym *s, int v); -static inline Sym *struct_find(int v); -static inline Sym *sym_find(int v); -static Sym *sym_push(int v, CType *type, int r, int c); -static Sym *global_identifier_push(int v, int t, int c); -static void sym_pop(Sym **ptop, Sym *b); - -BufferedFile *tcc_open(TCCState *s1, const char *filename); -void tcc_close(BufferedFile *bf); -static int tcc_compile(TCCState *s1); - -void expect(const char *msg); -void skip(int c); -static void test_lvalue(void); -void *resolve_sym(TCCState *s1, const char *sym); - -static inline int isid(int c) -{ - return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || c == '_'; -} - -static inline int isnum(int c) -{ - return c >= '0' && c <= '9'; -} - -static inline int isoct(int c) -{ - return c >= '0' && c <= '7'; -} - -static inline int toup(int c) -{ - if (c >= 'a' && c <= 'z') - return c - 'a' + 'A'; - else - return c; -} - /********************************************************/ +#ifndef NOTALLINONE +#include "tccpp.c" +#include "tccgen.c" +#include "tccelf.c" +#include "tccrun.c" #ifdef TCC_TARGET_I386 #include "i386-gen.c" #endif - #ifdef TCC_TARGET_ARM #include "arm-gen.c" #endif - #ifdef TCC_TARGET_C67 #include "c67-gen.c" #endif - #ifdef TCC_TARGET_X86_64 #include "x86_64-gen.c" #endif - -#include "tccpp.c" -#include "tccgen.c" - #ifdef CONFIG_TCC_ASM - +#include "tccasm.c" #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 #include "i386-asm.c" #endif - -#include "tccasm.c" -#else -static void asm_instr(void) -{ - error("inline asm() not supported"); -} -static void asm_global_instr(void) -{ - error("inline asm() not supported"); -} #endif - -#include "tccelf.c" - #ifdef TCC_TARGET_COFF #include "tcccoff.c" #endif - #ifdef TCC_TARGET_PE #include "tccpe.c" #endif - -#include "tccrun.c" +#endif /* ALL_IN_ONE */ /********************************************************/ +#ifndef CONFIG_TCC_ASM +ST_FUNC void asm_instr(void) +{ + error("inline asm() not supported"); +} +ST_FUNC void asm_global_instr(void) +{ + error("inline asm() not supported"); +} +#endif + +/********************************************************/ + #ifdef _WIN32 -char *normalize_slashes(char *path) +static char *normalize_slashes(char *path) { char *p; for (p = path; *p; ++p) @@ -369,10 +95,10 @@ char *normalize_slashes(char *path) return path; } -HMODULE tcc_module; +static HMODULE tcc_module; /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */ -void tcc_set_lib_path_w32(TCCState *s) +static void tcc_set_lib_path_w32(TCCState *s) { char path[1024], *p; GetModuleFileNameA(tcc_module, path, sizeof path); @@ -396,18 +122,8 @@ BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) #endif /********************************************************/ - -/* we use our own 'finite' function to avoid potential problems with - non standard math libs */ -/* XXX: endianness dependent */ -int ieee_finite(double d) -{ - int *p = (int *)&d; - return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; -} - /* copy a string and truncate it. */ -char *pstrcpy(char *buf, int buf_size, const char *s) +PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) { char *q, *q_end; int c; @@ -427,7 +143,7 @@ char *pstrcpy(char *buf, int buf_size, const char *s) } /* strcat and truncate. */ -char *pstrcat(char *buf, int buf_size, const char *s) +PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s) { int len; len = strlen(buf); @@ -437,7 +153,7 @@ char *pstrcat(char *buf, int buf_size, const char *s) } /* extract the basename of a file */ -char *tcc_basename(const char *name) +PUB_FUNC char *tcc_basename(const char *name) { char *p = strchr(name, 0); while (p > name && !IS_PATHSEP(p[-1])) @@ -445,21 +161,27 @@ char *tcc_basename(const char *name) return p; } -char *tcc_fileextension (const char *name) +PUB_FUNC char *tcc_fileextension (const char *name) { char *b = tcc_basename(name); char *e = strrchr(b, '.'); return e ? e : strchr(b, 0); } +/********************************************************/ /* memory management */ + +#undef free +#undef malloc +#undef realloc + #ifdef MEM_DEBUG int mem_cur_size; int mem_max_size; unsigned malloc_usable_size(void*); #endif -void tcc_free(void *ptr) +PUB_FUNC void tcc_free(void *ptr) { #ifdef MEM_DEBUG mem_cur_size -= malloc_usable_size(ptr); @@ -467,7 +189,7 @@ void tcc_free(void *ptr) free(ptr); } -void *tcc_malloc(unsigned long size) +PUB_FUNC void *tcc_malloc(unsigned long size) { void *ptr; ptr = malloc(size); @@ -481,7 +203,7 @@ void *tcc_malloc(unsigned long size) return ptr; } -void *tcc_mallocz(unsigned long size) +PUB_FUNC void *tcc_mallocz(unsigned long size) { void *ptr; ptr = tcc_malloc(size); @@ -489,7 +211,7 @@ void *tcc_mallocz(unsigned long size) return ptr; } -void *tcc_realloc(void *ptr, unsigned long size) +PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) { void *ptr1; #ifdef MEM_DEBUG @@ -505,7 +227,7 @@ void *tcc_realloc(void *ptr, unsigned long size) return ptr1; } -char *tcc_strdup(const char *str) +PUB_FUNC char *tcc_strdup(const char *str) { char *ptr; ptr = tcc_malloc(strlen(str) + 1); @@ -513,7 +235,7 @@ char *tcc_strdup(const char *str) return ptr; } -void tcc_memstats(void) +PUB_FUNC void tcc_memstats(void) { #ifdef MEM_DEBUG printf("memory in use: %d\n", mem_cur_size); @@ -524,7 +246,10 @@ void tcc_memstats(void) #define malloc(s) use_tcc_malloc(s) #define realloc(p, s) use_tcc_realloc(p, s) -void dynarray_add(void ***ptab, int *nb_ptr, void *data) +/********************************************************/ +/* dynarrays */ + +PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data) { int nb, nb_alloc; void **pp; @@ -546,7 +271,7 @@ void dynarray_add(void ***ptab, int *nb_ptr, void *data) *nb_ptr = nb; } -void dynarray_reset(void *pp, int *n) +PUB_FUNC void dynarray_reset(void *pp, int *n) { void **p; for (p = *(void***)pp; *n; ++p, --*n) @@ -556,43 +281,18 @@ void dynarray_reset(void *pp, int *n) *(void**)pp = NULL; } -/* symbol allocator */ -static Sym *__sym_malloc(void) +/* 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) { - Sym *sym_pool, *sym, *last_sym; - int i; - - sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym)); - dynarray_add(&sym_pools, &nb_sym_pools, sym_pool); - - last_sym = sym_free_first; - sym = sym_pool; - for(i = 0; i < SYM_POOL_NB; i++) { - sym->next = last_sym; - last_sym = sym; - sym++; - } - sym_free_first = last_sym; - return last_sym; + int *p = (int *)&d; + return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; } -static inline Sym *sym_malloc(void) -{ - Sym *sym; - sym = sym_free_first; - if (!sym) - sym = __sym_malloc(); - sym_free_first = sym->next; - return sym; -} +/********************************************************/ -static inline void sym_free(Sym *sym) -{ - sym->next = sym_free_first; - sym_free_first = sym; -} - -Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) +ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) { Section *sec; @@ -633,7 +333,7 @@ static void free_section(Section *s) } /* realloc section and set its content to zero */ -static void section_realloc(Section *sec, unsigned long new_size) +ST_FUNC void section_realloc(Section *sec, unsigned long new_size) { unsigned long size; unsigned char *data; @@ -653,7 +353,7 @@ static void section_realloc(Section *sec, unsigned long new_size) /* reserve at least 'size' bytes in section 'sec' from sec->data_offset. */ -static void *section_ptr_add(Section *sec, unsigned long size) +ST_FUNC void *section_ptr_add(Section *sec, unsigned long size) { unsigned long offset, offset1; @@ -667,7 +367,7 @@ static void *section_ptr_add(Section *sec, unsigned long size) /* return a reference to a section, and create it if it does not exists */ -Section *find_section(TCCState *s1, const char *name) +ST_FUNC Section *find_section(TCCState *s1, const char *name) { Section *sec; int i; @@ -682,7 +382,7 @@ Section *find_section(TCCState *s1, const char *name) /* update sym->c so that it points to an external symbol in section 'section' with value 'value' */ -static void put_extern_sym2(Sym *sym, Section *section, +ST_FUNC void put_extern_sym2(Sym *sym, Section *section, unsigned long value, unsigned long size, int can_add_underscore) { @@ -779,14 +479,14 @@ static void put_extern_sym2(Sym *sym, Section *section, } } -static void put_extern_sym(Sym *sym, Section *section, +ST_FUNC void put_extern_sym(Sym *sym, Section *section, unsigned long value, unsigned long size) { put_extern_sym2(sym, section, value, size, 1); } /* add a new relocation entry to symbol 'sym' in section 's' */ -static void greloc(Section *s, Sym *sym, unsigned long offset, int type) +ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) { int c = 0; if (sym) { @@ -798,6 +498,8 @@ static void greloc(Section *s, Sym *sym, unsigned long offset, int type) put_elf_reloc(symtab_section, s, offset, type, c); } +/********************************************************/ + static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) { int len; @@ -813,7 +515,7 @@ static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) va_end(ap); } -void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) +static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) { char buf[2048]; BufferedFile **f; @@ -850,7 +552,7 @@ void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) s1->nb_errors++; } -void tcc_set_error_func(TCCState *s, void *error_opaque, +LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, void (*error_func)(void *opaque, const char *msg)) { s->error_opaque = error_opaque; @@ -858,7 +560,7 @@ void tcc_set_error_func(TCCState *s, void *error_opaque, } /* error without aborting current compilation */ -void error_noabort(const char *fmt, ...) +PUB_FUNC void error_noabort(const char *fmt, ...) { TCCState *s1 = tcc_state; va_list ap; @@ -868,7 +570,7 @@ void error_noabort(const char *fmt, ...) va_end(ap); } -void error(const char *fmt, ...) +PUB_FUNC void error(const char *fmt, ...) { TCCState *s1 = tcc_state; va_list ap; @@ -885,12 +587,12 @@ void error(const char *fmt, ...) } } -void expect(const char *msg) +PUB_FUNC void expect(const char *msg) { error("%s expected", msg); } -void warning(const char *fmt, ...) +PUB_FUNC void warning(const char *fmt, ...) { TCCState *s1 = tcc_state; va_list ap; @@ -903,233 +605,10 @@ void warning(const char *fmt, ...) va_end(ap); } -void skip(int c) -{ - if (tok != c) - error("'%c' expected", c); - next(); -} - -static void test_lvalue(void) -{ - if (!(vtop->r & VT_LVAL)) - expect("lvalue"); -} - -/* CString handling */ - -static void cstr_realloc(CString *cstr, int new_size) -{ - int size; - void *data; - - size = cstr->size_allocated; - if (size == 0) - size = 8; /* no need to allocate a too small first string */ - while (size < new_size) - size = size * 2; - data = tcc_realloc(cstr->data_allocated, size); - if (!data) - error("memory full"); - cstr->data_allocated = data; - cstr->size_allocated = size; - cstr->data = data; -} - -/* add a byte */ -static inline void cstr_ccat(CString *cstr, int ch) -{ - int size; - size = cstr->size + 1; - if (size > cstr->size_allocated) - cstr_realloc(cstr, size); - ((unsigned char *)cstr->data)[size - 1] = ch; - cstr->size = size; -} - -static void cstr_cat(CString *cstr, const char *str) -{ - int c; - for(;;) { - c = *str; - if (c == '\0') - break; - cstr_ccat(cstr, c); - str++; - } -} - -/* add a wide char */ -static void cstr_wccat(CString *cstr, int ch) -{ - int size; - size = cstr->size + sizeof(nwchar_t); - if (size > cstr->size_allocated) - cstr_realloc(cstr, size); - *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch; - cstr->size = size; -} - -static void cstr_new(CString *cstr) -{ - memset(cstr, 0, sizeof(CString)); -} - -/* free string and reset it to NULL */ -static void cstr_free(CString *cstr) -{ - tcc_free(cstr->data_allocated); - cstr_new(cstr); -} - -#define cstr_reset(cstr) cstr_free(cstr) - -/* XXX: unicode ? */ -static void add_char(CString *cstr, int c) -{ - if (c == '\'' || c == '\"' || c == '\\') { - /* XXX: could be more precise if char or string */ - cstr_ccat(cstr, '\\'); - } - if (c >= 32 && c <= 126) { - cstr_ccat(cstr, c); - } else { - cstr_ccat(cstr, '\\'); - if (c == '\n') { - cstr_ccat(cstr, 'n'); - } else { - cstr_ccat(cstr, '0' + ((c >> 6) & 7)); - cstr_ccat(cstr, '0' + ((c >> 3) & 7)); - cstr_ccat(cstr, '0' + (c & 7)); - } - } -} - -/* push, without hashing */ -static Sym *sym_push2(Sym **ps, int v, int t, long c) -{ - Sym *s; - s = sym_malloc(); - s->v = v; - s->type.t = t; - s->type.ref = NULL; -#ifdef _WIN64 - s->d = NULL; -#endif - s->c = c; - s->next = NULL; - /* add in stack */ - s->prev = *ps; - *ps = s; - return s; -} - -/* find a symbol and return its associated structure. 's' is the top - of the symbol stack */ -static Sym *sym_find2(Sym *s, int v) -{ - while (s) { - if (s->v == v) - return s; - s = s->prev; - } - return NULL; -} - -/* structure lookup */ -static inline Sym *struct_find(int v) -{ - v -= TOK_IDENT; - if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) - return NULL; - return table_ident[v]->sym_struct; -} - -/* find an identifier */ -static inline Sym *sym_find(int v) -{ - v -= TOK_IDENT; - if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) - return NULL; - return table_ident[v]->sym_identifier; -} - -/* push a given symbol on the symbol stack */ -static Sym *sym_push(int v, CType *type, int r, int c) -{ - Sym *s, **ps; - TokenSym *ts; - - if (local_stack) - ps = &local_stack; - else - ps = &global_stack; - s = sym_push2(ps, v, type->t, c); - s->type.ref = type->ref; - s->r = r; - /* don't record fields or anonymous symbols */ - /* XXX: simplify */ - if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { - /* record symbol in token array */ - ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; - if (v & SYM_STRUCT) - ps = &ts->sym_struct; - else - ps = &ts->sym_identifier; - s->prev_tok = *ps; - *ps = s; - } - return s; -} - -/* push a global identifier */ -static Sym *global_identifier_push(int v, int t, int c) -{ - Sym *s, **ps; - s = sym_push2(&global_stack, v, t, c); - /* don't record anonymous symbol */ - if (v < SYM_FIRST_ANOM) { - ps = &table_ident[v - TOK_IDENT]->sym_identifier; - /* modify the top most local identifier, so that - sym_identifier will point to 's' when popped */ - while (*ps != NULL) - ps = &(*ps)->prev_tok; - s->prev_tok = NULL; - *ps = s; - } - return s; -} - -/* pop symbols until top reaches 'b' */ -static void sym_pop(Sym **ptop, Sym *b) -{ - Sym *s, *ss, **ps; - TokenSym *ts; - int v; - - s = *ptop; - while(s != b) { - ss = s->prev; - v = s->v; - /* remove symbol in token array */ - /* XXX: simplify */ - if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { - ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; - if (v & SYM_STRUCT) - ps = &ts->sym_struct; - else - ps = &ts->sym_identifier; - *ps = s->prev_tok; - } - sym_free(s); - s = ss; - } - *ptop = b; -} - +/********************************************************/ /* I/O layer */ -BufferedFile *tcc_open(TCCState *s1, const char *filename) +ST_FUNC BufferedFile *tcc_open(TCCState *s1, const char *filename) { int fd; BufferedFile *bf; @@ -1159,7 +638,7 @@ BufferedFile *tcc_open(TCCState *s1, const char *filename) return bf; } -void tcc_close(BufferedFile *bf) +ST_FUNC void tcc_close(BufferedFile *bf) { total_lines += bf->line_num; close(bf->fd); @@ -1272,7 +751,7 @@ static int tcc_compile(TCCState *s1) return s1->nb_errors != 0 ? -1 : 0; } -int tcc_compile_string(TCCState *s, const char *str) +LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) { BufferedFile bf1, *bf = &bf1; int ret, len; @@ -1301,7 +780,7 @@ int tcc_compile_string(TCCState *s, const char *str) } /* define a preprocessor symbol. A value can also be provided with the '=' operator */ -void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) +LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) { BufferedFile bf1, *bf = &bf1; @@ -1331,7 +810,7 @@ void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) } /* undefine a preprocessor symbol */ -void tcc_undefine_symbol(TCCState *s1, const char *sym) +LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym) { TokenSym *ts; Sym *s; @@ -1369,7 +848,7 @@ static void tcc_cleanup(void) macro_ptr = NULL; } -TCCState *tcc_new(void) +LIBTCCAPI TCCState *tcc_new(void) { TCCState *s; char buffer[100]; @@ -1477,6 +956,7 @@ TCCState *tcc_new(void) ".dynstrtab", ".dynhashtab", SHF_PRIVATE); s->alacarte_link = 1; + s->nocommon = 1; #ifdef CHAR_IS_UNSIGNED s->char_is_unsigned = 1; @@ -1485,17 +965,15 @@ TCCState *tcc_new(void) /* XXX: currently the PE linker is not ready to support that */ s->leading_underscore = 1; #endif - if (s->section_align == 0) s->section_align = ELF_PAGE_SIZE; - #ifdef TCC_TARGET_I386 s->seg_size = 32; #endif return s; } -void tcc_delete(TCCState *s1) +LIBTCCAPI void tcc_delete(TCCState *s1) { int i; @@ -1533,7 +1011,7 @@ void tcc_delete(TCCState *s1) tcc_free(s1); } -int tcc_add_include_path(TCCState *s1, const char *pathname) +LIBTCCAPI int tcc_add_include_path(TCCState *s1, const char *pathname) { char *pathname1; @@ -1542,7 +1020,7 @@ int tcc_add_include_path(TCCState *s1, const char *pathname) return 0; } -int tcc_add_sysinclude_path(TCCState *s1, const char *pathname) +LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s1, const char *pathname) { char *pathname1; @@ -1668,7 +1146,7 @@ the_end: return ret; } -int tcc_add_file(TCCState *s, const char *filename) +LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) { if (s->output_type == TCC_OUTPUT_PREPROCESS) return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS); @@ -1676,7 +1154,7 @@ int tcc_add_file(TCCState *s, const char *filename) return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR); } -int tcc_add_library_path(TCCState *s, const char *pathname) +LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) { char *pathname1; @@ -1687,7 +1165,7 @@ int tcc_add_library_path(TCCState *s, const char *pathname) /* find and load a dll. Return non zero if not found */ /* XXX: add '-rpath' option support ? */ -static int tcc_add_dll(TCCState *s, const char *filename, int flags) +ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags) { char buf[1024]; int i; @@ -1702,7 +1180,7 @@ static int tcc_add_dll(TCCState *s, const char *filename, int flags) } /* the library name is the same as the argument of the '-l' option */ -int tcc_add_library(TCCState *s, const char *libraryname) +LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) { char buf[1024]; int i; @@ -1728,7 +1206,7 @@ int tcc_add_library(TCCState *s, const char *libraryname) return -1; } -int tcc_add_symbol(TCCState *s, const char *name, void *val) +LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, void *val) { add_elf_sym(symtab_section, (uplong)val, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, @@ -1736,7 +1214,7 @@ int tcc_add_symbol(TCCState *s, const char *name, void *val) return 0; } -int tcc_set_output_type(TCCState *s, int output_type) +LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) { char buf[1024]; @@ -1825,7 +1303,7 @@ static const FlagDef warning_defs[] = { "implicit-function-declaration" }, }; -static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, +ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, const char *name, int value) { int i; @@ -1849,9 +1327,8 @@ static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, return 0; } - /* set/reset a warning */ -int tcc_set_warning(TCCState *s, const char *warning_name, int value) +LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value) { int i; const FlagDef *p; @@ -1876,20 +1353,13 @@ static const FlagDef flag_defs[] = { }; /* set/reset a flag */ -int tcc_set_flag(TCCState *s, const char *flag_name, int value) +PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value) { return set_flag(s, flag_defs, countof(flag_defs), flag_name, value); } -/* set CONFIG_TCCDIR at runtime */ -void tcc_set_lib_path(TCCState *s, const char *path) -{ - tcc_free(s->tcc_lib_path); - s->tcc_lib_path = tcc_strdup(path); -} - -void tcc_print_stats(TCCState *s, int64_t total_time) +PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time) { double tt; tt = (double)total_time / 1000000.0; @@ -1902,3 +1372,17 @@ void tcc_print_stats(TCCState *s, int64_t total_time) tt, (int)(total_lines / tt), total_bytes / tt / 1000000.0); } + +/* set CONFIG_TCCDIR at runtime */ +LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path) +{ + tcc_free(s->tcc_lib_path); + s->tcc_lib_path = tcc_strdup(path); +} + +PUB_FUNC void set_num_callers(int n) +{ +#ifdef CONFIG_TCC_BACKTRACE + num_callers = n; +#endif +} diff --git a/tcc.c b/tcc.c index aeda468..6c12b20 100644 --- a/tcc.c +++ b/tcc.c @@ -18,13 +18,25 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef TCC_USE_LIBTCC +#if defined NOTALLINONE || defined TCC_USE_LIBTCC #include "tcc.h" #else #include "libtcc.c" #endif -void help(void) +static char **files; +static int nb_files, nb_libraries; +static int multiple_files; +static int print_search_dirs; +static int output_type; +static int reloc_output; +static const char *outfile; +static int do_bench = 0; + +#define TCC_OPTION_HAS_ARG 0x0001 +#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ + +static void help(void) { printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n" "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n" @@ -65,18 +77,6 @@ void help(void) ); } -static char **files; -static int nb_files, nb_libraries; -static int multiple_files; -static int print_search_dirs; -static int output_type; -static int reloc_output; -static const char *outfile; -static int do_bench = 0; - -#define TCC_OPTION_HAS_ARG 0x0001 -#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ - typedef struct TCCOption { const char *name; uint16_t index; @@ -213,7 +213,7 @@ static int expand_args(char ***pargv, const char *str) return argc; } -int parse_args(TCCState *s, int argc, char **argv) +static int parse_args(TCCState *s, int argc, char **argv) { int optind; const TCCOption *popt; @@ -304,7 +304,7 @@ int parse_args(TCCState *s, int argc, char **argv) break; #ifdef CONFIG_TCC_BACKTRACE case TCC_OPTION_bt: - num_callers = atoi(optarg); + set_num_callers(atoi(optarg)); break; #endif #ifdef CONFIG_TCC_BCHECK diff --git a/tcc.h b/tcc.h index 16aba53..ea4ae21 100644 --- a/tcc.h +++ b/tcc.h @@ -18,6 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef _TCC_H +#define _TCC_H + #define _GNU_SOURCE #include "config.h" @@ -46,6 +49,7 @@ #include /* getcwd */ #define inline __inline #define inp next_inp +#define dlclose FreeLibrary #ifdef _WIN64 #define uplong unsigned long long #endif @@ -56,6 +60,7 @@ #include #include #include +#include #endif #endif /* !CONFIG_TCCBOOT */ @@ -766,11 +771,11 @@ enum tcc_token { #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \ || defined(__OpenBSD__) /* currently incorrect */ -long double strtold(const char *nptr, char **endptr) +static inline long double strtold(const char *nptr, char **endptr) { return (long double)strtod(nptr, endptr); } -float strtof(const char *nptr, char **endptr) +static inline float strtof(const char *nptr, char **endptr) { return (float)strtod(nptr, endptr); } @@ -790,38 +795,411 @@ extern long double strtold (const char *__nptr, char **__endptr); #define PATHCMP strcmp #endif -void error(const char *fmt, ...); -void error_noabort(const char *fmt, ...); -void warning(const char *fmt, ...); - -void tcc_set_lib_path_w32(TCCState *s); -int tcc_set_flag(TCCState *s, const char *flag_name, int value); -void tcc_print_stats(TCCState *s, int64_t total_time); - -void tcc_free(void *ptr); -void *tcc_malloc(unsigned long size); -void *tcc_mallocz(unsigned long size); -void *tcc_realloc(void *ptr, unsigned long size); -char *tcc_strdup(const char *str); - -char *tcc_basename(const char *name); -char *tcc_fileextension (const char *name); -char *pstrcpy(char *buf, int buf_size, const char *s); -char *pstrcat(char *buf, int buf_size, const char *s); -void dynarray_add(void ***ptab, int *nb_ptr, void *data); -void dynarray_reset(void *pp, int *n); - -/* true if float/double/long double type */ -static inline int is_float(int t) -{ - int bt; - bt = t & VT_BTYPE; - return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT; -} - /* space exlcuding newline */ static inline int is_space(int ch) { return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r'; } +static inline int isid(int c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; +} + +static inline int isnum(int c) +{ + return c >= '0' && c <= '9'; +} + +static inline int isoct(int c) +{ + return c >= '0' && c <= '7'; +} + +static inline int toup(int c) +{ + return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; +} + +#define PUB_FUNC + +#ifndef NOTALLINONE +#define ST_INLN static inline +#define ST_FUNC static +#define ST_DATA static +#else +#define ST_INLN +#define ST_FUNC +#define ST_DATA extern +#endif + +/* ------------ libtcc.c ------------ */ + +/* use GNU C extensions */ +ST_DATA int gnu_ext; +/* use Tiny C extensions */ +ST_DATA int tcc_ext; +/* XXX: get rid of this ASAP */ +ST_DATA struct TCCState *tcc_state; + +#ifdef CONFIG_TCC_BACKTRACE +ST_DATA int num_callers; +ST_DATA const char **rt_bound_error_msg; +ST_DATA void *rt_prog_main; +#endif + +#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */ +#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */ +#define AFF_PREPROCESS 0x0004 /* preprocess file */ + +/* public functions currently used by the tcc main function */ +PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s); +PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s); +PUB_FUNC char *tcc_basename(const char *name); +PUB_FUNC char *tcc_fileextension (const char *name); +PUB_FUNC void tcc_free(void *ptr); +PUB_FUNC void *tcc_malloc(unsigned long size); +PUB_FUNC void *tcc_mallocz(unsigned long size); +PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size); +PUB_FUNC char *tcc_strdup(const char *str); +#define free(p) use_tcc_free(p) +#define malloc(s) use_tcc_malloc(s) +#define realloc(p, s) use_tcc_realloc(p, s) +#undef strdup +#define strdup(s) use_tcc_strdup(s) +PUB_FUNC void tcc_memstats(void); +PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data); +PUB_FUNC void dynarray_reset(void *pp, int *n); +PUB_FUNC void error_noabort(const char *fmt, ...); +PUB_FUNC void error(const char *fmt, ...); +PUB_FUNC void expect(const char *msg); +PUB_FUNC void warning(const char *fmt, ...); + +/* other utilities */ +ST_INLN void cstr_ccat(CString *cstr, int ch); +ST_FUNC void cstr_cat(CString *cstr, const char *str); +ST_FUNC void cstr_wccat(CString *cstr, int ch); +ST_FUNC void cstr_new(CString *cstr); +ST_FUNC void cstr_free(CString *cstr); +ST_FUNC void add_char(CString *cstr, int c); +#define cstr_reset(cstr) cstr_free(cstr) + +ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags); +ST_FUNC void section_realloc(Section *sec, unsigned long new_size); +ST_FUNC void *section_ptr_add(Section *sec, unsigned long size); +ST_FUNC Section *find_section(TCCState *s1, const char *name); + +ST_FUNC void put_extern_sym2(Sym *sym, Section *section, unsigned long value, unsigned long size, int can_add_underscore); +ST_FUNC void put_extern_sym(Sym *sym, Section *section, unsigned long value, unsigned long size); +ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); + +ST_INLN void sym_free(Sym *sym); +ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c); +ST_FUNC Sym *sym_find2(Sym *s, int v); +ST_FUNC Sym *sym_push(int v, CType *type, int r, int c); +ST_FUNC void sym_pop(Sym **ptop, Sym *b); +ST_INLN Sym *struct_find(int v); +ST_INLN Sym *sym_find(int v); +ST_FUNC Sym *global_identifier_push(int v, int t, int c); + +ST_FUNC BufferedFile *tcc_open(TCCState *s1, const char *filename); +ST_FUNC void tcc_close(BufferedFile *bf); +ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags); +PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value); +PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time); +PUB_FUNC void set_num_callers(int n); + +ST_FUNC int ieee_finite(double d); + +/* ------------ tccpp.c ------------ */ + +ST_DATA struct BufferedFile *file; +ST_DATA int ch, tok; +ST_DATA CValue tokc; +ST_DATA int *macro_ptr; +ST_DATA int parse_flags; +ST_DATA int tok_flags; +ST_DATA CString tokcstr; /* current parsed string, if any */ + +/* display benchmark infos */ +ST_DATA int total_lines; +ST_DATA int total_bytes; +ST_DATA int tok_ident; +ST_DATA TokenSym **table_ident; + +#define TOK_FLAG_BOL 0x0001 /* beginning of line before */ +#define TOK_FLAG_BOF 0x0002 /* beginning of file before */ +#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */ +#define TOK_FLAG_EOF 0x0008 /* end of file */ + +#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */ +#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */ +#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a + token. line feed is also + returned at eof */ +#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ +#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ + +ST_FUNC TokenSym *tok_alloc(const char *str, int len); +ST_FUNC char *get_tok_str(int v, CValue *cv); +ST_FUNC void save_parse_state(ParseState *s); +ST_FUNC void restore_parse_state(ParseState *s); +ST_INLN void tok_str_new(TokenString *s); +ST_FUNC void tok_str_free(int *str); +ST_FUNC void tok_str_add(TokenString *s, int t); +ST_FUNC void tok_str_add_tok(TokenString *s); +ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg); +ST_FUNC void define_undef(Sym *s); +ST_INLN Sym *define_find(int v); +ST_FUNC void free_defines(Sym *b); +ST_FUNC Sym *label_find(int v); +ST_FUNC Sym *label_push(Sym **ptop, int v, int flags); +ST_FUNC void label_pop(Sym **ptop, Sym *slast); +ST_FUNC void parse_define(void); +ST_FUNC void preprocess(int is_bof); +ST_FUNC void next_nomacro(void); +ST_FUNC void next(void); +ST_INLN void unget_tok(int last_tok); +ST_FUNC void preprocess_init(TCCState *s1); +ST_FUNC void preprocess_new(); +ST_FUNC int tcc_preprocess(TCCState *s1); +ST_FUNC void skip(int c); + +/* ------------ tccgen.c ------------ */ + +ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ +ST_DATA Section *cur_text_section; /* current section where function code is generated */ +#ifdef CONFIG_TCC_ASM +ST_DATA Section *last_text_section; /* to handle .previous asm directive */ +#endif +#ifdef CONFIG_TCC_BCHECK +/* bound check related sections */ +ST_DATA Section *bounds_section; /* contains global data bound description */ +ST_DATA Section *lbounds_section; /* contains local data bound description */ +#endif +/* symbol sections */ +ST_DATA Section *symtab_section, *strtab_section; +/* debug sections */ +ST_DATA Section *stab_section, *stabstr_section; + +#define SYM_POOL_NB (8192 / sizeof(Sym)) +ST_DATA Sym *sym_free_first; +ST_DATA void **sym_pools; +ST_DATA int nb_sym_pools; + +ST_DATA Sym *global_stack; +ST_DATA Sym *local_stack; +ST_DATA Sym *local_label_stack; +ST_DATA Sym *global_label_stack; +ST_DATA Sym *define_stack; +ST_DATA CType char_pointer_type, func_old_type, int_type; +ST_DATA SValue vstack[VSTACK_SIZE], *vtop; +ST_DATA int rsym, anon_sym, ind, loc; + +ST_DATA int const_wanted; /* true if constant wanted */ +ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ +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_vc; +ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ +ST_DATA char *funcname; + +ST_INLN int is_float(int t); +ST_FUNC void test_lvalue(void); +ST_FUNC void swap(int *p, int *q); +ST_FUNC void vpushi(int v); +ST_FUNC Sym *external_global_sym(int v, CType *type, int r); +ST_FUNC void vset(CType *type, int r, int v); +ST_FUNC void vswap(void); +ST_FUNC void save_reg(int r); +ST_FUNC int get_reg(int rc); +ST_FUNC void save_regs(int n); +ST_FUNC int gv(int rc); +ST_FUNC void gv2(int rc1, int rc2); +ST_FUNC void vpop(void); +ST_FUNC void gen_op(int op); +ST_FUNC int type_size(CType *type, int *a); +ST_FUNC void mk_pointer(CType *type); +ST_FUNC void vstore(void); +ST_FUNC void inc(int post, int c); +ST_FUNC int lvalue_type(int t); +ST_FUNC void indir(void); +ST_FUNC void unary(void); +ST_FUNC void expr_prod(void); +ST_FUNC void expr_sum(void); +ST_FUNC void gexpr(void); +ST_FUNC int expr_const(void); +ST_FUNC void gen_inline_functions(void); +ST_FUNC void decl(int l); +#ifdef CONFIG_TCC_BCHECK +ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size); +#endif + +/* ------------ tccelf.c ------------ */ + +#define ARMAG "!\012" /* For COFF and a.out archives */ + +typedef struct { + unsigned int n_strx; /* index into string table of name */ + unsigned char n_type; /* type of symbol */ + unsigned char n_other; /* misc info (usually empty) */ + unsigned short n_desc; /* description field */ + unsigned int n_value; /* value of symbol */ +} Stab_Sym; + +ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags); + +ST_FUNC int put_elf_str(Section *s, const char *sym); +ST_FUNC int put_elf_sym(Section *s, unsigned long value, unsigned long size, int info, int other, int shndx, const char *name); +ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size, int info, int other, int sh_num, const char *name); +ST_FUNC int find_elf_sym(Section *s, const char *name); +ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); + +ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); +ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); +ST_FUNC void put_stabn(int type, int other, int desc, int value); +ST_FUNC void put_stabd(int type, int other, int desc); + +ST_FUNC void relocate_common_syms(void); +ST_FUNC void relocate_syms(TCCState *s1, int do_resolve); +ST_FUNC void relocate_section(TCCState *s1, Section *s); + +ST_FUNC void tcc_add_linker_symbols(TCCState *s1); +ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); +ST_FUNC int tcc_load_archive(TCCState *s1, int fd); +ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); +ST_FUNC void tcc_add_bcheck(TCCState *s1); + +ST_FUNC void build_got_entries(TCCState *s1); +ST_FUNC void tcc_add_runtime(TCCState *s1); + +#ifndef TCC_TARGET_PE +ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); +ST_FUNC int tcc_load_ldscript(TCCState *s1); +ST_FUNC uint8_t *parse_comment(uint8_t *p); +ST_FUNC void minp(void); +ST_INLN void inp(void); +ST_FUNC int handle_eob(void); +#endif + +/* ------------ xxx-gen.c ------------ */ + +ST_FUNC void gsym_addr(int t, int a); +ST_FUNC void gsym(int t); +ST_FUNC void load(int r, SValue *sv); +ST_FUNC void store(int r, SValue *v); +ST_FUNC void gfunc_call(int nb_args); +ST_FUNC void gfunc_prolog(CType *func_type); +ST_FUNC void gfunc_epilog(void); +ST_FUNC int gjmp(int t); +ST_FUNC void gjmp_addr(int a); +ST_FUNC int gtst(int inv, int t); +ST_FUNC void gen_opi(int op); +ST_FUNC void gen_opf(int op); +ST_FUNC void gen_cvt_ftoi(int t); +ST_FUNC void gen_cvt_ftof(int t); +ST_FUNC void ggoto(void); +#ifndef TCC_TARGET_C67 +ST_FUNC void o(unsigned int c); +#endif +#ifndef TCC_TARGET_ARM +ST_FUNC void gen_cvt_itof(int t); +#endif + +/* ------------ i386-gen.c ------------ */ +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 +ST_FUNC void g(int c); +ST_FUNC int oad(int c, int s); +ST_FUNC void gen_le16(int c); +ST_FUNC void gen_le32(int c); +ST_FUNC void gen_addr32(int r, Sym *sym, int c); +ST_FUNC void gen_addrpc32(int r, Sym *sym, int c); +#endif + +#ifdef CONFIG_TCC_BCHECK +ST_FUNC void gen_bounded_ptr_add(void); +ST_FUNC void gen_bounded_ptr_deref(void); +#endif + +/* ------------ x86_64-gen.c ------------ */ +#ifdef TCC_TARGET_X86_64 +ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); +#endif + +/* ------------ arm-gen.c ------------ */ +#ifdef TCC_TARGET_ARM +ST_FUNC unsigned long encbranch(int pos,int addr,int fail); +ST_FUNC void gen_cvt_itof1(int t); +#endif + +/* ------------ c67-gen.c ------------ */ +#ifdef TCC_TARGET_C67 +#endif + +/* ------------ tcccoff.c ------------ */ + +#ifdef TCC_TARGET_COFF +ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f); +#endif + +/* ------------ tccasm.c ------------ */ +ST_FUNC void asm_instr(void); +ST_FUNC void asm_global_instr(void); + +#ifdef CONFIG_TCC_ASM +ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp); +ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); +ST_FUNC int asm_int_expr(TCCState *s1); +ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess); +/* ------------ i386-asm.c ------------ */ +ST_FUNC void gen_expr32(ExprValue *pe); +ST_FUNC void asm_opcode(TCCState *s1, int opcode); +ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg); +ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier); +ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg); +ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str); +#endif +/* ------------ tccpe.c -------------- */ +#ifdef TCC_TARGET_PE +ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd); +ST_FUNC int pe_add_dll(struct TCCState *s, const char *libraryname); +ST_FUNC int pe_output_file(TCCState * s1, const char *filename); +ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)); +/* tiny_impdef.c */ +ST_FUNC char *get_export_names(FILE *fp); +#endif + +/* ------------ tccrun.c ----------------- */ +#if !defined CONFIG_TCC_STATIC && !defined _WIN32 +ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol); +#endif + +/********************************************************/ +/* include the target specific definitions */ + +#define TARGET_DEFS_ONLY +#ifdef TCC_TARGET_I386 +#include "i386-gen.c" +#endif +#ifdef TCC_TARGET_X86_64 +#include "x86_64-gen.c" +#endif +#ifdef TCC_TARGET_ARM +#include "arm-gen.c" +#endif +#ifdef TCC_TARGET_C67 +#include "c67-gen.c" +#endif +#undef TARGET_DEFS_ONLY + +ST_DATA const int reg_classes[NB_REGS]; + +/********************************************************/ +#undef ST_DATA +#ifndef NOTALLINONE +#define ST_DATA static +#else +#define ST_DATA +#endif +/********************************************************/ +#endif /* _TCC_H */ diff --git a/tccasm.c b/tccasm.c index 56bf6cd..28161be 100644 --- a/tccasm.c +++ b/tccasm.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -static int asm_get_local_label_name(TCCState *s1, unsigned int n) +#include "tcc.h" + +ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n) { char buf[64]; TokenSym *ts; @@ -28,7 +30,7 @@ static int asm_get_local_label_name(TCCState *s1, unsigned int n) return ts->tok; } -static void asm_expr(TCCState *s1, ExprValue *pe); +ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); /* We do not use the C expression parser to handle symbols. Maybe the C expression parser could be tweaked to do so. */ @@ -238,12 +240,12 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe) } } -static void asm_expr(TCCState *s1, ExprValue *pe) +ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe) { asm_expr_sum(s1, pe); } -static int asm_int_expr(TCCState *s1) +ST_FUNC int asm_int_expr(TCCState *s1) { ExprValue e; asm_expr(s1, &e); @@ -699,7 +701,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) } /* Assemble the current file */ -static int tcc_assemble(TCCState *s1, int do_preprocess) +ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) { Sym *define_start; int ret; @@ -765,7 +767,7 @@ static void tcc_assemble_inline(TCCState *s1, char *str, int len) /* 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 */ -static int find_constraint(ASMOperand *operands, int nb_operands, +ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp) { int index; @@ -916,7 +918,7 @@ static void parse_asm_str(CString *astr) } /* parse the GCC asm() instruction */ -static void asm_instr(void) +ST_FUNC void asm_instr(void) { CString astr, astr1; ASMOperand operands[MAX_ASM_OPERANDS]; @@ -1017,7 +1019,7 @@ static void asm_instr(void) cstr_free(&astr1); } -static void asm_global_instr(void) +ST_FUNC void asm_global_instr(void) { CString astr; diff --git a/tcccoff.c b/tcccoff.c index 0dcbe50..0ab9ace 100644 --- a/tcccoff.c +++ b/tcccoff.c @@ -18,6 +18,8 @@ * 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" #include "coff.h" #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ @@ -73,7 +75,7 @@ typedef struct { unsigned short dummy4; } AUXEF; -int tcc_output_coff(TCCState *s1, FILE *f) +ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) { Section *tcc_sect; SCNHDR *coff_sec; diff --git a/tccelf.c b/tccelf.c index 1b4a804..25d80d7 100644 --- a/tccelf.c +++ b/tccelf.c @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "tcc.h" + #ifdef TCC_TARGET_X86_64 #define ElfW_Rel ElfW(Rela) #define SHT_RELX SHT_RELA @@ -33,7 +35,7 @@ /* XXX: DLL with PLT would only work with x86-64 for now */ //#define TCC_OUTPUT_DLL_WITH_PLT -static int put_elf_str(Section *s, const char *sym) +ST_FUNC int put_elf_str(Section *s, const char *sym) { int offset, len; char *ptr; @@ -95,7 +97,7 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets) } /* return the symbol number */ -static int put_elf_sym(Section *s, +ST_FUNC int put_elf_sym(Section *s, unsigned long value, unsigned long size, int info, int other, int shndx, const char *name) { @@ -145,7 +147,7 @@ static int put_elf_sym(Section *s, /* find global ELF symbol 'name' and return its index. Return 0 if not found. */ -static int find_elf_sym(Section *s, const char *name) +ST_FUNC int find_elf_sym(Section *s, const char *name) { ElfW(Sym) *sym; Section *hs; @@ -185,20 +187,20 @@ static void *get_elf_sym_addr(TCCState *s, const char *name, int err) } /* return elf symbol value */ -void *tcc_get_symbol(TCCState *s, const char *name) +LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name) { return get_elf_sym_addr(s, name, 0); } /* return elf symbol value or error */ -void *tcc_get_symbol_err(TCCState *s, const char *name) +ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name) { return get_elf_sym_addr(s, name, 1); } /* add an elf symbol : check if it is already defined and patch it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ -static int add_elf_sym(Section *s, uplong value, unsigned long size, +ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size, int info, int other, int sh_num, const char *name) { ElfW(Sym) *esym; @@ -272,7 +274,7 @@ static int add_elf_sym(Section *s, uplong value, unsigned long size, } /* put relocation */ -static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, +ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol) { char buf[256]; @@ -301,15 +303,7 @@ static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, /* put stab debug information */ -typedef struct { - unsigned int n_strx; /* index into string table of name */ - unsigned char n_type; /* type of symbol */ - unsigned char n_other; /* misc info (usually empty) */ - unsigned short n_desc; /* description field */ - unsigned int n_value; /* value of symbol */ -} Stab_Sym; - -static void put_stabs(const char *str, int type, int other, int desc, +ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value) { Stab_Sym *sym; @@ -326,7 +320,7 @@ static void put_stabs(const char *str, int type, int other, int desc, sym->n_value = value; } -static void put_stabs_r(const char *str, int type, int other, int desc, +ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index) { put_stabs(str, type, other, desc, value); @@ -335,12 +329,12 @@ static void put_stabs_r(const char *str, int type, int other, int desc, R_DATA_32, sym_index); } -static void put_stabn(int type, int other, int desc, int value) +ST_FUNC void put_stabn(int type, int other, int desc, int value) { put_stabs(NULL, type, other, desc, value); } -static void put_stabd(int type, int other, int desc) +ST_FUNC void put_stabd(int type, int other, int desc) { put_stabs(NULL, type, other, desc, 0); } @@ -410,7 +404,7 @@ static void sort_syms(TCCState *s1, Section *s) } /* relocate common symbols in the .bss section */ -static void relocate_common_syms(void) +ST_FUNC void relocate_common_syms(void) { ElfW(Sym) *sym, *sym_end; unsigned long offset, align; @@ -434,7 +428,7 @@ static void relocate_common_syms(void) /* relocate symbol table, resolve undefined symbols if do_resolve is true and output error if undefined symbol. */ -static void relocate_syms(TCCState *s1, int do_resolve) +ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) { ElfW(Sym) *sym, *esym, *sym_end; int sym_bind, sh_num, sym_index; @@ -513,7 +507,7 @@ static unsigned long add_got_table(TCCState *s1, unsigned long val) #endif /* relocate a given section (CPU dependent) */ -static void relocate_section(TCCState *s1, Section *s) +ST_FUNC void relocate_section(TCCState *s1, Section *s) { Section *sr; ElfW_Rel *rel, *rel_end, *qrel; @@ -1012,7 +1006,7 @@ static void put_got_entry(TCCState *s1, } /* build GOT and PLT entries */ -static void build_got_entries(TCCState *s1) +ST_FUNC void build_got_entries(TCCState *s1) { Section *s, *symtab; ElfW_Rel *rel, *rel_end; @@ -1120,7 +1114,7 @@ static void build_got_entries(TCCState *s1) } } -static Section *new_symtab(TCCState *s1, +ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags) @@ -1186,7 +1180,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) s->sh_num, sym_end); } -static void tcc_add_bcheck(TCCState *s1) +ST_FUNC void tcc_add_bcheck(TCCState *s1) { #ifdef CONFIG_TCC_BCHECK unsigned long *ptr; @@ -1227,7 +1221,7 @@ static void tcc_add_bcheck(TCCState *s1) } /* add tcc runtime libraries */ -static void tcc_add_runtime(TCCState *s1) +ST_FUNC void tcc_add_runtime(TCCState *s1) { tcc_add_bcheck(s1); @@ -1252,7 +1246,7 @@ static void tcc_add_runtime(TCCState *s1) /* add various standard linker symbols (must be done after the sections are filled (for example after allocating common symbols)) */ -static void tcc_add_linker_symbols(TCCState *s1) +ST_FUNC void tcc_add_linker_symbols(TCCState *s1) { char buf[1024]; int i; @@ -1371,7 +1365,7 @@ void patch_dynsym_undef(TCCState *s1, Section *s) /* output an ELF file */ /* XXX: suppress unneeded sections */ -int elf_output_file(TCCState *s1, const char *filename) +static int elf_output_file(TCCState *s1, const char *filename) { ElfW(Ehdr) ehdr; FILE *f; @@ -2110,7 +2104,7 @@ int elf_output_file(TCCState *s1, const char *filename) return ret; } -int tcc_output_file(TCCState *s, const char *filename) +LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) { int ret; #ifdef TCC_TARGET_PE @@ -2143,7 +2137,7 @@ typedef struct SectionMergeInfo { /* load an object file and merge it with current files */ /* XXX: handle correctly stab (debug) info */ -static int tcc_load_object_file(TCCState *s1, +ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset) { ElfW(Ehdr) ehdr; @@ -2412,8 +2406,6 @@ static int tcc_load_object_file(TCCState *s1, return ret; } -#define ARMAG "!\012" /* For COFF and a.out archives */ - typedef struct ArchiveHeader { char ar_name[16]; /* name of this member */ char ar_date[12]; /* file mtime */ @@ -2474,7 +2466,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size) } /* load a '.a' file */ -static int tcc_load_archive(TCCState *s1, int fd) +ST_FUNC int tcc_load_archive(TCCState *s1, int fd) { ArchiveHeader hdr; char ar_size[11]; @@ -2529,7 +2521,7 @@ static int tcc_load_archive(TCCState *s1, int fd) /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL is referenced by the user (so it should be added as DT_NEEDED in the generated ELF file) */ -static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) +ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) { ElfW(Ehdr) ehdr; ElfW(Shdr) *shdr, *sh, *sh1; @@ -2802,7 +2794,7 @@ static int ld_add_file_list(TCCState *s1, int as_needed) /* interpret a subset of GNU ldscripts to handle the dummy libc.so files */ -static int tcc_load_ldscript(TCCState *s1) +ST_FUNC int tcc_load_ldscript(TCCState *s1) { char cmd[64]; char filename[1024]; diff --git a/tccgen.c b/tccgen.c index 9866c55..af1abc1 100644 --- a/tccgen.c +++ b/tccgen.c @@ -18,7 +18,244 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -void swap(int *p, int *q) +#include "tcc.h" + +/********************************************************/ +/* global variables */ + +/* loc : local variable index + ind : output code index + rsym: return symbol + anon_sym: anonymous symbol index +*/ +ST_DATA int rsym, anon_sym, ind, loc; + +ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ +ST_DATA Section *cur_text_section; /* current section where function code is generated */ +#ifdef CONFIG_TCC_ASM +ST_DATA Section *last_text_section; /* to handle .previous asm directive */ +#endif +#ifdef CONFIG_TCC_BCHECK +/* bound check related sections */ +ST_DATA Section *bounds_section; /* contains global data bound description */ +ST_DATA Section *lbounds_section; /* contains local data bound description */ +#endif +/* symbol sections */ +ST_DATA Section *symtab_section, *strtab_section; +/* debug sections */ +ST_DATA Section *stab_section, *stabstr_section; +ST_DATA Sym *sym_free_first; +ST_DATA void **sym_pools; +ST_DATA int nb_sym_pools; + +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; + +ST_DATA SValue vstack[VSTACK_SIZE], *vtop; + +ST_DATA int const_wanted; /* true if constant wanted */ +ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ +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_vc; +ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ +ST_DATA char *funcname; + +ST_DATA CType char_pointer_type, func_old_type, int_type; + +/* ------------------------------------------------------------------------- */ +static void gen_cast(CType *type); +static inline CType *pointed_type(CType *type); +static int is_compatible_types(CType *type1, CType *type2); +static int parse_btype(CType *type, AttributeDef *ad); +static void type_decl(CType *type, AttributeDef *ad, int *v, int td); +static void parse_expr_type(CType *type); +static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only); +static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg, int is_expr); +static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); +static void expr_eq(void); +static void unary_type(CType *type); +static int is_compatible_parameter_types(CType *type1, CType *type2); +static void expr_type(CType *type); + +ST_INLN int is_float(int t) +{ + int bt; + bt = t & VT_BTYPE; + return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT; +} + +ST_FUNC void test_lvalue(void) +{ + if (!(vtop->r & VT_LVAL)) + expect("lvalue"); +} + +/* ------------------------------------------------------------------------- */ +/* symbol allocator */ +static Sym *__sym_malloc(void) +{ + Sym *sym_pool, *sym, *last_sym; + int i; + + sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym)); + dynarray_add(&sym_pools, &nb_sym_pools, sym_pool); + + last_sym = sym_free_first; + sym = sym_pool; + for(i = 0; i < SYM_POOL_NB; i++) { + sym->next = last_sym; + last_sym = sym; + sym++; + } + sym_free_first = last_sym; + return last_sym; +} + +static inline Sym *sym_malloc(void) +{ + Sym *sym; + sym = sym_free_first; + if (!sym) + sym = __sym_malloc(); + sym_free_first = sym->next; + return sym; +} + +ST_INLN void sym_free(Sym *sym) +{ + sym->next = sym_free_first; + sym_free_first = sym; +} + +/* push, without hashing */ +ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) +{ + Sym *s; + s = sym_malloc(); + s->v = v; + s->type.t = t; + s->type.ref = NULL; +#ifdef _WIN64 + s->d = NULL; +#endif + s->c = c; + s->next = NULL; + /* add in stack */ + s->prev = *ps; + *ps = s; + return s; +} + +/* 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) +{ + while (s) { + if (s->v == v) + return s; + s = s->prev; + } + return NULL; +} + +/* structure lookup */ +ST_INLN Sym *struct_find(int v) +{ + v -= TOK_IDENT; + if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) + return NULL; + return table_ident[v]->sym_struct; +} + +/* find an identifier */ +ST_INLN Sym *sym_find(int v) +{ + v -= TOK_IDENT; + if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) + return NULL; + return table_ident[v]->sym_identifier; +} + +/* push a given symbol on the symbol stack */ +ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) +{ + Sym *s, **ps; + TokenSym *ts; + + if (local_stack) + ps = &local_stack; + else + ps = &global_stack; + s = sym_push2(ps, v, type->t, c); + s->type.ref = type->ref; + s->r = r; + /* don't record fields or anonymous symbols */ + /* XXX: simplify */ + if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { + /* record symbol in token array */ + ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; + if (v & SYM_STRUCT) + ps = &ts->sym_struct; + else + ps = &ts->sym_identifier; + s->prev_tok = *ps; + *ps = s; + } + return s; +} + +/* push a global identifier */ +ST_FUNC Sym *global_identifier_push(int v, int t, int c) +{ + Sym *s, **ps; + s = sym_push2(&global_stack, v, t, c); + /* don't record anonymous symbol */ + if (v < SYM_FIRST_ANOM) { + ps = &table_ident[v - TOK_IDENT]->sym_identifier; + /* modify the top most local identifier, so that + sym_identifier will point to 's' when popped */ + while (*ps != NULL) + ps = &(*ps)->prev_tok; + s->prev_tok = NULL; + *ps = s; + } + return s; +} + +/* pop symbols until top reaches 'b' */ +ST_FUNC void sym_pop(Sym **ptop, Sym *b) +{ + Sym *s, *ss, **ps; + TokenSym *ts; + int v; + + s = *ptop; + while(s != b) { + ss = s->prev; + v = s->v; + /* remove symbol in token array */ + /* XXX: simplify */ + if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { + ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; + if (v & SYM_STRUCT) + ps = &ts->sym_struct; + else + ps = &ts->sym_identifier; + *ps = s->prev_tok; + } + sym_free(s); + s = ss; + } + *ptop = b; +} + +/* ------------------------------------------------------------------------- */ + +ST_FUNC void swap(int *p, int *q) { int t; t = *p; @@ -26,7 +263,7 @@ void swap(int *p, int *q) *q = t; } -void vsetc(CType *type, int r, CValue *vc) +static void vsetc(CType *type, int r, CValue *vc) { int v; @@ -48,7 +285,7 @@ void vsetc(CType *type, int r, CValue *vc) } /* push integer constant */ -void vpushi(int v) +ST_FUNC void vpushi(int v) { CValue cval; cval.i = v; @@ -56,7 +293,7 @@ void vpushi(int v) } /* push long long constant */ -void vpushll(long long v) +static void vpushll(long long v) { CValue cval; CType ctype; @@ -67,8 +304,7 @@ void vpushll(long long v) } /* Return a static symbol pointing to a section */ -static Sym *get_sym_ref(CType *type, Section *sec, - unsigned long offset, unsigned long size) +ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) { int v; Sym *sym; @@ -92,7 +328,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' */ -static Sym *external_global_sym(int v, CType *type, int r) +ST_FUNC Sym *external_global_sym(int v, CType *type, int r) { Sym *s; @@ -139,7 +375,7 @@ static void vpush_global_sym(CType *type, int v) vtop->sym = sym; } -void vset(CType *type, int r, int v) +ST_FUNC void vset(CType *type, int r, int v) { CValue cval; @@ -147,7 +383,7 @@ void vset(CType *type, int r, int v) vsetc(type, r, &cval); } -void vseti(int r, int v) +static void vseti(int r, int v) { CType type; type.t = VT_INT; @@ -155,7 +391,7 @@ void vseti(int r, int v) vset(&type, r, v); } -void vswap(void) +ST_FUNC void vswap(void) { SValue tmp; @@ -164,7 +400,7 @@ void vswap(void) vtop[-1] = tmp; } -void vpushv(SValue *v) +static void vpushv(SValue *v) { if (vtop >= vstack + (VSTACK_SIZE - 1)) error("memory full"); @@ -172,13 +408,13 @@ void vpushv(SValue *v) *vtop = *v; } -void vdup(void) +static void vdup(void) { vpushv(vtop); } /* save r to the memory stack, and mark it as being free */ -void save_reg(int r) +ST_FUNC void save_reg(int r) { int l, saved, size, align; SValue *p, sv; @@ -240,9 +476,10 @@ void save_reg(int r) } } +#ifdef TCC_TARGET_ARM /* find a register of class 'rc2' with at most one reference on stack. * If none, call get_reg(rc) */ -int get_reg_ex(int rc, int rc2) +ST_FUNC int get_reg_ex(int rc, int rc2) { int r; SValue *p; @@ -262,9 +499,10 @@ int get_reg_ex(int rc, int rc2) } return get_reg(rc); } +#endif /* find a free register of class 'rc'. If none, save one register */ -int get_reg(int rc) +ST_FUNC int get_reg(int rc) { int r; SValue *p; @@ -302,7 +540,7 @@ int get_reg(int rc) } /* save registers up to (vtop - n) stack entry */ -void save_regs(int n) +ST_FUNC void save_regs(int n) { int r; SValue *p, *p1; @@ -317,7 +555,7 @@ void save_regs(int n) /* move register 's' to 'r', and flush previous value of r to memory if needed */ -void move_reg(int r, int s) +static void move_reg(int r, int s) { SValue sv; @@ -331,7 +569,7 @@ void move_reg(int r, int s) } /* get address of vtop (vtop MUST BE an lvalue) */ -void gaddrof(void) +static void gaddrof(void) { vtop->r &= ~VT_LVAL; /* tricky: if saved lvalue, then we can go back to lvalue */ @@ -341,7 +579,7 @@ void gaddrof(void) #ifdef CONFIG_TCC_BCHECK /* generate lvalue bound code */ -void gbound(void) +static void gbound(void) { int lval_type; CType type1; @@ -370,7 +608,7 @@ void gbound(void) /* 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). */ -int gv(int rc) +ST_FUNC int gv(int rc) { int r, rc2, bit_pos, bit_size, size, align, i; @@ -537,7 +775,7 @@ int gv(int rc) } /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ -void gv2(int rc1, int rc2) +ST_FUNC void gv2(int rc1, int rc2) { int v; @@ -569,7 +807,7 @@ void gv2(int rc1, int rc2) } /* wrapper around RC_FRET to return a register by type */ -int rc_fret(int t) +static int rc_fret(int t) { #ifdef TCC_TARGET_X86_64 if (t == VT_LDOUBLE) { @@ -580,7 +818,7 @@ int rc_fret(int t) } /* wrapper around REG_FRET to return a register by type */ -int reg_fret(int t) +static int reg_fret(int t) { #ifdef TCC_TARGET_X86_64 if (t == VT_LDOUBLE) { @@ -591,7 +829,7 @@ int reg_fret(int t) } /* expand long long on stack in two int registers */ -void lexpand(void) +static void lexpand(void) { int u; @@ -607,7 +845,7 @@ void lexpand(void) #ifdef TCC_TARGET_ARM /* expand long long on stack */ -void lexpand_nr(void) +ST_FUNC void lexpand_nr(void) { int u,v; @@ -634,7 +872,7 @@ void lexpand_nr(void) #endif /* build a long long from two ints */ -void lbuild(int t) +static void lbuild(int t) { gv2(RC_INT, RC_INT); vtop[-1].r2 = vtop[0].r; @@ -645,7 +883,7 @@ void lbuild(int t) /* rotate n first stack elements to the bottom I1 ... In -> I2 ... In I1 [top is right] */ -void vrotb(int n) +static void vrotb(int n) { int i; SValue tmp; @@ -659,7 +897,7 @@ void vrotb(int n) /* rotate n first stack elements to the top I1 ... In -> In I1 ... I(n-1) [top is right] */ -void vrott(int n) +static void vrott(int n) { int i; SValue tmp; @@ -687,7 +925,7 @@ void vnrott(int n) #endif /* pop stack value */ -void vpop(void) +ST_FUNC void vpop(void) { int v; v = vtop->r & VT_VALMASK; @@ -706,7 +944,7 @@ void vpop(void) /* convert stack entry to register and duplicate its value in another register */ -void gv_dup(void) +static void gv_dup(void) { int rc, t, r, r1; SValue sv; @@ -753,7 +991,7 @@ void gv_dup(void) #ifndef TCC_TARGET_X86_64 /* generate CPU independent (unsigned) long long operations */ -void gen_opl(int op) +static void gen_opl(int op) { int t, a, b, op1, c, i; int func; @@ -990,7 +1228,7 @@ void gen_opl(int op) /* handle integer constant optimizations and various machine independent opt */ -void gen_opic(int op) +static void gen_opic(int op) { int c1, c2, t1, t2, n; SValue *v1, *v2; @@ -1130,7 +1368,7 @@ void gen_opic(int op) } /* generate a floating point operation with constant propagation */ -void gen_opif(int op) +static void gen_opif(int op) { int c1, c2; SValue *v1, *v2; @@ -1262,7 +1500,7 @@ static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) } /* generic gen_op: handles types problems */ -void gen_op(int op) +ST_FUNC void gen_op(int op) { int u, t1, t2, bt1, bt2, t; CType type1; @@ -1411,7 +1649,7 @@ void gen_op(int op) #ifndef TCC_TARGET_ARM /* generic itof for unsigned long long case */ -void gen_cvt_itof1(int t) +static void gen_cvt_itof1(int t) { if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) { @@ -1435,7 +1673,7 @@ void gen_cvt_itof1(int t) #endif /* generic ftoi for unsigned long long case */ -void gen_cvt_ftoi1(int t) +static void gen_cvt_ftoi1(int t) { int st; @@ -1461,7 +1699,7 @@ void gen_cvt_ftoi1(int t) } /* force char or short cast */ -void force_charshort_cast(int t) +static void force_charshort_cast(int t) { int bits, dbt; dbt = t & VT_BTYPE; @@ -1672,7 +1910,7 @@ static void gen_cast(CType *type) } /* return type size. Put alignment at 'a' */ -static int type_size(CType *type, int *a) +ST_FUNC int type_size(CType *type, int *a) { Sym *s; int bt; @@ -1738,7 +1976,7 @@ static inline CType *pointed_type(CType *type) } /* modify type so that its it is a pointer to type. */ -static void mk_pointer(CType *type) +ST_FUNC void mk_pointer(CType *type) { Sym *s; s = sym_push(SYM_FIELD, type, 0, -1); @@ -1829,7 +2067,7 @@ static int is_compatible_parameter_types(CType *type1, CType *type2) printed in the type */ /* XXX: union */ /* XXX: add array and function pointers */ -void type_to_str(char *buf, int buf_size, +static void type_to_str(char *buf, int buf_size, CType *type, const char *varstr) { int bt, v, t; @@ -2000,7 +2238,7 @@ static void gen_assign_cast(CType *dt) } /* store vtop in lvalue pushed on stack */ -void vstore(void) +ST_FUNC void vstore(void) { int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast; @@ -2161,7 +2399,7 @@ void vstore(void) } /* post defines POST/PRE add. c is the token ++ or -- */ -void inc(int post, int c) +ST_FUNC void inc(int post, int c) { test_lvalue(); vdup(); /* save lvalue */ @@ -2879,7 +3117,7 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) } /* compute the lvalue VT_LVAL_xxx needed to match type t. */ -static int lvalue_type(int t) +ST_FUNC int lvalue_type(int t) { int bt, r; r = VT_LVAL; @@ -2896,7 +3134,7 @@ static int lvalue_type(int t) } /* indirection with full error checking and bound check */ -static void indir(void) +ST_FUNC void indir(void) { if ((vtop->type.t & VT_BTYPE) != VT_PTR) { if ((vtop->type.t & VT_BTYPE) == VT_FUNC) @@ -2976,7 +3214,7 @@ static void vpush_tokc(int t) vsetc(&type, VT_CONST, &tokc); } -static void unary(void) +ST_FUNC void unary(void) { int n, t, align, size, r; CType type; @@ -3444,7 +3682,7 @@ static void uneq(void) } } -static void expr_prod(void) +ST_FUNC void expr_prod(void) { int t; @@ -3457,7 +3695,7 @@ static void expr_prod(void) } } -static void expr_sum(void) +ST_FUNC void expr_sum(void) { int t; @@ -3745,7 +3983,7 @@ static void expr_eq(void) } } -static void gexpr(void) +ST_FUNC void gexpr(void) { while (1) { expr_eq(); @@ -3794,7 +4032,7 @@ static void expr_const1(void) } /* parse an integer constant and return its value. */ -static int expr_const(void) +ST_FUNC int expr_const(void) { int c; expr_const1(); @@ -4848,7 +5086,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, no_alloc: ; } -void put_func_debug(Sym *sym) +static void put_func_debug(Sym *sym) { char buf[512]; @@ -4951,7 +5189,7 @@ static void gen_function(Sym *sym) nocode_wanted = saved_nocode_wanted; } -static void gen_inline_functions(void) +ST_FUNC void gen_inline_functions(void) { Sym *sym; int *str, inline_generated, i; @@ -4994,7 +5232,7 @@ static void gen_inline_functions(void) } /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ -static void decl(int l) +ST_FUNC void decl(int l) { int v, has_init, r; CType type, btype; diff --git a/tccpe.c b/tccpe.c index d603a5e..1b2724d 100644 --- a/tccpe.c +++ b/tccpe.c @@ -18,11 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef TCC_TARGET_PE - -#define ST_FN static -#define ST_DATA static -#define PUB_FN +#include "tcc.h" #ifndef _WIN32 #define stricmp strcasecmp @@ -300,7 +296,7 @@ enum { sec_last }; -ST_DATA const DWORD pe_sec_flags[] = { +static const DWORD pe_sec_flags[] = { 0x60000020, /* ".text" , */ 0xC0000040, /* ".data" , */ 0xC0000080, /* ".bss" , */ @@ -366,7 +362,7 @@ struct pe_info { /* --------------------------------------------*/ -ST_FN const char* get_alt_symbol(char *buffer, const char *symbol) +static const char* get_alt_symbol(char *buffer, const char *symbol) { const char *p; p = strrchr(symbol, '@'); @@ -384,7 +380,7 @@ ST_FN const char* get_alt_symbol(char *buffer, const char *symbol) return buffer; } -ST_FN int pe_find_import(TCCState * s1, const char *symbol) +static int pe_find_import(TCCState * s1, const char *symbol) { char buffer[200]; const char *s; @@ -399,7 +395,7 @@ ST_FN int pe_find_import(TCCState * s1, const char *symbol) /*----------------------------------------------------------------------------*/ -ST_FN int dynarray_assoc(void **pp, int n, int key) +static int dynarray_assoc(void **pp, int n, int key) { int i; for (i = 0; i < n; ++i, ++pp) @@ -415,35 +411,35 @@ ST_FN DWORD umin(DWORD a, DWORD b) } #endif -ST_FN DWORD umax(DWORD a, DWORD b) +static DWORD umax(DWORD a, DWORD b) { return a < b ? b : a; } -ST_FN DWORD pe_file_align(struct pe_info *pe, DWORD n) +static DWORD pe_file_align(struct pe_info *pe, DWORD n) { return (n + (pe->file_align - 1)) & ~(pe->file_align - 1); } -ST_FN DWORD pe_virtual_align(struct pe_info *pe, DWORD n) +static DWORD pe_virtual_align(struct pe_info *pe, DWORD n) { return (n + (pe->section_align - 1)) & ~(pe->section_align - 1); } -ST_FN void pe_align_section(Section *s, int a) +static void pe_align_section(Section *s, int a) { int i = s->data_offset & (a-1); if (i) section_ptr_add(s, a - i); } -ST_FN void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size) +static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size) { hdr->opthdr.DataDirectory[dir].VirtualAddress = addr; hdr->opthdr.DataDirectory[dir].Size = size; } -ST_FN int pe_fwrite(void *data, unsigned len, FILE *fp, DWORD *psum) +static int pe_fwrite(void *data, unsigned len, FILE *fp, DWORD *psum) { if (psum) { DWORD sum = *psum; @@ -458,7 +454,7 @@ ST_FN int pe_fwrite(void *data, unsigned len, FILE *fp, DWORD *psum) return len == fwrite(data, 1, len, fp) ? 0 : -1; } -ST_FN void pe_fpad(FILE *fp, DWORD new_pos) +static void pe_fpad(FILE *fp, DWORD new_pos) { DWORD pos = ftell(fp); while (++pos <= new_pos) @@ -466,7 +462,7 @@ ST_FN void pe_fpad(FILE *fp, DWORD new_pos) } /*----------------------------------------------------------------------------*/ -ST_FN int pe_write(struct pe_info *pe) +static int pe_write(struct pe_info *pe) { static const struct pe_header pe_template = { { @@ -745,7 +741,7 @@ ST_FN int pe_write(struct pe_info *pe) #endif /*----------------------------------------------------------------------------*/ -ST_FN struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index) +static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index) { int i; int dll_index; @@ -777,7 +773,7 @@ found_dll: } /*----------------------------------------------------------------------------*/ -ST_FN void pe_build_imports(struct pe_info *pe) +static void pe_build_imports(struct pe_info *pe) { int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i; DWORD rva_base = pe->thunk->sh_addr - pe->imagebase; @@ -860,14 +856,14 @@ struct pe_sort_sym const char *name; }; -ST_FN int sym_cmp(const void *va, const void *vb) +static int sym_cmp(const void *va, const void *vb) { const char *ca = (*(struct pe_sort_sym**)va)->name; const char *cb = (*(struct pe_sort_sym**)vb)->name; return strcmp(ca, cb); } -ST_FN void pe_build_exports(struct pe_info *pe) +static void pe_build_exports(struct pe_info *pe) { ElfW(Sym) *sym; int sym_index, sym_end; @@ -967,7 +963,7 @@ ST_FN void pe_build_exports(struct pe_info *pe) } /* ------------------------------------------------------------- */ -ST_FN void pe_build_reloc (struct pe_info *pe) +static void pe_build_reloc (struct pe_info *pe) { DWORD offset, block_ptr, addr; int count, i; @@ -1023,7 +1019,7 @@ ST_FN void pe_build_reloc (struct pe_info *pe) } /* ------------------------------------------------------------- */ -ST_FN int pe_section_class(Section *s) +static int pe_section_class(Section *s) { int type, flags; const char *name; @@ -1055,7 +1051,7 @@ ST_FN int pe_section_class(Section *s) return -1; } -ST_FN int pe_assign_addresses (struct pe_info *pe) +static int pe_assign_addresses (struct pe_info *pe) { int i, k, o, c; DWORD addr; @@ -1153,7 +1149,7 @@ ST_FN int pe_assign_addresses (struct pe_info *pe) } /* ------------------------------------------------------------- */ -ST_FN void pe_relocate_rva (struct pe_info *pe, Section *s) +static void pe_relocate_rva (struct pe_info *pe, Section *s) { Section *sr = s->reloc; ElfW_Rel *rel, *rel_end; @@ -1173,6 +1169,7 @@ ST_FN void pe_relocate_rva (struct pe_info *pe, Section *s) } /*----------------------------------------------------------------------------*/ + static int pe_isafunc(int sym_index) { Section *sr = text_section->reloc; @@ -1188,7 +1185,7 @@ static int pe_isafunc(int sym_index) } /*----------------------------------------------------------------------------*/ -ST_FN int pe_check_symbols(struct pe_info *pe) +static int pe_check_symbols(struct pe_info *pe) { ElfW(Sym) *sym; int sym_index, sym_end; @@ -1282,7 +1279,7 @@ ST_FN int pe_check_symbols(struct pe_info *pe) /*----------------------------------------------------------------------------*/ #ifdef PE_PRINT_SECTIONS -ST_FN void pe_print_section(FILE * f, Section * s) +static void pe_print_section(FILE * f, Section * s) { /* just if you'r curious */ BYTE *p, *e, b; @@ -1404,7 +1401,7 @@ ST_FN void pe_print_section(FILE * f, Section * s) fprintf(f, "\n\n"); } -ST_FN void pe_print_sections(TCCState *s1, const char *fname) +static void pe_print_sections(TCCState *s1, const char *fname) { Section *s; FILE *f; @@ -1420,34 +1417,8 @@ ST_FN void pe_print_sections(TCCState *s1, const char *fname) #endif /* ------------------------------------------------------------- */ -/* helper function for load/store to insert one more indirection */ -int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)) -{ - int t; - if ((sv->r & (VT_VALMASK|VT_SYM|VT_CONST)) != (VT_SYM|VT_CONST)) - return 0; - t = sv->sym->type.t; - if (0 == (t & VT_IMPORT)) - return 0; - - sv->sym->type.t = t & ~VT_IMPORT; - //printf("import %x %04x %s\n", t, ind, get_tok_str(sv->sym->v, NULL)); - - *++vtop = *sv; - vtop->type.t &= ~(VT_ARRAY|VT_IMPORT); - mk_pointer(&vtop->type); - indir(); - fn(r, vtop); - --vtop; - - sv->sym->type.t = t; - return 1; -} - -/* ------------------------------------------------------------- */ - -ST_FN int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) +static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) { fseek(fp, offset, 0); return len == fread(buffer, 1, len, fp); @@ -1458,7 +1429,7 @@ ST_FN int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) * as generated by 'windres.exe -O coff ...'. */ -ST_FN int pe_load_res(TCCState *s1, FILE *fp) +static int pe_load_res(TCCState *s1, FILE *fp) { struct pe_rsrc_header hdr; Section *rsrc_section; @@ -1498,14 +1469,14 @@ quit: } /* ------------------------------------------------------------- */ -ST_FN char *trimfront(char *p) +static char *trimfront(char *p) { while (*p && (unsigned char)*p <= ' ') ++p; return p; } -ST_FN char *trimback(char *a, char *e) +static char *trimback(char *a, char *e) { while (e > a && (unsigned char)e[-1] <= ' ') --e; @@ -1513,7 +1484,7 @@ ST_FN char *trimback(char *a, char *e) return a; } -ST_FN char *get_line(char *line, int size, FILE *fp) +static char *get_line(char *line, int size, FILE *fp) { if (NULL == fgets(line, size, fp)) return NULL; @@ -1522,7 +1493,7 @@ ST_FN char *get_line(char *line, int size, FILE *fp) } /* ------------------------------------------------------------- */ -ST_FN int pe_load_def(TCCState *s1, FILE *fp) +static int pe_load_def(TCCState *s1, FILE *fp) { DLLReference *dllref; int state = 0, ret = -1; @@ -1571,7 +1542,7 @@ quit: #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY #include "win32/tools/tiny_impdef.c" -ST_FN int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp) +static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp) { int i = 0; char *p, *q; @@ -1594,7 +1565,7 @@ ST_FN int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp) } /* ------------------------------------------------------------- */ -PUB_FN int pe_load_file(struct TCCState *s1, const char *filename, int fd) +ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd) { FILE *fp = fdopen(dup(fd), "rb"); int ret = -1; @@ -1611,7 +1582,7 @@ PUB_FN int pe_load_file(struct TCCState *s1, const char *filename, int fd) return ret; } -int pe_add_dll(struct TCCState *s, const char *libname) +ST_FUNC int pe_add_dll(struct TCCState *s, const char *libname) { static const char *pat[] = { "%s.def", "lib%s.def", "%s.dll", "lib%s.dll", NULL @@ -1626,6 +1597,32 @@ int pe_add_dll(struct TCCState *s, const char *libname) return -1; } +/* ------------------------------------------------------------- */ +/* helper function for load/store to insert one more indirection */ + +ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)) +{ + int t; + if ((sv->r & (VT_VALMASK|VT_SYM|VT_CONST)) != (VT_SYM|VT_CONST)) + return 0; + t = sv->sym->type.t; + if (0 == (t & VT_IMPORT)) + return 0; + + sv->sym->type.t = t & ~VT_IMPORT; + //printf("import %x %04x %s\n", t, ind, get_tok_str(sv->sym->v, NULL)); + + *++vtop = *sv; + vtop->type.t &= ~(VT_ARRAY|VT_IMPORT); + mk_pointer(&vtop->type); + indir(); + fn(r, vtop); + --vtop; + + sv->sym->type.t = t; + return 1; +} + /* ------------------------------------------------------------- */ #ifdef TCC_TARGET_X86_64 #define PE_STDSYM(n,s) n @@ -1633,7 +1630,7 @@ int pe_add_dll(struct TCCState *s, const char *libname) #define PE_STDSYM(n,s) "_" n s #endif -ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe) +static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe) { const char *start_symbol; unsigned long addr = 0; @@ -1690,7 +1687,7 @@ ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe) pe->start_addr = addr; } -PUB_FN int pe_output_file(TCCState * s1, const char *filename) +ST_FUNC int pe_output_file(TCCState * s1, const char *filename) { int ret; struct pe_info pe; @@ -1780,5 +1777,3 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename) } /* ------------------------------------------------------------- */ -#endif /* def TCC_TARGET_PE */ -/* ------------------------------------------------------------- */ diff --git a/tccpp.c b/tccpp.c index ecdaf17..162d081 100644 --- a/tccpp.c +++ b/tccpp.c @@ -18,6 +18,49 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "tcc.h" + +/********************************************************/ +/* global variables */ + +ST_DATA int tok_flags; +/* additional informations about token */ +#define TOK_FLAG_BOL 0x0001 /* beginning of line before */ +#define TOK_FLAG_BOF 0x0002 /* beginning of file before */ +#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */ +#define TOK_FLAG_EOF 0x0008 /* end of file */ + +ST_DATA int parse_flags; +#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */ +#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */ +#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a + token. line feed is also + returned at eof */ +#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ +#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ + +ST_DATA struct BufferedFile *file; +ST_DATA int ch, tok; +ST_DATA CValue tokc; +ST_DATA int *macro_ptr; +ST_DATA CString tokcstr; /* current parsed string, if any */ + +/* display benchmark infos */ +ST_DATA int total_lines; +ST_DATA int total_bytes; +ST_DATA int tok_ident; +ST_DATA TokenSym **table_ident; + +/* ------------------------------------------------------------------------- */ + +static int *macro_ptr_allocated; +static int *unget_saved_macro_ptr; +static int unget_saved_buffer[TOK_MAX_SIZE + 1]; +static int unget_buffer_enabled; +static TokenSym *hash_ident[TOK_HASH_SIZE]; +static char token_buf[STRING_MAX_SIZE + 1]; +/* true if isid(c) || isnum(c) */ +static unsigned char isidnum_table[256-CH_EOF]; static const char tcc_keywords[] = #define DEF(id, str) str "\0" @@ -30,21 +73,115 @@ static const unsigned char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253" "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; -/* true if isid(c) || isnum(c) */ -static unsigned char isidnum_table[256-CH_EOF]; - - struct macro_level { struct macro_level *prev; int *p; }; -static void next_nomacro(void); +ST_FUNC void next_nomacro(void); static void next_nomacro_spc(void); -static void macro_subst(TokenString *tok_str, Sym **nested_list, - const int *macro_str, struct macro_level **can_read_stream); +static void macro_subst( + TokenString *tok_str, + Sym **nested_list, + const int *macro_str, + struct macro_level **can_read_stream + ); +ST_FUNC void skip(int c) +{ + if (tok != c) + error("'%c' expected", c); + next(); +} +/* ------------------------------------------------------------------------- */ +/* CString handling */ +static void cstr_realloc(CString *cstr, int new_size) +{ + int size; + void *data; + + size = cstr->size_allocated; + if (size == 0) + size = 8; /* no need to allocate a too small first string */ + while (size < new_size) + size = size * 2; + data = tcc_realloc(cstr->data_allocated, size); + if (!data) + error("memory full"); + cstr->data_allocated = data; + cstr->size_allocated = size; + cstr->data = data; +} + +/* add a byte */ +ST_INLN void cstr_ccat(CString *cstr, int ch) +{ + int size; + size = cstr->size + 1; + if (size > cstr->size_allocated) + cstr_realloc(cstr, size); + ((unsigned char *)cstr->data)[size - 1] = ch; + cstr->size = size; +} + +ST_FUNC void cstr_cat(CString *cstr, const char *str) +{ + int c; + for(;;) { + c = *str; + if (c == '\0') + break; + cstr_ccat(cstr, c); + str++; + } +} + +/* add a wide char */ +ST_FUNC void cstr_wccat(CString *cstr, int ch) +{ + int size; + size = cstr->size + sizeof(nwchar_t); + if (size > cstr->size_allocated) + cstr_realloc(cstr, size); + *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch; + cstr->size = size; +} + +ST_FUNC void cstr_new(CString *cstr) +{ + memset(cstr, 0, sizeof(CString)); +} + +/* free string and reset it to NULL */ +ST_FUNC void cstr_free(CString *cstr) +{ + tcc_free(cstr->data_allocated); + cstr_new(cstr); +} + +/* XXX: unicode ? */ +ST_FUNC void add_char(CString *cstr, int c) +{ + if (c == '\'' || c == '\"' || c == '\\') { + /* XXX: could be more precise if char or string */ + cstr_ccat(cstr, '\\'); + } + if (c >= 32 && c <= 126) { + cstr_ccat(cstr, c); + } else { + cstr_ccat(cstr, '\\'); + if (c == '\n') { + cstr_ccat(cstr, 'n'); + } else { + cstr_ccat(cstr, '0' + ((c >> 6) & 7)); + cstr_ccat(cstr, '0' + ((c >> 3) & 7)); + cstr_ccat(cstr, '0' + (c & 7)); + } + } +} + +/* ------------------------------------------------------------------------- */ /* allocate a new token */ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) { @@ -82,7 +219,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c)) /* find a token and add it if not found */ -static TokenSym *tok_alloc(const char *str, int len) +ST_FUNC TokenSym *tok_alloc(const char *str, int len) { TokenSym *ts, **pts; int i; @@ -107,7 +244,7 @@ static TokenSym *tok_alloc(const char *str, int len) /* XXX: buffer overflow */ /* XXX: float tokens */ -char *get_tok_str(int v, CValue *cv) +ST_FUNC char *get_tok_str(int v, CValue *cv) { static char buf[STRING_MAX_SIZE + 1]; static CString cstr_buf; @@ -243,13 +380,13 @@ static int tcc_peekc_slow(BufferedFile *bf) /* return the current character, handling end of block if necessary (but not stray) */ -static int handle_eob(void) +ST_FUNC int handle_eob(void) { return tcc_peekc_slow(file); } /* read next char from current input file and handle end of input buffer */ -static inline void inp(void) +ST_INLN void inp(void) { ch = *(++(file->buf_ptr)); /* end of buffer/file handling */ @@ -334,7 +471,7 @@ static int handle_stray1(uint8_t *p) /* input with '\[\r]\n' handling. Note that this function cannot handle other characters after '\', so you cannot call it inside strings or comments */ -static void minp(void) +ST_FUNC void minp(void) { inp(); if (ch == '\\') @@ -380,7 +517,7 @@ static uint8_t *parse_line_comment(uint8_t *p) } /* C comments */ -static uint8_t *parse_comment(uint8_t *p) +ST_FUNC uint8_t *parse_comment(uint8_t *p) { int c; @@ -537,7 +674,7 @@ static uint8_t *parse_pp_string(uint8_t *p, /* skip block of text until #else, #elif or #endif. skip also pairs of #if/#endif */ -void preprocess_skip(void) +static void preprocess_skip(void) { int a, start_of_line, c, in_warn_or_error; uint8_t *p; @@ -629,7 +766,7 @@ _default: files */ /* save current parse state in 's' */ -void save_parse_state(ParseState *s) +ST_FUNC void save_parse_state(ParseState *s) { s->line_num = file->line_num; s->macro_ptr = macro_ptr; @@ -638,7 +775,7 @@ void save_parse_state(ParseState *s) } /* restore parse state from 's' */ -void restore_parse_state(ParseState *s) +ST_FUNC void restore_parse_state(ParseState *s) { file->line_num = s->line_num; macro_ptr = s->macro_ptr; @@ -677,7 +814,7 @@ static inline int tok_ext_size(int t) /* token string handling */ -static inline void tok_str_new(TokenString *s) +ST_INLN void tok_str_new(TokenString *s) { s->str = NULL; s->len = 0; @@ -685,7 +822,7 @@ static inline void tok_str_new(TokenString *s) s->last_line_num = -1; } -static void tok_str_free(int *str) +ST_FUNC void tok_str_free(int *str) { tcc_free(str); } @@ -707,7 +844,7 @@ static int *tok_str_realloc(TokenString *s) return str; } -static void tok_str_add(TokenString *s, int t) +ST_FUNC void tok_str_add(TokenString *s, int t) { int len, *str; @@ -790,7 +927,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) } /* add the current parse token in token string 's' */ -static void tok_str_add_tok(TokenString *s) +ST_FUNC void tok_str_add_tok(TokenString *s) { CValue cval; @@ -861,7 +998,7 @@ static void tok_str_add_tok(TokenString *s) } /* defines handling */ -static inline void define_push(int v, int macro_type, int *str, Sym *first_arg) +ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) { Sym *s; @@ -872,7 +1009,7 @@ static inline void define_push(int v, int macro_type, int *str, Sym *first_arg) } /* undefined a define symbol. Its name is just set to zero */ -static void define_undef(Sym *s) +ST_FUNC void define_undef(Sym *s) { int v; v = s->v; @@ -881,7 +1018,7 @@ static void define_undef(Sym *s) s->v = 0; } -static inline Sym *define_find(int v) +ST_INLN Sym *define_find(int v) { v -= TOK_IDENT; if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) @@ -890,7 +1027,7 @@ static inline Sym *define_find(int v) } /* free define stack until top reaches 'b' */ -static void free_defines(Sym *b) +ST_FUNC void free_defines(Sym *b) { Sym *top, *top1; int v; @@ -911,7 +1048,7 @@ static void free_defines(Sym *b) } /* label lookup */ -static Sym *label_find(int v) +ST_FUNC Sym *label_find(int v) { v -= TOK_IDENT; if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) @@ -919,7 +1056,7 @@ static Sym *label_find(int v) return table_ident[v]->sym_label; } -static Sym *label_push(Sym **ptop, int v, int flags) +ST_FUNC Sym *label_push(Sym **ptop, int v, int flags) { Sym *s, **ps; s = sym_push2(ptop, v, 0, 0); @@ -938,7 +1075,7 @@ static 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. */ -static void label_pop(Sym **ptop, Sym *slast) +ST_FUNC void label_pop(Sym **ptop, Sym *slast) { Sym *s, *s1; for(s = *ptop; s != slast; s = s1) { @@ -1017,7 +1154,7 @@ static void tok_print(int *str) #endif /* parse after #define */ -static void parse_define(void) +ST_FUNC void parse_define(void) { Sym *s, *first, **ps; int v, t, varg, is_vaargs, spc; @@ -1193,7 +1330,7 @@ static void pragma_parse(TCCState *s1) } /* is_bof is true if first non space token at beginning of file */ -static void preprocess(int is_bof) +ST_FUNC void preprocess(int is_bof) { TCCState *s1 = tcc_state; int i, c, n, saved_parse_flags; @@ -1350,7 +1487,7 @@ static void preprocess(int is_bof) pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf1); file = f; /* add include file debug info */ - if (tcc_state->do_debug) { + if (s1->do_debug) { put_stabs(file->filename, N_BINCL, 0, 0, 0); } tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL; @@ -1598,7 +1735,7 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long #define BN_SIZE 2 /* bn = (bn << shift) | or_val */ -void bn_lshift(unsigned int *bn, int shift, int or_val) +static void bn_lshift(unsigned int *bn, int shift, int or_val) { int i; unsigned int v; @@ -1609,7 +1746,7 @@ void bn_lshift(unsigned int *bn, int shift, int or_val) } } -void bn_zero(unsigned int *bn) +static void bn_zero(unsigned int *bn) { int i; for(i=0;iinclude_stack_ptr = s1->include_stack; /* XXX: move that before to avoid having to initialize @@ -2823,7 +2960,7 @@ static void preprocess_init(TCCState *s1) s1->pack_stack_ptr = s1->pack_stack; } -void preprocess_new() +ST_FUNC void preprocess_new() { int i, c; const char *p, *r; @@ -2852,9 +2989,10 @@ void preprocess_new() } /* Preprocess the current file */ -static int tcc_preprocess(TCCState *s1) +ST_FUNC int tcc_preprocess(TCCState *s1) { Sym *define_start; + BufferedFile *file_ref, **iptr, **iptr_new; int token_seen, line_ref, d; const char *s; @@ -2868,8 +3006,8 @@ static int tcc_preprocess(TCCState *s1) token_seen = 0; line_ref = 0; file_ref = NULL; - iptr = s1->include_stack_ptr; + for (;;) { next(); if (tok == TOK_EOF) { @@ -2904,7 +3042,6 @@ print_line: } fputs(get_tok_str(tok, &tokc), s1->outfile); } - free_defines(define_start); + free_defines(define_start); return 0; } - diff --git a/tccrun.c b/tccrun.c index e984c0f..e88f87e 100644 --- a/tccrun.c +++ b/tccrun.c @@ -1,5 +1,5 @@ /* - * TCC - Tiny C Compiler + * TCC - Tiny C Compiler - Support for -run switch * * Copyright (c) 2001-2004 Fabrice Bellard * @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* tccrun.c - support for tcc -run */ +#include "tcc.h" #ifdef _WIN32 #define ucontext_t CONTEXT @@ -26,7 +26,7 @@ static void set_pages_executable(void *ptr, unsigned long length); static void set_exception_handler(void); -static int rt_get_caller_pc(unsigned long *paddr, ucontext_t *uc, int level); +static int rt_get_caller_pc(uplong *paddr, ucontext_t *uc, int level); static void rt_error(ucontext_t *uc, const char *fmt, ...); static int tcc_relocate_ex(TCCState *s1, void *ptr); @@ -173,8 +173,8 @@ static void set_pages_executable(void *ptr, unsigned long length) VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); #else unsigned long start, end; - start = (unsigned long)ptr & ~(PAGESIZE - 1); - end = (unsigned long)ptr + length; + start = (uplong)ptr & ~(PAGESIZE - 1); + end = (uplong)ptr + length; end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); #endif @@ -185,7 +185,7 @@ static void set_pages_executable(void *ptr, unsigned long length) /* print the position in the source file of PC value 'pc' by reading the stabs debug information */ -static unsigned long rt_printline(unsigned long wanted_pc) +static uplong rt_printline(uplong wanted_pc) { Stab_Sym *sym, *sym_end; char func_name[128], last_func_name[128]; @@ -194,7 +194,7 @@ static unsigned long rt_printline(unsigned long wanted_pc) int incl_index, len, last_line_num, i; const char *str, *p; - fprintf(stderr, "0x%08lx:", wanted_pc); + fprintf(stderr, "0x%08lx:", (unsigned long)wanted_pc); func_name[0] = '\0'; func_addr = 0; @@ -311,7 +311,7 @@ static unsigned long rt_printline(unsigned long wanted_pc) static void rt_error(ucontext_t *uc, const char *fmt, ...) { va_list ap; - unsigned long pc; + uplong pc; int i; va_start(ap, fmt); @@ -327,7 +327,7 @@ static void rt_error(ucontext_t *uc, const char *fmt, ...) else fprintf(stderr, "by "); pc = rt_printline(pc); - if (pc == (unsigned long)rt_prog_main && pc) + if (pc == (uplong)rt_prog_main && pc) break; } exit(255); @@ -505,11 +505,15 @@ static void set_exception_handler(void) SetUnhandledExceptionFilter(cpu_exception_handler); } +#ifdef _WIN64 +#define Eip Rip +#define Ebp Rbp +#endif + /* return the PC at frame level 'level'. Return non zero if not found */ -static int rt_get_caller_pc(unsigned long *paddr, - CONTEXT *uc, int level) +static int rt_get_caller_pc(uplong *paddr, CONTEXT *uc, int level) { - unsigned long fp; + uplong fp; int i; if (level == 0) { @@ -521,13 +525,16 @@ static int rt_get_caller_pc(unsigned long *paddr, /* XXX: check address validity with program info */ if (fp <= 0x1000 || fp >= 0xc0000000) return -1; - fp = ((unsigned long *)fp)[0]; + fp = ((uplong*)fp)[0]; } - *paddr = ((unsigned long *)fp)[1]; + *paddr = ((uplong*)fp)[1]; return 0; } } +#undef Eip +#undef Ebp + #endif /* _WIN32 */ #endif /* CONFIG_TCC_BACKTRACE */ /* ------------------------------------------------------------- */ @@ -584,13 +591,7 @@ void *resolve_sym(TCCState *s1, const char *symbol) return NULL; } -#elif defined(_WIN32) - -#define dlclose FreeLibrary - -#else - -#include +#elif !defined(_WIN32) void *resolve_sym(TCCState *s1, const char *sym) { diff --git a/x86_64-gen.c b/x86_64-gen.c index 86ec4ea..d9f7528 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -20,10 +20,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#ifdef TARGET_DEFS_ONLY /* number of available registers */ -#define NB_REGS 5 +#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 @@ -60,14 +61,6 @@ enum { #define REX_BASE(reg) (((reg) >> 3) & 1) #define REG_VALUE(reg) ((reg) & 7) -const int reg_classes[NB_REGS] = { - /* eax */ RC_INT | RC_RAX, - /* ecx */ RC_INT | RC_RCX, - /* edx */ RC_INT | RC_RDX, - /* xmm0 */ RC_FLOAT | RC_XMM0, - /* st0 */ RC_ST0, -}; - /* return registers for function */ #define REG_IRET TREG_RAX /* single word int return register */ #define REG_LRET TREG_RDX /* second word return register (for long long) */ @@ -85,6 +78,9 @@ const int reg_classes[NB_REGS] = { /* maximum alignment (for aligned attribute support) */ #define MAX_ALIGN 8 +ST_FUNC void gen_opl(int op); +ST_FUNC void gen_le64(int64_t c); + /******************************************************/ /* ELF defines */ @@ -100,6 +96,18 @@ const int reg_classes[NB_REGS] = { #define ELF_PAGE_SIZE 0x1000 /******************************************************/ +#else /* ! TARGET_DEFS_ONLY */ +/******************************************************/ +#include "tcc.h" +#include + +ST_DATA const int reg_classes[NB_REGS] = { + /* eax */ RC_INT | RC_RAX, + /* ecx */ RC_INT | RC_RCX, + /* edx */ RC_INT | RC_RDX, + /* xmm0 */ RC_FLOAT | RC_XMM0, + /* st0 */ RC_ST0, +}; static unsigned long func_sub_sp_offset; static int func_ret_sub; @@ -184,7 +192,7 @@ static int is_sse_float(int t) { } /* instruction + 4 bytes data. Return the address of the data */ -static int oad(int c, int s) +ST_FUNC int oad(int c, int s) { int ind1; @@ -198,7 +206,7 @@ static int oad(int c, int s) return s; } -static void gen_addr32(int r, Sym *sym, int c) +ST_FUNC void gen_addr32(int r, Sym *sym, int c) { if (r & VT_SYM) greloc(cur_text_section, sym, ind, R_X86_64_32); @@ -206,7 +214,7 @@ static void gen_addr32(int r, Sym *sym, int c) } /* output constant with relocation if 'r & VT_SYM' is true */ -static void gen_addr64(int r, Sym *sym, int64_t c) +ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c) { if (r & VT_SYM) greloc(cur_text_section, sym, ind, R_X86_64_64); @@ -214,7 +222,7 @@ static void gen_addr64(int r, Sym *sym, int64_t c) } /* output constant with relocation if 'r & VT_SYM' is true */ -static void gen_addrpc32(int r, Sym *sym, int c) +ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) { if (r & VT_SYM) greloc(cur_text_section, sym, ind, R_X86_64_PC32); @@ -1537,3 +1545,5 @@ void ggoto(void) /* end of x86-64 code generator */ /*************************************************************/ +#endif /* ! TARGET_DEFS_ONLY */ +/******************************************************/