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

98
tcc.c
View file

@ -163,7 +163,9 @@ int section_num;
Section *text_section, *data_section, *bss_section; /* predefined sections */
Section *cur_text_section; /* current section where function code is
generated */
/* bound check related sections */
Section *bounds_section; /* contains global data bound description */
Section *lbounds_section; /* contains local data bound description */
/* debug sections */
Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
@ -221,6 +223,8 @@ int tcc_ext = 1;
#define VT_FORWARD 0x0200 /* value is forward reference */
#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 */
/* types */
#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);
int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
int gv(int rc);
void gv2(int rc1, int rc2);
void move_reg(int r, int s);
void save_regs(void);
void save_reg(int r);
@ -2339,6 +2344,20 @@ void gaddrof(void)
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
converted to values. Cannot be used if cannot be converted to
register value (such as structures). */
@ -2377,6 +2396,9 @@ int gv(int rc)
data_offset += size << 2;
data_section->data_ptr = (unsigned char *)data_offset;
}
if (vtop->r & VT_MUSTBOUND)
gbound();
r = vtop->r & VT_VALMASK;
/* need to reload if:
- constant
@ -2436,6 +2458,33 @@ int gv(int rc)
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 */
void lexpand(void)
{
@ -2454,10 +2503,7 @@ void lexpand(void)
/* build a long long from two ints */
void lbuild(int t)
{
vswap();
gv(RC_INT);
vswap();
gv(RC_INT);
gv2(RC_INT, RC_INT);
vtop[-1].r2 = vtop[0].r;
vtop[-1].t = t;
vpop();
@ -2890,13 +2936,15 @@ void gen_op(int op)
vpushi(pointed_size(vtop[-1].t));
gen_op('*');
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 == '-') {
vpushi(0);
vswap();
gen_op('-');
}
gen_bounded_ptr_add();
gen_bounded_ptr_add1();
gen_bounded_ptr_add2(0);
} else {
gen_opc(op);
}
@ -3503,10 +3551,16 @@ void vstore(void)
/* store result */
vstore();
} else {
/* bound check case */
if (vtop[-1].r & VT_MUSTBOUND) {
vswap();
gbound();
vswap();
}
rc = RC_INT;
if (is_float(ft))
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 ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
SValue sv;
@ -4043,8 +4097,13 @@ void indir(void)
if (vtop->r & VT_LVAL)
gv(RC_INT);
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;
/* 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 */
@ -4659,7 +4718,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
} else {
gv(RC_IRET);
}
vpop();
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
}
skip(';');
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)
align = ad->aligned;
if ((r & VT_VALMASK) == VT_LOCAL) {
if (do_bounds_check && (t & VT_ARRAY))
loc--;
loc = (loc - size) & -align;
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 {
/* compute section */
sec = ad->section;
@ -5219,7 +5293,7 @@ int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
int *bounds_ptr;
/* first, we need to add at least one byte between each region */
data_offset++;
/* then add global data info */
/* then add global bound info */
bounds_ptr = (int *)bounds_section->data_ptr;
*bounds_ptr++ = addr;
*bounds_ptr++ = size;
@ -6059,9 +6133,11 @@ int main(int argc, char **argv)
} else if (r[1] == 'b') {
if (!do_bounds_check) {
do_bounds_check = 1;
/* create bounds section for global data */
/* create bounds sections */
bounds_section = new_section(".bounds",
SHT_PROGBITS, SHF_ALLOC);
lbounds_section = new_section(".lbounds",
SHT_PROGBITS, SHF_ALLOC);
/* debug is implied */
goto debug_opt;
}