Tests in abitest.c now work on Win32.

I expect that Linux-x86 is probably fine. All other architectures
except ARM are definitely broken since I haven't yet implemented
gfunc_sret for these, although replicating the current behaviour
should be straightforward.
This commit is contained in:
James Lyon
2013-04-18 17:27:34 +01:00
parent ce5e12c2f9
commit 2bbfaf436f
7 changed files with 173 additions and 66 deletions

View File

@ -3850,7 +3850,7 @@ ST_FUNC void unary(void)
} else if (tok == '(') {
SValue ret;
Sym *sa;
int nb_args;
int nb_args, sret;
/* function call */
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
@ -3874,18 +3874,26 @@ ST_FUNC void unary(void)
ret.r2 = VT_CONST;
/* compute first implicit argument if a structure is returned */
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
/* get some space for the returned structure */
size = type_size(&s->type, &align);
loc = (loc - size) & -align;
ret.type = s->type;
ret.r = VT_LOCAL | VT_LVAL;
/* pass it as 'int' to avoid structure arg passing
problems */
vseti(VT_LOCAL, loc);
ret.c = vtop->c;
nb_args++;
int ret_align;
sret = gfunc_sret(&s->type, &ret.type, &ret_align);
if (sret) {
/* get some space for the returned structure */
size = type_size(&s->type, &align);
loc = (loc - size) & -align;
ret.type = s->type;
ret.r = VT_LOCAL | VT_LVAL;
/* pass it as 'int' to avoid structure arg passing
problems */
vseti(VT_LOCAL, loc);
ret.c = vtop->c;
nb_args++;
}
} else {
ret.type = s->type;
sret = 0;
ret.type = s->type;
}
if (!sret) {
/* return in register */
if (is_float(ret.type.t)) {
ret.r = reg_fret(ret.type.t);
@ -3919,6 +3927,17 @@ ST_FUNC void unary(void)
/* return value */
vsetc(&ret.type, ret.r, &ret.c);
vtop->r2 = ret.r2;
/* handle packed struct return */
if (((s->type.t & VT_BTYPE) == VT_STRUCT) && !sret) {
size = type_size(&s->type, &align);
loc = (loc - size) & -align;
int addr = loc;
vset(&ret.type, VT_LOCAL | VT_LVAL, addr);
vswap();
vstore();
vtop--;
vset(&s->type, VT_LOCAL | VT_LVAL, addr);
}
} else {
break;
}
@ -4466,40 +4485,38 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
gexpr();
gen_assign_cast(&func_vt);
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
CType type;
/* if returning structure, must copy it to implicit
first pointer arg location */
#ifdef TCC_ARM_EABI
int align, size;
size = type_size(&func_vt,&align);
if(size <= 4)
{
if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
&& (align & 3))
{
int addr;
loc = (loc - size) & -4;
CType type, ret_type;
int ret_align;
if (gfunc_sret(&func_vt, &ret_type, &ret_align)) {
/* if returning structure, must copy it to implicit
first pointer arg location */
type = func_vt;
mk_pointer(&type);
vset(&type, VT_LOCAL | VT_LVAL, func_vc);
indir();
vswap();
/* copy structure value to pointer */
vstore();
} else {
/* returning structure packed into registers */
int size, addr, align;
size = type_size(&func_vt,&align);
if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1)))
&& (align & (ret_align-1))) {
loc = (loc - size) & -align;
addr = loc;
type = func_vt;
vset(&type, VT_LOCAL | VT_LVAL, addr);
vswap();
vstore();
vset(&int_type, VT_LOCAL | VT_LVAL, addr);
vset(&ret_type, VT_LOCAL | VT_LVAL, addr);
}
vtop->type = int_type;
gv(RC_IRET);
} else {
#endif
type = func_vt;
mk_pointer(&type);
vset(&type, VT_LOCAL | VT_LVAL, func_vc);
indir();
vswap();
/* copy structure value to pointer */
vstore();
#ifdef TCC_ARM_EABI
vtop->type = ret_type;
if (is_float(ret_type.t))
gv(rc_fret(ret_type.t));
else
gv(RC_IRET);
}
#endif
} else if (is_float(func_vt.t)) {
gv(rc_fret(func_vt.t));
} else {