aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Glöckner <daniel-gl@gmx.net>2016-10-08 18:54:42 +0200
committerDaniel Glöckner <daniel-gl@gmx.net>2016-10-08 19:03:01 +0200
commit6775c7cb3a6d87c2c048ce9d128e16b6aad42f7b (patch)
tree2cc923a5cc42a96b738010530b1721e7288a4ea3
parentc09b6ce975190dfef22943ffeb0502f4d217e269 (diff)
downloadtinycc-6775c7cb3a6d87c2c048ce9d128e16b6aad42f7b.tar.gz
tinycc-6775c7cb3a6d87c2c048ce9d128e16b6aad42f7b.tar.bz2
tccgen.c: fix multi-register structure return when not on stack
We need to preserve the type of the pointer to the structure, f.ex. when a global structure is returned. This is not a perfect solution. Registers loaded in the first iteration might be overwritten in a following iteration as the register is no longer on vtop. This is not a problem for ARM32 as gfunc_sret returns a maximum of 1 in the integer case.
-rw-r--r--tccgen.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/tccgen.c b/tccgen.c
index bb10fe6..ab00308 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5111,16 +5111,21 @@ static void block(int *bsym, int *csym, int is_expr)
else
r = RC_IRET;
- for (;;) {
+ if (ret_nregs == 1)
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;
- vtop->c.i += regsize;
- vtop->r = VT_LOCAL | VT_LVAL;
+ else {
+ for (;;) {
+ vdup();
+ gv(r);
+ vpop();
+ 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;
+ vtop->c.i += regsize;
+ }
}
}
} else if (is_float(func_vt.t)) {