mirror of
https://github.com/frida/tinycc
synced 2024-12-26 23:09:41 +03:00
Return to: e20c1eb99e
1: The new patch for the other machines still have the problem. 2: libcrt Rename (what if gcc had libcrt as well) 3: parse_number exact problem 4: VT_VLS is to allow tcc Compile the following int b = 9; struct st { int a; int b [b] }; struct st st1; st1.b [8] = 9; printf ("% d \ n", st1.b [8]); tcc a problem. Due to problems in front, and now can not be improved 5: they commit much, bug difficult to lock, you can not let other people help develop. 6: ('\ t') too Thanks to Michael and Ray Their criticism I have benefited!
This commit is contained in:
parent
089dea355a
commit
5e56fb635a
58
Makefile
58
Makefile
@ -22,7 +22,7 @@ endif
|
||||
endif
|
||||
else # not GCC
|
||||
ifeq (-$(findstring clang,$(CC))-,-clang-)
|
||||
# make clang accept gnuisms in libcrt.c
|
||||
# make clang accept gnuisms in libtcc1.c
|
||||
CFLAGS+=-fheinous-gnu-extensions
|
||||
endif
|
||||
endif
|
||||
@ -101,11 +101,11 @@ $(ARM_EABI_CROSS)_LINK = arm-eabi-tcc$(EXESUF)
|
||||
|
||||
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
||||
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
||||
I386_FILES = $(CORE_FILES) i386-gen.c asmx86.c i386-asm.h asmx86-tok.h
|
||||
WIN32_FILES = $(CORE_FILES) i386-gen.c asmx86.c i386-asm.h asmx86-tok.h tccpe.c
|
||||
WIN64_FILES = $(CORE_FILES) x86_64-gen.c asmx86.c x86_64-asm.h tccpe.c
|
||||
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h
|
||||
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
|
||||
WIN64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h tccpe.c
|
||||
WINCE_FILES = $(CORE_FILES) arm-gen.c tccpe.c
|
||||
X86_64_FILES = $(CORE_FILES) x86_64-gen.c asmx86.c x86_64-asm.h
|
||||
X86_64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h
|
||||
ARM_FILES = $(CORE_FILES) arm-gen.c
|
||||
C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c
|
||||
|
||||
@ -113,29 +113,29 @@ ifdef CONFIG_WIN64
|
||||
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
|
||||
NATIVE_FILES=$(WIN64_FILES)
|
||||
PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/i386-win32/libcrt.a
|
||||
LIBCRT=libcrt.a
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifdef CONFIG_WIN32
|
||||
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
|
||||
NATIVE_FILES=$(WIN32_FILES)
|
||||
PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/x86_64-win32/libcrt.a
|
||||
LIBCRT=libcrt.a
|
||||
LIBTCC1_CROSS=lib/x86_64-win32/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),i386)
|
||||
NATIVE_FILES=$(I386_FILES)
|
||||
PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/i386-win32/libcrt.a lib/x86_64-win32/libcrt.a
|
||||
LIBCRT=libcrt.a
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),x86-64)
|
||||
NATIVE_FILES=$(X86_64_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/i386-win32/libcrt.a lib/x86_64-win32/libcrt.a lib/i386/libcrt.a
|
||||
LIBCRT=libcrt.a
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),arm)
|
||||
NATIVE_FILES=$(ARM_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
|
||||
LIBCRT=libcrt.a
|
||||
LIBTCC1_CROSS=lib/i386-win32/libcrt.a lib/x86_64-win32/libcrt.a lib/i386/libcrt.a
|
||||
LIBTCC1=libtcc1.a
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
|
||||
endif
|
||||
PROGS_CROSS_LINK=$(foreach PROG_CROSS,$(PROGS_CROSS),$($(PROG_CROSS)_LINK))
|
||||
|
||||
@ -143,7 +143,7 @@ ifeq ($(TARGETOS),Darwin)
|
||||
PROGS+=tiny_libmaker$(EXESUF)
|
||||
endif
|
||||
|
||||
TCCLIBS = $(LIBCRT) $(LIBTCC) $(LIBTCC_EXTRA)
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCC_EXTRA)
|
||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||
|
||||
ifdef CONFIG_CROSS
|
||||
@ -225,9 +225,9 @@ tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
# TinyCC runtime libraries
|
||||
libcrt.a : FORCE
|
||||
libtcc1.a : FORCE
|
||||
$(MAKE) -C lib native
|
||||
lib/%/libcrt.a : FORCE $(PROGS_CROSS)
|
||||
lib/%/libtcc1.a : FORCE $(PROGS_CROSS)
|
||||
$(MAKE) -C lib cross TARGET=$*
|
||||
|
||||
FORCE:
|
||||
@ -258,8 +258,8 @@ endif
|
||||
-$(INSTALL) -m644 tcc-doc.info "$(infodir)"
|
||||
mkdir -p "$(tccdir)"
|
||||
mkdir -p "$(tccdir)/include"
|
||||
ifneq ($(LIBCRT),)
|
||||
$(INSTALL) -m644 $(LIBCRT) "$(tccdir)"
|
||||
ifneq ($(LIBTCC1),)
|
||||
$(INSTALL) -m644 $(LIBTCC1) "$(tccdir)"
|
||||
endif
|
||||
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include"
|
||||
mkdir -p "$(libdir)"
|
||||
@ -277,19 +277,19 @@ ifdef CONFIG_CROSS
|
||||
mkdir -p "$(tccdir)/win32/lib/64"
|
||||
ifneq ($(ARCH),i386)
|
||||
mkdir -p "$(tccdir)/i386"
|
||||
$(INSTALL) -m644 lib/i386/libcrt.a "$(tccdir)/i386"
|
||||
$(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386"
|
||||
cp -r "$(tccdir)/include" "$(tccdir)/i386"
|
||||
endif
|
||||
$(INSTALL) -m644 $(top_srcdir)/win32/lib/*.def "$(tccdir)/win32/lib"
|
||||
$(INSTALL) -m644 lib/i386-win32/libcrt.a "$(tccdir)/win32/lib/32"
|
||||
$(INSTALL) -m644 lib/x86_64-win32/libcrt.a "$(tccdir)/win32/lib/64"
|
||||
$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/win32/lib/32"
|
||||
$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/win32/lib/64"
|
||||
cp -r $(top_srcdir)/win32/include/. "$(tccdir)/win32/include"
|
||||
cp -r "$(tccdir)/include" "$(tccdir)/win32"
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
rm -fv $(foreach P,$(PROGS),"$(bindir)/$P")
|
||||
rm -fv $(foreach P,$(LIBCRT),"$(tccdir)/$P")
|
||||
rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P")
|
||||
rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P")
|
||||
rm -fv "$(tccdir)/include/tcclib.h"
|
||||
rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
|
||||
@ -310,7 +310,7 @@ install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
mkdir -p "$(tccdir)/doc"
|
||||
mkdir -p "$(tccdir)/libtcc"
|
||||
$(INSTALLBIN) -m755 $(PROGS) "$(tccdir)"
|
||||
$(INSTALL) -m644 $(LIBCRT) $(top_srcdir)/win32/lib/*.def "$(tccdir)/lib"
|
||||
$(INSTALL) -m644 $(LIBTCC1) $(top_srcdir)/win32/lib/*.def "$(tccdir)/lib"
|
||||
cp -r $(top_srcdir)/win32/include/. "$(tccdir)/include"
|
||||
cp -r $(top_srcdir)/win32/examples/. "$(tccdir)/examples"
|
||||
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include"
|
||||
@ -320,8 +320,8 @@ install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
ifdef CONFIG_CROSS
|
||||
mkdir -p "$(tccdir)/lib/32"
|
||||
mkdir -p "$(tccdir)/lib/64"
|
||||
-$(INSTALL) -m644 lib/i386-win32/libcrt.a "$(tccdir)/lib/32"
|
||||
-$(INSTALL) -m644 lib/x86_64-win32/libcrt.a "$(tccdir)/lib/64"
|
||||
-$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/lib/32"
|
||||
-$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/lib/64"
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
@ -340,7 +340,7 @@ tcc-doc.info: tcc-doc.texi
|
||||
-makeinfo $<
|
||||
|
||||
# in tests subdir
|
||||
export LIBCRT
|
||||
export LIBTCC1
|
||||
|
||||
%est:
|
||||
$(MAKE) -C tests $@ 'PROGS_CROSS=$(PROGS_CROSS)'
|
||||
@ -348,7 +348,7 @@ export LIBCRT
|
||||
clean:
|
||||
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.exe libtcc_test$(EXESUF)
|
||||
$(MAKE) -C tests $@
|
||||
ifneq ($(LIBCRT),)
|
||||
ifneq ($(LIBTCC1),)
|
||||
$(MAKE) -C lib $@
|
||||
endif
|
||||
|
||||
|
93
arm-gen.c
93
arm-gen.c
@ -61,7 +61,7 @@
|
||||
#define RC_IRET RC_R0 /* function return: integer register */
|
||||
#define RC_LRET RC_R1 /* function return: second integer register */
|
||||
#define RC_FRET RC_F0 /* function return: float register */
|
||||
#define RC_MASK (RC_INT|RC_FLOAT)
|
||||
|
||||
/* pretty names for the registers */
|
||||
enum {
|
||||
TREG_R0 = 0,
|
||||
@ -540,14 +540,6 @@ void load(int r, SValue *sv)
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
uint32_t base = 0xB; // fp
|
||||
if(fr & VT_TMP){
|
||||
int size, align;
|
||||
if((ft & VT_BTYPE) == VT_FUNC)
|
||||
size = PTR_SIZE;
|
||||
else
|
||||
size = type_size(&sv->type, &align);
|
||||
loc_stack(size, 0);
|
||||
}
|
||||
if(v == VT_LLOCAL) {
|
||||
v1.type.t = VT_PTR;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
@ -1417,60 +1409,37 @@ void gjmp_addr(int a)
|
||||
/* generate a test. set 'inv' to invert test. Stack entry is popped */
|
||||
int gtst(int inv, int t)
|
||||
{
|
||||
int v, r;
|
||||
uint32_t op;
|
||||
v = vtop->r & VT_VALMASK;
|
||||
r=ind;
|
||||
if (v == VT_CMP) {
|
||||
op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
|
||||
op|=encbranch(r,t,1);
|
||||
o(op);
|
||||
t=r;
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
if ((v & 1) == inv) {
|
||||
if(!vtop->c.i)
|
||||
vtop->c.i=t;
|
||||
else {
|
||||
uint32_t *x;
|
||||
int p,lp;
|
||||
if(t) {
|
||||
p = vtop->c.i;
|
||||
do {
|
||||
p = decbranch(lp=p);
|
||||
} while(p);
|
||||
x = (uint32_t *)(cur_text_section->data + lp);
|
||||
*x &= 0xff000000;
|
||||
*x |= encbranch(lp,t,1);
|
||||
}
|
||||
t = vtop->c.i;
|
||||
}
|
||||
} else {
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
int v, r;
|
||||
uint32_t op;
|
||||
v = vtop->r & VT_VALMASK;
|
||||
r=ind;
|
||||
if (v == VT_CMP) {
|
||||
op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
|
||||
op|=encbranch(r,t,1);
|
||||
o(op);
|
||||
t=r;
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
if ((v & 1) == inv) {
|
||||
if(!vtop->c.i)
|
||||
vtop->c.i=t;
|
||||
else {
|
||||
uint32_t *x;
|
||||
int p,lp;
|
||||
if(t) {
|
||||
p = vtop->c.i;
|
||||
do {
|
||||
p = decbranch(lp=p);
|
||||
} while(p);
|
||||
x = (uint32_t *)(cur_text_section->data + lp);
|
||||
*x &= 0xff000000;
|
||||
*x |= encbranch(lp,t,1);
|
||||
}
|
||||
t = vtop->c.i;
|
||||
}
|
||||
} else {
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t)) {
|
||||
r=gv(RC_FLOAT);
|
||||
#ifdef TCC_ARM_VFP
|
||||
o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */
|
||||
o(0xEEF1FA10); /* fmstat */
|
||||
#else
|
||||
o(0xEE90F118|(fpr(r)<<16));
|
||||
#endif
|
||||
vtop->r = VT_CMP;
|
||||
vtop->c.i = TOK_NE;
|
||||
return gtst(inv, t);
|
||||
} else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
v = gv(RC_INT);
|
||||
o(0xE3300000|(intr(v)<<16));
|
||||
vtop->r = VT_CMP;
|
||||
vtop->c.i = TOK_NE;
|
||||
return gtst(inv, t);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
|
44
c67-gen.c
44
c67-gen.c
@ -58,7 +58,7 @@
|
||||
#define RC_IRET RC_C67_A4 /* function return: integer register */
|
||||
#define RC_LRET RC_C67_A5 /* function return: second integer register */
|
||||
#define RC_FRET RC_C67_A4 /* function return: float register */
|
||||
#define RC_MASK (RC_INT|RC_FLOAT)
|
||||
|
||||
/* pretty names for the registers */
|
||||
enum {
|
||||
TREG_EAX = 0, // really A2
|
||||
@ -1571,21 +1571,12 @@ void load(int r, SValue * sv)
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
if(fr & VT_TMP){
|
||||
int size, align;
|
||||
if((ft & VT_BTYPE) == VT_FUNC)
|
||||
size = PTR_SIZE;
|
||||
else
|
||||
size = type_size(&sv->type, &align);
|
||||
loc_stack(size, 0);
|
||||
}
|
||||
if (v == VT_LLOCAL) {
|
||||
v1.type.t = VT_INT;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
v1.c.ul = fc;
|
||||
load(r, &v1);
|
||||
fr = r;
|
||||
fc = 0;
|
||||
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
||||
tcc_error("long double not supported");
|
||||
} else if ((ft & VT_TYPE) == VT_BYTE) {
|
||||
@ -2111,7 +2102,7 @@ int gtst(int inv, int t)
|
||||
C67_NOP(5);
|
||||
t = ind1; //return where we need to patch
|
||||
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -2137,37 +2128,6 @@ int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t)) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
// I think we need to get the value on the stack
|
||||
// into a register, test it, and generate a branch
|
||||
// return the address of the branch, so it can be
|
||||
// later patched
|
||||
|
||||
v = gv(RC_INT); // get value into a reg
|
||||
ind1 = ind;
|
||||
C67_MVKL(C67_A0, t); //r=reg to load, constant
|
||||
C67_MVKH(C67_A0, t); //r=reg to load, constant
|
||||
|
||||
if (v != TREG_EAX && // check if not already in a conditional test reg
|
||||
v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
|
||||
C67_MV(v, C67_B2);
|
||||
v = C67_B2;
|
||||
}
|
||||
|
||||
C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A0
|
||||
C67_NOP(5);
|
||||
t = ind1; //return where we need to patch
|
||||
ind1 = ind;
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
|
@ -239,36 +239,6 @@ static const uint16_t op0_codes[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef PRINTF_ASM_CODE
|
||||
void printf_asm_opcode(){
|
||||
const ASMInstr *pa;
|
||||
int freq[4];
|
||||
int op_vals[500];
|
||||
int nb_op_vals, i, j;
|
||||
nb_op_vals = 0;
|
||||
memset(freq, 0, sizeof(freq));
|
||||
for(pa = asm_instrs; pa->sym != 0; pa++) {
|
||||
freq[pa->nb_ops]++;
|
||||
for(i=0;i<pa->nb_ops;i++) {
|
||||
for(j=0;j<nb_op_vals;j++) {
|
||||
if (pa->op_type[i] == op_vals[j])
|
||||
goto found;
|
||||
}
|
||||
op_vals[nb_op_vals++] = pa->op_type[i];
|
||||
found: ;
|
||||
}
|
||||
}
|
||||
for(i=0;i<nb_op_vals;i++) {
|
||||
int v = op_vals[i];
|
||||
if ((v & (v - 1)) != 0)
|
||||
printf("%3d: %08x\n", i, v);
|
||||
}
|
||||
printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
|
||||
(int)sizeof(asm_instrs), (int)sizeof(asm_instrs) / sizeof(ASMInstr),
|
||||
freq[0], freq[1], freq[2], freq[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int get_reg_shift(TCCState *s1)
|
||||
{
|
||||
int shift, v;
|
||||
@ -746,8 +716,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
||||
g(b >> 8);
|
||||
g(b);
|
||||
return;
|
||||
} else if (opcode <= TOK_ASM_alllast) {
|
||||
tcc_error("bad operand with opcode '%s'", get_tok_str(opcode, NULL));
|
||||
} else if (opcode <= TOK_ASM_alllast) {
|
||||
tcc_error("bad operand with opcode '%s'",
|
||||
get_tok_str(opcode, NULL));
|
||||
} else {
|
||||
tcc_error("unknown opcode '%s'",
|
||||
get_tok_str(opcode, NULL));
|
||||
@ -1098,7 +1069,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
uint8_t regs_allocated[NB_ASM_REGS];
|
||||
|
||||
/* init fields */
|
||||
for(i=0; i<nb_operands; i++) {
|
||||
for(i=0;i<nb_operands;i++) {
|
||||
op = &operands[i];
|
||||
op->input_index = -1;
|
||||
op->ref_index = -1;
|
||||
@ -1108,7 +1079,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
}
|
||||
/* compute constraint priority and evaluate references to output
|
||||
constraints if input constraints */
|
||||
for(i=0; i<nb_operands; i++) {
|
||||
for(i=0;i<nb_operands;i++) {
|
||||
op = &operands[i];
|
||||
str = op->constraint;
|
||||
str = skip_constraint_modifiers(str);
|
||||
@ -1528,4 +1499,4 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
||||
tcc_error("invalid clobber register '%s'", str);
|
||||
}
|
||||
clobber_regs[reg] = 1;
|
||||
}
|
||||
}
|
190
i386-gen.c
190
i386-gen.c
@ -21,7 +21,7 @@
|
||||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
/* number of available registers */
|
||||
#define NB_REGS 8
|
||||
#define NB_REGS 4
|
||||
#define NB_ASM_REGS 8
|
||||
|
||||
/* a register can belong to several classes. The classes must be
|
||||
@ -33,24 +33,17 @@
|
||||
#define RC_ST0 0x0008
|
||||
#define RC_ECX 0x0010
|
||||
#define RC_EDX 0x0020
|
||||
#define RC_EBX 0x0040
|
||||
#define RC_ESI 0x0080
|
||||
#define RC_EDI 0x0100
|
||||
#define RC_INT2 0x0200
|
||||
#define RC_IRET RC_EAX /* function return: integer register */
|
||||
#define RC_LRET RC_EDX /* function return: second integer register */
|
||||
#define RC_FRET RC_ST0 /* function return: float register */
|
||||
#define RC_MASK (RC_INT|RC_INT2|RC_FLOAT)
|
||||
|
||||
/* pretty names for the registers */
|
||||
enum {
|
||||
TREG_EAX = 0,
|
||||
TREG_ECX,
|
||||
TREG_EDX,
|
||||
TREG_EBX,
|
||||
TREG_ESP,
|
||||
TREG_ST0,
|
||||
TREG_ESI,
|
||||
TREG_EDI,
|
||||
TREG_ESP = 4
|
||||
};
|
||||
|
||||
/* return registers for function */
|
||||
@ -97,14 +90,10 @@ enum {
|
||||
#include "tcc.h"
|
||||
|
||||
ST_DATA const int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_EAX | RC_INT2,
|
||||
/* ecx */ RC_INT | RC_ECX | RC_INT2,
|
||||
/* eax */ RC_INT | RC_EAX,
|
||||
/* ecx */ RC_INT | RC_ECX,
|
||||
/* edx */ RC_INT | RC_EDX,
|
||||
RC_INT|RC_INT2|RC_EBX,
|
||||
0,
|
||||
/* st0 */ RC_FLOAT | RC_ST0,
|
||||
RC_ESI|RC_INT2,
|
||||
RC_EDI|RC_INT2,
|
||||
};
|
||||
|
||||
static unsigned long func_sub_sp_offset;
|
||||
@ -237,14 +226,6 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
if(fr & VT_TMP){
|
||||
int size, align;
|
||||
if((ft & VT_BTYPE) == VT_FUNC)
|
||||
size = PTR_SIZE;
|
||||
else
|
||||
size = type_size(&sv->type, &align);
|
||||
loc_stack(size, 0);
|
||||
}
|
||||
if (v == VT_LLOCAL) {
|
||||
v1.type.t = VT_INT;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
@ -253,7 +234,6 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
if (!(reg_classes[fr] & RC_INT))
|
||||
fr = get_reg(RC_INT);
|
||||
load(fr, &v1);
|
||||
fc = 0;
|
||||
}
|
||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||
o(0xd9); /* flds */
|
||||
@ -697,7 +677,7 @@ ST_FUNC int gtst(int inv, int t)
|
||||
/* fast case : can jump directly since flags are set */
|
||||
g(0x0f);
|
||||
t = psym((vtop->c.i - 16) ^ inv, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -710,23 +690,6 @@ ST_FUNC int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t) ||
|
||||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
v = gv(RC_INT);
|
||||
o(0x85);
|
||||
o(0xc0 + v * 9);
|
||||
g(0x0f);
|
||||
t = psym(0x85 ^ inv, t);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
@ -735,48 +698,40 @@ ST_FUNC int gtst(int inv, int t)
|
||||
/* generate an integer binary operation */
|
||||
ST_FUNC void gen_opi(int op)
|
||||
{
|
||||
int r, fr, opc, fc, c;
|
||||
int cc, uu, tt2;
|
||||
|
||||
fr = vtop[0].r;
|
||||
fc = vtop->c.ul;
|
||||
cc = (fr & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
||||
tt2 = (fr & (VT_LVAL | VT_LVAL_TYPE)) == VT_LVAL;
|
||||
int r, fr, opc, c;
|
||||
|
||||
switch(op) {
|
||||
case '+':
|
||||
case TOK_ADDC1: /* add with carry generation */
|
||||
opc = 0;
|
||||
gen_op8:
|
||||
vswap();
|
||||
r = gv(RC_INT);
|
||||
vswap();
|
||||
if (cc) {
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant case */
|
||||
vswap();
|
||||
r = gv(RC_INT);
|
||||
vswap();
|
||||
c = vtop->c.i;
|
||||
if (c == (char)c) {
|
||||
/* generate inc and dec for smaller code */
|
||||
if (c == 1 && opc == 0) {
|
||||
if (c==1 && opc==0) {
|
||||
o (0x40 | r); // inc
|
||||
} else if (c == 1 && opc == 5) {
|
||||
} else if (c==1 && opc==5) {
|
||||
o (0x48 | r); // dec
|
||||
} else {
|
||||
o(0x83);
|
||||
o(0xc0 + r + opc*8);
|
||||
o(0xc0 | (opc << 3) | r);
|
||||
g(c);
|
||||
}
|
||||
} else {
|
||||
o(0x81);
|
||||
oad(0xc0 + r+ opc*8, c);
|
||||
oad(0xc0 | (opc << 3) | r, c);
|
||||
}
|
||||
} else {
|
||||
if(!tt2)
|
||||
fr = gv(RC_INT);
|
||||
o(0x03 + opc*8);
|
||||
if(fr >= VT_CONST)
|
||||
gen_modrm(r, fr, vtop->sym, fc);
|
||||
else
|
||||
o(0xc0 + fr + r*8);
|
||||
gv2(RC_INT, RC_INT);
|
||||
r = vtop[-1].r;
|
||||
fr = vtop[0].r;
|
||||
o((opc << 3) | 0x01);
|
||||
o(0xc0 + r + fr * 8);
|
||||
}
|
||||
vtop--;
|
||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||
@ -804,28 +759,12 @@ ST_FUNC void gen_opi(int op)
|
||||
opc = 1;
|
||||
goto gen_op8;
|
||||
case '*':
|
||||
opc = 5;
|
||||
vswap();
|
||||
r = gv(RC_INT);
|
||||
vswap();
|
||||
if(!tt2)
|
||||
fr = gv(RC_INT);
|
||||
if(r == TREG_EAX){
|
||||
if(fr != TREG_EDX)
|
||||
save_reg(TREG_EDX);
|
||||
o(0xf7);
|
||||
if(fr >= VT_CONST)
|
||||
gen_modrm(opc, fr, vtop->sym, fc);
|
||||
else
|
||||
o(0xc0 + fr + opc*8);
|
||||
}else{
|
||||
o(0xaf0f); /* imul fr, r */
|
||||
if(fr >= VT_CONST)
|
||||
gen_modrm(r, fr, vtop->sym, fc);
|
||||
else
|
||||
o(0xc0 + fr + r*8);
|
||||
}
|
||||
gv2(RC_INT, RC_INT);
|
||||
r = vtop[-1].r;
|
||||
fr = vtop[0].r;
|
||||
vtop--;
|
||||
o(0xaf0f); /* imul fr, r */
|
||||
o(0xc0 + fr + r * 8);
|
||||
break;
|
||||
case TOK_SHL:
|
||||
opc = 4;
|
||||
@ -836,71 +775,56 @@ ST_FUNC void gen_opi(int op)
|
||||
case TOK_SAR:
|
||||
opc = 7;
|
||||
gen_shift:
|
||||
if (cc) {
|
||||
opc = 0xc0 | (opc << 3);
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant case */
|
||||
vswap();
|
||||
r = gv(RC_INT);
|
||||
vswap();
|
||||
c = vtop->c.i;
|
||||
if(c == 1){
|
||||
o(0xd1);
|
||||
o(0xc0 + r + opc*8);
|
||||
}else{
|
||||
o(0xc1); /* shl/shr/sar $xxx, r */
|
||||
o(0xc0 + r + opc*8);
|
||||
g(c & 0x1f);
|
||||
}
|
||||
c = vtop->c.i & 0x1f;
|
||||
o(0xc1); /* shl/shr/sar $xxx, r */
|
||||
o(opc | r);
|
||||
g(c);
|
||||
} else {
|
||||
/* we generate the shift in ecx */
|
||||
gv2(RC_INT, RC_ECX);
|
||||
r = vtop[-1].r;
|
||||
o(0xd3); /* shl/shr/sar %cl, r */
|
||||
o(0xc0 + r + opc*8);
|
||||
o(opc | r);
|
||||
}
|
||||
vtop--;
|
||||
break;
|
||||
case TOK_UMOD:
|
||||
opc = 4;
|
||||
uu = 1;
|
||||
goto divmod;
|
||||
case TOK_UDIV:
|
||||
case TOK_UMULL:
|
||||
opc = 6;
|
||||
uu = 1;
|
||||
goto divmod;
|
||||
case '/':
|
||||
case '%':
|
||||
case TOK_UDIV:
|
||||
case TOK_PDIV:
|
||||
opc = 7;
|
||||
uu = 0;
|
||||
divmod:
|
||||
case '%':
|
||||
case TOK_UMOD:
|
||||
case TOK_UMULL:
|
||||
/* first operand must be in eax */
|
||||
/* XXX: need better constraint for second operand */
|
||||
if(!tt2){
|
||||
gv2(RC_EAX, RC_INT2);
|
||||
fr = vtop[0].r;
|
||||
}else{
|
||||
vswap();
|
||||
gv(RC_EAX);
|
||||
vswap();
|
||||
}
|
||||
save_reg(TREG_EDX);
|
||||
if (op == TOK_UMULL) {
|
||||
gv2(RC_EAX, RC_ECX);
|
||||
r = vtop[-1].r;
|
||||
fr = vtop[0].r;
|
||||
vtop--;
|
||||
save_reg(TREG_EDX);
|
||||
if (op == TOK_UMULL) {
|
||||
o(0xf7); /* mul fr */
|
||||
vtop->r2 = TREG_EDX;
|
||||
}else{
|
||||
o(uu ? 0xd231 : 0x99); /* xor %edx,%edx : cdq RDX:RAX <- sign-extend of RAX. */
|
||||
o(0xf7); /* div fr, %eax */
|
||||
}
|
||||
if(fr >= VT_CONST)
|
||||
gen_modrm(opc, fr, vtop->sym, fc);
|
||||
else
|
||||
o(0xc0 + fr + opc*8);
|
||||
if (op == '%' || op == TOK_UMOD)
|
||||
r = TREG_EDX;
|
||||
else
|
||||
o(0xe0 + fr);
|
||||
vtop->r2 = TREG_EDX;
|
||||
r = TREG_EAX;
|
||||
vtop--;
|
||||
} else {
|
||||
if (op == TOK_UDIV || op == TOK_UMOD) {
|
||||
o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
|
||||
o(0xf0 + fr);
|
||||
} else {
|
||||
o(0xf799); /* cltd, idiv fr, %eax */
|
||||
o(0xf8 + fr);
|
||||
}
|
||||
if (op == '%' || op == TOK_UMOD)
|
||||
r = TREG_EDX;
|
||||
else
|
||||
r = TREG_EAX;
|
||||
}
|
||||
vtop->r = r;
|
||||
break;
|
||||
default:
|
||||
|
15
il-gen.c
15
il-gen.c
@ -516,7 +516,7 @@ int gtst(int inv, int t)
|
||||
break;
|
||||
}
|
||||
t = out_opj(c, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -529,19 +529,6 @@ int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->t)) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
v = gv(RC_INT);
|
||||
t = out_opj(IL_OP_BRTRUE - inv, t);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
|
16
lib/Makefile
16
lib/Makefile
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Tiny C Compiler Makefile for libcrt.a
|
||||
# Tiny C Compiler Makefile for libtcc1.a
|
||||
#
|
||||
|
||||
TOP = ..
|
||||
@ -38,15 +38,15 @@ endif
|
||||
|
||||
DIR = $(TARGET)
|
||||
|
||||
native : ../libcrt.a
|
||||
cross : $(DIR)/libcrt.a
|
||||
native : ../libtcc1.a
|
||||
cross : $(DIR)/libtcc1.a
|
||||
|
||||
native : TCC = $(TOP)/tcc$(EXESUF)
|
||||
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
|
||||
|
||||
I386_O = libcrt.o alloca86.o alloca86-bt.o $(BCHECK_O)
|
||||
X86_64_O = libcrt.o alloca86_64.o
|
||||
ARM_O = libcrt.o armeabi.o alloca-arm.o
|
||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
|
||||
X86_64_O = libtcc1.o alloca86_64.o
|
||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o
|
||||
WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
|
||||
@ -83,7 +83,7 @@ ifeq "$(TARGET)" "arm"
|
||||
TGT = -DTCC_TARGET_ARM
|
||||
XCC ?= $(TCC) -B$(TOP)
|
||||
else
|
||||
$(error libcrt.a not supported on target '$(TARGET)')
|
||||
$(error libtcc1.a not supported on target '$(TARGET)')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@ -102,7 +102,7 @@ ifdef XAR
|
||||
AR = $(XAR)
|
||||
endif
|
||||
|
||||
$(DIR)/libcrt.a ../libcrt.a : $(OBJ) $(XAR)
|
||||
$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
|
||||
$(AR) rcs $@ $(OBJ)
|
||||
$(DIR)/%.o : %.c
|
||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
@ -533,24 +533,23 @@ unsigned long long __fixunssfdi (float a1)
|
||||
register union float_long fl1;
|
||||
register int exp;
|
||||
register unsigned long l;
|
||||
int s;
|
||||
|
||||
fl1.f = a1;
|
||||
|
||||
if (fl1.l == 0)
|
||||
return 0;
|
||||
return (0);
|
||||
|
||||
exp = EXP (fl1.l) - EXCESS - 24;
|
||||
|
||||
l = MANT(fl1.l);
|
||||
s = SIGN(fl1.l)? -1: 1;
|
||||
if (exp >= 64)
|
||||
if (exp >= 41)
|
||||
return (unsigned long long)-1;
|
||||
else if (exp >= 0)
|
||||
return ((unsigned long long)l << exp)*s;
|
||||
return (unsigned long long)l << exp;
|
||||
else if (exp >= -23)
|
||||
return (l >> -exp)*s;
|
||||
return l >> -exp;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long long __fixunsdfdi (double a1)
|
||||
@ -558,7 +557,7 @@ unsigned long long __fixunsdfdi (double a1)
|
||||
register union double_long dl1;
|
||||
register int exp;
|
||||
register unsigned long long l;
|
||||
int s;
|
||||
|
||||
dl1.d = a1;
|
||||
|
||||
if (dl1.ll == 0)
|
||||
@ -567,15 +566,15 @@ unsigned long long __fixunsdfdi (double a1)
|
||||
exp = EXPD (dl1) - EXCESSD - 53;
|
||||
|
||||
l = MANTD_LL(dl1);
|
||||
s = SIGND(dl1)? -1: 1;
|
||||
if (exp >= 64)
|
||||
|
||||
if (exp >= 12)
|
||||
return (unsigned long long)-1;
|
||||
else if (exp >= 0)
|
||||
return (l << exp)*s;
|
||||
return l << exp;
|
||||
else if (exp >= -52)
|
||||
return (l >> -exp)*s;
|
||||
return l >> -exp;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long long __fixunsxfdi (long double a1)
|
||||
@ -583,24 +582,22 @@ unsigned long long __fixunsxfdi (long double a1)
|
||||
register union ldouble_long dl1;
|
||||
register int exp;
|
||||
register unsigned long long l;
|
||||
int s;
|
||||
|
||||
dl1.ld = a1;
|
||||
|
||||
if (dl1.l.lower == 0 && dl1.l.upper == 0)
|
||||
return (0);
|
||||
|
||||
exp = EXPLD (dl1) - EXCESSLD - 64;
|
||||
s = SIGNLD(dl1)? -1: 1;
|
||||
|
||||
l = dl1.l.lower;
|
||||
|
||||
if (exp >= 64)
|
||||
if (exp > 0)
|
||||
return (unsigned long long)-1;
|
||||
else if (exp >= 0)
|
||||
return ((unsigned long long)l << exp)*s;
|
||||
else if (exp >= -64)
|
||||
return (l >> -exp)*s;
|
||||
else if (exp >= -63)
|
||||
return l >> -exp;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long __fixsfdi (float a1)
|
||||
@ -640,7 +637,7 @@ extern void abort(void);
|
||||
#endif
|
||||
|
||||
enum __va_arg_type {
|
||||
__va_gen_reg, __va_float_reg, __va_ld_reg, __va_stack
|
||||
__va_gen_reg, __va_float_reg, __va_stack
|
||||
};
|
||||
|
||||
//This should be in sync with the declaration on our include/stdarg.h
|
||||
@ -691,11 +688,10 @@ void *__va_arg(__va_list_struct *ap,
|
||||
size = 8;
|
||||
goto use_overflow_area;
|
||||
|
||||
case __va_ld_reg:
|
||||
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
|
||||
case __va_stack:
|
||||
use_overflow_area:
|
||||
ap->overflow_arg_area += size;
|
||||
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
|
||||
return ap->overflow_arg_area - size;
|
||||
|
||||
default:
|
12
libtcc.c
12
libtcc.c
@ -52,10 +52,10 @@ ST_DATA struct TCCState *tcc_state;
|
||||
#include "x86_64-gen.c"
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#include "asmx86.c"
|
||||
#endif
|
||||
#include "tccasm.c"
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#include "i386-asm.c"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef TCC_TARGET_COFF
|
||||
#include "tcccoff.c"
|
||||
@ -868,7 +868,6 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
||||
static void tcc_cleanup(void)
|
||||
{
|
||||
int i, n;
|
||||
CSym *def;
|
||||
if (NULL == tcc_state)
|
||||
return;
|
||||
tcc_state = NULL;
|
||||
@ -878,11 +877,8 @@ static void tcc_cleanup(void)
|
||||
|
||||
/* free tokens */
|
||||
n = tok_ident - TOK_IDENT;
|
||||
for(i = 0; i < n; i++){
|
||||
def = &table_ident[i]->sym_define;
|
||||
tcc_free(def->data);
|
||||
for(i = 0; i < n; i++)
|
||||
tcc_free(table_ident[i]);
|
||||
}
|
||||
tcc_free(table_ident);
|
||||
|
||||
/* free sym_pools */
|
||||
|
40
tcc.h
40
tcc.h
@ -39,7 +39,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef CONFIG_TCCASSERT
|
||||
#include <assert.h>
|
||||
@ -148,7 +147,6 @@
|
||||
/* #define MEM_DEBUG */
|
||||
/* assembler debug */
|
||||
/* #define ASM_DEBUG */
|
||||
/* #define PRINTF_ASM_CODE */
|
||||
|
||||
/* target selection */
|
||||
/* #define TCC_TARGET_I386 *//* i386 code generator */
|
||||
@ -276,7 +274,7 @@
|
||||
# define DEFAULT_ELFINTERP(s) default_elfinterp(s)
|
||||
#endif
|
||||
|
||||
/* library to use with CONFIG_USE_LIBGCC instead of libcrt.a */
|
||||
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
|
||||
#define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -305,22 +303,15 @@
|
||||
#define VSTACK_SIZE 256
|
||||
#define STRING_MAX_SIZE 1024
|
||||
#define PACK_STACK_SIZE 8
|
||||
#define MACRO_STACK_SIZE 4
|
||||
|
||||
#define TOK_HASH_SIZE 8192 /* must be a power of two */
|
||||
#define TOK_ALLOC_INCR 512 /* must be a power of two */
|
||||
#define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
|
||||
|
||||
typedef struct CSym {
|
||||
int off;
|
||||
int size;/* size in *sym */
|
||||
struct Sym **data; /* if non NULL, data has been malloced */
|
||||
} CSym;
|
||||
|
||||
/* token symbol management */
|
||||
typedef struct TokenSym {
|
||||
struct TokenSym *hash_next;
|
||||
struct CSym sym_define; /* direct pointer to define */
|
||||
struct Sym *sym_define; /* direct pointer to define */
|
||||
struct Sym *sym_label; /* direct pointer to label */
|
||||
struct Sym *sym_struct; /* direct pointer to structure */
|
||||
struct Sym *sym_identifier; /* direct pointer to identifier */
|
||||
@ -366,8 +357,8 @@ typedef union CValue {
|
||||
/* value on stack */
|
||||
typedef struct SValue {
|
||||
CType type; /* type */
|
||||
unsigned int r; /* register + flags */
|
||||
unsigned int r2; /* second register, used for 'long long'
|
||||
unsigned short r; /* register + flags */
|
||||
unsigned short r2; /* second register, used for 'long long'
|
||||
type. If not used, set to VT_CONST */
|
||||
CValue c; /* constant, if VT_CONST */
|
||||
struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
|
||||
@ -747,21 +738,19 @@ struct TCCState {
|
||||
#define VT_CMP 0x0033 /* the value is stored in processor flags (in vc) */
|
||||
#define VT_JMP 0x0034 /* value is the consequence of jmp true (even) */
|
||||
#define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */
|
||||
#define TREG_MEM 0x0040 /* x86_64-gen.c add for tcc.h: The current value can be */
|
||||
#define VT_REF 0x0080 /* value is pointer to structure rather than address */
|
||||
#define VT_REF 0x0040 /* value is pointer to structure rather than address */
|
||||
#define VT_LVAL 0x0100 /* var is an lvalue */
|
||||
#define VT_SYM 0x0200 /* a symbol value is added */
|
||||
#define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
|
||||
char/short stored in integer registers) */
|
||||
#define VT_MUSTBOUND 0x0800 /* bound checking must be done before
|
||||
dereferencing value */
|
||||
#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
|
||||
bounding function call point is in vc */
|
||||
#define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
|
||||
#define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
|
||||
#define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
|
||||
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
|
||||
#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
|
||||
bounding function call point is in vc */
|
||||
#define VT_TMP 0x10000 /* luck or tmp stack */
|
||||
|
||||
/* types */
|
||||
#define VT_BTYPE 0x000f /* mask for basic type */
|
||||
@ -789,7 +778,6 @@ struct TCCState {
|
||||
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
||||
#define VT_DEFSIGN 0x2000 /* signed type */
|
||||
#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
||||
#define VT_VLS 0x00080000 /* VLA type (also has VT_PTR and VT_STRUCT) */
|
||||
|
||||
/* storage */
|
||||
#define VT_EXTERN 0x00000080 /* extern definition */
|
||||
@ -800,14 +788,14 @@ struct TCCState {
|
||||
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
|
||||
#define VT_WEAK 0x00010000 /* weak symbol */
|
||||
#define VT_TLS 0x00040000 /* thread-local storage */
|
||||
#define VT_VIS_SHIFT 20 /* shift for symbol visibility, overlapping
|
||||
#define VT_VIS_SHIFT 19 /* shift for symbol visibility, overlapping
|
||||
bitfield values, because bitfields never
|
||||
have linkage and hence never have
|
||||
visibility. */
|
||||
#define VT_VIS_SIZE 2 /* We have four visibilities. */
|
||||
#define VT_VIS_MASK (((1 << VT_VIS_SIZE)-1) << VT_VIS_SHIFT)
|
||||
|
||||
#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (max: 32 - 2*6) */
|
||||
#define VT_STRUCT_SHIFT 19 /* shift for bitfield shift values (max: 32 - 2*6) */
|
||||
|
||||
|
||||
/* type mask (except storage) */
|
||||
@ -1136,8 +1124,7 @@ ST_DATA TokenSym **table_ident;
|
||||
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) */
|
||||
#define PARSE_FLAG_PACK 0x0020 /* #pragma pack */
|
||||
#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);
|
||||
@ -1195,7 +1182,7 @@ ST_DATA Sym *define_stack;
|
||||
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
|
||||
ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop;
|
||||
#define vstack (__vstack + 1)
|
||||
ST_DATA int rsym, anon_sym, ind, loc, ex_rc;
|
||||
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 */
|
||||
@ -1205,14 +1192,12 @@ ST_DATA int func_var; /* true if current function is variadic */
|
||||
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 int pop_stack;
|
||||
|
||||
ST_INLN int is_float(int t);
|
||||
ST_FUNC int ieee_finite(double d);
|
||||
ST_FUNC void test_lvalue(void);
|
||||
ST_FUNC void swap(int *p, int *q);
|
||||
ST_FUNC void vpushi(int v);
|
||||
ST_FUNC void vpushs(addr_t 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);
|
||||
@ -1246,9 +1231,6 @@ ST_FUNC void gexpr(void);
|
||||
ST_FUNC int expr_const(void);
|
||||
ST_FUNC void gen_inline_functions(void);
|
||||
ST_FUNC void decl(int l);
|
||||
ST_FUNC void vdup(void);
|
||||
ST_FUNC void gaddrof(void);
|
||||
ST_FUNC int loc_stack(int size, int is_sub);
|
||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
|
||||
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
|
||||
#endif
|
||||
|
49
tccasm.c
49
tccasm.c
@ -20,6 +20,7 @@
|
||||
|
||||
#include "tcc.h"
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
|
||||
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
{
|
||||
char buf[64];
|
||||
@ -482,7 +483,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
case TOK_ASM_globl:
|
||||
case TOK_ASM_global:
|
||||
case TOK_ASM_weak:
|
||||
case TOK_ASM_hidden:
|
||||
case TOK_ASM_hidden:
|
||||
tok1 = tok;
|
||||
do {
|
||||
Sym *sym;
|
||||
@ -493,12 +494,12 @@ static void asm_parse_directive(TCCState *s1)
|
||||
sym = label_push(&s1->asm_labels, tok, 0);
|
||||
sym->type.t = VT_VOID;
|
||||
}
|
||||
if (tok1 != TOK_ASM_hidden)
|
||||
if (tok1 != TOK_ASM_hidden)
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
if (tok1 == TOK_ASM_weak)
|
||||
sym->type.t |= VT_WEAK;
|
||||
else if (tok1 == TOK_ASM_hidden)
|
||||
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
|
||||
else if (tok1 == TOK_ASM_hidden)
|
||||
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
|
||||
next();
|
||||
} while (tok == ',');
|
||||
break;
|
||||
@ -696,15 +697,42 @@ static void asm_parse_directive(TCCState *s1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* assemble a file */
|
||||
static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
{
|
||||
int opcode;
|
||||
|
||||
#ifdef PRINTF_ASM_CODE
|
||||
ST_FUNC void printf_asm_opcode();
|
||||
#if 0
|
||||
/* print stats about opcodes */
|
||||
printf_asm_opcode();
|
||||
{
|
||||
const ASMInstr *pa;
|
||||
int freq[4];
|
||||
int op_vals[500];
|
||||
int nb_op_vals, i, j;
|
||||
|
||||
nb_op_vals = 0;
|
||||
memset(freq, 0, sizeof(freq));
|
||||
for(pa = asm_instrs; pa->sym != 0; pa++) {
|
||||
freq[pa->nb_ops]++;
|
||||
for(i=0;i<pa->nb_ops;i++) {
|
||||
for(j=0;j<nb_op_vals;j++) {
|
||||
if (pa->op_type[i] == op_vals[j])
|
||||
goto found;
|
||||
}
|
||||
op_vals[nb_op_vals++] = pa->op_type[i];
|
||||
found: ;
|
||||
}
|
||||
}
|
||||
for(i=0;i<nb_op_vals;i++) {
|
||||
int v = op_vals[i];
|
||||
if ((v & (v - 1)) != 0)
|
||||
printf("%3d: %08x\n", i, v);
|
||||
}
|
||||
printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
|
||||
sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
|
||||
freq[0], freq[1], freq[2], freq[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: undefine C labels */
|
||||
@ -786,8 +814,9 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
|
||||
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
||||
symbols can be safely used */
|
||||
put_elf_sym(symtab_section, 0, 0, ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
||||
SHN_ABS, file->filename);
|
||||
put_elf_sym(symtab_section, 0, 0,
|
||||
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
||||
SHN_ABS, file->filename);
|
||||
|
||||
ret = tcc_assemble_internal(s1, do_preprocess);
|
||||
|
||||
@ -1090,4 +1119,4 @@ ST_FUNC void asm_global_instr(void)
|
||||
|
||||
cstr_free(&astr);
|
||||
}
|
||||
#endif /* CONFIG_TCC_ASM */
|
||||
#endif /* CONFIG_TCC_ASM */
|
||||
|
12
tccelf.c
12
tccelf.c
@ -1443,16 +1443,16 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
#ifdef CONFIG_USE_LIBGCC
|
||||
if (!s1->static_link) {
|
||||
tcc_add_file(s1, TCC_LIBGCC);
|
||||
tcc_add_support(s1, "libcrt.a");
|
||||
tcc_add_support(s1, "libtcc1.a");
|
||||
} else
|
||||
tcc_add_support(s1, "libcrt.a");
|
||||
tcc_add_support(s1, "libtcc1.a");
|
||||
#else
|
||||
tcc_add_support(s1, "libcrt.a");
|
||||
tcc_add_support(s1, "libtcc1.a");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* tcc_add_bcheck tries to relocate a call to __bound_init in _init so
|
||||
libcrt.a must be loaded before for __bound_init to be defined and
|
||||
libtcc1.a must be loaded before for __bound_init to be defined and
|
||||
crtn.o must be loaded after to not finalize _init too early. */
|
||||
tcc_add_bcheck(s1);
|
||||
|
||||
@ -1596,7 +1596,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
|
||||
put32(s1->got->data + offset, sym->st_value & 0xffffffff);
|
||||
}
|
||||
|
||||
/* Perform relocation to GOT or PLT entries */
|
||||
/* Perform relocation to GOT or PLT entries */
|
||||
ST_FUNC void fill_got(TCCState *s1)
|
||||
{
|
||||
Section *s;
|
||||
@ -2469,7 +2469,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
/* Perform relocation to GOT or PLT entries */
|
||||
/* Perform relocation to GOT or PLT entries */
|
||||
if (file_type == TCC_OUTPUT_EXE && s1->static_link)
|
||||
fill_got(s1);
|
||||
|
||||
|
2
tccpe.c
2
tccpe.c
@ -1773,7 +1773,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||
|
||||
if (0 == s1->nostdlib) {
|
||||
static const char *libs[] = {
|
||||
"libcrt.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||
"libtcc1.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||
};
|
||||
const char **pp, *p;
|
||||
for (pp = libs; 0 != (p = *pp); ++pp) {
|
||||
|
302
tccpp.c
302
tccpp.c
@ -233,10 +233,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
|
||||
ts = tcc_malloc(sizeof(TokenSym) + len);
|
||||
table_ident[i] = ts;
|
||||
ts->tok = tok_ident++;
|
||||
ts->sym_define.data = tcc_malloc(sizeof(Sym**));
|
||||
ts->sym_define.off = 0;
|
||||
ts->sym_define.data[0] = NULL;
|
||||
ts->sym_define.size = 1;
|
||||
ts->sym_define = NULL;
|
||||
ts->sym_label = NULL;
|
||||
ts->sym_struct = NULL;
|
||||
ts->sym_identifier = NULL;
|
||||
@ -1055,62 +1052,52 @@ static int macro_is_equal(const int *a, const int *b)
|
||||
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
|
||||
{
|
||||
Sym *s;
|
||||
CSym *def;
|
||||
|
||||
s = define_find(v);
|
||||
if (s && !macro_is_equal(s->d, str))
|
||||
tcc_warning("%s redefined", get_tok_str(v, NULL));
|
||||
|
||||
s = sym_push2(&define_stack, v, macro_type, 0);
|
||||
s->d = str;
|
||||
s->next = first_arg;
|
||||
def = &table_ident[v - TOK_IDENT]->sym_define;
|
||||
def->data[def->off] = s;
|
||||
table_ident[v - TOK_IDENT]->sym_define = s;
|
||||
}
|
||||
|
||||
/* undefined a define symbol. Its name is just set to zero */
|
||||
ST_FUNC void define_undef(Sym *s)
|
||||
{
|
||||
int v;
|
||||
CSym *def;
|
||||
v = s->v - TOK_IDENT;
|
||||
if ((unsigned)v < (unsigned)(tok_ident - TOK_IDENT)){
|
||||
def = &table_ident[v]->sym_define;
|
||||
def->data[def->off] = NULL;
|
||||
}
|
||||
v = s->v;
|
||||
if (v >= TOK_IDENT && v < tok_ident)
|
||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
||||
s->v = 0;
|
||||
}
|
||||
|
||||
ST_INLN Sym *define_find(int v)
|
||||
{
|
||||
CSym *def;
|
||||
v -= TOK_IDENT;
|
||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||
return NULL;
|
||||
def = &table_ident[v]->sym_define;
|
||||
return def->data[def->off];
|
||||
return table_ident[v]->sym_define;
|
||||
}
|
||||
|
||||
/* free define stack until top reaches 'b' */
|
||||
ST_FUNC void free_defines(Sym *b)
|
||||
{
|
||||
Sym *top, *tmp;
|
||||
Sym *top, *top1;
|
||||
int v;
|
||||
CSym *def;
|
||||
|
||||
top = define_stack;
|
||||
while (top != b) {
|
||||
tmp = top->prev;
|
||||
top1 = top->prev;
|
||||
/* do not free args or predefined defines */
|
||||
if (top->d)
|
||||
tok_str_free(top->d);
|
||||
v = top->v - TOK_IDENT;
|
||||
if ((unsigned)v < (unsigned)(tok_ident - TOK_IDENT)){
|
||||
def = &table_ident[v]->sym_define;
|
||||
if(def->off)
|
||||
def->off = 0;
|
||||
if(def->data[0])
|
||||
def->data[0] = NULL;
|
||||
}
|
||||
v = top->v;
|
||||
if (v >= TOK_IDENT && v < tok_ident)
|
||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
||||
sym_free(top);
|
||||
top = tmp;
|
||||
top = top1;
|
||||
}
|
||||
define_stack = b;
|
||||
}
|
||||
@ -1351,18 +1338,66 @@ static inline void add_cached_include(TCCState *s1, const char *filename, int if
|
||||
s1->cached_includes_hash[h] = s1->nb_cached_includes;
|
||||
}
|
||||
|
||||
static void pragma_parse(TCCState *s1)
|
||||
{
|
||||
int val;
|
||||
|
||||
next();
|
||||
if (tok == TOK_pack) {
|
||||
/*
|
||||
This may be:
|
||||
#pragma pack(1) // set
|
||||
#pragma pack() // reset to default
|
||||
#pragma pack(push,1) // push & set
|
||||
#pragma pack(pop) // restore previous
|
||||
*/
|
||||
next();
|
||||
skip('(');
|
||||
if (tok == TOK_ASM_pop) {
|
||||
next();
|
||||
if (s1->pack_stack_ptr <= s1->pack_stack) {
|
||||
stk_error:
|
||||
tcc_error("out of pack stack");
|
||||
}
|
||||
s1->pack_stack_ptr--;
|
||||
} else {
|
||||
val = 0;
|
||||
if (tok != ')') {
|
||||
if (tok == TOK_ASM_push) {
|
||||
next();
|
||||
if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
|
||||
goto stk_error;
|
||||
s1->pack_stack_ptr++;
|
||||
skip(',');
|
||||
}
|
||||
if (tok != TOK_CINT) {
|
||||
pack_error:
|
||||
tcc_error("invalid pack pragma");
|
||||
}
|
||||
val = tokc.i;
|
||||
if (val < 1 || val > 16 || (val & (val - 1)) != 0)
|
||||
goto pack_error;
|
||||
next();
|
||||
}
|
||||
*s1->pack_stack_ptr = val;
|
||||
skip(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* is_bof is true if first non space token at beginning of file */
|
||||
ST_FUNC void preprocess(int is_bof)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
int i, c, n, saved_parse_flags;
|
||||
uint8_t buf[1024], *p;
|
||||
char buf[1024], *q;
|
||||
Sym *s;
|
||||
|
||||
saved_parse_flags = parse_flags;
|
||||
parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_LINEFEED;
|
||||
parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
|
||||
PARSE_FLAG_LINEFEED;
|
||||
next_nomacro();
|
||||
redo:
|
||||
redo:
|
||||
switch(tok) {
|
||||
case TOK_DEFINE:
|
||||
next_nomacro();
|
||||
@ -1385,21 +1420,19 @@ redo:
|
||||
goto read_name;
|
||||
} else if (ch == '\"') {
|
||||
c = ch;
|
||||
read_name:
|
||||
read_name:
|
||||
inp();
|
||||
p = buf;
|
||||
q = buf;
|
||||
while (ch != c && ch != '\n' && ch != CH_EOF) {
|
||||
if ((p - buf) < sizeof(buf) - 1)
|
||||
*p++ = ch;
|
||||
if ((q - buf) < sizeof(buf) - 1)
|
||||
*q++ = ch;
|
||||
if (ch == '\\') {
|
||||
if (handle_stray_noerror() == 0)
|
||||
--p;
|
||||
--q;
|
||||
} else
|
||||
inp();
|
||||
}
|
||||
if (ch != c)
|
||||
goto include_syntax;
|
||||
*p = '\0';
|
||||
*q = '\0';
|
||||
minp();
|
||||
#if 0
|
||||
/* eat all spaces and comments after include */
|
||||
@ -1437,8 +1470,6 @@ read_name:
|
||||
c = '>';
|
||||
}
|
||||
}
|
||||
if(!buf[0])
|
||||
tcc_error(" empty filename in #include");
|
||||
|
||||
if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
|
||||
tcc_error("#include recursion too deep");
|
||||
@ -1505,7 +1536,8 @@ include_trynext:
|
||||
printf("%s: including %s\n", file->prev->filename, file->filename);
|
||||
#endif
|
||||
/* update target deps */
|
||||
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, tcc_strdup(buf1));
|
||||
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
|
||||
tcc_strdup(buf1));
|
||||
/* push current file in stack */
|
||||
++s1->include_stack_ptr;
|
||||
/* add include file debug info */
|
||||
@ -1538,7 +1570,7 @@ include_done:
|
||||
file->ifndef_macro = tok;
|
||||
}
|
||||
}
|
||||
c = !!define_find(tok) ^ c;
|
||||
c = (define_find(tok) != 0) ^ c;
|
||||
do_if:
|
||||
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
|
||||
tcc_error("memory full (ifdef)");
|
||||
@ -1562,12 +1594,12 @@ include_done:
|
||||
goto skip;
|
||||
c = expr_preprocess();
|
||||
s1->ifdef_stack_ptr[-1] = c;
|
||||
test_else:
|
||||
test_else:
|
||||
if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1)
|
||||
file->ifndef_macro = 0;
|
||||
test_skip:
|
||||
test_skip:
|
||||
if (!(c & 1)) {
|
||||
skip:
|
||||
skip:
|
||||
preprocess_skip();
|
||||
is_bof = 0;
|
||||
goto redo;
|
||||
@ -1585,11 +1617,11 @@ skip:
|
||||
/* need to set to zero to avoid false matches if another
|
||||
#ifndef at middle of file */
|
||||
file->ifndef_macro = 0;
|
||||
while (tok != TOK_LINEFEED)
|
||||
next_nomacro();
|
||||
tok_flags |= TOK_FLAG_ENDIF;
|
||||
goto the_end;
|
||||
}
|
||||
next_nomacro();
|
||||
if (tok != TOK_LINEFEED)
|
||||
tcc_warning("Ignoring: %s", get_tok_str(tok, &tokc));
|
||||
break;
|
||||
case TOK_LINE:
|
||||
next();
|
||||
@ -1600,7 +1632,8 @@ skip:
|
||||
if (tok != TOK_LINEFEED) {
|
||||
if (tok != TOK_STR)
|
||||
tcc_error("#line");
|
||||
pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.cstr->data);
|
||||
pstrcpy(file->filename, sizeof(file->filename),
|
||||
(char *)tokc.cstr->data);
|
||||
}
|
||||
break;
|
||||
case TOK_ERROR:
|
||||
@ -1608,161 +1641,24 @@ skip:
|
||||
c = tok;
|
||||
ch = file->buf_ptr[0];
|
||||
skip_spaces();
|
||||
p = buf;
|
||||
q = buf;
|
||||
while (ch != '\n' && ch != CH_EOF) {
|
||||
if ((p - buf) < sizeof(buf) - 1)
|
||||
*p++ = ch;
|
||||
if ((q - buf) < sizeof(buf) - 1)
|
||||
*q++ = ch;
|
||||
if (ch == '\\') {
|
||||
if (handle_stray_noerror() == 0)
|
||||
--p;
|
||||
--q;
|
||||
} else
|
||||
inp();
|
||||
}
|
||||
*p = '\0';
|
||||
*q = '\0';
|
||||
if (c == TOK_ERROR)
|
||||
tcc_error("#error %s", buf);
|
||||
else
|
||||
tcc_warning("#warning %s", buf);
|
||||
break;
|
||||
case TOK_PRAGMA:
|
||||
next();
|
||||
if (tok == TOK_pack && parse_flags & PARSE_FLAG_PACK) {
|
||||
/*
|
||||
This may be:
|
||||
#pragma pack(1) // set
|
||||
#pragma pack() // reset to default
|
||||
#pragma pack(push,1) // push & set
|
||||
#pragma pack(pop) // restore previous
|
||||
*/
|
||||
next();
|
||||
skip('(');
|
||||
if (tok == TOK_ASM_pop) {
|
||||
next();
|
||||
if (s1->pack_stack_ptr <= s1->pack_stack) {
|
||||
stk_error:
|
||||
tcc_error("out of pack stack");
|
||||
}
|
||||
s1->pack_stack_ptr--;
|
||||
} else {
|
||||
int val = 0;
|
||||
if (tok != ')') {
|
||||
if (tok == TOK_ASM_push) {
|
||||
next();
|
||||
s1->pack_stack_ptr++;
|
||||
if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE)
|
||||
goto stk_error;
|
||||
skip(',');
|
||||
}
|
||||
if (tok != TOK_CINT) {
|
||||
pack_error:
|
||||
tcc_error("invalid pack pragma");
|
||||
}
|
||||
val = tokc.i;
|
||||
if (val < 1 || val > 16)
|
||||
goto pack_error;
|
||||
if (val < 1 || val > 16)
|
||||
tcc_error("Value must be greater than 1 is less than or equal to 16");
|
||||
if ((val & (val - 1)) != 0)
|
||||
tcc_error("Value must be a power of 2 curtain");
|
||||
next();
|
||||
}
|
||||
*s1->pack_stack_ptr = val;
|
||||
skip(')');
|
||||
}
|
||||
}else if (tok == TOK_PUSH_MACRO || tok == TOK_POP_MACRO) {
|
||||
TokenSym *ts;
|
||||
CSym *def;
|
||||
uint8_t *p1;
|
||||
int len, t;
|
||||
t = tok;
|
||||
ch = file->buf_ptr[0];
|
||||
skip_spaces();
|
||||
if (ch != '(')
|
||||
goto macro_xxx_syntax;
|
||||
/* XXX: incorrect if comments : use next_nomacro with a special mode */
|
||||
inp();
|
||||
skip_spaces();
|
||||
if (ch == '\"'){
|
||||
inp();
|
||||
p = buf;
|
||||
while (ch != '\"' && ch != '\n' && ch != CH_EOF) {
|
||||
if ((p - buf) < sizeof(buf) - 1)
|
||||
*p++ = ch;
|
||||
if (ch == CH_EOB) {
|
||||
--p;
|
||||
handle_stray();
|
||||
}else
|
||||
inp();
|
||||
}
|
||||
if(ch != '\"')
|
||||
goto macro_xxx_syntax;
|
||||
*p = '\0';
|
||||
minp();
|
||||
next();
|
||||
}else{
|
||||
/* computed #pragma macro_xxx for #define xxx */
|
||||
next();
|
||||
buf[0] = '\0';
|
||||
while (tok != ')') {
|
||||
if (tok != TOK_STR) {
|
||||
macro_xxx_syntax:
|
||||
tcc_error("'macro_xxx' expects (\"NAME\")");
|
||||
}
|
||||
pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
|
||||
next();
|
||||
}
|
||||
}
|
||||
skip (')');
|
||||
if(!buf[0])
|
||||
tcc_error(" empty string in #pragma");
|
||||
/* find TokenSym */
|
||||
p = buf;
|
||||
while (is_space(*p))
|
||||
p++;
|
||||
p1 = p;
|
||||
for(;;){
|
||||
if (!isidnum_table[p[0] - CH_EOF])
|
||||
break;
|
||||
++p;
|
||||
}
|
||||
len = p - p1;
|
||||
while (is_space(*p))
|
||||
p++;
|
||||
if(!p) //'\0'
|
||||
tcc_error("unrecognized string: %s", buf);
|
||||
ts = tok_alloc(p1, len);
|
||||
if(ts){
|
||||
def = &ts->sym_define;
|
||||
if(t == TOK_PUSH_MACRO){
|
||||
void *tmp = def->data[def->off];
|
||||
if(tmp){
|
||||
def->off++;
|
||||
if(def->off >= def->size){
|
||||
int size = def->size;
|
||||
size *= 2;
|
||||
if (size >= MACRO_STACK_SIZE)
|
||||
tcc_error("stack full");
|
||||
def->data = tcc_realloc(def->data, size*sizeof(Sym**));
|
||||
def->size = size;
|
||||
}
|
||||
def->data[def->off] = tmp;
|
||||
}
|
||||
}else{
|
||||
if(def->off){
|
||||
--def->off;
|
||||
}else{
|
||||
tcc_warning("stack empty");
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
fputs("#pragma ", s1->ppfp);
|
||||
while (tok != TOK_LINEFEED){
|
||||
fputs(get_tok_str(tok, &tokc), s1->ppfp);
|
||||
next();
|
||||
}
|
||||
goto the_end;
|
||||
}
|
||||
pragma_parse(s1);
|
||||
break;
|
||||
default:
|
||||
if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_PPNUM) {
|
||||
@ -1782,7 +1678,7 @@ pack_error:
|
||||
/* ignore other preprocess commands or #! for C scripts */
|
||||
while (tok != TOK_LINEFEED)
|
||||
next_nomacro();
|
||||
the_end:
|
||||
the_end:
|
||||
parse_flags = saved_parse_flags;
|
||||
}
|
||||
|
||||
@ -3134,13 +3030,12 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
|
||||
ch = file->buf_ptr[0];
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
||||
PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
|
||||
PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
|
||||
token_seen = 0;
|
||||
line_ref = 0;
|
||||
file_ref = NULL;
|
||||
iptr = s1->include_stack_ptr;
|
||||
tok = TOK_LINEFEED; /* print line */
|
||||
goto print_line;
|
||||
|
||||
for (;;) {
|
||||
next();
|
||||
if (tok == TOK_EOF) {
|
||||
@ -3148,11 +3043,11 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
|
||||
} else if (file != file_ref) {
|
||||
goto print_line;
|
||||
} else if (tok == TOK_LINEFEED) {
|
||||
if (token_seen)
|
||||
if (!token_seen)
|
||||
continue;
|
||||
++line_ref;
|
||||
token_seen = 1;
|
||||
} else if (token_seen) {
|
||||
token_seen = 0;
|
||||
} else if (!token_seen) {
|
||||
d = file->line_num - line_ref;
|
||||
if (file != file_ref || d < 0 || d >= 8) {
|
||||
print_line:
|
||||
@ -3160,7 +3055,8 @@ print_line:
|
||||
s = iptr_new > iptr ? " 1"
|
||||
: iptr_new < iptr ? " 2"
|
||||
: iptr_new > s1->include_stack ? " 3"
|
||||
: "";
|
||||
: ""
|
||||
;
|
||||
iptr = iptr_new;
|
||||
fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
|
||||
} else {
|
||||
@ -3168,8 +3064,8 @@ print_line:
|
||||
fputs("\n", s1->ppfp), --d;
|
||||
}
|
||||
line_ref = (file_ref = file)->line_num;
|
||||
token_seen = tok == TOK_LINEFEED;
|
||||
if (token_seen)
|
||||
token_seen = tok != TOK_LINEFEED;
|
||||
if (!token_seen)
|
||||
continue;
|
||||
}
|
||||
fputs(get_tok_str(tok, &tokc), s1->ppfp);
|
||||
|
4
tcctok.h
4
tcctok.h
@ -138,8 +138,6 @@
|
||||
|
||||
/* pragma */
|
||||
DEF(TOK_pack, "pack")
|
||||
DEF(TOK_PUSH_MACRO, "push_macro")
|
||||
DEF(TOK_POP_MACRO, "pop_macro")
|
||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64)
|
||||
/* already defined for assembler */
|
||||
DEF(TOK_ASM_push, "push")
|
||||
@ -287,5 +285,5 @@
|
||||
#endif
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#include "asmx86-tok.h"
|
||||
#include "i386-tok.h"
|
||||
#endif
|
||||
|
@ -66,11 +66,11 @@ RUN_TCC = $(NATIVE_DEFINES) -DONE_SOURCE -run $(top_srcdir)/tcc.c $(TCCFLAGS)
|
||||
DISAS = objdump -d
|
||||
|
||||
# libtcc test
|
||||
ifdef LIBCRT
|
||||
LIBCRT:=$(TOP)/$(LIBCRT)
|
||||
ifdef LIBTCC1
|
||||
LIBTCC1:=$(TOP)/$(LIBTCC1)
|
||||
endif
|
||||
|
||||
all test : clean $(TESTS)
|
||||
all test : $(TESTS)
|
||||
|
||||
hello-exe: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
@ -89,7 +89,7 @@ hello-run: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run $<
|
||||
|
||||
libtest: libtcc_test$(EXESUF) $(LIBCRT)
|
||||
libtest: libtcc_test$(EXESUF) $(LIBTCC1)
|
||||
@echo ------------ $@ ------------
|
||||
./libtcc_test$(EXESUF) lib_path=..
|
||||
|
||||
@ -101,7 +101,7 @@ moretests:
|
||||
$(MAKE) -C tests2
|
||||
|
||||
w32-prep:
|
||||
cp ../libcrt.a ../lib
|
||||
cp ../libtcc1.a ../lib
|
||||
|
||||
# test.ref - generate using cc
|
||||
test.ref: tcctest.c
|
||||
@ -210,14 +210,10 @@ abitest-cc$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC)
|
||||
abitest-tcc$(EXESUF): abitest.c libtcc.c
|
||||
$(TCC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) -DONE_SOURCE $(LIBS) $(LDFLAGS) -I$(top_srcdir)
|
||||
|
||||
abitest-tcc1$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC)
|
||||
$(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS) -I$(top_srcdir)
|
||||
|
||||
abitest: abitest-cc$(EXESUF) abitest-tcc$(EXESUF) abitest-tcc1$(EXESUF)
|
||||
abitest: abitest-cc$(EXESUF) abitest-tcc$(EXESUF)
|
||||
@echo ------------ $@ ------------
|
||||
./abitest-cc$(EXESUF) lib_path=.. include="$(top_srcdir)/include"
|
||||
./abitest-tcc$(EXESUF) lib_path=.. include="$(top_srcdir)/include"
|
||||
./abitest-tcc1$(EXESUF) lib_path=.. include="$(top_srcdir)/include"
|
||||
|
||||
vla_test$(EXESUF): vla_test.c
|
||||
$(TCC) -o $@ $^ $(CPPFLAGS) $(CFLAGS)
|
||||
@ -244,6 +240,6 @@ cache: tcc_g
|
||||
clean:
|
||||
$(MAKE) -C tests2 $@
|
||||
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc \
|
||||
*-cc *-tcc *.exe *-tcc1\
|
||||
*-cc *-tcc *.exe \
|
||||
hello libtcc_test vla_test tcctest[1234] ex? tcc_g tcclib.h \
|
||||
../lib/libcrt.a
|
||||
../lib/libtcc1.a
|
||||
|
@ -468,7 +468,7 @@ int main(int argc, char **argv) {
|
||||
const char *testname = NULL;
|
||||
int retval = EXIT_SUCCESS;
|
||||
|
||||
/* if tcclib.h and libcrt.a are not installed, where can we find them */
|
||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (!memcmp(argv[i], "lib_path=",9))
|
||||
tccdir = argv[i] + 9;
|
||||
|
@ -43,7 +43,7 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* if tcclib.h and libcrt.a are not installed, where can we find them */
|
||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||
if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
|
||||
tcc_set_lib_path(s, argv[1]+9);
|
||||
|
||||
|
@ -235,7 +235,7 @@ void intdiv_test(void)
|
||||
|
||||
void macro_test(void)
|
||||
{
|
||||
printf("macro:\n");
|
||||
printf("macro:\n");
|
||||
pf("N=%d\n", N);
|
||||
printf("aaa=%d\n", AAA);
|
||||
|
||||
@ -379,23 +379,6 @@ comment
|
||||
/* And again when the name and parenthes are separated by a
|
||||
comment. */
|
||||
TEST2 /* the comment */ ();
|
||||
/* macro_push and macro_pop test */
|
||||
#define MACRO_TEST "macro_test1\n"
|
||||
#pragma push_macro("MACRO_TEST")
|
||||
#undef MACRO_TEST
|
||||
#define MACRO_TEST "macro_test2\n"
|
||||
printf(MACRO_TEST);
|
||||
#pragma pop_macro("MACRO_TEST")
|
||||
printf(MACRO_TEST);
|
||||
/* gcc does not support
|
||||
#define MACRO_TEST_MACRO "MACRO_TEST"
|
||||
#pragma push_macro(MACRO_TEST_MACRO)
|
||||
#undef MACRO_TEST
|
||||
#define MACRO_TEST "macro_test3\n"
|
||||
printf(MACRO_TEST);
|
||||
#pragma pop_macro(MACRO_TEST_MACRO)
|
||||
printf(MACRO_TEST);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -1697,6 +1680,7 @@ void prefix ## fcast(type a)\
|
||||
printf("ftof: %f %f %Lf\n", fa, da, la);\
|
||||
ia = (int)a;\
|
||||
llia = (long long)a;\
|
||||
a = (a >= 0) ? a : -a;\
|
||||
ua = (unsigned int)a;\
|
||||
llua = (unsigned long long)a;\
|
||||
printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\
|
||||
@ -1726,18 +1710,6 @@ void prefix ## call(void)\
|
||||
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
|
||||
}\
|
||||
\
|
||||
void prefix ## calc(type x, type y)\
|
||||
{\
|
||||
x=x*x;y=y*y;\
|
||||
printf("%d, %d\n", (int)x, (int)y);\
|
||||
x=x-y;y=y-x;\
|
||||
printf("%d, %d\n", (int)x, (int)y);\
|
||||
x=x/y;y=y/x;\
|
||||
printf("%d, %d\n", (int)x, (int)y);\
|
||||
x=x+x;y=y+y;\
|
||||
printf("%d, %d\n", (int)x, (int)y);\
|
||||
}\
|
||||
\
|
||||
void prefix ## signed_zeros(void) \
|
||||
{\
|
||||
type x = 0.0, y = -0.0, n, p;\
|
||||
@ -1760,7 +1732,7 @@ void prefix ## signed_zeros(void) \
|
||||
1.0 / x != 1.0 / p);\
|
||||
else\
|
||||
printf ("x != +y; this is wrong!\n");\
|
||||
p = -y;\
|
||||
p = -y;\
|
||||
if (x == p)\
|
||||
printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\
|
||||
1.0 / x != 1.0 / p);\
|
||||
@ -1776,8 +1748,7 @@ void prefix ## test(void)\
|
||||
prefix ## fcast(234.6);\
|
||||
prefix ## fcast(-2334.6);\
|
||||
prefix ## call();\
|
||||
prefix ## calc(1, 1.0000000000000001);\
|
||||
prefix ## signed_zeros();\
|
||||
prefix ## signed_zeros();\
|
||||
}
|
||||
|
||||
FTEST(f, float, float, "%f")
|
||||
@ -2184,15 +2155,14 @@ void whitespace_test(void)
|
||||
{
|
||||
char *str;
|
||||
|
||||
|
||||
#if 1
|
||||
#if 1
|
||||
pri\
|
||||
ntf("whitspace:\n");
|
||||
ntf("whitspace:\n");
|
||||
#endif
|
||||
pf("N=%d\n", 2);
|
||||
|
||||
#ifdef CORRECT_CR_HANDLING
|
||||
pri\
|
||||
pri\
|
||||
ntf("aaa=%d\n", 3);
|
||||
#endif
|
||||
|
||||
@ -2204,12 +2174,11 @@ ntf("min=%d\n", 4);
|
||||
printf("len1=%d\n", strlen("
|
||||
"));
|
||||
#ifdef CORRECT_CR_HANDLING
|
||||
str = "
|
||||
str = "
|
||||
";
|
||||
printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
|
||||
#endif
|
||||
printf("len1=%d\n", strlen("
|
||||
a
|
||||
printf("len1=%d\n", strlen("
a
|
||||
"));
|
||||
#endif /* ACCEPT_CR_IN_STRINGS */
|
||||
}
|
||||
@ -2603,6 +2572,7 @@ int constant_p_var;
|
||||
|
||||
void builtin_test(void)
|
||||
{
|
||||
#if GCC_MAJOR >= 3
|
||||
COMPAT_TYPE(int, int);
|
||||
COMPAT_TYPE(int, unsigned int);
|
||||
COMPAT_TYPE(int, char);
|
||||
@ -2612,9 +2582,9 @@ void builtin_test(void)
|
||||
COMPAT_TYPE(int *, void *);
|
||||
COMPAT_TYPE(int *, const int *);
|
||||
COMPAT_TYPE(char *, unsigned char *);
|
||||
COMPAT_TYPE(char, unsigned char);
|
||||
/* space is needed because tcc preprocessor introduces a space between each token */
|
||||
COMPAT_TYPE(char **, void *);
|
||||
COMPAT_TYPE(char * *, void *);
|
||||
#endif
|
||||
printf("res = %d\n", __builtin_constant_p(1));
|
||||
printf("res = %d\n", __builtin_constant_p(1 + 2));
|
||||
printf("res = %d\n", __builtin_constant_p(&constant_p_var));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This program is for making libcrt.a without ar
|
||||
* This program is for making libtcc1.a without ar
|
||||
* tiny_libmaker - tiny elf lib maker
|
||||
* usage: tiny_libmaker [lib] files...
|
||||
* Copyright (c) 2007 Timppa
|
||||
|
1378
x86_64-gen.c
1378
x86_64-gen.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user