aboutsummaryrefslogtreecommitdiff
path: root/x86_64-gen.c
diff options
context:
space:
mode:
authorjiang <30155751@qq.com>2014-05-02 23:45:48 +0800
committerjiang <30155751@qq.com>2014-05-02 23:45:48 +0800
commite647c3137d91f5daa1096b21e09d689ddf71335b (patch)
treef7544e0b50f09aa2fe800888f869196af0e1fcb6 /x86_64-gen.c
parent6c8207633fd42e420e32bdf4912be9fbf307f5ad (diff)
downloadtinycc-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.c51
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
}