diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2022-03-17 10:57:09 +0100 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2022-03-17 10:57:09 +0100 |
commit | bf2a90ef7c183e9e0442d14d6f74fb6d5f79c6bb (patch) | |
tree | 47f42ddf38f84b8e78acc828033a47a7dd64d553 | |
parent | cec9855fa0c8d9566d4c9755ef7677f49634bc60 (diff) | |
download | roux-bf2a90ef7c183e9e0442d14d6f74fb6d5f79c6bb.tar.gz |
fix return for big aggregates
The recent changes in arm and riscv typclass() set ngp to 1 when a struct is returned via a caller-provided buffer. This interacts bogusly with selret() that ends up declaring a gp register live when none is set in the returning sequence. The fix is simply to set cty to zero (all registers dead) in case a caller- provided buffer is used.
-rw-r--r-- | arm64/abi.c | 6 | ||||
-rw-r--r-- | rv64/abi.c | 3 |
2 files changed, 6 insertions, 3 deletions
diff --git a/arm64/abi.c b/arm64/abi.c index 396c704..b2b5973 100644 --- a/arm64/abi.c +++ b/arm64/abi.c @@ -183,12 +183,14 @@ selret(Blk *b, Fn *fn) if (j == Jretc) { typclass(&cr, &typ[fn->retty], gpreg, fpreg); - cty = (cr.nfp << 2) | cr.ngp; if (cr.class & Cptr) { assert(rtype(fn->retr) == RTmp); blit0(fn->retr, r, cr.t->size, fn); - } else + cty = 0; + } else { ldregs(cr.reg, cr.cls, cr.nreg, r, fn); + cty = (cr.nfp << 2) | cr.ngp; + } } else { k = j - Jretw; if (KBASE(k) == 0) { diff --git a/rv64/abi.c b/rv64/abi.c index 0baaa67..3a97a6a 100644 --- a/rv64/abi.c +++ b/rv64/abi.c @@ -220,12 +220,13 @@ selret(Blk *b, Fn *fn) if (j == Jretc) { typclass(&cr, &typ[fn->retty], 1, gpreg, fpreg); - cty = (cr.nfp << 2) | cr.ngp; if (cr.class & Cptr) { assert(rtype(fn->retr) == RTmp); blit0(fn->retr, r, cr.type->size, fn); + cty = 0; } else { ldregs(&cr, r, fn); + cty = (cr.nfp << 2) | cr.ngp; } } else { k = j - Jretw; |