From e647c3137d91f5daa1096b21e09d689ddf71335b Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Fri, 2 May 2014 23:45:48 +0800 Subject: 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 --- x86_64-gen.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'x86_64-gen.c') 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 } -- cgit v1.3.1