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!
master
jiang 2014-05-04 13:18:31 +08:00
parent 089dea355a
commit 5e56fb635a
23 changed files with 1416 additions and 1814 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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;

View File

@ -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)

View File

@ -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:

View File

@ -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
View File

@ -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

View File

@ -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 */

View File

@ -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);

850
tccgen.c

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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

File diff suppressed because it is too large Load Diff