From e647c3137d91f5daa1096b21e09d689ddf71335b Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Fri, 2 May 2014 23:45:48 +0800 Subject: [PATCH] Fix x86-64 vla For example, it should look like this High stack ------------- ----- Func_ret_sub ------------ ---- Vla stack ------------- ---- Known loc -------------- Low Increased loc_stack () function is used for temporary stack management, call save_reg (), released by load () Like this Before use High ----- Known loc ---- --- ---- ---- Pop_stack Low loc_stack (size, 1) After use High ----- Known loc ---- Pop_stack --- ---- ---- Low --- tcc.h | 4 +- tccgen.c | 458 ++++++++++++++++++++++++++++++++------------------- x86_64-gen.c | 51 ++++-- 3 files changed, 322 insertions(+), 191 deletions(-) diff --git a/tcc.h b/tcc.h index 266b43a..f56273f 100644 --- a/tcc.h +++ b/tcc.h @@ -761,7 +761,7 @@ struct TCCState { #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 +#define VT_TMP 0x10000 /* luck or tmp stack */ /* types */ #define VT_BTYPE 0x000f /* mask for basic type */ @@ -1212,6 +1212,7 @@ 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); @@ -1247,6 +1248,7 @@ 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 diff --git a/tccgen.c b/tccgen.c index 456005e..9e6275e 100644 --- a/tccgen.c +++ b/tccgen.c @@ -370,7 +370,7 @@ ST_FUNC void vpushi(int v) } /* push a pointer sized constant */ -static void vpushs(addr_t v) +ST_FUNC void vpushs(addr_t v) { CValue cval; cval.ptr_offset = v; @@ -525,6 +525,41 @@ ST_FUNC void vdup(void) vpushv(vtop); } +static int align_size(int size) +{ +#ifdef TCC_TARGET_X86_64 + if(size > 4) + return 8; + else +#endif + if(size > 2) + return 4; + else if(size > 1) + return 2; + else + return 1; +} + +int loc_stack(int size, int is_sub){ + int l, align; + align = align_size(size); + size = (size + align - 1) & - align; + if(is_sub){ + pop_stack -= size; + if(pop_stack >= 0) + l = loc + pop_stack; + else{ + loc += pop_stack; + l = loc &= -align; + pop_stack = 0; + } + }else{ + pop_stack += size; + l = loc + pop_stack; + } + return l; +} + /* save r to the memory stack, and mark it as being free */ ST_FUNC void save_reg(int r) { @@ -533,57 +568,76 @@ ST_FUNC void save_reg(int r) CType *type; /* modify all stack values */ - saved = 0; - l = 0; - for(p=vstack;p<=vtop;p++) { - if ((p->r & VT_VALMASK) == r || - ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) { + l = saved = 0; + for(p = vstack; p <= vtop; p++) { +#ifdef TCC_TARGET_X86_64 + if ((p->r & VT_VALMASK) == r || + ((((p->type.t & VT_BTYPE) == VT_QLONG) || ((p->type.t & VT_BTYPE) == VT_QFLOAT)) && + ((p->r2 & VT_VALMASK) == r))) +#else + if ((p->r & VT_VALMASK) == r || ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) +#endif + { /* must save value on stack if not already done */ if (!saved) { /* NOTE: must reload 'r' because r might be equal to r2 */ r = p->r & VT_VALMASK; /* store register in the stack */ type = &p->type; - if ((p->r & VT_LVAL) || - (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG)) + if((type->t & VT_BTYPE) == VT_STRUCT){ + int ret_align; + SValue ret; + gfunc_sret(type, func_var, &ret.type, &ret_align); + type = &ret.type; + } + if ((p->r & VT_LVAL) || ((type->t & VT_BTYPE) == VT_FUNC)) #ifdef TCC_TARGET_X86_64 type = &char_pointer_type; #else type = &int_type; #endif - size = type_size(type, &align); - loc = (loc - size) & -align; - sv.type.t = type->t; + size = type_size(type, &align); + l = loc_stack(size, 1); sv.r = VT_LOCAL | VT_LVAL; - sv.c.ul = loc; - store(r, &sv); + sv.c.ul = l; +#ifdef TCC_TARGET_X86_64 + if (((type->t & VT_BTYPE) == VT_QLONG) || ((type->t & VT_BTYPE) == VT_QFLOAT)) +#else + if ((type->t & VT_BTYPE) == VT_LLONG) +#endif + { +#ifdef TCC_TARGET_X86_64 + int load_size = 8, load_type = ((type->t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE; +#else + int load_size = 4, load_type = VT_INT; +#endif + sv.type.t = load_type; + store(r, &sv); + sv.c.ul += load_size; + store(p->r2, &sv); + }else{ + sv.type.t = type->t; + store(r, &sv); + } #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) /* x86 specific: need to pop fp register ST0 if saved */ if (r == TREG_ST0) { o(0xd8dd); /* fstp %st(0) */ } #endif -#ifndef TCC_TARGET_X86_64 - /* special long long case */ - if ((type->t & VT_BTYPE) == VT_LLONG) { - sv.c.ul += 4; - store(p->r2, &sv); - } -#endif - l = loc; - saved = 1; + saved = 1; } - /* mark that stack entry as being saved on the stack */ - if (p->r & VT_LVAL) { - /* also clear the bounded flag because the - relocation address of the function was stored in - p->c.ul */ - p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL; - } else { - p->r = lvalue_type(p->type.t) | VT_LOCAL; - } - p->r2 = VT_CONST; - p->c.ul = l; + /* mark that stack entry as being saved on the stack */ + if (p->r & VT_LVAL) { + /* also clear the bounded flag because the + relocation address of the function was stored in + p->c.ul */ + p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL; + } else { + p->r = lvalue_type(p->type.t) | VT_LOCAL | VT_TMP; + } + p->r2 = VT_CONST; + p->c.ul = l; } } } @@ -613,42 +667,57 @@ ST_FUNC int get_reg_ex(int rc, int rc2) } #endif -/* find a free register of class 'rc'. If none, save one register */ -ST_FUNC int get_reg(int rc) +static int for_reg(int rc) { - int r; + int r; + SValue *p; + if(rc){ + for(r = 0; r < NB_REGS; r++) { + if (reg_classes[r] & rc) { + for(p = vstack; p <= vtop; p++) { + if ((p->r & VT_VALMASK) == r || (p->r2 & VT_VALMASK) == r) + goto notfound; + } + goto found; + } + notfound:; + } + } + r = -1; +found: + return r; +} + +/* find a free register of class 'rc'. If none, save one register */ +int get_reg(int rc) +{ + int r; SValue *p; /* find a free register */ - for(r=0;rr & VT_VALMASK) == r || - (p->r2 & VT_VALMASK) == r) - goto notfound; - } - return r; - } - notfound: ; - } - + r = for_reg(rc); + if (r != -1) + return r; /* no register left : free the first one on the stack (VERY IMPORTANT to start from the bottom to ensure that we don't spill registers used in gen_opi()) */ - for(p=vstack;p<=vtop;p++) { + for(p = vstack; p <= vtop; p++) { /* look at second register (if long long) */ + if(p->r & VT_TMP) + continue; r = p->r2 & VT_VALMASK; if (r < VT_CONST && (reg_classes[r] & rc)) goto save_found; r = p->r & VT_VALMASK; if (r < VT_CONST && (reg_classes[r] & rc)) { - save_found: - save_reg(r); +save_found: + save_reg(r); return r; } } /* Should never comes here */ - return -1; + assert(0); + return -1; } /* save registers up to (vtop - n) stack entry */ @@ -689,9 +758,7 @@ ST_FUNC void gaddrof(void) vtop->r &= ~VT_LVAL; /* tricky: if saved lvalue, then we can go back to lvalue */ if ((vtop->r & VT_VALMASK) == VT_LLOCAL) - vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL; - - + vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL| VT_TMP; } #ifdef CONFIG_TCC_BCHECK @@ -1067,8 +1134,9 @@ ST_FUNC void vrott(int n) /* pop stack value */ ST_FUNC void vpop(void) { - int v; - v = vtop->r & VT_VALMASK; + int v, fr; + fr = vtop->r; + v = fr & VT_VALMASK; #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) /* for x86, we need to pop the FP stack */ if (v == TREG_ST0 && !nocode_wanted) { @@ -1079,6 +1147,17 @@ ST_FUNC void vpop(void) /* need to put correct jump if && or || without test */ gsym(vtop->c.ul); } + if(fr & VT_TMP){ + int size, align; + SValue ret; + if((vtop->type.t & VT_BTYPE) == VT_FUNC) + size = 8; + else{ + gfunc_sret(&vtop->type, func_var, &ret.type, &align); + size = type_size(&ret.type, &align); + } + loc_stack(size, 0); + } vtop--; } @@ -2154,7 +2233,7 @@ ST_FUNC void vla_runtime_type_size(CType *type, int *a) static void vla_sp_save(void) { if (!(vla_flags & VLA_SP_LOC_SET)) { - *vla_sp_loc = (loc -= PTR_SIZE); + *vla_sp_loc = loc_stack(PTR_SIZE, 1); vla_flags |= VLA_SP_LOC_SET; } if (!(vla_flags & VLA_SP_SAVED)) { @@ -2423,6 +2502,8 @@ static void gen_assign_cast(CType *dt) if (sbt == VT_PTR || sbt == VT_FUNC) { tcc_warning("assignment makes integer from pointer without a cast"); } + if (sbt == VT_STRUCT) + goto error; /* XXX: more tests */ break; case VT_STRUCT: @@ -2466,7 +2547,7 @@ static void vstore_im(){ #else sv.type.t = VT_INT; #endif - sv.r = VT_LOCAL | VT_LVAL; + sv.r = VT_LOCAL | VT_LVAL | VT_TMP; sv.c.ul = vtop[-1].c.ul; load(t, &sv); vtop[-1].r = t | VT_LVAL; @@ -2534,7 +2615,7 @@ ST_FUNC void vstore(void) SValue ret; int ret_nregs, ret_align; ret_nregs = gfunc_sret(&vtop->type, func_var, &ret.type, &ret_align); - if(0){ + if(ret_nregs){ vswap(); vpushv(vtop - 1); vtop[0].type = ret.type; @@ -2565,7 +2646,7 @@ ST_FUNC void vstore(void) vtop->type.t = VT_PTR; gaddrof(); /* type size */ - vpushi(size); + vpushs(size); gfunc_call(3); #else /* destination */ @@ -2577,7 +2658,7 @@ ST_FUNC void vstore(void) vtop->type.t = VT_PTR; gaddrof(); /* size */ - vpushi(size); + vpushs(size); struct_copy(&vtop[-2], &vtop[-1], &vtop[0]); vtop -=3; #endif @@ -3298,7 +3379,7 @@ static void asm_label_instr(CString *astr) static void post_type(CType *type, AttributeDef *ad) { - int n, l, t1, arg_size, align; + int n, l, t1, arg_size, size, align; Sym **plast, *s, *first; AttributeDef ad1; CType pt; @@ -3402,13 +3483,12 @@ static void post_type(CType *type, AttributeDef *ad) t1 |= type->t & VT_VLA; if (t1 & VT_VLA) { - loc -= type_size(&int_type, &align); - loc &= -align; - n = loc; + size = type_size(&int_type, &align); + n = loc_stack(size, 1); vla_runtime_type_size(type, &align); gen_op('*'); - vset(&int_type, VT_LOCAL|VT_LVAL, loc); + vset(&int_type, VT_LOCAL|VT_LVAL, n); vswap(); vstore(); } @@ -4004,47 +4084,94 @@ ST_FUNC void unary(void) /* post operations */ while (1) { + SValue ret; + int ret_nregs, ret_align; if (tok == TOK_INC || tok == TOK_DEC) { inc(1, tok); next(); } else if (tok == '.' || tok == TOK_ARROW) { - int qualifiers; + int qualifiers, add, is_lval; /* field */ - if (tok == TOK_ARROW) - indir(); - qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); - test_lvalue(); - gaddrof(); - next(); - /* expect pointer on structure */ - if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) - expect("struct or union"); - s = vtop->type.ref; - /* find field */ - tok |= SYM_FIELD; - while ((s = s->next) != NULL) { - if (s->v == tok) - break; - } - if (!s) - tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL)); - /* add field offset to pointer */ - vtop->type = char_pointer_type; /* change type to 'char *' */ - vpushi(s->c); - gen_op('+'); - /* change type to field type, and set to lvalue */ - vtop->type = s->type; - vtop->type.t |= qualifiers; - /* an array is never an lvalue */ - if (!(vtop->type.t & VT_ARRAY)) { - vtop->r |= lvalue_type(vtop->type.t); -#ifdef CONFIG_TCC_BCHECK - /* if bound checking, the referenced pointer must be checked */ - if (tcc_state->do_bounds_check) - vtop->r |= VT_MUSTBOUND; + qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); + add = 0; + if (tok == TOK_ARROW) + indir(); + + type = vtop->type; + is_lval = (vtop->r & (VT_VALMASK | VT_LVAL)) >= VT_CONST; + if(is_lval){ + test_lvalue(); + gaddrof(); + vtop->type = char_pointer_type; /* change type to 'char *' */ + }else + gfunc_sret(&vtop->type, func_var, &ret.type, &ret_align); + do{ + next(); + /* expect pointer on structure */ + if ((type.t & VT_BTYPE) != VT_STRUCT) + expect("struct or union"); + s = type.ref; + /* find field */ + tok |= SYM_FIELD; + while ((s = s->next) != NULL) { + if (s->v == tok) + break; + } + if (!s) + tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL)); + /* add bit */ + add += s->c; + /* change type to field type, and set to lvalue */ + type = s->type; + next(); + }while(tok == '.'); + + type.t |= qualifiers; + if (is_lval){ + p_lval: + vpushi(add); + gen_op('+'); + /* an array is never an lvalue */ + if (!(type.t & VT_ARRAY)) { + vtop->r |= lvalue_type(type.t); + #ifdef CONFIG_TCC_BCHECK + /* if bound checking, the referenced pointer must be checked */ + if (tcc_state->do_bounds_check) + vtop->r |= VT_MUSTBOUND; + #endif + } + }else{ + gfunc_sret(&vtop->type, func_var, &ret.type, &ret_align); + if(is_float(ret.type.t) || (type.t & VT_ARRAY)){ +#ifdef TCC_TARGET_X86_64 + if((ret.type.t & VT_BTYPE) != VT_LDOUBLE) #endif - } - next(); + { + save_reg(vtop->r); + vtop->r &= ~VT_TMP; + gaddrof(); + vtop->type = char_pointer_type; /* change type to 'char *' */ + goto p_lval; + } + }else{ +#ifdef TCC_TARGET_X86_64 + int load_size = 8; +#else + int load_size = 4; +#endif + if(add & load_size){ + add -= load_size; + vtop->r = vtop->r2; + vtop->r2 = VT_CONST; + } + if(add){ + vtop->type.t = VT_LLONG; + vpushi(add*8); + gen_op(TOK_SAR); + } + } + } + vtop->type = type; } else if (tok == '[') { next(); gexpr(); @@ -4052,9 +4179,8 @@ ST_FUNC void unary(void) indir(); skip(']'); } else if (tok == '(') { - SValue ret; Sym *sa; - int nb_args, ret_nregs, ret_align, variadic; + int nb_args, variadic, addr; /* function call */ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { @@ -4072,7 +4198,6 @@ ST_FUNC void unary(void) } /* get return type */ s = vtop->type.ref; - next(); sa = s->next; /* first parameter */ nb_args = 0; ret.r2 = VT_CONST; @@ -4084,12 +4209,12 @@ ST_FUNC void unary(void) if (!ret_nregs) { /* get some space for the returned structure */ size = type_size(&s->type, &align); - loc = (loc - size) & -align; + addr = loc_stack(size, 1); ret.type = s->type; ret.r = VT_LOCAL | VT_LVAL; /* pass it as 'int' to avoid structure arg passing problems */ - vseti(VT_LOCAL, loc); + vseti(VT_LOCAL, addr); ret.c = vtop->c; nb_args++; } @@ -4117,6 +4242,7 @@ ST_FUNC void unary(void) } ret.c.i = 0; } + next(); if (tok != ')') { for(;;) { expr_eq(); @@ -4145,25 +4271,8 @@ ST_FUNC void unary(void) } /* handle packed struct return */ - if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { - int addr, offset; - - size = type_size(&s->type, &align); - loc = (loc - size) & -align; - addr = loc; - offset = 0; - for (;;) { - vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); - vswap(); - vstore(); - vtop--; - if (--ret_nregs == 0) - break; - /* XXX: compatible with arm only: ret_align == register_size */ - offset += ret_align; - } - vset(&s->type, VT_LOCAL | VT_LVAL, addr); - } + if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) + vtop->type = s->type; } else { break; } @@ -4332,8 +4441,8 @@ static void expr_lor(void) /* XXX: better constant handling */ static void expr_cond(void) { - int tt, u, r1, r2, rc, t1, t2, bt1, bt2; - SValue sv; + int tt, u, r, rc, t1, t2, bt1, bt2, ret_nregs, ret_align; + SValue sv, ret; CType type, type1, type2; if (const_wanted) { @@ -4375,8 +4484,7 @@ static void expr_cond(void) } else rc = RC_INT; - gv(rc); - save_regs(1); + save_regs(1); } if (tok == ':' && gnu_ext) { gv_dup(); @@ -4415,16 +4523,14 @@ static void expr_cond(void) (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } else if (bt1 == VT_PTR || bt2 == VT_PTR) { - /* If one is a null ptr constant the result type - is the other. */ - if (is_null_pointer (vtop)) - type = type1; - else if (is_null_pointer (&sv)) - type = type2; - /* XXX: test pointer compatibility, C99 has more elaborate - rules here. */ - else - type = type1; + /* If one is a null ptr constant the result type is the other. */ + if (is_null_pointer (vtop)) + type = type1; + else if (is_null_pointer (&sv)) + type = type2; + /* XXX: test pointer compatibility, C99 has more elaborate rules here. */ + else + type = type1; } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { /* XXX: test function pointer compatibility */ type = bt1 == VT_FUNC ? type1 : type2; @@ -4442,26 +4548,35 @@ static void expr_cond(void) (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } - + /* now we convert second operand */ gen_cast(&type); - if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) - gaddrof(); - rc = RC_INT; - if (is_float(type.t)) { + ret_nregs = 0; + if (VT_STRUCT == (type.t & VT_BTYPE)){ + ret_nregs = gfunc_sret(&type, func_var, &ret.type, &ret_align); + if(ret_nregs) + vtop->type = ret.type; + else + gaddrof(); + } + + if (is_float(vtop->type.t)) { rc = RC_FLOAT; #ifdef TCC_TARGET_X86_64 if ((type.t & VT_BTYPE) == VT_LDOUBLE) { rc = RC_ST0; } #endif - } else if ((type.t & VT_BTYPE) == VT_LLONG) { - /* for long longs, we use fixed registers to avoid having - to handle a complicated move */ - rc = RC_IRET; - } - - r2 = gv(rc); + } else + rc = RC_INT; + r = gv(rc); + rc = reg_classes[r] & ~RC_MASK; +#ifdef TCC_TARGET_X86_64 + if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) +#else + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) +#endif + ex_rc = reg_classes[vtop->r2] & ~RC_MASK; /* this is horrible, but we must also convert first operand */ tt = gjmp(0); @@ -4469,12 +4584,21 @@ static void expr_cond(void) /* put again first value and cast it */ *vtop = sv; gen_cast(&type); - if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) - gaddrof(); - r1 = gv(rc); - move_reg(r2, r1, type.t); - vtop->r = r2; + if (VT_STRUCT == (type.t & VT_BTYPE)){ + if(ret_nregs) + vtop->type = ret.type; + else + gaddrof(); + } + gv(rc); gsym(tt); + + if (VT_STRUCT == (type.t & VT_BTYPE)){ + if(ret_nregs) + vtop->type = type; + else + vtop->r |= VT_LVAL; + } } } } @@ -4747,18 +4871,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, vstore(); } else { /* returning structure packed into registers */ - int rc, size, addr, align; - size = type_size(&func_vt,&align); - if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1))) - && (align & (ret_align-1))) { - loc = (loc - size) & -align; - addr = loc; - type = func_vt; - vset(&type, VT_LOCAL | VT_LVAL, addr); - vswap(); - vstore(); - vset(&ret_type, VT_LOCAL | VT_LVAL, addr); - } + int rc; vtop->type = ret_type; if (is_float(ret_type.t)) rc = rc_fret(ret_type.t); @@ -5606,11 +5719,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, sec = NULL; #ifdef CONFIG_TCC_BCHECK if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { - loc--; + loc_stack(1, 1); } #endif - loc = (loc - size) & -align; - addr = loc; + addr = loc_stack(size, 1); #ifdef CONFIG_TCC_BCHECK /* handles bounds */ /* XXX: currently, since we do only one pass, we cannot track @@ -5618,7 +5730,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { unsigned long *bounds_ptr; /* add padding between regions */ - loc--; + loc_stack(1, 1); /* then add local bound info */ bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long)); bounds_ptr[0] = addr; diff --git a/x86_64-gen.c b/x86_64-gen.c index 0307792..7a79278 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -405,6 +405,14 @@ 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 = 8; + 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; @@ -602,6 +610,24 @@ static void gcall_or_jmp(int is_jmp) } } +static int func_scratch; +static int r_loc; + +int reloc_add(int inds) +{ + return psym(0, inds); +} + +void reloc_use(int t, int data) +{ + int *ptr; + while (t) { + ptr = (int *)(cur_text_section->data + t); + t = *ptr; /* next value */ + *ptr = data; + } +} + void struct_copy(SValue *d, SValue *s, SValue *c) { if(!c->c.i) @@ -647,9 +673,6 @@ void gen_offs_sp(int b, int r, int off) } } -static int func_scratch; -static int r_loc; - #ifdef TCC_TARGET_PE #define REGN 4 @@ -905,7 +928,7 @@ void gfunc_epilog(void) ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; /* align local size to word & save local variables */ v = (func_scratch + -loc + 15) & -16; - + reloc_use(r_loc, func_scratch); if (v >= 4096) { Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); oad(0xb8, v); /* mov stacksize, %eax */ @@ -1210,6 +1233,7 @@ doing: /* Must ensure TREG_ST0 only */ if((vtop->type.t & VT_BTYPE) == VT_STRUCT){ vdup(); + vtop[-1].r = VT_CONST; vtop->type = type; gv(RC_ST0); args_size -= size; @@ -1228,7 +1252,7 @@ doing: vpushv(&vtop[-1]); vtop->type = char_pointer_type; gaddrof(); - vpushi(size); + vpushs(size); struct_copy(&vtop[-2], &vtop[-1], &vtop[0]); vtop -= 3; break; @@ -1474,6 +1498,7 @@ void gfunc_epilog(void) } /* align local size to word & save local variables */ v = (func_scratch -loc + 15) & -16; + reloc_use(r_loc, func_scratch); saved_ind = ind; ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; o(0xe5894855); /* push %rbp, mov %rsp, %rbp */ @@ -2043,27 +2068,19 @@ ST_FUNC void gen_vla_sp_restore(int addr) { /* Subtract from the stack pointer, and push the resulting value onto the stack */ ST_FUNC void gen_vla_alloc(CType *type, int align) { -#ifdef TCC_TARGET_PE - /* alloca does more than just adjust %rsp on Windows */ - vpush_global_sym(&func_old_type, TOK_alloca); - vswap(); /* Move alloca ref past allocation size */ - gfunc_call(1); - vset(type, REG_IRET, 0); -#else int r; r = gv(RC_INT); /* allocation size */ /* sub r,%rsp */ o(0x2b48); o(0xe0 | REG_VALUE(r)); - /* We align to 16 bytes rather than align */ - /* and ~15, %rsp */ + /* and ~15, %rsp */ o(0xf0e48348); /* mov %rsp, r */ - o(0x8948); - o(0xe0 | REG_VALUE(r)); + orex(1, 0, r, 0x8d); + o(0x2484 | (REG_VALUE(r)*8)); + r_loc = reloc_add(r_loc); vpop(); vset(type, r, 0); -#endif }