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
				
			
		
							
								
								
									
										118
									
								
								tcc.c
									
										
									
									
									
								
							
							
						
						
									
										118
									
								
								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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -209,18 +211,20 @@ int gnu_ext = 1;
 | 
			
		|||
int tcc_ext = 1;
 | 
			
		||||
 | 
			
		||||
/* The current value can be: */
 | 
			
		||||
#define VT_VALMASK  0x00ff
 | 
			
		||||
#define VT_CONST    0x00f0  /* constant in vc 
 | 
			
		||||
#define VT_VALMASK   0x00ff
 | 
			
		||||
#define VT_CONST     0x00f0  /* constant in vc 
 | 
			
		||||
                              (must be first non register value) */
 | 
			
		||||
#define VT_LLOCAL   0x00f1  /* lvalue, 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_JMP      0x00f4  /* value is the consequence of jmp true (even) */
 | 
			
		||||
#define VT_JMPI     0x00f5  /* value is the consequence of jmp false (odd) */
 | 
			
		||||
#define VT_LVAL     0x0100  /* var is an lvalue */
 | 
			
		||||
#define VT_FORWARD  0x0200  /* value is forward reference */
 | 
			
		||||
#define VT_MUSTCAST 0x0400  /* value must be casted to be correct (used for
 | 
			
		||||
#define VT_LLOCAL    0x00f1  /* lvalue, 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_JMP       0x00f4  /* value is the consequence of jmp true (even) */
 | 
			
		||||
#define VT_JMPI      0x00f5  /* value is the consequence of jmp false (odd) */
 | 
			
		||||
#define VT_LVAL      0x0100  /* var is an lvalue */
 | 
			
		||||
#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