aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/tccgen.c b/tccgen.c
index 52541e2..58c8b13 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -4153,7 +4153,7 @@ ST_FUNC void unary(void)
} else if (tok == '(') {
SValue ret;
Sym *sa;
- int nb_args, ret_nregs, ret_align, variadic;
+ int nb_args, ret_nregs, ret_align, regsize, variadic;
/* function call */
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
@@ -4179,7 +4179,7 @@ ST_FUNC void unary(void)
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
variadic = (s->c == FUNC_ELLIPSIS);
ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,
- &ret_align);
+ &ret_align, &regsize);
if (!ret_nregs) {
/* get some space for the returned structure */
size = type_size(&s->type, &align);
@@ -4259,6 +4259,10 @@ ST_FUNC void unary(void)
int addr, offset;
size = type_size(&s->type, &align);
+ /* We're writing whole regs often, make sure there's enough
+ space. Assume register size is power of 2. */
+ if (regsize > align)
+ align = regsize;
loc = (loc - size) & -align;
addr = loc;
offset = 0;
@@ -4269,8 +4273,7 @@ ST_FUNC void unary(void)
vtop--;
if (--ret_nregs == 0)
break;
- /* XXX: compatible with arm only: ret_align == register_size */
- offset += ret_align;
+ offset += regsize;
}
vset(&s->type, VT_LOCAL | VT_LVAL, addr);
}
@@ -4850,9 +4853,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
#else
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
CType type, ret_type;
- int ret_align, ret_nregs;
+ int ret_align, ret_nregs, regsize;
ret_nregs = gfunc_sret(&func_vt, func_var, &ret_type,
- &ret_align);
+ &ret_align, &regsize);
if (0 == ret_nregs) {
/* if returning structure, must copy it to implicit
first pointer arg location */
@@ -4890,9 +4893,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
/* We assume that when a structure is returned in multiple
registers, their classes are consecutive values of the
suite s(n) = 2^n */
+ /* XXX This seems confused, if r == 0, this never
+ changes r. */
r <<= 1;
- /* XXX: compatible with arm only: ret_align == register_size */
- vtop->c.i += ret_align;
+ vtop->c.i += regsize;
vtop->r = VT_LOCAL | VT_LVAL;
}
}