diff options
| author | grischka <grischka> | 2017-07-09 12:07:40 +0200 |
|---|---|---|
| committer | grischka <grischka> | 2017-07-09 12:07:40 +0200 |
| commit | 9f79b62ec4d84d07cf4a2fba969cb67c8f6ed8e5 (patch) | |
| tree | 2ed2cab29b41d9b17c434d4a15565fb3e8387345 /x86_64-gen.c | |
| parent | 6c468c10f70d74e962591a0584765e42ce1bcaf2 (diff) | |
| download | tinycc-9f79b62ec4d84d07cf4a2fba969cb67c8f6ed8e5.tar.gz tinycc-9f79b62ec4d84d07cf4a2fba969cb67c8f6ed8e5.tar.bz2 | |
unsorted adjustments
- configure
* use aarch64 instead of arm64
- Makefile
* rename the custom include file to "config-extra.mak"
* Also avoid "rm -r /*" if $(tccdir) is empty
- pp/Makefile
* fix .expect generation with gcc
- tcc.h
* cleanup #defines for _MSC_VER
- tccgen.c:
* fix const-propagation for &,|
* fix anonymous named struct (ms-extension) and enable
-fms-extension by default
- i386-gen.c
* clear VT_DEFSIGN
- x86_64-gen.c/win64:
* fix passing structs in registers
* fix alloca (need to keep "func_scratch" below each alloca area on stack)
(This allows to compile a working gnu-make on win64)
- tccpp.c
* alternative approach to 37999a4fbf3487b363fd0c2f9b7ab622401b202a
This is to avoid some slowdown with ## token pasting.
* get_tok_str() : return <eof> for TOK_EOF
* -funsigned-char: apply to "string" literals as well
- tccpe/tools.c: -impdef: support both 32 and 64 bit dlls anyway
Diffstat (limited to 'x86_64-gen.c')
| -rw-r--r-- | x86_64-gen.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/x86_64-gen.c b/x86_64-gen.c index 19d5dd7..1873a9d 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -728,13 +728,13 @@ static int arg_prepare_reg(int idx) { return arg_regs[idx]; } -static int func_scratch; +static int func_scratch, func_alloca; /* Generate function call. The function address is pushed first, then all the parameters in call order. This functions pops all the parameters and the function address. */ -void gen_offs_sp(int b, int r, int d) +static void gen_offs_sp(int b, int r, int d) { orex(1,0,r & 0x100 ? 0 : r, b); if (d == (char)d) { @@ -746,6 +746,11 @@ void gen_offs_sp(int b, int r, int d) } } +static int using_regs(int size) +{ + return !(size > 8 || (size & (size - 1))); +} + /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) @@ -754,7 +759,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *ret_align = 1; // Never have to re-align return values for x86-64 *regsize = 8; size = type_size(vt, &align); - if (size > 8 || (size & (size - 1))) + if (!using_regs(size)) return 0; if (size == 8) ret->t = VT_LLONG; @@ -774,7 +779,7 @@ static int is_sse_float(int t) { return bt == VT_DOUBLE || bt == VT_FLOAT; } -int gfunc_arg_size(CType *type) { +static int gfunc_arg_size(CType *type) { int align; if (type->t & (VT_ARRAY|VT_BITFIELD)) return 8; @@ -801,7 +806,7 @@ void gfunc_call(int nb_args) bt = (sv->type.t & VT_BTYPE); size = gfunc_arg_size(&sv->type); - if (size <= 8) + if (using_regs(size)) continue; /* arguments smaller than 8 bytes passed in registers or on stack */ if (bt == VT_STRUCT) { @@ -835,7 +840,7 @@ void gfunc_call(int nb_args) bt = (vtop->type.t & VT_BTYPE); size = gfunc_arg_size(&vtop->type); - if (size > 8) { + if (!using_regs(size)) { /* align to stack align size */ size = (size + 15) & ~15; if (arg >= REGN) { @@ -895,6 +900,12 @@ void gfunc_call(int nb_args) } gcall_or_jmp(0); + + if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) { + /* need to add the "func_scratch" area after alloca */ + o(0x0548), gen_le32(func_alloca), func_alloca = ind - 4; + } + /* other compilers don't clear the upper bits when returning char/short */ bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED); if (bt == (VT_BYTE | VT_UNSIGNED)) @@ -926,6 +937,7 @@ void gfunc_prolog(CType *func_type) func_ret_sub = 0; func_scratch = 0; + func_alloca = 0; loc = 0; addr = PTR_SIZE * 2; @@ -940,7 +952,7 @@ void gfunc_prolog(CType *func_type) func_vt = sym->type; func_var = (sym->c == FUNC_ELLIPSIS); size = gfunc_arg_size(&func_vt); - if (size > 8) { + if (!using_regs(size)) { gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); func_vc = addr; reg_param_index++; @@ -952,7 +964,7 @@ void gfunc_prolog(CType *func_type) type = &sym->type; bt = type->t & VT_BTYPE; size = gfunc_arg_size(type); - if (size > 8) { + if (!using_regs(size)) { if (reg_param_index < REGN) { gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); } @@ -1015,6 +1027,13 @@ void gfunc_epilog(void) gen_le32(v); } + /* add the "func_scratch" area after each alloca seen */ + while (func_alloca) { + unsigned char *ptr = cur_text_section->data + func_alloca; + func_alloca = read32le(ptr); + write32le(ptr, func_scratch); + } + cur_text_section->data_offset = saved_ind; pe_add_unwind_data(ind, saved_ind, v); ind = cur_text_section->data_offset; |
