Fix "Add support for struct > 4B returned via registers"

- avoid assumption "ret_align == register_size" which is
  false for non-arm targets
- rename symbol "sret" to more descriptive "ret_nregs"

This fixes commit dcec8673f2

Also:
- remove multiple definitions in win32/include/math.h
master
grischka 2013-12-16 15:38:10 +01:00
parent 46dd2971ab
commit fbc8810334
3 changed files with 31 additions and 16 deletions

View File

@ -392,7 +392,7 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
} else { } else {
ret->ref = NULL; ret->ref = NULL;
ret->t = VT_INT; ret->t = VT_INT;
return 0; return 1;
} }
#else #else
*ret_align = 1; // Never have to re-align return values for x86 *ret_align = 1; // Never have to re-align return values for x86

View File

@ -3927,7 +3927,7 @@ ST_FUNC void unary(void)
} else if (tok == '(') { } else if (tok == '(') {
SValue ret; SValue ret;
Sym *sa; Sym *sa;
int nb_args, sret, ret_align; int nb_args, ret_nregs, ret_align;
/* function call */ /* function call */
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
@ -3951,8 +3951,8 @@ ST_FUNC void unary(void)
ret.r2 = VT_CONST; ret.r2 = VT_CONST;
/* compute first implicit argument if a structure is returned */ /* compute first implicit argument if a structure is returned */
if ((s->type.t & VT_BTYPE) == VT_STRUCT) { if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
sret = gfunc_sret(&s->type, &ret.type, &ret_align); ret_nregs = gfunc_sret(&s->type, &ret.type, &ret_align);
if (!sret) { if (!ret_nregs) {
/* get some space for the returned structure */ /* get some space for the returned structure */
size = type_size(&s->type, &align); size = type_size(&s->type, &align);
loc = (loc - size) & -align; loc = (loc - size) & -align;
@ -3965,11 +3965,11 @@ ST_FUNC void unary(void)
nb_args++; nb_args++;
} }
} else { } else {
sret = 1; ret_nregs = 1;
ret.type = s->type; ret.type = s->type;
} }
if (sret) { if (ret_nregs) {
/* return in register */ /* return in register */
if (is_float(ret.type.t)) { if (is_float(ret.type.t)) {
ret.r = reg_fret(ret.type.t); ret.r = reg_fret(ret.type.t);
@ -4008,23 +4008,30 @@ ST_FUNC void unary(void)
} else { } else {
vtop -= (nb_args + 1); vtop -= (nb_args + 1);
} }
/* return value */ /* return value */
for (r = ret.r + sret + !sret; r-- > ret.r;) { for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {
vsetc(&ret.type, r, &ret.c); vsetc(&ret.type, r, &ret.c);
vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */ vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */
} }
/* handle packed struct return */ /* handle packed struct return */
if (((s->type.t & VT_BTYPE) == VT_STRUCT) && sret) { if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) {
int addr, offset; int addr, offset;
size = type_size(&s->type, &align); size = type_size(&s->type, &align);
loc = (loc - size) & -align; loc = (loc - size) & -align;
addr = loc; addr = loc;
for(offset = 0; offset < size; offset += ret_align) { offset = 0;
for (;;) {
vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);
vswap(); vswap();
vstore(); vstore();
vtop--; vtop--;
if (--ret_nregs == 0)
break;
/* XXX: compatible with arm only: ret_align == register_size */
offset += ret_align;
} }
vset(&s->type, VT_LOCAL | VT_LVAL, addr); vset(&s->type, VT_LOCAL | VT_LVAL, addr);
} }
@ -4596,8 +4603,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
gen_assign_cast(&func_vt); gen_assign_cast(&func_vt);
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
CType type, ret_type; CType type, ret_type;
int ret_align; int ret_align, ret_nregs;
if (!gfunc_sret(&func_vt, &ret_type, &ret_align)) { ret_nregs = gfunc_sret(&func_vt, &ret_type, &ret_align);
if (0 == ret_nregs) {
/* if returning structure, must copy it to implicit /* if returning structure, must copy it to implicit
first pointer arg location */ first pointer arg location */
type = func_vt; type = func_vt;
@ -4609,7 +4617,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
vstore(); vstore();
} else { } else {
/* returning structure packed into registers */ /* returning structure packed into registers */
int r, size, addr, offset, align; int r, size, addr, align;
size = type_size(&func_vt,&align); size = type_size(&func_vt,&align);
if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1))) if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1)))
&& (align & (ret_align-1))) { && (align & (ret_align-1))) {
@ -4626,11 +4634,16 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
r = rc_fret(ret_type.t); r = rc_fret(ret_type.t);
else else
r = RC_IRET; r = RC_IRET;
/* We assume that when a structure is returned in multiple
registers, their classes are consecutive values of the for (;;) {
suite s(n) = 2^n */
for (offset = 0; offset < size; offset += ret_align, r<<=1) {
gv(r); gv(r);
if (--ret_nregs == 0)
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 <<= 1;
/* XXX: compatible with arm only: ret_align == register_size */
vtop->c.i += ret_align; vtop->c.i += ret_align;
vtop->r = VT_LOCAL | VT_LVAL; vtop->r = VT_LOCAL | VT_LVAL;
} }

View File

@ -666,6 +666,7 @@ extern "C" {
extern long double __cdecl fmal (long double, long double, long double); extern long double __cdecl fmal (long double, long double, long double);
#if 0 // gr: duplicate, see below
/* 7.12.14 */ /* 7.12.14 */
/* /*
* With these functions, comparisons involving quiet NaNs set the FP * With these functions, comparisons involving quiet NaNs set the FP
@ -708,6 +709,7 @@ extern "C" {
& 0x4500) == 0x4500) & 0x4500) == 0x4500)
#endif #endif
#endif //0
#endif /* __STDC_VERSION__ >= 199901L */ #endif /* __STDC_VERSION__ >= 199901L */