Add support for struct > 4B returned via registers
On ARM with hardfloat calling convention, structure containing 4 fields or less of the same float type are returned via float registers. This means that a structure can be returned in up to 4 double registers in a structure is composed of 4 doubles. This commit adds support for return of structures in several registers.
This commit is contained in:
48
arm-gen.c
48
arm-gen.c
@ -746,24 +746,6 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
|
||||
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
|
||||
#ifdef TCC_ARM_EABI
|
||||
int size, align;
|
||||
size = type_size(vt, &align);
|
||||
if (size > 4) {
|
||||
return 1;
|
||||
} else {
|
||||
*ret_align = 4;
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_INT;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCC_ARM_HARDFLOAT
|
||||
/* Return whether a structure is an homogeneous float aggregate or not.
|
||||
The answer is true if all the elements of the structure are of the same
|
||||
@ -831,6 +813,33 @@ int assign_vfpreg(struct avail_regs *avregs, int align, int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the number of registers needed to return the struct, or 0 if
|
||||
returning via struct pointer. */
|
||||
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
|
||||
#ifdef TCC_ARM_EABI
|
||||
int size, align;
|
||||
size = type_size(vt, &align);
|
||||
#ifdef TCC_ARM_HARDFLOAT
|
||||
if (is_float(vt->t) || is_hgen_float_aggr(vt)) {
|
||||
*ret_align = 8;
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_DOUBLE;
|
||||
return (size + 7) >> 3;
|
||||
} else
|
||||
#endif
|
||||
if (size > 4) {
|
||||
return 0;
|
||||
} else {
|
||||
*ret_align = 4;
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_INT;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Parameters are classified according to how they are copied to their final
|
||||
destination for the function call. Because the copying is performed class
|
||||
after class according to the order in the union below, it is important that
|
||||
@ -1198,6 +1207,9 @@ void gfunc_prolog(CType *func_type)
|
||||
n = nf = 0;
|
||||
variadic = (func_type->ref->c == FUNC_ELLIPSIS);
|
||||
if((func_vt.t & VT_BTYPE) == VT_STRUCT
|
||||
#ifdef TCC_ARM_HARDFLOAT
|
||||
&& (variadic || !is_hgen_float_aggr(&func_vt))
|
||||
#endif
|
||||
&& type_size(&func_vt,&align) > 4)
|
||||
{
|
||||
n++;
|
||||
|
||||
Reference in New Issue
Block a user