diff options
| author | jiang <30155751@qq.com> | 2014-05-02 23:45:48 +0800 |
|---|---|---|
| committer | jiang <30155751@qq.com> | 2014-05-02 23:45:48 +0800 |
| commit | e647c3137d91f5daa1096b21e09d689ddf71335b (patch) | |
| tree | f7544e0b50f09aa2fe800888f869196af0e1fcb6 /x86_64-gen.c | |
| parent | 6c8207633fd42e420e32bdf4912be9fbf307f5ad (diff) | |
| download | tinycc-e647c3137d91f5daa1096b21e09d689ddf71335b.tar.gz tinycc-e647c3137d91f5daa1096b21e09d689ddf71335b.tar.bz2 | |
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
Diffstat (limited to 'x86_64-gen.c')
| -rw-r--r-- | x86_64-gen.c | 51 |
1 files changed, 34 insertions, 17 deletions
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 } |
