finished bound check code (still slow) - fixed binary ops code gen - fixed float return
This commit is contained in:
parent
ad28d4c5b0
commit
5f85585b77
1 changed files with 97 additions and 21 deletions
98
tcc.c
98
tcc.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue