qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

commit bf2a90ef7c183e9e0442d14d6f74fb6d5f79c6bb
parent cec9855fa0c8d9566d4c9755ef7677f49634bc60
Author: Quentin Carbonneaux <quentin@c9x.me>
Date:   Thu, 17 Mar 2022 10:57:09 +0100

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.

Diffstat:
Marm64/abi.c | 6++++--
Mrv64/abi.c | 3++-
2 files changed, 6 insertions(+), 3 deletions(-)

diff --git 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 @@ -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;