allow tcc be build from separate objects

If you want that, run: make NOTALLINONE=1
master
grischka 2009-12-20 01:53:49 +01:00
parent 7fa712e00c
commit 88a3ccab9f
16 changed files with 1322 additions and 1045 deletions

View File

@ -113,11 +113,13 @@ ifdef CONFIG_CROSS
PROGS+=$(PROGS_CROSS) PROGS+=$(PROGS_CROSS)
endif endif
# NOTALLINONE = 1
all: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc-doc.html tcc.1 libtcc_test$(EXESUF) all: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc-doc.html tcc.1 libtcc_test$(EXESUF)
# Host Tiny C Compiler # Host Tiny C Compiler
tcc$(EXESUF): $(NATIVE_FILES) tcc$(EXESUF): tcc.o libtcc.a
$(CC) -o $@ $< $(NATIVE_TARGET) $(CFLAGS) $(LIBS) $(CC) -o $@ $^ $(LIBS)
# Cross Tiny C Compilers # Cross Tiny C Compilers
i386-tcc$(EXESUF): $(I386_FILES) 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) $(CC) -o $@ $< -DTCC_TARGET_ARM -DTCC_ARM_EABI $(CFLAGS) $(LIBS)
# libtcc generation and test # 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 $@ $^ $(AR) rcs $@ $^
libtcc_test$(EXESUF): tests/libtcc_test.c libtcc.a libtcc_test$(EXESUF): tests/libtcc_test.c libtcc.a
@ -260,19 +274,18 @@ tar:
rm -rf /tmp/$(TCC-VERSION) rm -rf /tmp/$(TCC-VERSION)
# in tests subdir # in tests subdir
test clean: %est:
$(MAKE) -C tests $@ $(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: config.mak:
@echo Running configure ... @echo Running configure ...
@./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),.) endif # ifeq ($(TOP),.)

View File

@ -20,11 +20,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifdef TARGET_DEFS_ONLY
#ifdef TCC_ARM_EABI #ifdef TCC_ARM_EABI
#define TCC_ARM_VFP #define TCC_ARM_VFP
#endif #endif
/* number of available registers */ /* number of available registers */
#ifdef TCC_ARM_VFP #ifdef TCC_ARM_VFP
#define NB_REGS 13 #define NB_REGS 13
@ -75,32 +76,6 @@ enum {
#endif #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 #ifdef TCC_ARM_VFP
#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0) #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
#endif #endif
@ -171,10 +146,42 @@ static CType float_type, double_type, func_float_type, func_double_type;
#define ELF_PAGE_SIZE 0x1000 #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 unsigned long func_sub_sp_offset,last_itod_magic;
static int leaffunc; 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*/ /* this is a good place to start adding big-endian support*/
int ind1; 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-=pos+8;
addr/=4; addr/=4;
@ -1571,7 +1578,7 @@ void gen_opf(int op)
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int' /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
and 'long long' cases. */ and 'long long' cases. */
void gen_cvt_itof1(int t) ST_FUNC void gen_cvt_itof1(int t)
{ {
int r,r2,bt; int r,r2,bt;
bt=vtop->type.t & VT_BTYPE; bt=vtop->type.t & VT_BTYPE;
@ -1732,4 +1739,5 @@ void ggoto(void)
/* end of ARM code generator */ /* end of ARM code generator */
/*************************************************************/ /*************************************************************/
#endif
/*************************************************************/

View File

@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifdef TARGET_DEFS_ONLY
//#define ASSEMBLY_LISTING_C67 //#define ASSEMBLY_LISTING_C67
/* number of available registers */ /* number of available registers */
@ -85,62 +87,18 @@ enum {
TREG_C67_B13, 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 */ /* return registers for function */
#define REG_IRET TREG_C67_A4 /* single word int return register */ #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_LRET TREG_C67_A5 /* second word return register (for long long) */
#define REG_FRET TREG_C67_A4 /* float return register */ #define REG_FRET TREG_C67_A4 /* float return register */
#define ALWAYS_ASSERT(x) \ #define ALWAYS_ASSERT(x) \
do {\ do {\
if (!(x))\ if (!(x))\
error("internal compiler error file at %s:%d", __FILE__, __LINE__);\ error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
} while (0) } 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 */ /* defined if function parameters must be evaluated in reverse order */
//#define INVERT_FUNC_PARAMS //#define INVERT_FUNC_PARAMS
/* defined if structures are passed as pointers. Otherwise structures /* defined if structures are passed as pointers. Otherwise structures
@ -171,7 +129,52 @@ int TotalBytesPushedOnStack;
#define ELF_PAGE_SIZE 0x1000 #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 unsigned long func_sub_sp_offset;
static int func_ret_sub; static int func_ret_sub;
@ -2545,5 +2548,7 @@ void ggoto(void)
vtop--; vtop--;
} }
/* end of X86 code generator */ /* end of C67 code generator */
/*************************************************************/
#endif
/*************************************************************/ /*************************************************************/

View File

@ -19,7 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 MAX_OPERANDS 3
#define NB_SAVED_REGS 3
#define TOK_ASM_first TOK_ASM_clc #define TOK_ASM_first TOK_ASM_clc
#define TOK_ASM_last TOK_ASM_emms #define TOK_ASM_last TOK_ASM_emms
@ -398,7 +402,8 @@ static void parse_operand(TCCState *s1, Operand *op)
op->type |= indir; 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); 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; const ASMInstr *pa;
int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix; 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 #endif
} }
#define NB_SAVED_REGS 3
#define NB_ASM_REGS 8
/* return the constraint priority (we allocate first the lowest /* return the constraint priority (we allocate first the lowest
numbered constraints) */ numbered constraints) */
static inline int constraint_priority(const char *str) 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) #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, int nb_operands, int nb_outputs,
const uint8_t *clobber_regs, const uint8_t *clobber_regs,
int *pout_reg) int *pout_reg)
@ -1262,7 +1264,7 @@ static void asm_compute_constraints(ASMOperand *operands,
#endif #endif
} }
static void subst_asm_operand(CString *add_str, ST_FUNC void subst_asm_operand(CString *add_str,
SValue *sv, int modifier) SValue *sv, int modifier)
{ {
int r, reg, size, val; 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 */ /* 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, int nb_outputs, int is_output,
uint8_t *clobber_regs, uint8_t *clobber_regs,
int out_reg) 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; int reg;
TokenSym *ts; TokenSym *ts;

View File

@ -18,8 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifdef TARGET_DEFS_ONLY
/* number of available registers */ /* 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 /* a register can belong to several classes. The classes must be
sorted from more general to more precise (see gv2() code which does sorted from more general to more precise (see gv2() code which does
@ -42,13 +45,6 @@ enum {
TREG_ST0, 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 */ /* return registers for function */
#define REG_IRET TREG_EAX /* single word int return register */ #define REG_IRET TREG_EAX /* single word int return register */
#define REG_LRET TREG_EDX /* second word return register (for long long) */ #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) */ /* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8 #define MAX_ALIGN 8
#define psym oad
/******************************************************/ /******************************************************/
/* ELF defines */ /* ELF defines */
@ -85,6 +84,16 @@ const int reg_classes[NB_REGS] = {
#define ELF_PAGE_SIZE 0x1000 #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 unsigned long func_sub_sp_offset;
static int func_ret_sub; static int func_ret_sub;
@ -93,7 +102,7 @@ static unsigned long func_bound_offset;
#endif #endif
/* XXX: make it faster ? */ /* XXX: make it faster ? */
void g(int c) ST_FUNC void g(int c)
{ {
int ind1; int ind1;
ind1 = ind + 1; ind1 = ind + 1;
@ -103,7 +112,7 @@ void g(int c)
ind = ind1; ind = ind1;
} }
void o(unsigned int c) ST_FUNC void o(unsigned int c)
{ {
while (c) { while (c) {
g(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);
g(v >> 8); g(v >> 8);
} }
void gen_le32(int c) ST_FUNC void gen_le32(int c)
{ {
g(c); g(c);
g(c >> 8); g(c >> 8);
@ -126,7 +135,7 @@ void gen_le32(int c)
} }
/* output a symbol and patch all calls to it */ /* 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; int n, *ptr;
while (t) { 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); gsym_addr(t, ind);
} }
@ -147,7 +156,7 @@ void gsym(int t)
#define psym oad #define psym oad
/* instruction + 4 bytes data. Return the address of the data */ /* 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; int ind1;
@ -162,14 +171,14 @@ static int oad(int c, int s)
} }
/* output constant with relocation if 'r & VT_SYM' is true */ /* 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) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_386_32); greloc(cur_text_section, sym, ind, R_386_32);
gen_le32(c); 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) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_386_PC32); 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' */ /* 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; int v, t, ft, fc, fr;
SValue v1; SValue v1;
@ -269,7 +278,7 @@ void load(int r, SValue *sv)
} }
/* store register 'r' in lvalue 'v' */ /* 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; 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 /* Generate function call. The function address is pushed first, then
all the parameters in call order. This functions pops all the all the parameters in call order. This functions pops all the
parameters and the function address. */ 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; int size, align, r, args_size, i, func_call;
Sym *func_sym; Sym *func_sym;
@ -442,7 +451,7 @@ void gfunc_call(int nb_args)
#endif #endif
/* generate function prolog of type 't' */ /* 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 addr, align, size, func_call, fastcall_nb_regs;
int param_index, param_addr; int param_index, param_addr;
@ -524,7 +533,7 @@ void gfunc_prolog(CType *func_type)
} }
/* generate function epilog */ /* generate function epilog */
void gfunc_epilog(void) ST_FUNC void gfunc_epilog(void)
{ {
int v, saved_ind; int v, saved_ind;
@ -595,13 +604,13 @@ void gfunc_epilog(void)
} }
/* generate a jump to a label */ /* generate a jump to a label */
int gjmp(int t) ST_FUNC int gjmp(int t)
{ {
return psym(0xe9, t); return psym(0xe9, t);
} }
/* generate a jump to a fixed address */ /* generate a jump to a fixed address */
void gjmp_addr(int a) ST_FUNC void gjmp_addr(int a)
{ {
int r; int r;
r = a - ind - 2; 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 */ /* 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; int v, *p;
@ -659,7 +668,7 @@ int gtst(int inv, int t)
} }
/* generate an integer binary operation */ /* generate an integer binary operation */
void gen_opi(int op) ST_FUNC void gen_opi(int op)
{ {
int r, fr, opc, c; 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 /* generate a floating point operation 'v = t1 op t2' instruction. The
two operands are guaranted to have the same floating point type */ two operands are guaranted to have the same floating point type */
/* XXX: need to use ST1 too */ /* XXX: need to use ST1 too */
void gen_opf(int op) ST_FUNC void gen_opf(int op)
{ {
int a, ft, fc, swapped, r; 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' /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
and 'long long' cases. */ and 'long long' cases. */
void gen_cvt_itof(int t) ST_FUNC void gen_cvt_itof(int t)
{ {
save_reg(TREG_ST0); save_reg(TREG_ST0);
gv(RC_INT); gv(RC_INT);
@ -935,7 +944,7 @@ void gen_cvt_itof(int t)
/* convert fp to int 't' type */ /* convert fp to int 't' type */
/* XXX: handle long long case */ /* XXX: handle long long case */
void gen_cvt_ftoi(int t) ST_FUNC void gen_cvt_ftoi(int t)
{ {
int r, r2, size; int r, r2, size;
Sym *sym; Sym *sym;
@ -986,14 +995,14 @@ void gen_cvt_ftoi(int t)
} }
/* convert from one floating point type to another */ /* 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 */ /* all we have to do on i386 is to put the float in a register */
gv(RC_FLOAT); gv(RC_FLOAT);
} }
/* computed goto support */ /* computed goto support */
void ggoto(void) ST_FUNC void ggoto(void)
{ {
gcall_or_jmp(1); gcall_or_jmp(1);
vtop--; vtop--;
@ -1003,7 +1012,7 @@ void ggoto(void)
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
/* generate a bounded pointer addition */ /* generate a bounded pointer addition */
void gen_bounded_ptr_add(void) ST_FUNC void gen_bounded_ptr_add(void)
{ {
Sym *sym; Sym *sym;
@ -1026,7 +1035,7 @@ void gen_bounded_ptr_add(void)
/* patch pointer addition in vtop so that pointer dereferencing is /* patch pointer addition in vtop so that pointer dereferencing is
also tested */ also tested */
void gen_bounded_ptr_deref(void) ST_FUNC void gen_bounded_ptr_deref(void)
{ {
int func; int func;
int size, align; int size, align;
@ -1068,4 +1077,5 @@ void gen_bounded_ptr_deref(void)
/* end of X86 code generator */ /* end of X86 code generator */
/*************************************************************/ /*************************************************************/
#endif
/*************************************************************/

734
libtcc.c

File diff suppressed because it is too large Load Diff

32
tcc.c
View File

@ -18,13 +18,25 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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" #include "tcc.h"
#else #else
#include "libtcc.c" #include "libtcc.c"
#endif #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" 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" "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 { typedef struct TCCOption {
const char *name; const char *name;
uint16_t index; uint16_t index;
@ -213,7 +213,7 @@ static int expand_args(char ***pargv, const char *str)
return argc; return argc;
} }
int parse_args(TCCState *s, int argc, char **argv) static int parse_args(TCCState *s, int argc, char **argv)
{ {
int optind; int optind;
const TCCOption *popt; const TCCOption *popt;
@ -304,7 +304,7 @@ int parse_args(TCCState *s, int argc, char **argv)
break; break;
#ifdef CONFIG_TCC_BACKTRACE #ifdef CONFIG_TCC_BACKTRACE
case TCC_OPTION_bt: case TCC_OPTION_bt:
num_callers = atoi(optarg); set_num_callers(atoi(optarg));
break; break;
#endif #endif
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK

440
tcc.h
View File

@ -18,6 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef _TCC_H
#define _TCC_H
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h" #include "config.h"
@ -46,6 +49,7 @@
#include <direct.h> /* getcwd */ #include <direct.h> /* getcwd */
#define inline __inline #define inline __inline
#define inp next_inp #define inp next_inp
#define dlclose FreeLibrary
#ifdef _WIN64 #ifdef _WIN64
#define uplong unsigned long long #define uplong unsigned long long
#endif #endif
@ -56,6 +60,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/ucontext.h> #include <sys/ucontext.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <dlfcn.h>
#endif #endif
#endif /* !CONFIG_TCCBOOT */ #endif /* !CONFIG_TCCBOOT */
@ -766,11 +771,11 @@ enum tcc_token {
#elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \ #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
|| defined(__OpenBSD__) || defined(__OpenBSD__)
/* currently incorrect */ /* 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); 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); return (float)strtod(nptr, endptr);
} }
@ -790,38 +795,411 @@ extern long double strtold (const char *__nptr, char **__endptr);
#define PATHCMP strcmp #define PATHCMP strcmp
#endif #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 */ /* space exlcuding newline */
static inline int is_space(int ch) static inline int is_space(int ch)
{ {
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r'; 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 "!<arch>\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 */

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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]; char buf[64];
TokenSym *ts; TokenSym *ts;
@ -28,7 +30,7 @@ static int asm_get_local_label_name(TCCState *s1, unsigned int n)
return ts->tok; 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 /* We do not use the C expression parser to handle symbols. Maybe the
C expression parser could be tweaked to do so. */ 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); asm_expr_sum(s1, pe);
} }
static int asm_int_expr(TCCState *s1) ST_FUNC int asm_int_expr(TCCState *s1)
{ {
ExprValue e; ExprValue e;
asm_expr(s1, &e); asm_expr(s1, &e);
@ -699,7 +701,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
} }
/* Assemble the current file */ /* 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; Sym *define_start;
int ret; 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 /* find a constraint by its number or id (gcc 3 extended
syntax). return -1 if not found. Return in *pp in char after the syntax). return -1 if not found. Return in *pp in char after the
constraint */ 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) const char *name, const char **pp)
{ {
int index; int index;
@ -916,7 +918,7 @@ static void parse_asm_str(CString *astr)
} }
/* parse the GCC asm() instruction */ /* parse the GCC asm() instruction */
static void asm_instr(void) ST_FUNC void asm_instr(void)
{ {
CString astr, astr1; CString astr, astr1;
ASMOperand operands[MAX_ASM_OPERANDS]; ASMOperand operands[MAX_ASM_OPERANDS];
@ -1017,7 +1019,7 @@ static void asm_instr(void)
cstr_free(&astr1); cstr_free(&astr1);
} }
static void asm_global_instr(void) ST_FUNC void asm_global_instr(void)
{ {
CString astr; CString astr;

View File

@ -18,6 +18,8 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "tcc.h"
#include "coff.h" #include "coff.h"
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
@ -73,7 +75,7 @@ typedef struct {
unsigned short dummy4; unsigned short dummy4;
} AUXEF; } AUXEF;
int tcc_output_coff(TCCState *s1, FILE *f) ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
{ {
Section *tcc_sect; Section *tcc_sect;
SCNHDR *coff_sec; SCNHDR *coff_sec;

View File

@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "tcc.h"
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
#define ElfW_Rel ElfW(Rela) #define ElfW_Rel ElfW(Rela)
#define SHT_RELX SHT_RELA #define SHT_RELX SHT_RELA
@ -33,7 +35,7 @@
/* XXX: DLL with PLT would only work with x86-64 for now */ /* XXX: DLL with PLT would only work with x86-64 for now */
//#define TCC_OUTPUT_DLL_WITH_PLT //#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; int offset, len;
char *ptr; char *ptr;
@ -95,7 +97,7 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets)
} }
/* return the symbol number */ /* 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, unsigned long value, unsigned long size,
int info, int other, int shndx, const char *name) 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 /* find global ELF symbol 'name' and return its index. Return 0 if not
found. */ 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; ElfW(Sym) *sym;
Section *hs; Section *hs;
@ -185,20 +187,20 @@ static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
} }
/* return elf symbol value */ /* 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 get_elf_sym_addr(s, name, 0);
} }
/* return elf symbol value or error */ /* 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); return get_elf_sym_addr(s, name, 1);
} }
/* add an elf symbol : check if it is already defined and patch /* add an elf symbol : check if it is already defined and patch
it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ 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) int info, int other, int sh_num, const char *name)
{ {
ElfW(Sym) *esym; ElfW(Sym) *esym;
@ -272,7 +274,7 @@ static int add_elf_sym(Section *s, uplong value, unsigned long size,
} }
/* put relocation */ /* 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) int type, int symbol)
{ {
char buf[256]; char buf[256];
@ -301,15 +303,7 @@ static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
/* put stab debug information */ /* put stab debug information */
typedef struct { ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
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,
unsigned long value) unsigned long value)
{ {
Stab_Sym *sym; Stab_Sym *sym;
@ -326,7 +320,7 @@ static void put_stabs(const char *str, int type, int other, int desc,
sym->n_value = value; 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) unsigned long value, Section *sec, int sym_index)
{ {
put_stabs(str, type, other, desc, value); 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); 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); 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); 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 */ /* 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; ElfW(Sym) *sym, *sym_end;
unsigned long offset, align; unsigned long offset, align;
@ -434,7 +428,7 @@ static void relocate_common_syms(void)
/* relocate symbol table, resolve undefined symbols if do_resolve is /* relocate symbol table, resolve undefined symbols if do_resolve is
true and output error if undefined symbol. */ 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; ElfW(Sym) *sym, *esym, *sym_end;
int sym_bind, sh_num, sym_index; int sym_bind, sh_num, sym_index;
@ -513,7 +507,7 @@ static unsigned long add_got_table(TCCState *s1, unsigned long val)
#endif #endif
/* relocate a given section (CPU dependent) */ /* 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; Section *sr;
ElfW_Rel *rel, *rel_end, *qrel; ElfW_Rel *rel, *rel_end, *qrel;
@ -1012,7 +1006,7 @@ static void put_got_entry(TCCState *s1,
} }
/* build GOT and PLT entries */ /* build GOT and PLT entries */
static void build_got_entries(TCCState *s1) ST_FUNC void build_got_entries(TCCState *s1)
{ {
Section *s, *symtab; Section *s, *symtab;
ElfW_Rel *rel, *rel_end; 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 *symtab_name, int sh_type, int sh_flags,
const char *strtab_name, const char *strtab_name,
const char *hash_name, int hash_sh_flags) 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); s->sh_num, sym_end);
} }
static void tcc_add_bcheck(TCCState *s1) ST_FUNC void tcc_add_bcheck(TCCState *s1)
{ {
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
unsigned long *ptr; unsigned long *ptr;
@ -1227,7 +1221,7 @@ static void tcc_add_bcheck(TCCState *s1)
} }
/* add tcc runtime libraries */ /* add tcc runtime libraries */
static void tcc_add_runtime(TCCState *s1) ST_FUNC void tcc_add_runtime(TCCState *s1)
{ {
tcc_add_bcheck(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 /* add various standard linker symbols (must be done after the
sections are filled (for example after allocating common sections are filled (for example after allocating common
symbols)) */ symbols)) */
static void tcc_add_linker_symbols(TCCState *s1) ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
{ {
char buf[1024]; char buf[1024];
int i; int i;
@ -1371,7 +1365,7 @@ void patch_dynsym_undef(TCCState *s1, Section *s)
/* output an ELF file */ /* output an ELF file */
/* XXX: suppress unneeded sections */ /* 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; ElfW(Ehdr) ehdr;
FILE *f; FILE *f;
@ -2110,7 +2104,7 @@ int elf_output_file(TCCState *s1, const char *filename)
return ret; return ret;
} }
int tcc_output_file(TCCState *s, const char *filename) LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
{ {
int ret; int ret;
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
@ -2143,7 +2137,7 @@ typedef struct SectionMergeInfo {
/* load an object file and merge it with current files */ /* load an object file and merge it with current files */
/* XXX: handle correctly stab (debug) info */ /* 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) int fd, unsigned long file_offset)
{ {
ElfW(Ehdr) ehdr; ElfW(Ehdr) ehdr;
@ -2412,8 +2406,6 @@ static int tcc_load_object_file(TCCState *s1,
return ret; return ret;
} }
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
typedef struct ArchiveHeader { typedef struct ArchiveHeader {
char ar_name[16]; /* name of this member */ char ar_name[16]; /* name of this member */
char ar_date[12]; /* file mtime */ 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 */ /* 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; ArchiveHeader hdr;
char ar_size[11]; 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 /* 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 is referenced by the user (so it should be added as DT_NEEDED in
the generated ELF file) */ 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(Ehdr) ehdr;
ElfW(Shdr) *shdr, *sh, *sh1; 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 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
files */ files */
static int tcc_load_ldscript(TCCState *s1) ST_FUNC int tcc_load_ldscript(TCCState *s1)
{ {
char cmd[64]; char cmd[64];
char filename[1024]; char filename[1024];

342
tccgen.c
View File

@ -18,7 +18,244 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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; int t;
t = *p; t = *p;
@ -26,7 +263,7 @@ void swap(int *p, int *q)
*q = t; *q = t;
} }
void vsetc(CType *type, int r, CValue *vc) static void vsetc(CType *type, int r, CValue *vc)
{ {
int v; int v;
@ -48,7 +285,7 @@ void vsetc(CType *type, int r, CValue *vc)
} }
/* push integer constant */ /* push integer constant */
void vpushi(int v) ST_FUNC void vpushi(int v)
{ {
CValue cval; CValue cval;
cval.i = v; cval.i = v;
@ -56,7 +293,7 @@ void vpushi(int v)
} }
/* push long long constant */ /* push long long constant */
void vpushll(long long v) static void vpushll(long long v)
{ {
CValue cval; CValue cval;
CType ctype; CType ctype;
@ -67,8 +304,7 @@ void vpushll(long long v)
} }
/* Return a static symbol pointing to a section */ /* Return a static symbol pointing to a section */
static Sym *get_sym_ref(CType *type, Section *sec, ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
unsigned long offset, unsigned long size)
{ {
int v; int v;
Sym *sym; 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' */ /* 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; Sym *s;
@ -139,7 +375,7 @@ static void vpush_global_sym(CType *type, int v)
vtop->sym = sym; vtop->sym = sym;
} }
void vset(CType *type, int r, int v) ST_FUNC void vset(CType *type, int r, int v)
{ {
CValue cval; CValue cval;
@ -147,7 +383,7 @@ void vset(CType *type, int r, int v)
vsetc(type, r, &cval); vsetc(type, r, &cval);
} }
void vseti(int r, int v) static void vseti(int r, int v)
{ {
CType type; CType type;
type.t = VT_INT; type.t = VT_INT;
@ -155,7 +391,7 @@ void vseti(int r, int v)
vset(&type, r, v); vset(&type, r, v);
} }
void vswap(void) ST_FUNC void vswap(void)
{ {
SValue tmp; SValue tmp;
@ -164,7 +400,7 @@ void vswap(void)
vtop[-1] = tmp; vtop[-1] = tmp;
} }
void vpushv(SValue *v) static void vpushv(SValue *v)
{ {
if (vtop >= vstack + (VSTACK_SIZE - 1)) if (vtop >= vstack + (VSTACK_SIZE - 1))
error("memory full"); error("memory full");
@ -172,13 +408,13 @@ void vpushv(SValue *v)
*vtop = *v; *vtop = *v;
} }
void vdup(void) static void vdup(void)
{ {
vpushv(vtop); vpushv(vtop);
} }
/* save r to the memory stack, and mark it as being free */ /* 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; int l, saved, size, align;
SValue *p, sv; 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. /* find a register of class 'rc2' with at most one reference on stack.
* If none, call get_reg(rc) */ * 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; int r;
SValue *p; SValue *p;
@ -262,9 +499,10 @@ int get_reg_ex(int rc, int rc2)
} }
return get_reg(rc); return get_reg(rc);
} }
#endif
/* find a free register of class 'rc'. If none, save one register */ /* 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; int r;
SValue *p; SValue *p;
@ -302,7 +540,7 @@ int get_reg(int rc)
} }
/* save registers up to (vtop - n) stack entry */ /* save registers up to (vtop - n) stack entry */
void save_regs(int n) ST_FUNC void save_regs(int n)
{ {
int r; int r;
SValue *p, *p1; 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 /* move register 's' to 'r', and flush previous value of r to memory
if needed */ if needed */
void move_reg(int r, int s) static void move_reg(int r, int s)
{ {
SValue sv; SValue sv;
@ -331,7 +569,7 @@ void move_reg(int r, int s)
} }
/* get address of vtop (vtop MUST BE an lvalue) */ /* get address of vtop (vtop MUST BE an lvalue) */
void gaddrof(void) static void gaddrof(void)
{ {
vtop->r &= ~VT_LVAL; vtop->r &= ~VT_LVAL;
/* tricky: if saved lvalue, then we can go back to lvalue */ /* tricky: if saved lvalue, then we can go back to lvalue */
@ -341,7 +579,7 @@ void gaddrof(void)
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
/* generate lvalue bound code */ /* generate lvalue bound code */
void gbound(void) static void gbound(void)
{ {
int lval_type; int lval_type;
CType type1; CType type1;
@ -370,7 +608,7 @@ void gbound(void)
/* store vtop a register belonging to class 'rc'. lvalues are /* store vtop a register belonging to class 'rc'. lvalues are
converted to values. Cannot be used if cannot be converted to converted to values. Cannot be used if cannot be converted to
register value (such as structures). */ 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; 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 */ /* 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; int v;
@ -569,7 +807,7 @@ void gv2(int rc1, int rc2)
} }
/* wrapper around RC_FRET to return a register by type */ /* 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 #ifdef TCC_TARGET_X86_64
if (t == VT_LDOUBLE) { if (t == VT_LDOUBLE) {
@ -580,7 +818,7 @@ int rc_fret(int t)
} }
/* wrapper around REG_FRET to return a register by type */ /* 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 #ifdef TCC_TARGET_X86_64
if (t == VT_LDOUBLE) { if (t == VT_LDOUBLE) {
@ -591,7 +829,7 @@ int reg_fret(int t)
} }
/* expand long long on stack in two int registers */ /* expand long long on stack in two int registers */
void lexpand(void) static void lexpand(void)
{ {
int u; int u;
@ -607,7 +845,7 @@ void lexpand(void)
#ifdef TCC_TARGET_ARM #ifdef TCC_TARGET_ARM
/* expand long long on stack */ /* expand long long on stack */
void lexpand_nr(void) ST_FUNC void lexpand_nr(void)
{ {
int u,v; int u,v;
@ -634,7 +872,7 @@ void lexpand_nr(void)
#endif #endif
/* build a long long from two ints */ /* build a long long from two ints */
void lbuild(int t) static void lbuild(int t)
{ {
gv2(RC_INT, RC_INT); gv2(RC_INT, RC_INT);
vtop[-1].r2 = vtop[0].r; vtop[-1].r2 = vtop[0].r;
@ -645,7 +883,7 @@ void lbuild(int t)
/* rotate n first stack elements to the bottom /* rotate n first stack elements to the bottom
I1 ... In -> I2 ... In I1 [top is right] I1 ... In -> I2 ... In I1 [top is right]
*/ */
void vrotb(int n) static void vrotb(int n)
{ {
int i; int i;
SValue tmp; SValue tmp;
@ -659,7 +897,7 @@ void vrotb(int n)
/* rotate n first stack elements to the top /* rotate n first stack elements to the top
I1 ... In -> In I1 ... I(n-1) [top is right] I1 ... In -> In I1 ... I(n-1) [top is right]
*/ */
void vrott(int n) static void vrott(int n)
{ {
int i; int i;
SValue tmp; SValue tmp;
@ -687,7 +925,7 @@ void vnrott(int n)
#endif #endif
/* pop stack value */ /* pop stack value */
void vpop(void) ST_FUNC void vpop(void)
{ {
int v; int v;
v = vtop->r & VT_VALMASK; v = vtop->r & VT_VALMASK;
@ -706,7 +944,7 @@ void vpop(void)
/* convert stack entry to register and duplicate its value in another /* convert stack entry to register and duplicate its value in another
register */ register */
void gv_dup(void) static void gv_dup(void)
{ {
int rc, t, r, r1; int rc, t, r, r1;
SValue sv; SValue sv;
@ -753,7 +991,7 @@ void gv_dup(void)
#ifndef TCC_TARGET_X86_64 #ifndef TCC_TARGET_X86_64
/* generate CPU independent (unsigned) long long operations */ /* 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 t, a, b, op1, c, i;
int func; int func;
@ -990,7 +1228,7 @@ void gen_opl(int op)
/* handle integer constant optimizations and various machine /* handle integer constant optimizations and various machine
independent opt */ independent opt */
void gen_opic(int op) static void gen_opic(int op)
{ {
int c1, c2, t1, t2, n; int c1, c2, t1, t2, n;
SValue *v1, *v2; SValue *v1, *v2;
@ -1130,7 +1368,7 @@ void gen_opic(int op)
} }
/* generate a floating point operation with constant propagation */ /* generate a floating point operation with constant propagation */
void gen_opif(int op) static void gen_opif(int op)
{ {
int c1, c2; int c1, c2;
SValue *v1, *v2; 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 */ /* 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; int u, t1, t2, bt1, bt2, t;
CType type1; CType type1;
@ -1411,7 +1649,7 @@ void gen_op(int op)
#ifndef TCC_TARGET_ARM #ifndef TCC_TARGET_ARM
/* generic itof for unsigned long long case */ /* 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)) == if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
(VT_LLONG | VT_UNSIGNED)) { (VT_LLONG | VT_UNSIGNED)) {
@ -1435,7 +1673,7 @@ void gen_cvt_itof1(int t)
#endif #endif
/* generic ftoi for unsigned long long case */ /* generic ftoi for unsigned long long case */
void gen_cvt_ftoi1(int t) static void gen_cvt_ftoi1(int t)
{ {
int st; int st;
@ -1461,7 +1699,7 @@ void gen_cvt_ftoi1(int t)
} }
/* force char or short cast */ /* force char or short cast */
void force_charshort_cast(int t) static void force_charshort_cast(int t)
{ {
int bits, dbt; int bits, dbt;
dbt = t & VT_BTYPE; dbt = t & VT_BTYPE;
@ -1672,7 +1910,7 @@ static void gen_cast(CType *type)
} }
/* return type size. Put alignment at 'a' */ /* 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; Sym *s;
int bt; int bt;
@ -1738,7 +1976,7 @@ static inline CType *pointed_type(CType *type)
} }
/* modify type so that its it is a pointer to 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; Sym *s;
s = sym_push(SYM_FIELD, type, 0, -1); 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 */ printed in the type */
/* XXX: union */ /* XXX: union */
/* XXX: add array and function pointers */ /* 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) CType *type, const char *varstr)
{ {
int bt, v, t; int bt, v, t;
@ -2000,7 +2238,7 @@ static void gen_assign_cast(CType *dt)
} }
/* store vtop in lvalue pushed on stack */ /* 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; 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 -- */ /* 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(); test_lvalue();
vdup(); /* save 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. */ /* 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; int bt, r;
r = VT_LVAL; r = VT_LVAL;
@ -2896,7 +3134,7 @@ static int lvalue_type(int t)
} }
/* indirection with full error checking and bound check */ /* 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_PTR) {
if ((vtop->type.t & VT_BTYPE) == VT_FUNC) if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
@ -2976,7 +3214,7 @@ static void vpush_tokc(int t)
vsetc(&type, VT_CONST, &tokc); vsetc(&type, VT_CONST, &tokc);
} }
static void unary(void) ST_FUNC void unary(void)
{ {
int n, t, align, size, r; int n, t, align, size, r;
CType type; CType type;
@ -3444,7 +3682,7 @@ static void uneq(void)
} }
} }
static void expr_prod(void) ST_FUNC void expr_prod(void)
{ {
int t; int t;
@ -3457,7 +3695,7 @@ static void expr_prod(void)
} }
} }
static void expr_sum(void) ST_FUNC void expr_sum(void)
{ {
int t; int t;
@ -3745,7 +3983,7 @@ static void expr_eq(void)
} }
} }
static void gexpr(void) ST_FUNC void gexpr(void)
{ {
while (1) { while (1) {
expr_eq(); expr_eq();
@ -3794,7 +4032,7 @@ static void expr_const1(void)
} }
/* parse an integer constant and return its value. */ /* parse an integer constant and return its value. */
static int expr_const(void) ST_FUNC int expr_const(void)
{ {
int c; int c;
expr_const1(); expr_const1();
@ -4848,7 +5086,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
no_alloc: ; no_alloc: ;
} }
void put_func_debug(Sym *sym) static void put_func_debug(Sym *sym)
{ {
char buf[512]; char buf[512];
@ -4951,7 +5189,7 @@ static void gen_function(Sym *sym)
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
} }
static void gen_inline_functions(void) ST_FUNC void gen_inline_functions(void)
{ {
Sym *sym; Sym *sym;
int *str, inline_generated, i; 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 */ /* '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; int v, has_init, r;
CType type, btype; CType type, btype;

129
tccpe.c
View File

@ -18,11 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifdef TCC_TARGET_PE #include "tcc.h"
#define ST_FN static
#define ST_DATA static
#define PUB_FN
#ifndef _WIN32 #ifndef _WIN32
#define stricmp strcasecmp #define stricmp strcasecmp
@ -300,7 +296,7 @@ enum {
sec_last sec_last
}; };
ST_DATA const DWORD pe_sec_flags[] = { static const DWORD pe_sec_flags[] = {
0x60000020, /* ".text" , */ 0x60000020, /* ".text" , */
0xC0000040, /* ".data" , */ 0xC0000040, /* ".data" , */
0xC0000080, /* ".bss" , */ 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; const char *p;
p = strrchr(symbol, '@'); p = strrchr(symbol, '@');
@ -384,7 +380,7 @@ ST_FN const char* get_alt_symbol(char *buffer, const char *symbol)
return buffer; 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]; char buffer[200];
const char *s; 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; int i;
for (i = 0; i < n; ++i, ++pp) for (i = 0; i < n; ++i, ++pp)
@ -415,35 +411,35 @@ ST_FN DWORD umin(DWORD a, DWORD b)
} }
#endif #endif
ST_FN DWORD umax(DWORD a, DWORD b) static DWORD umax(DWORD a, DWORD b)
{ {
return a < b ? b : a; 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); 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); 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); int i = s->data_offset & (a-1);
if (i) if (i)
section_ptr_add(s, a - 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].VirtualAddress = addr;
hdr->opthdr.DataDirectory[dir].Size = size; 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) { if (psum) {
DWORD sum = *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; 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); DWORD pos = ftell(fp);
while (++pos <= new_pos) 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 = { static const struct pe_header pe_template = {
{ {
@ -745,7 +741,7 @@ ST_FN int pe_write(struct pe_info *pe)
#endif #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 i;
int dll_index; 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; int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
DWORD rva_base = pe->thunk->sh_addr - pe->imagebase; DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
@ -860,14 +856,14 @@ struct pe_sort_sym
const char *name; 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 *ca = (*(struct pe_sort_sym**)va)->name;
const char *cb = (*(struct pe_sort_sym**)vb)->name; const char *cb = (*(struct pe_sort_sym**)vb)->name;
return strcmp(ca, cb); 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; ElfW(Sym) *sym;
int sym_index, sym_end; 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; DWORD offset, block_ptr, addr;
int count, i; 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; int type, flags;
const char *name; const char *name;
@ -1055,7 +1051,7 @@ ST_FN int pe_section_class(Section *s)
return -1; 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; int i, k, o, c;
DWORD addr; 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; Section *sr = s->reloc;
ElfW_Rel *rel, *rel_end; 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) static int pe_isafunc(int sym_index)
{ {
Section *sr = text_section->reloc; 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; ElfW(Sym) *sym;
int sym_index, sym_end; int sym_index, sym_end;
@ -1282,7 +1279,7 @@ ST_FN int pe_check_symbols(struct pe_info *pe)
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
#ifdef PE_PRINT_SECTIONS #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 */ /* just if you'r curious */
BYTE *p, *e, b; BYTE *p, *e, b;
@ -1404,7 +1401,7 @@ ST_FN void pe_print_section(FILE * f, Section * s)
fprintf(f, "\n\n"); 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; Section *s;
FILE *f; FILE *f;
@ -1420,34 +1417,8 @@ ST_FN void pe_print_sections(TCCState *s1, const char *fname)
#endif #endif
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* helper function for load/store to insert one more indirection */
int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)) static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
{
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)
{ {
fseek(fp, offset, 0); fseek(fp, offset, 0);
return len == fread(buffer, 1, len, fp); 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 ...'. * 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; struct pe_rsrc_header hdr;
Section *rsrc_section; Section *rsrc_section;
@ -1498,14 +1469,14 @@ quit:
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
ST_FN char *trimfront(char *p) static char *trimfront(char *p)
{ {
while (*p && (unsigned char)*p <= ' ') while (*p && (unsigned char)*p <= ' ')
++p; ++p;
return 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] <= ' ') while (e > a && (unsigned char)e[-1] <= ' ')
--e; --e;
@ -1513,7 +1484,7 @@ ST_FN char *trimback(char *a, char *e)
return a; 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)) if (NULL == fgets(line, size, fp))
return NULL; 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; DLLReference *dllref;
int state = 0, ret = -1; int state = 0, ret = -1;
@ -1571,7 +1542,7 @@ quit:
#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
#include "win32/tools/tiny_impdef.c" #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; int i = 0;
char *p, *q; 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"); FILE *fp = fdopen(dup(fd), "rb");
int ret = -1; int ret = -1;
@ -1611,7 +1582,7 @@ PUB_FN int pe_load_file(struct TCCState *s1, const char *filename, int fd)
return ret; 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[] = { static const char *pat[] = {
"%s.def", "lib%s.def", "%s.dll", "lib%s.dll", NULL "%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; 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 #ifdef TCC_TARGET_X86_64
#define PE_STDSYM(n,s) n #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 #define PE_STDSYM(n,s) "_" n s
#endif #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; const char *start_symbol;
unsigned long addr = 0; 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; 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; int ret;
struct pe_info pe; struct pe_info pe;
@ -1780,5 +1777,3 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
#endif /* def TCC_TARGET_PE */
/* ------------------------------------------------------------- */

221
tccpp.c
View File

@ -18,6 +18,49 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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[] = static const char tcc_keywords[] =
#define DEF(id, str) str "\0" #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" "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253"
"-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; "-=\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 {
struct macro_level *prev; struct macro_level *prev;
int *p; int *p;
}; };
static void next_nomacro(void); ST_FUNC void next_nomacro(void);
static void next_nomacro_spc(void); static void next_nomacro_spc(void);
static void macro_subst(TokenString *tok_str, Sym **nested_list, static void macro_subst(
const int *macro_str, struct macro_level **can_read_stream); 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 */ /* allocate a new token */
static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) 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)) #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
/* find a token and add it if not found */ /* 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; TokenSym *ts, **pts;
int i; int i;
@ -107,7 +244,7 @@ static TokenSym *tok_alloc(const char *str, int len)
/* XXX: buffer overflow */ /* XXX: buffer overflow */
/* XXX: float tokens */ /* 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 char buf[STRING_MAX_SIZE + 1];
static CString cstr_buf; 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 /* return the current character, handling end of block if necessary
(but not stray) */ (but not stray) */
static int handle_eob(void) ST_FUNC int handle_eob(void)
{ {
return tcc_peekc_slow(file); return tcc_peekc_slow(file);
} }
/* read next char from current input file and handle end of input buffer */ /* 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)); ch = *(++(file->buf_ptr));
/* end of buffer/file handling */ /* 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 /* input with '\[\r]\n' handling. Note that this function cannot
handle other characters after '\', so you cannot call it inside handle other characters after '\', so you cannot call it inside
strings or comments */ strings or comments */
static void minp(void) ST_FUNC void minp(void)
{ {
inp(); inp();
if (ch == '\\') if (ch == '\\')
@ -380,7 +517,7 @@ static uint8_t *parse_line_comment(uint8_t *p)
} }
/* C comments */ /* C comments */
static uint8_t *parse_comment(uint8_t *p) ST_FUNC uint8_t *parse_comment(uint8_t *p)
{ {
int c; 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 /* skip block of text until #else, #elif or #endif. skip also pairs of
#if/#endif */ #if/#endif */
void preprocess_skip(void) static void preprocess_skip(void)
{ {
int a, start_of_line, c, in_warn_or_error; int a, start_of_line, c, in_warn_or_error;
uint8_t *p; uint8_t *p;
@ -629,7 +766,7 @@ _default:
files */ files */
/* save current parse state in 's' */ /* 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->line_num = file->line_num;
s->macro_ptr = macro_ptr; s->macro_ptr = macro_ptr;
@ -638,7 +775,7 @@ void save_parse_state(ParseState *s)
} }
/* restore parse state from '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; file->line_num = s->line_num;
macro_ptr = s->macro_ptr; macro_ptr = s->macro_ptr;
@ -677,7 +814,7 @@ static inline int tok_ext_size(int t)
/* token string handling */ /* token string handling */
static inline void tok_str_new(TokenString *s) ST_INLN void tok_str_new(TokenString *s)
{ {
s->str = NULL; s->str = NULL;
s->len = 0; s->len = 0;
@ -685,7 +822,7 @@ static inline void tok_str_new(TokenString *s)
s->last_line_num = -1; s->last_line_num = -1;
} }
static void tok_str_free(int *str) ST_FUNC void tok_str_free(int *str)
{ {
tcc_free(str); tcc_free(str);
} }
@ -707,7 +844,7 @@ static int *tok_str_realloc(TokenString *s)
return str; return str;
} }
static void tok_str_add(TokenString *s, int t) ST_FUNC void tok_str_add(TokenString *s, int t)
{ {
int len, *str; 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' */ /* 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; CValue cval;
@ -861,7 +998,7 @@ static void tok_str_add_tok(TokenString *s)
} }
/* defines handling */ /* 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; 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 */ /* 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; int v;
v = s->v; v = s->v;
@ -881,7 +1018,7 @@ static void define_undef(Sym *s)
s->v = 0; s->v = 0;
} }
static inline Sym *define_find(int v) ST_INLN Sym *define_find(int v)
{ {
v -= TOK_IDENT; v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - 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' */ /* free define stack until top reaches 'b' */
static void free_defines(Sym *b) ST_FUNC void free_defines(Sym *b)
{ {
Sym *top, *top1; Sym *top, *top1;
int v; int v;
@ -911,7 +1048,7 @@ static void free_defines(Sym *b)
} }
/* label lookup */ /* label lookup */
static Sym *label_find(int v) ST_FUNC Sym *label_find(int v)
{ {
v -= TOK_IDENT; v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - 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; 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; Sym *s, **ps;
s = sym_push2(ptop, v, 0, 0); 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 /* pop labels until element last is reached. Look if any labels are
undefined. Define symbols if '&&label' was used. */ 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; Sym *s, *s1;
for(s = *ptop; s != slast; s = s1) { for(s = *ptop; s != slast; s = s1) {
@ -1017,7 +1154,7 @@ static void tok_print(int *str)
#endif #endif
/* parse after #define */ /* parse after #define */
static void parse_define(void) ST_FUNC void parse_define(void)
{ {
Sym *s, *first, **ps; Sym *s, *first, **ps;
int v, t, varg, is_vaargs, spc; 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 */ /* 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; TCCState *s1 = tcc_state;
int i, c, n, saved_parse_flags; 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); pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf1);
file = f; file = f;
/* add include file debug info */ /* add include file debug info */
if (tcc_state->do_debug) { if (s1->do_debug) {
put_stabs(file->filename, N_BINCL, 0, 0, 0); put_stabs(file->filename, N_BINCL, 0, 0, 0);
} }
tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL; 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 #define BN_SIZE 2
/* bn = (bn << shift) | or_val */ /* 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; int i;
unsigned int v; 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; int i;
for(i=0;i<BN_SIZE;i++) { for(i=0;i<BN_SIZE;i++) {
@ -1619,7 +1756,7 @@ void bn_zero(unsigned int *bn)
/* parse number in null terminated string 'p' and return it in the /* parse number in null terminated string 'p' and return it in the
current token */ current token */
void parse_number(const char *p) static void parse_number(const char *p)
{ {
int b, t, shift, frac_bits, s, exp_val, ch; int b, t, shift, frac_bits, s, exp_val, ch;
char *q; char *q;
@ -2353,7 +2490,7 @@ static void next_nomacro_spc(void)
} }
} }
static void next_nomacro(void) ST_FUNC void next_nomacro(void)
{ {
do { do {
next_nomacro_spc(); next_nomacro_spc();
@ -2734,7 +2871,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
} }
/* return next token with macro substitution */ /* return next token with macro substitution */
static void next(void) ST_FUNC void next(void)
{ {
Sym *nested_list, *s; Sym *nested_list, *s;
TokenString str; TokenString str;
@ -2790,7 +2927,7 @@ static void next(void)
/* push back current token and set current token to 'last_tok'. Only /* push back current token and set current token to 'last_tok'. Only
identifier case handled for labels. */ identifier case handled for labels. */
static inline void unget_tok(int last_tok) ST_INLN void unget_tok(int last_tok)
{ {
int i, n; int i, n;
int *q; int *q;
@ -2809,7 +2946,7 @@ static inline void unget_tok(int last_tok)
/* better than nothing, but needs extension to handle '-E' option /* better than nothing, but needs extension to handle '-E' option
correctly too */ correctly too */
static void preprocess_init(TCCState *s1) ST_FUNC void preprocess_init(TCCState *s1)
{ {
s1->include_stack_ptr = s1->include_stack; s1->include_stack_ptr = s1->include_stack;
/* XXX: move that before to avoid having to initialize /* 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; s1->pack_stack_ptr = s1->pack_stack;
} }
void preprocess_new() ST_FUNC void preprocess_new()
{ {
int i, c; int i, c;
const char *p, *r; const char *p, *r;
@ -2852,9 +2989,10 @@ void preprocess_new()
} }
/* Preprocess the current file */ /* Preprocess the current file */
static int tcc_preprocess(TCCState *s1) ST_FUNC int tcc_preprocess(TCCState *s1)
{ {
Sym *define_start; Sym *define_start;
BufferedFile *file_ref, **iptr, **iptr_new; BufferedFile *file_ref, **iptr, **iptr_new;
int token_seen, line_ref, d; int token_seen, line_ref, d;
const char *s; const char *s;
@ -2868,8 +3006,8 @@ static int tcc_preprocess(TCCState *s1)
token_seen = 0; token_seen = 0;
line_ref = 0; line_ref = 0;
file_ref = NULL; file_ref = NULL;
iptr = s1->include_stack_ptr; iptr = s1->include_stack_ptr;
for (;;) { for (;;) {
next(); next();
if (tok == TOK_EOF) { if (tok == TOK_EOF) {
@ -2904,7 +3042,6 @@ print_line:
} }
fputs(get_tok_str(tok, &tokc), s1->outfile); fputs(get_tok_str(tok, &tokc), s1->outfile);
} }
free_defines(define_start); free_defines(define_start);
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
* TCC - Tiny C Compiler * TCC - Tiny C Compiler - Support for -run switch
* *
* Copyright (c) 2001-2004 Fabrice Bellard * Copyright (c) 2001-2004 Fabrice Bellard
* *
@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* tccrun.c - support for tcc -run */ #include "tcc.h"
#ifdef _WIN32 #ifdef _WIN32
#define ucontext_t CONTEXT #define ucontext_t CONTEXT
@ -26,7 +26,7 @@
static void set_pages_executable(void *ptr, unsigned long length); static void set_pages_executable(void *ptr, unsigned long length);
static void set_exception_handler(void); 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 void rt_error(ucontext_t *uc, const char *fmt, ...);
static int tcc_relocate_ex(TCCState *s1, void *ptr); 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); VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
#else #else
unsigned long start, end; unsigned long start, end;
start = (unsigned long)ptr & ~(PAGESIZE - 1); start = (uplong)ptr & ~(PAGESIZE - 1);
end = (unsigned long)ptr + length; end = (uplong)ptr + length;
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
#endif #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 /* print the position in the source file of PC value 'pc' by reading
the stabs debug information */ 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; Stab_Sym *sym, *sym_end;
char func_name[128], last_func_name[128]; 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; int incl_index, len, last_line_num, i;
const char *str, *p; const char *str, *p;
fprintf(stderr, "0x%08lx:", wanted_pc); fprintf(stderr, "0x%08lx:", (unsigned long)wanted_pc);
func_name[0] = '\0'; func_name[0] = '\0';
func_addr = 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, ...) static void rt_error(ucontext_t *uc, const char *fmt, ...)
{ {
va_list ap; va_list ap;
unsigned long pc; uplong pc;
int i; int i;
va_start(ap, fmt); va_start(ap, fmt);
@ -327,7 +327,7 @@ static void rt_error(ucontext_t *uc, const char *fmt, ...)
else else
fprintf(stderr, "by "); fprintf(stderr, "by ");
pc = rt_printline(pc); pc = rt_printline(pc);
if (pc == (unsigned long)rt_prog_main && pc) if (pc == (uplong)rt_prog_main && pc)
break; break;
} }
exit(255); exit(255);
@ -505,11 +505,15 @@ static void set_exception_handler(void)
SetUnhandledExceptionFilter(cpu_exception_handler); 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 */ /* return the PC at frame level 'level'. Return non zero if not found */
static int rt_get_caller_pc(unsigned long *paddr, static int rt_get_caller_pc(uplong *paddr, CONTEXT *uc, int level)
CONTEXT *uc, int level)
{ {
unsigned long fp; uplong fp;
int i; int i;
if (level == 0) { if (level == 0) {
@ -521,13 +525,16 @@ static int rt_get_caller_pc(unsigned long *paddr,
/* XXX: check address validity with program info */ /* XXX: check address validity with program info */
if (fp <= 0x1000 || fp >= 0xc0000000) if (fp <= 0x1000 || fp >= 0xc0000000)
return -1; return -1;
fp = ((unsigned long *)fp)[0]; fp = ((uplong*)fp)[0];
} }
*paddr = ((unsigned long *)fp)[1]; *paddr = ((uplong*)fp)[1];
return 0; return 0;
} }
} }
#undef Eip
#undef Ebp
#endif /* _WIN32 */ #endif /* _WIN32 */
#endif /* CONFIG_TCC_BACKTRACE */ #endif /* CONFIG_TCC_BACKTRACE */
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -584,13 +591,7 @@ void *resolve_sym(TCCState *s1, const char *symbol)
return NULL; return NULL;
} }
#elif defined(_WIN32) #elif !defined(_WIN32)
#define dlclose FreeLibrary
#else
#include <dlfcn.h>
void *resolve_sym(TCCState *s1, const char *sym) void *resolve_sym(TCCState *s1, const char *sym)
{ {

View File

@ -20,10 +20,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <assert.h> #ifdef TARGET_DEFS_ONLY
/* number of available registers */ /* 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 /* a register can belong to several classes. The classes must be
sorted from more general to more precise (see gv2() code which does 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 REX_BASE(reg) (((reg) >> 3) & 1)
#define REG_VALUE(reg) ((reg) & 7) #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 */ /* return registers for function */
#define REG_IRET TREG_RAX /* single word int return register */ #define REG_IRET TREG_RAX /* single word int return register */
#define REG_LRET TREG_RDX /* second word return register (for long long) */ #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) */ /* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8 #define MAX_ALIGN 8
ST_FUNC void gen_opl(int op);
ST_FUNC void gen_le64(int64_t c);
/******************************************************/ /******************************************************/
/* ELF defines */ /* ELF defines */
@ -100,6 +96,18 @@ const int reg_classes[NB_REGS] = {
#define ELF_PAGE_SIZE 0x1000 #define ELF_PAGE_SIZE 0x1000
/******************************************************/ /******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#include "tcc.h"
#include <assert.h>
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 unsigned long func_sub_sp_offset;
static int func_ret_sub; 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 */ /* 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; int ind1;
@ -198,7 +206,7 @@ static int oad(int c, int s)
return 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) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_X86_64_32); 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 */ /* 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) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_X86_64_64); 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 */ /* 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) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_X86_64_PC32); greloc(cur_text_section, sym, ind, R_X86_64_PC32);
@ -1537,3 +1545,5 @@ void ggoto(void)
/* end of x86-64 code generator */ /* end of x86-64 code generator */
/*************************************************************/ /*************************************************************/
#endif /* ! TARGET_DEFS_ONLY */
/******************************************************/