allow tcc be build from separate objects
If you want that, run: make NOTALLINONE=1
This commit is contained in:
parent
7fa712e00c
commit
88a3ccab9f
16 changed files with 1322 additions and 1045 deletions
41
Makefile
41
Makefile
|
@ -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),.)
|
||||||
|
|
70
arm-gen.c
70
arm-gen.c
|
@ -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
|
||||||
|
/*************************************************************/
|
||||||
|
|
95
c67-gen.c
95
c67-gen.c
|
@ -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
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
|
20
i386-asm.c
20
i386-asm.c
|
@ -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;
|
||||||
|
|
78
i386-gen.c
78
i386-gen.c
|
@ -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
|
||||||
|
/*************************************************************/
|
||||||
|
|
32
tcc.c
32
tcc.c
|
@ -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
440
tcc.h
|
@ -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 */
|
||||||
|
|
18
tccasm.c
18
tccasm.c
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
62
tccelf.c
62
tccelf.c
|
@ -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
342
tccgen.c
|
@ -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
129
tccpe.c
|
@ -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
221
tccpp.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
43
tccrun.c
43
tccrun.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
38
x86_64-gen.c
38
x86_64-gen.c
|
@ -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 */
|
||||||
|
/******************************************************/
|
||||||
|
|
Loading…
Reference in a new issue