mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-26 12:04:59 +08:00
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
This commit is contained in:
parent
46dd2971ab
commit
fbc8810334
@ -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
|
||||||
|
43
tccgen.c
43
tccgen.c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user