mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-25 06:00:11 +08:00
Revert "fix-mixed-struct (patch by Pip Cet)"
This reverts commit 4e04f67c94
. Requested by grischka.
This commit is contained in:
parent
89ad24e7d6
commit
ef3d38c5c9
22
arm-gen.c
22
arm-gen.c
@ -34,8 +34,6 @@
|
||||
#define NB_REGS 9
|
||||
#endif
|
||||
|
||||
typedef int RegArgs;
|
||||
|
||||
#ifndef TCC_ARM_VERSION
|
||||
# define TCC_ARM_VERSION 5
|
||||
#endif
|
||||
@ -869,14 +867,9 @@ int floats_in_core_regs(SValue *sval)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC int regargs_nregs(RegArgs *args)
|
||||
{
|
||||
return *args;
|
||||
}
|
||||
|
||||
/* 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, RegArgs *args) {
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
|
||||
#ifdef TCC_ARM_EABI
|
||||
int size, align;
|
||||
size = type_size(vt, &align);
|
||||
@ -886,20 +879,18 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
|
||||
*regsize = 8;
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_DOUBLE;
|
||||
*args = (size + 7) >> 3;
|
||||
return (size + 7) >> 3;
|
||||
} else if (size <= 4) {
|
||||
*ret_align = 4;
|
||||
*regsize = 4;
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_INT;
|
||||
*args = 1;
|
||||
return 1;
|
||||
} else
|
||||
*args = 0;
|
||||
return 0;
|
||||
#else
|
||||
*args = 0;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return *args != 0;
|
||||
}
|
||||
|
||||
/* Parameters are classified according to how they are copied to their final
|
||||
@ -1269,7 +1260,6 @@ void gfunc_prolog(CType *func_type)
|
||||
int n, nf, size, align, rs, struct_ret = 0;
|
||||
int addr, pn, sn; /* pn=core, sn=stack */
|
||||
CType ret_type;
|
||||
RegArgs dummy;
|
||||
|
||||
#ifdef TCC_ARM_EABI
|
||||
struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
|
||||
@ -1281,7 +1271,7 @@ void gfunc_prolog(CType *func_type)
|
||||
|
||||
n = nf = 0;
|
||||
if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&
|
||||
!gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy))
|
||||
!gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs))
|
||||
{
|
||||
n++;
|
||||
struct_ret = 1;
|
||||
|
11
arm64-gen.c
11
arm64-gen.c
@ -14,8 +14,6 @@
|
||||
// Number of registers available to allocator:
|
||||
#define NB_REGS 28 // x0-x18, x30, v0-v7
|
||||
|
||||
typedef int RegArgs;
|
||||
|
||||
#define TREG_R(x) (x) // x = 0..18
|
||||
#define TREG_R30 19
|
||||
#define TREG_F(x) (x + 20) // x = 0..7
|
||||
@ -1198,15 +1196,8 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC int regargs_nregs(RegArgs *args)
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize)
|
||||
{
|
||||
return *args;
|
||||
}
|
||||
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize, RegArgs *args)
|
||||
{
|
||||
*args = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
11
c67-gen.c
11
c67-gen.c
@ -25,8 +25,6 @@
|
||||
/* number of available registers */
|
||||
#define NB_REGS 24
|
||||
|
||||
typedef int RegArgs;
|
||||
|
||||
/* a register can belong to several classes. The classes must be
|
||||
sorted from more general to more precise (see gv2() code which does
|
||||
assumptions on it). */
|
||||
@ -1881,17 +1879,10 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC int regargs_nregs(RegArgs *args)
|
||||
{
|
||||
return *args;
|
||||
}
|
||||
|
||||
/* 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, RegArgs *args) {
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
|
||||
*ret_align = 1; // Never have to re-align return values for x86-64
|
||||
*args = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
19
i386-gen.c
19
i386-gen.c
@ -24,8 +24,6 @@
|
||||
#define NB_REGS 4
|
||||
#define NB_ASM_REGS 8
|
||||
|
||||
typedef int RegArgs;
|
||||
|
||||
/* a register can belong to several classes. The classes must be
|
||||
sorted from more general to more precise (see gv2() code which does
|
||||
assumptions on it). */
|
||||
@ -376,14 +374,9 @@ static void gcall_or_jmp(int is_jmp)
|
||||
static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
|
||||
static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
|
||||
|
||||
ST_FUNC int regargs_nregs(RegArgs *args)
|
||||
{
|
||||
return *args;
|
||||
}
|
||||
|
||||
/* 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, RegArgs *args)
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
|
||||
{
|
||||
#ifdef TCC_TARGET_PE
|
||||
int size, align;
|
||||
@ -392,22 +385,20 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
|
||||
*regsize = 4;
|
||||
size = type_size(vt, &align);
|
||||
if (size > 8) {
|
||||
*args = 0;
|
||||
return 0;
|
||||
} else if (size > 4) {
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_LLONG;
|
||||
*args = 1;
|
||||
return 1;
|
||||
} else {
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_INT;
|
||||
*args = 1;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
*ret_align = 1; // Never have to re-align return values for x86
|
||||
*args = 0;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return *args != 0;
|
||||
}
|
||||
|
||||
/* Generate function call. The function address is pushed first, then
|
||||
|
8
tcc.h
8
tcc.h
@ -796,8 +796,8 @@ struct TCCState {
|
||||
#define VT_LLONG 12 /* 64 bit integer */
|
||||
#define VT_LONG 13 /* long integer (NEVER USED as type, only
|
||||
during parsing) */
|
||||
#define VT_QLONG 14 /* 128-bit integer. No longer used. */
|
||||
#define VT_QFLOAT 15 /* 128-bit float. No longer used. */
|
||||
#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */
|
||||
#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */
|
||||
#define VT_UNSIGNED 0x0010 /* unsigned type */
|
||||
#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
|
||||
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
||||
@ -1267,7 +1267,6 @@ ST_FUNC void save_regs(int n);
|
||||
ST_FUNC void gaddrof(void);
|
||||
ST_FUNC int gv(int rc);
|
||||
ST_FUNC void gv2(int rc1, int rc2);
|
||||
ST_FUNC void vdup(void);
|
||||
ST_FUNC void vpop(void);
|
||||
ST_FUNC void gen_op(int op);
|
||||
ST_FUNC int type_size(CType *type, int *a);
|
||||
@ -1356,8 +1355,7 @@ ST_FUNC void gsym_addr(int t, int a);
|
||||
ST_FUNC void gsym(int t);
|
||||
ST_FUNC void load(int r, SValue *sv);
|
||||
ST_FUNC void store(int r, SValue *v);
|
||||
ST_FUNC int regargs_nregs(RegArgs *args);
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize, RegArgs *args);
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||
ST_FUNC void gfunc_call(int nb_args);
|
||||
ST_FUNC void gfunc_prolog(CType *func_type);
|
||||
ST_FUNC void gfunc_epilog(void);
|
||||
|
86
tccgen.c
86
tccgen.c
@ -525,7 +525,7 @@ ST_FUNC void vpushv(SValue *v)
|
||||
*vtop = *v;
|
||||
}
|
||||
|
||||
ST_FUNC void vdup(void)
|
||||
static void vdup(void)
|
||||
{
|
||||
vpushv(vtop);
|
||||
}
|
||||
@ -4200,7 +4200,6 @@ ST_FUNC void unary(void)
|
||||
SValue ret;
|
||||
Sym *sa;
|
||||
int nb_args, ret_nregs, ret_align, regsize, variadic;
|
||||
RegArgs args;
|
||||
|
||||
/* function call */
|
||||
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
||||
@ -4225,10 +4224,8 @@ ST_FUNC void unary(void)
|
||||
/* compute first implicit argument if a structure is returned */
|
||||
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
variadic = (s->c == FUNC_ELLIPSIS);
|
||||
gfunc_sret(&s->type, variadic, &ret.type,
|
||||
&ret_align, ®size, &args);
|
||||
ret_nregs = regargs_nregs(&args);
|
||||
|
||||
ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,
|
||||
&ret_align, ®size);
|
||||
if (!ret_nregs) {
|
||||
/* get some space for the returned structure */
|
||||
size = type_size(&s->type, &align);
|
||||
@ -4306,10 +4303,6 @@ ST_FUNC void unary(void)
|
||||
/* handle packed struct return */
|
||||
if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) {
|
||||
int addr, offset;
|
||||
#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE)
|
||||
int i;
|
||||
#endif
|
||||
|
||||
|
||||
size = type_size(&s->type, &align);
|
||||
/* We're writing whole regs often, make sure there's enough
|
||||
@ -4318,34 +4311,6 @@ ST_FUNC void unary(void)
|
||||
align = regsize;
|
||||
loc = (loc - size) & -align;
|
||||
addr = loc;
|
||||
#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE)
|
||||
for (i=0; i<REG_ARGS_MAX; i++) {
|
||||
offset = args.ireg[i];
|
||||
|
||||
if (offset == -1)
|
||||
break;
|
||||
|
||||
ret.type.t = VT_LLONG;
|
||||
vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);
|
||||
vsetc(&ret.type, i ? REG_LRET : REG_IRET, &ret.c);
|
||||
vstore();
|
||||
vtop--;
|
||||
vtop--;
|
||||
}
|
||||
for (i=0; i<REG_ARGS_MAX; i++) {
|
||||
offset = args.freg[i];
|
||||
|
||||
if (offset == -1)
|
||||
break;
|
||||
|
||||
ret.type.t = VT_DOUBLE;
|
||||
vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);
|
||||
vsetc(&ret.type, i ? REG_QRET : REG_FRET, &ret.c);
|
||||
vstore();
|
||||
vtop--;
|
||||
vtop--;
|
||||
}
|
||||
#else
|
||||
offset = 0;
|
||||
for (;;) {
|
||||
vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);
|
||||
@ -4356,7 +4321,6 @@ ST_FUNC void unary(void)
|
||||
break;
|
||||
offset += regsize;
|
||||
}
|
||||
#endif
|
||||
vset(&s->type, VT_LOCAL | VT_LVAL, addr);
|
||||
}
|
||||
} else {
|
||||
@ -4927,11 +4891,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
|
||||
CType type, ret_type;
|
||||
int ret_align, ret_nregs, regsize;
|
||||
RegArgs args;
|
||||
|
||||
gfunc_sret(&func_vt, func_var, &ret_type,
|
||||
&ret_align, ®size, &args);
|
||||
ret_nregs = regargs_nregs(&args);
|
||||
ret_nregs = gfunc_sret(&func_vt, func_var, &ret_type,
|
||||
&ret_align, ®size);
|
||||
if (0 == ret_nregs) {
|
||||
/* if returning structure, must copy it to implicit
|
||||
first pointer arg location */
|
||||
@ -4945,9 +4906,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||
} else {
|
||||
/* returning structure packed into registers */
|
||||
int r, size, addr, align;
|
||||
#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE)
|
||||
int i;
|
||||
#endif
|
||||
size = type_size(&func_vt,&align);
|
||||
if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1)))
|
||||
&& (align & (ret_align-1))) {
|
||||
@ -4961,39 +4919,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||
vset(&ret_type, VT_LOCAL | VT_LVAL, addr);
|
||||
}
|
||||
vtop->type = ret_type;
|
||||
#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE)
|
||||
for (i=0; i<REG_ARGS_MAX; i++) {
|
||||
int off = args.ireg[i];
|
||||
|
||||
if (off == -1)
|
||||
break;
|
||||
|
||||
r = i ? RC_LRET : RC_IRET;
|
||||
|
||||
vdup();
|
||||
vtop->c.i += off;
|
||||
vtop->type.t = VT_LLONG;
|
||||
gv(r);
|
||||
vpop();
|
||||
}
|
||||
for (i=0; i<REG_ARGS_MAX; i++) {
|
||||
int off = args.freg[i];
|
||||
|
||||
if (off == -1)
|
||||
break;
|
||||
|
||||
/* We assume that when a structure is returned in multiple
|
||||
registers, their classes are consecutive values of the
|
||||
suite s(n) = 2^n */
|
||||
r = rc_fret(ret_type.t) << i;
|
||||
|
||||
vdup();
|
||||
vtop->c.i += off;
|
||||
vtop->type.t = VT_DOUBLE;
|
||||
gv(r);
|
||||
vpop();
|
||||
}
|
||||
#else
|
||||
if (is_float(ret_type.t))
|
||||
r = rc_fret(ret_type.t);
|
||||
else
|
||||
@ -5010,7 +4935,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||
vtop->c.i += regsize;
|
||||
vtop->r = VT_LOCAL | VT_LVAL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (is_float(func_vt.t)) {
|
||||
gv(rc_fret(func_vt.t));
|
||||
|
@ -637,10 +637,10 @@ int main(int argc, char **argv) {
|
||||
RUN_TEST(ret_longdouble_test);
|
||||
RUN_TEST(ret_2float_test);
|
||||
RUN_TEST(ret_2double_test);
|
||||
RUN_TEST(ret_8plus2double_test);
|
||||
RUN_TEST(ret_6plus2longlong_test);
|
||||
RUN_TEST(ret_mixed_test);
|
||||
RUN_TEST(ret_mixed2_test);
|
||||
/* RUN_TEST(ret_8plus2double_test); currently broken on x86_64 */
|
||||
/* RUN_TEST(ret_6plus2longlong_test); currently broken on x86_64 */
|
||||
/* RUN_TEST(ret_mixed_test); currently broken on x86_64 */
|
||||
/* RUN_TEST(ret_mixed2_test); currently broken on x86_64 */
|
||||
RUN_TEST(ret_mixed3_test);
|
||||
RUN_TEST(reg_pack_test);
|
||||
RUN_TEST(reg_pack_longlong_test);
|
||||
|
523
x86_64-gen.c
523
x86_64-gen.c
@ -25,24 +25,6 @@
|
||||
/* number of available registers */
|
||||
#define NB_REGS 25
|
||||
#define NB_ASM_REGS 8
|
||||
#define REG_ARGS_MAX 2 /* at most 2 registers used for each argument */
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
typedef int RegArgs;
|
||||
#else
|
||||
/* This struct stores the struct offsets at which %rax, %rdx, %xmm0, and
|
||||
* %xmm1 are to be stored.
|
||||
*
|
||||
* struct { long long l; double x; }: ireg = { 0, -1 } freg = { 8, -1 }
|
||||
* struct { double x; long long l; }: ireg = { 8, -1 } freg = { 0, -1 }
|
||||
* struct { long long l; long long l2; }: ireg = { 0, 8 } freg = { -1, -1 }
|
||||
* struct { double x; double x2; }: ireg = { -1, -1 } freg = { 0, 8 }
|
||||
*/
|
||||
typedef struct {
|
||||
int ireg[REG_ARGS_MAX];
|
||||
int freg[REG_ARGS_MAX];
|
||||
} RegArgs;
|
||||
#endif
|
||||
|
||||
/* a register can belong to several classes. The classes must be
|
||||
sorted from more general to more precise (see gv2() code which does
|
||||
@ -763,14 +745,9 @@ void gen_offs_sp(int b, int r, int d)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC int regargs_nregs(RegArgs *args)
|
||||
{
|
||||
return *args;
|
||||
}
|
||||
|
||||
/* 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, RegArgs *args)
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
|
||||
{
|
||||
int size, align;
|
||||
*regsize = 8;
|
||||
@ -778,22 +755,20 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
|
||||
size = type_size(vt, &align);
|
||||
ret->ref = NULL;
|
||||
if (size > 8) {
|
||||
*args = 0;
|
||||
return 0;
|
||||
} else if (size > 4) {
|
||||
ret->t = VT_LLONG;
|
||||
*args = 1;
|
||||
return 1;
|
||||
} else if (size > 2) {
|
||||
ret->t = VT_INT;
|
||||
*args = 1;
|
||||
return 1;
|
||||
} else if (size > 1) {
|
||||
ret->t = VT_SHORT;
|
||||
*args = 1;
|
||||
return 1;
|
||||
} else {
|
||||
ret->t = VT_BYTE;
|
||||
*args = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return *args != 0;
|
||||
}
|
||||
|
||||
static int is_sse_float(int t) {
|
||||
@ -1066,9 +1041,7 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b)
|
||||
return x86_64_mode_sse;
|
||||
}
|
||||
|
||||
/* classify the x86 eightbytes from byte index start to byte index
|
||||
* end, at offset offset from the root struct */
|
||||
static X86_64_Mode classify_x86_64_inner(CType *ty, int offset, int start, int end)
|
||||
static X86_64_Mode classify_x86_64_inner(CType *ty)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
Sym *f;
|
||||
@ -1094,10 +1067,8 @@ static X86_64_Mode classify_x86_64_inner(CType *ty, int offset, int start, int e
|
||||
f = ty->ref;
|
||||
|
||||
mode = x86_64_mode_none;
|
||||
while ((f = f->next) != NULL) {
|
||||
if (f->c + offset >= start && f->c + offset < end)
|
||||
mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type, f->c + offset, start, end));
|
||||
}
|
||||
for (f = f->next; f; f = f->next)
|
||||
mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
|
||||
|
||||
return mode;
|
||||
}
|
||||
@ -1105,79 +1076,61 @@ static X86_64_Mode classify_x86_64_inner(CType *ty, int offset, int start, int e
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static X86_64_Mode classify_x86_64_arg_eightbyte(CType *ty, int offset)
|
||||
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
|
||||
assert((ty->t & VT_BTYPE) == VT_STRUCT);
|
||||
|
||||
mode = classify_x86_64_inner(ty, 0, offset, offset + 8);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void regargs_init(RegArgs *args)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<REG_ARGS_MAX; i++) {
|
||||
args->ireg[i] = -1;
|
||||
args->freg[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, RegArgs *args)
|
||||
{
|
||||
X86_64_Mode mode = x86_64_mode_none;
|
||||
int size, align, ret_t = 0;
|
||||
int ireg = 0, freg = 0;
|
||||
|
||||
if (args)
|
||||
regargs_init(args);
|
||||
|
||||
|
||||
if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
|
||||
*psize = 8;
|
||||
*palign = 8;
|
||||
if (args)
|
||||
args->ireg[ireg++] = 0;
|
||||
*reg_count = 1;
|
||||
ret_t = ty->t;
|
||||
mode = x86_64_mode_integer;
|
||||
} else {
|
||||
size = type_size(ty, &align);
|
||||
*psize = (size + 7) & ~7;
|
||||
*palign = (align + 7) & ~7;
|
||||
|
||||
|
||||
if (size > 16) {
|
||||
mode = x86_64_mode_memory;
|
||||
} else {
|
||||
int start;
|
||||
|
||||
for(start=0; start < size; start += 8) {
|
||||
if ((ty->t & VT_BTYPE) == VT_STRUCT) {
|
||||
mode = classify_x86_64_arg_eightbyte(ty, start);
|
||||
mode = classify_x86_64_inner(ty);
|
||||
switch (mode) {
|
||||
case x86_64_mode_integer:
|
||||
if (size > 8) {
|
||||
*reg_count = 2;
|
||||
ret_t = VT_QLONG;
|
||||
} else {
|
||||
mode = classify_x86_64_inner(ty, 0, 0, size);
|
||||
}
|
||||
|
||||
if (mode == x86_64_mode_integer) {
|
||||
if (args)
|
||||
args->ireg[ireg++] = start;
|
||||
*reg_count = 1;
|
||||
ret_t = (size > 4) ? VT_LLONG : VT_INT;
|
||||
} else if (mode == x86_64_mode_sse) {
|
||||
if (args)
|
||||
args->freg[freg++] = start;
|
||||
ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
|
||||
} else {
|
||||
ret_t = VT_LDOUBLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case x86_64_mode_x87:
|
||||
*reg_count = 1;
|
||||
ret_t = VT_LDOUBLE;
|
||||
break;
|
||||
|
||||
case x86_64_mode_sse:
|
||||
if (size > 8) {
|
||||
*reg_count = 2;
|
||||
ret_t = VT_QFLOAT;
|
||||
} else {
|
||||
*reg_count = 1;
|
||||
ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
|
||||
}
|
||||
break;
|
||||
default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ret) {
|
||||
ret->ref = NULL;
|
||||
ret->t = ret_t;
|
||||
}
|
||||
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
@ -1187,8 +1140,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty)
|
||||
enum __va_arg_type {
|
||||
__va_gen_reg, __va_float_reg, __va_stack
|
||||
};
|
||||
int size, align;
|
||||
X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, NULL);
|
||||
int size, align, reg_count;
|
||||
X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, ®_count);
|
||||
switch (mode) {
|
||||
default: return __va_stack;
|
||||
case x86_64_mode_integer: return __va_gen_reg;
|
||||
@ -1196,57 +1149,14 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty)
|
||||
}
|
||||
}
|
||||
|
||||
static int regargs_iregs(RegArgs *args)
|
||||
/* 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)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
for(i=0; i<REG_ARGS_MAX; i++) {
|
||||
if(args->ireg[i] != -1)
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int regargs_fregs(RegArgs *args)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
for(i=0; i<REG_ARGS_MAX; i++) {
|
||||
if(args->freg[i] != -1)
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Count the total number of registers used by args */
|
||||
ST_FUNC int regargs_nregs(RegArgs *args)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
for(i=0; i<REG_ARGS_MAX; i++) {
|
||||
if(args->ireg[i] != -1)
|
||||
ret++;
|
||||
|
||||
if(args->freg[i] != -1)
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize, RegArgs *args)
|
||||
{
|
||||
int size, align;
|
||||
X86_64_Mode mode;
|
||||
int size, align, reg_count;
|
||||
*ret_align = 1; // Never have to re-align return values for x86-64
|
||||
*regsize = 8;
|
||||
|
||||
mode = classify_x86_64_arg(vt, ret, &size, &align, args);
|
||||
|
||||
return mode != x86_64_mode_memory &&
|
||||
mode != x86_64_mode_none;
|
||||
return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory);
|
||||
}
|
||||
|
||||
#define REGN 6
|
||||
@ -1269,28 +1179,18 @@ void gfunc_call(int nb_args)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
CType type;
|
||||
int size, align, r, args_size, stack_adjust, run_start, run_end, i;
|
||||
int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count;
|
||||
int nb_reg_args = 0;
|
||||
int nb_sse_args = 0;
|
||||
int sse_reg = 0, gen_reg = 0;
|
||||
RegArgs *reg_args = alloca(nb_args * sizeof *reg_args);
|
||||
int sse_reg, gen_reg;
|
||||
|
||||
/* calculate the number of integer/float register arguments */
|
||||
for(i = nb_args - 1; i >= 0; i--) {
|
||||
int fregs, iregs;
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_args[i]);
|
||||
fregs = regargs_fregs(®_args[i]);
|
||||
iregs = regargs_iregs(®_args[i]);
|
||||
|
||||
nb_sse_args += fregs;
|
||||
nb_reg_args += iregs;
|
||||
|
||||
if (sse_reg + fregs > 8 || gen_reg + iregs > REGN) {
|
||||
regargs_init(®_args[i]);
|
||||
} else {
|
||||
sse_reg += fregs;
|
||||
gen_reg += iregs;
|
||||
}
|
||||
for(i = 0; i < nb_args; i++) {
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count);
|
||||
if (mode == x86_64_mode_sse)
|
||||
nb_sse_args += reg_count;
|
||||
else if (mode == x86_64_mode_integer)
|
||||
nb_reg_args += reg_count;
|
||||
}
|
||||
|
||||
/* arguments are collected in runs. Each run is a collection of 8-byte aligned arguments
|
||||
@ -1309,14 +1209,27 @@ void gfunc_call(int nb_args)
|
||||
run_end = nb_args;
|
||||
stack_adjust = 0;
|
||||
for(i = run_start; (i < nb_args) && (run_end == nb_args); i++) {
|
||||
int stack = regargs_nregs(®_args[i]) == 0;
|
||||
classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, NULL);
|
||||
|
||||
if (stack) {
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count);
|
||||
switch (mode) {
|
||||
case x86_64_mode_memory:
|
||||
case x86_64_mode_x87:
|
||||
stack_arg:
|
||||
if (align == 16)
|
||||
run_end = i;
|
||||
else
|
||||
stack_adjust += size;
|
||||
break;
|
||||
|
||||
case x86_64_mode_sse:
|
||||
sse_reg -= reg_count;
|
||||
if (sse_reg + reg_count > 8) goto stack_arg;
|
||||
break;
|
||||
|
||||
case x86_64_mode_integer:
|
||||
gen_reg -= reg_count;
|
||||
if (gen_reg + reg_count > REGN) goto stack_arg;
|
||||
break;
|
||||
default: break; /* nothing to be done for x86_64_mode_none */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1336,38 +1249,44 @@ void gfunc_call(int nb_args)
|
||||
}
|
||||
|
||||
for(i = run_start; i < run_end;) {
|
||||
int arg_stored = regargs_nregs(®_args[i]) == 0;
|
||||
SValue tmp;
|
||||
RegArgs args;
|
||||
|
||||
if (!arg_stored) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Swap argument to top, it will possibly be changed here,
|
||||
and might use more temps. At the end of the loop we keep
|
||||
in on the stack and swap it back to its original position
|
||||
if it is a register. */
|
||||
tmp = vtop[0];
|
||||
SValue tmp = vtop[0];
|
||||
int arg_stored = 1;
|
||||
|
||||
vtop[0] = vtop[-i];
|
||||
vtop[-i] = tmp;
|
||||
mode = classify_x86_64_arg(&vtop->type, NULL, &size, &align, ®_count);
|
||||
|
||||
classify_x86_64_arg(&vtop->type, NULL, &size, &align, &args);
|
||||
|
||||
switch (vtop->type.t & VT_BTYPE) {
|
||||
case VT_STRUCT:
|
||||
/* allocate the necessary size on stack */
|
||||
o(0x48);
|
||||
oad(0xec81, size); /* sub $xxx, %rsp */
|
||||
/* generate structure store */
|
||||
r = get_reg(RC_INT);
|
||||
orex(1, r, 0, 0x89); /* mov %rsp, r */
|
||||
o(0xe0 + REG_VALUE(r));
|
||||
vset(&vtop->type, r | VT_LVAL, 0);
|
||||
vswap();
|
||||
vstore();
|
||||
args_size += size;
|
||||
if (mode == x86_64_mode_sse) {
|
||||
if (sse_reg > 8)
|
||||
sse_reg -= reg_count;
|
||||
else
|
||||
arg_stored = 0;
|
||||
} else if (mode == x86_64_mode_integer) {
|
||||
if (gen_reg > REGN)
|
||||
gen_reg -= reg_count;
|
||||
else
|
||||
arg_stored = 0;
|
||||
}
|
||||
|
||||
if (arg_stored) {
|
||||
/* allocate the necessary size on stack */
|
||||
o(0x48);
|
||||
oad(0xec81, size); /* sub $xxx, %rsp */
|
||||
/* generate structure store */
|
||||
r = get_reg(RC_INT);
|
||||
orex(1, r, 0, 0x89); /* mov %rsp, r */
|
||||
o(0xe0 + REG_VALUE(r));
|
||||
vset(&vtop->type, r | VT_LVAL, 0);
|
||||
vswap();
|
||||
vstore();
|
||||
args_size += size;
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_LDOUBLE:
|
||||
@ -1376,43 +1295,57 @@ void gfunc_call(int nb_args)
|
||||
|
||||
case VT_FLOAT:
|
||||
case VT_DOUBLE:
|
||||
r = gv(RC_FLOAT);
|
||||
o(0x50); /* push $rax */
|
||||
/* movq %xmmN, (%rsp) */
|
||||
o(0xd60f66);
|
||||
o(0x04 + REG_VALUE(r)*8);
|
||||
o(0x24);
|
||||
args_size += size;
|
||||
assert(mode == x86_64_mode_sse);
|
||||
if (sse_reg > 8) {
|
||||
--sse_reg;
|
||||
r = gv(RC_FLOAT);
|
||||
o(0x50); /* push $rax */
|
||||
/* movq %xmmN, (%rsp) */
|
||||
o(0xd60f66);
|
||||
o(0x04 + REG_VALUE(r)*8);
|
||||
o(0x24);
|
||||
args_size += size;
|
||||
} else {
|
||||
arg_stored = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(mode == x86_64_mode_integer);
|
||||
/* simple type */
|
||||
/* XXX: implicit cast ? */
|
||||
--gen_reg;
|
||||
r = gv(RC_INT);
|
||||
orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
|
||||
args_size += size;
|
||||
if (gen_reg > REGN) {
|
||||
--gen_reg;
|
||||
r = gv(RC_INT);
|
||||
orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
|
||||
args_size += size;
|
||||
} else {
|
||||
arg_stored = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* And swap the argument back to its original position. */
|
||||
|
||||
/* And swap the argument back to it's original position. */
|
||||
tmp = vtop[0];
|
||||
vtop[0] = vtop[-i];
|
||||
vtop[-i] = tmp;
|
||||
|
||||
vrotb(i+1);
|
||||
assert((vtop->type.t == tmp.type.t) && (vtop->r == tmp.r));
|
||||
vpop();
|
||||
memmove(reg_args + i, reg_args + i + 1, (nb_args - i - 1) * sizeof *reg_args);
|
||||
--nb_args;
|
||||
--run_end;
|
||||
if (arg_stored) {
|
||||
vrotb(i+1);
|
||||
assert((vtop->type.t == tmp.type.t) && (vtop->r == tmp.r));
|
||||
vpop();
|
||||
--nb_args;
|
||||
--run_end;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle 16 byte aligned arguments at end of run */
|
||||
run_start = i = run_end;
|
||||
while (i < nb_args) {
|
||||
/* Rotate argument to top since it will always be popped */
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, NULL);
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count);
|
||||
if (align != 16)
|
||||
break;
|
||||
|
||||
@ -1442,24 +1375,13 @@ void gfunc_call(int nb_args)
|
||||
}
|
||||
|
||||
vpop();
|
||||
memmove(reg_args + i, reg_args + i + 1, (nb_args - i - 1) * sizeof *reg_args);
|
||||
--nb_args;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* XXX This should be superfluous. */
|
||||
save_regs(0); /* save used temporary registers */
|
||||
|
||||
/* recalculate the number of register arguments there actually
|
||||
* are. This is slow but more obviously correct than using the
|
||||
* old counts. */
|
||||
gen_reg = 0;
|
||||
sse_reg = 0;
|
||||
for(i = 0; i < nb_args; i++) {
|
||||
gen_reg += regargs_iregs(®_args[i]);
|
||||
sse_reg += regargs_fregs(®_args[i]);
|
||||
}
|
||||
|
||||
/* then, we prepare register passing arguments.
|
||||
Note that we cannot set RDX and RCX in this loop because gv()
|
||||
may break these temporary registers. Let's use R10 and R11
|
||||
@ -1467,62 +1389,40 @@ void gfunc_call(int nb_args)
|
||||
assert(gen_reg <= REGN);
|
||||
assert(sse_reg <= 8);
|
||||
for(i = 0; i < nb_args; i++) {
|
||||
RegArgs args;
|
||||
|
||||
args = reg_args[i];
|
||||
|
||||
mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, ®_count);
|
||||
/* Alter stack entry type so that gv() knows how to treat it */
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
int k;
|
||||
|
||||
for(k=REG_ARGS_MAX-1; k>=0; k--) {
|
||||
if (args.freg[k] == -1)
|
||||
continue;
|
||||
|
||||
sse_reg--;
|
||||
assert(sse_reg >= 0);
|
||||
|
||||
vdup();
|
||||
vtop->type.t = VT_DOUBLE;
|
||||
vtop->c.ull += args.freg[k];
|
||||
gv(RC_XMM0 << sse_reg);
|
||||
vpop();
|
||||
}
|
||||
for(k=REG_ARGS_MAX-1; k>=0; k--) {
|
||||
int d;
|
||||
if (args.ireg[k] == -1)
|
||||
continue;
|
||||
|
||||
gen_reg--;
|
||||
|
||||
vdup();
|
||||
vtop->type.t = VT_LLONG;
|
||||
vtop->c.ull += args.ireg[k];
|
||||
r = gv(RC_INT);
|
||||
d = arg_prepare_reg(gen_reg);
|
||||
orex(1,d,r,0x89); /* mov */
|
||||
o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
|
||||
vpop();
|
||||
}
|
||||
} else {
|
||||
/* XXX is it really necessary to set vtop->type? */
|
||||
classify_x86_64_arg(&vtop->type, &type, &size, &align, NULL);
|
||||
vtop->type = type;
|
||||
if (args.freg[0] != -1) {
|
||||
vtop->type = type;
|
||||
if (mode == x86_64_mode_sse) {
|
||||
if (reg_count == 2) {
|
||||
sse_reg -= 2;
|
||||
gv(RC_FRET); /* Use pair load into xmm0 & xmm1 */
|
||||
if (sse_reg) { /* avoid redundant movaps %xmm0, %xmm0 */
|
||||
/* movaps %xmm0, %xmmN */
|
||||
o(0x280f);
|
||||
o(0xc0 + (sse_reg << 3));
|
||||
/* movaps %xmm1, %xmmN */
|
||||
o(0x280f);
|
||||
o(0xc1 + ((sse_reg+1) << 3));
|
||||
}
|
||||
} else {
|
||||
assert(reg_count == 1);
|
||||
--sse_reg;
|
||||
/* Load directly to register */
|
||||
gv(RC_XMM0 << sse_reg);
|
||||
} else if (args.ireg[0] != -1) {
|
||||
int d;
|
||||
/* simple type */
|
||||
/* XXX: implicit cast ? */
|
||||
gen_reg--;
|
||||
r = gv(RC_INT);
|
||||
d = arg_prepare_reg(gen_reg);
|
||||
orex(1,d,r,0x89); /* mov */
|
||||
o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
} else if (mode == x86_64_mode_integer) {
|
||||
/* simple type */
|
||||
/* XXX: implicit cast ? */
|
||||
int d;
|
||||
gen_reg -= reg_count;
|
||||
r = gv(RC_INT);
|
||||
d = arg_prepare_reg(gen_reg);
|
||||
orex(1,d,r,0x89); /* mov */
|
||||
o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
|
||||
if (reg_count == 2) {
|
||||
d = arg_prepare_reg(gen_reg+1);
|
||||
orex(1,d,vtop->r2,0x89); /* mov */
|
||||
o(0xc0 + REG_VALUE(vtop->r2) * 8 + REG_VALUE(d));
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
@ -1563,7 +1463,7 @@ static void push_arg_reg(int i) {
|
||||
void gfunc_prolog(CType *func_type)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
int i, addr, align, size;
|
||||
int i, addr, align, size, reg_count;
|
||||
int param_addr = 0, reg_param_index, sse_param_index;
|
||||
Sym *sym;
|
||||
CType *type;
|
||||
@ -1583,37 +1483,31 @@ void gfunc_prolog(CType *func_type)
|
||||
/* count the number of seen parameters */
|
||||
sym = func_type->ref;
|
||||
while ((sym = sym->next) != NULL) {
|
||||
RegArgs args;
|
||||
|
||||
type = &sym->type;
|
||||
mode = classify_x86_64_arg(type, NULL, &size, &align, &args);
|
||||
|
||||
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
|
||||
switch (mode) {
|
||||
default:
|
||||
stack_arg:
|
||||
seen_stack_size = ((seen_stack_size + align - 1) & -align) + size;
|
||||
break;
|
||||
|
||||
|
||||
case x86_64_mode_integer:
|
||||
case x86_64_mode_sse: {
|
||||
int stack = 0;
|
||||
|
||||
seen_sse_num += regargs_fregs(&args);
|
||||
seen_reg_num += regargs_iregs(&args);
|
||||
|
||||
if (seen_reg_num > 8) {
|
||||
if (seen_reg_num + reg_count <= 8) {
|
||||
seen_reg_num += reg_count;
|
||||
} else {
|
||||
seen_reg_num = 8;
|
||||
stack = 1;
|
||||
}
|
||||
if (seen_sse_num > 8) {
|
||||
seen_sse_num = 8;
|
||||
stack = 1;
|
||||
}
|
||||
|
||||
if (stack)
|
||||
goto stack_arg;
|
||||
}
|
||||
break;
|
||||
|
||||
case x86_64_mode_sse:
|
||||
if (seen_sse_num + reg_count <= 8) {
|
||||
seen_sse_num += reg_count;
|
||||
} else {
|
||||
seen_sse_num = 8;
|
||||
goto stack_arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1650,7 +1544,7 @@ void gfunc_prolog(CType *func_type)
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->type;
|
||||
mode = classify_x86_64_arg(&func_vt, NULL, &size, &align, NULL);
|
||||
mode = classify_x86_64_arg(&func_vt, NULL, &size, &align, ®_count);
|
||||
if (mode == x86_64_mode_memory) {
|
||||
push_arg_reg(reg_param_index);
|
||||
func_vc = loc;
|
||||
@ -1658,40 +1552,19 @@ void gfunc_prolog(CType *func_type)
|
||||
}
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
RegArgs args;
|
||||
int reg_count_integer = 0;
|
||||
int reg_count_sse = 0;
|
||||
int arg_stored = 1;
|
||||
|
||||
type = &sym->type;
|
||||
mode = classify_x86_64_arg(type, NULL, &size, &align, &args);
|
||||
reg_count_integer = regargs_iregs(&args);
|
||||
reg_count_sse = regargs_fregs(&args);
|
||||
|
||||
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
|
||||
switch (mode) {
|
||||
case x86_64_mode_integer:
|
||||
case x86_64_mode_sse:
|
||||
if (reg_count_integer || reg_count_sse) {
|
||||
if ((reg_count_sse == 0 || sse_param_index + reg_count_sse <= 8) &&
|
||||
(reg_count_integer == 0 || reg_param_index + reg_count_integer <= REGN)) {
|
||||
/* argument fits into registers */
|
||||
arg_stored = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arg_stored) {
|
||||
if (sse_param_index + reg_count <= 8) {
|
||||
/* save arguments passed by register */
|
||||
loc -= (reg_count_sse + reg_count_integer) * 8;
|
||||
loc -= reg_count * 8;
|
||||
param_addr = loc;
|
||||
for (i = 0; i < reg_count_sse; ++i) {
|
||||
for (i = 0; i < reg_count; ++i) {
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(sse_param_index, VT_LOCAL, NULL, param_addr + args.freg[i]);
|
||||
gen_modrm(sse_param_index, VT_LOCAL, NULL, param_addr + i*8);
|
||||
++sse_param_index;
|
||||
}
|
||||
for (i = 0; i < reg_count_integer; ++i) {
|
||||
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, param_addr + args.ireg[i]);
|
||||
++reg_param_index;
|
||||
}
|
||||
} else {
|
||||
addr = (addr + align - 1) & -align;
|
||||
param_addr = addr;
|
||||
@ -1705,6 +1578,23 @@ void gfunc_prolog(CType *func_type)
|
||||
param_addr = addr;
|
||||
addr += size;
|
||||
break;
|
||||
|
||||
case x86_64_mode_integer: {
|
||||
if (reg_param_index + reg_count <= REGN) {
|
||||
/* save arguments passed by register */
|
||||
loc -= reg_count * 8;
|
||||
param_addr = loc;
|
||||
for (i = 0; i < reg_count; ++i) {
|
||||
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, param_addr + i*8);
|
||||
++reg_param_index;
|
||||
}
|
||||
} else {
|
||||
addr = (addr + align - 1) & -align;
|
||||
param_addr = addr;
|
||||
addr += size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break; /* nothing to be done for x86_64_mode_none */
|
||||
}
|
||||
sym_push(sym->v & ~SYM_FIELD, type,
|
||||
@ -1741,7 +1631,7 @@ void gfunc_epilog(void)
|
||||
*bounds_ptr = 0;
|
||||
|
||||
/* generate bound local allocation */
|
||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||
func_bound_offset, lbounds_section->data_offset);
|
||||
saved_ind = ind;
|
||||
ind = func_bound_ind;
|
||||
@ -2343,7 +2233,8 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
||||
gfunc_call(1);
|
||||
vset(type, REG_IRET, 0);
|
||||
#else
|
||||
int r = gv(RC_INT); /* allocation size */
|
||||
int r;
|
||||
r = gv(RC_INT); /* allocation size */
|
||||
/* sub r,%rsp */
|
||||
o(0x2b48);
|
||||
o(0xe0 | REG_VALUE(r));
|
||||
|
Loading…
Reference in New Issue
Block a user