Fix stack overwrite on structure return

The common code to move a returned structure packed into
registers into memory on the caller side didn't take the
register size into account when allocating local storage,
so sometimes that lead to stack overwrites (e.g. in 73_arm64.c),
on x86_64.  This fixes it by generally making gfunc_sret also return
the register size.
This commit is contained in:
Michael Matz
2015-03-09 00:19:59 +01:00
parent d73b488401
commit 50899e30ab
7 changed files with 26 additions and 17 deletions

View File

@ -869,18 +869,20 @@ int floats_in_core_regs(SValue *sval)
/* 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) {
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);
if (float_abi == ARM_HARD_FLOAT && !variadic &&
(is_float(vt->t) || is_hgen_float_aggr(vt))) {
*ret_align = 8;
*regsize = 8;
ret->ref = NULL;
ret->t = VT_DOUBLE;
return (size + 7) >> 3;
} else if (size <= 4) {
*ret_align = 4;
*regsize = 4;
ret->ref = NULL;
ret->t = VT_INT;
return 1;
@ -1255,7 +1257,7 @@ void gfunc_call(int nb_args)
void gfunc_prolog(CType *func_type)
{
Sym *sym,*sym2;
int n, nf, size, align, struct_ret = 0;
int n, nf, size, align, rs, struct_ret = 0;
int addr, pn, sn; /* pn=core, sn=stack */
CType ret_type;
@ -1269,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))
!gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs))
{
n++;
struct_ret = 1;