finished bound check code (still slow) - fixed binary ops code gen - fixed float return

This commit is contained in:
bellard 2002-01-05 16:15:57 +00:00
parent ad28d4c5b0
commit 5f85585b77

118
tcc.c
View file

@ -163,7 +163,9 @@ int section_num;
Section *text_section, *data_section, *bss_section; /* predefined sections */ Section *text_section, *data_section, *bss_section; /* predefined sections */
Section *cur_text_section; /* current section where function code is Section *cur_text_section; /* current section where function code is
generated */ generated */
/* bound check related sections */
Section *bounds_section; /* contains global data bound description */ Section *bounds_section; /* contains global data bound description */
Section *lbounds_section; /* contains local data bound description */
/* debug sections */ /* debug sections */
Section *stab_section, *stabstr_section, *symtab_section, *strtab_section; Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
@ -209,18 +211,20 @@ int gnu_ext = 1;
int tcc_ext = 1; int tcc_ext = 1;
/* The current value can be: */ /* The current value can be: */
#define VT_VALMASK 0x00ff #define VT_VALMASK 0x00ff
#define VT_CONST 0x00f0 /* constant in vc #define VT_CONST 0x00f0 /* constant in vc
(must be first non register value) */ (must be first non register value) */
#define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */ #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
#define VT_LOCAL 0x00f2 /* offset on stack */ #define VT_LOCAL 0x00f2 /* offset on stack */
#define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */ #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
#define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */ #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
#define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */ #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
#define VT_LVAL 0x0100 /* var is an lvalue */ #define VT_LVAL 0x0100 /* var is an lvalue */
#define VT_FORWARD 0x0200 /* value is forward reference */ #define VT_FORWARD 0x0200 /* value is forward reference */
#define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
char/short stored in integer registers) */ char/short stored in integer registers) */
#define VT_MUSTBOUND 0x0800 /* bound checking must be done before
dereferencing value */
/* types */ /* types */
#define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */ #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
@ -402,6 +406,7 @@ void decl(int l);
void decl_initializer(int t, int r, int c, int first, int size_only); void decl_initializer(int t, int r, int c, int first, int size_only);
int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init); int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
int gv(int rc); int gv(int rc);
void gv2(int rc1, int rc2);
void move_reg(int r, int s); void move_reg(int r, int s);
void save_regs(void); void save_regs(void);
void save_reg(int r); void save_reg(int r);
@ -2339,6 +2344,20 @@ void gaddrof(void)
vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL; vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
} }
/* generate lvalue bound code */
void gbound(void)
{
vtop->r &= ~VT_MUSTBOUND;
/* if lvalue, then use checking code before dereferencing */
if (vtop->r & VT_LVAL) {
gaddrof();
vpushi(0);
gen_bounded_ptr_add1();
gen_bounded_ptr_add2(1);
vtop->r |= VT_LVAL;
}
}
/* store vtop a register belonging to class 'rc'. lvalues are /* store vtop a register belonging to class 'rc'. lvalues are
converted to values. Cannot be used if cannot be converted to converted to values. Cannot be used if cannot be converted to
register value (such as structures). */ register value (such as structures). */
@ -2377,6 +2396,9 @@ int gv(int rc)
data_offset += size << 2; data_offset += size << 2;
data_section->data_ptr = (unsigned char *)data_offset; data_section->data_ptr = (unsigned char *)data_offset;
} }
if (vtop->r & VT_MUSTBOUND)
gbound();
r = vtop->r & VT_VALMASK; r = vtop->r & VT_VALMASK;
/* need to reload if: /* need to reload if:
- constant - constant
@ -2436,6 +2458,33 @@ int gv(int rc)
return r; return r;
} }
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
void gv2(int rc1, int rc2)
{
/* generate more generic register first */
if (rc1 <= rc2) {
vswap();
gv(rc1);
vswap();
gv(rc2);
/* test if reload is needed for first register */
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
vswap();
gv(rc1);
vswap();
}
} else {
gv(rc2);
vswap();
gv(rc1);
vswap();
/* test if reload is needed for first register */
if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
gv(rc2);
}
}
}
/* expand long long on stack in two int registers */ /* expand long long on stack in two int registers */
void lexpand(void) void lexpand(void)
{ {
@ -2454,10 +2503,7 @@ void lexpand(void)
/* build a long long from two ints */ /* build a long long from two ints */
void lbuild(int t) void lbuild(int t)
{ {
vswap(); gv2(RC_INT, RC_INT);
gv(RC_INT);
vswap();
gv(RC_INT);
vtop[-1].r2 = vtop[0].r; vtop[-1].r2 = vtop[0].r;
vtop[-1].t = t; vtop[-1].t = t;
vpop(); vpop();
@ -2890,13 +2936,15 @@ void gen_op(int op)
vpushi(pointed_size(vtop[-1].t)); vpushi(pointed_size(vtop[-1].t));
gen_op('*'); gen_op('*');
if (do_bounds_check) { if (do_bounds_check) {
/* if bounded pointers, we generate a special code to test bounds */ /* if bounded pointers, we generate a special code to
test bounds */
if (op == '-') { if (op == '-') {
vpushi(0); vpushi(0);
vswap(); vswap();
gen_op('-'); gen_op('-');
} }
gen_bounded_ptr_add(); gen_bounded_ptr_add1();
gen_bounded_ptr_add2(0);
} else { } else {
gen_opc(op); gen_opc(op);
} }
@ -3503,10 +3551,16 @@ void vstore(void)
/* store result */ /* store result */
vstore(); vstore();
} else { } else {
/* bound check case */
if (vtop[-1].r & VT_MUSTBOUND) {
vswap();
gbound();
vswap();
}
rc = RC_INT; rc = RC_INT;
if (is_float(ft)) if (is_float(ft))
rc = RC_FLOAT; rc = RC_FLOAT;
r = gv(rc); /* generate value (XXX: move that to store code) */ r = gv(rc); /* generate value */
/* if lvalue was saved on stack, must read it */ /* if lvalue was saved on stack, must read it */
if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
SValue sv; SValue sv;
@ -4043,8 +4097,13 @@ void indir(void)
if (vtop->r & VT_LVAL) if (vtop->r & VT_LVAL)
gv(RC_INT); gv(RC_INT);
vtop->t = pointed_type(vtop->t); vtop->t = pointed_type(vtop->t);
if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */ /* an array is never an lvalue */
if (!(vtop->t & VT_ARRAY)) {
vtop->r |= VT_LVAL; vtop->r |= VT_LVAL;
/* if bound checking, the referenced pointer must be checked */
if (do_bounds_check)
vtop->r |= VT_MUSTBOUND;
}
} }
/* pass a parameter to a function and do type checking and casting */ /* pass a parameter to a function and do type checking and casting */
@ -4659,7 +4718,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
} else { } else {
gv(RC_IRET); gv(RC_IRET);
} }
vpop(); vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
} }
skip(';'); skip(';');
rsym = gjmp(rsym); /* jmp */ rsym = gjmp(rsym); /* jmp */
@ -5195,8 +5254,23 @@ int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
if (ad->aligned > align) if (ad->aligned > align)
align = ad->aligned; align = ad->aligned;
if ((r & VT_VALMASK) == VT_LOCAL) { if ((r & VT_VALMASK) == VT_LOCAL) {
if (do_bounds_check && (t & VT_ARRAY))
loc--;
loc = (loc - size) & -align; loc = (loc - size) & -align;
addr = loc; addr = loc;
/* handles bounds */
/* XXX: currently, since we do only one pass, we cannot track
'&' operators, so we add only arrays */
if (do_bounds_check && (t & VT_ARRAY)) {
int *bounds_ptr;
/* add padding between regions */
loc--;
/* then add local bound info */
bounds_ptr = (int *)lbounds_section->data_ptr;
*bounds_ptr++ = addr;
*bounds_ptr++ = size;
lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
}
} else { } else {
/* compute section */ /* compute section */
sec = ad->section; sec = ad->section;
@ -5219,7 +5293,7 @@ int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
int *bounds_ptr; int *bounds_ptr;
/* first, we need to add at least one byte between each region */ /* first, we need to add at least one byte between each region */
data_offset++; data_offset++;
/* then add global data info */ /* then add global bound info */
bounds_ptr = (int *)bounds_section->data_ptr; bounds_ptr = (int *)bounds_section->data_ptr;
*bounds_ptr++ = addr; *bounds_ptr++ = addr;
*bounds_ptr++ = size; *bounds_ptr++ = size;
@ -6059,9 +6133,11 @@ int main(int argc, char **argv)
} else if (r[1] == 'b') { } else if (r[1] == 'b') {
if (!do_bounds_check) { if (!do_bounds_check) {
do_bounds_check = 1; do_bounds_check = 1;
/* create bounds section for global data */ /* create bounds sections */
bounds_section = new_section(".bounds", bounds_section = new_section(".bounds",
SHT_PROGBITS, SHF_ALLOC); SHT_PROGBITS, SHF_ALLOC);
lbounds_section = new_section(".lbounds",
SHT_PROGBITS, SHF_ALLOC);
/* debug is implied */ /* debug is implied */
goto debug_opt; goto debug_opt;
} }