From f7d68175fc2b52230b8f78bf78145c7f1d0ad9c5 Mon Sep 17 00:00:00 2001 From: lemon Date: Sat, 6 Dec 2025 18:59:53 +0100 Subject: abi: fix aggregate passed by regs 2nd reg offset It was broken for example `struct { i32 a; f64 b; }` (would try to load/store b from byte offset 4, not 8). Introduce r2off, realize in x86-64 it's always 8; even `struct {i32 a; f32 b;}` gets passed in one (integer) register. But not so in (future) ABIs like RISC-V, I believe there `{i32, f32}` would get passed in 1 integer and 1 float register (r2off = 4). --- ir/ir.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'ir/ir.h') diff --git a/ir/ir.h b/ir/ir.h index b2077a0..297de82 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -51,6 +51,7 @@ struct call { ushort argstksiz; struct abiarg *abiarg; struct abiarg abiret[2]; + uchar r2off; }; enum refkind { @@ -193,23 +194,25 @@ struct mctarg { enum objkind objkind; /* abiret: lower return type: * scalar/small struct -> returns number of regs (1..2), - * r & cls filled with reg and irclass of each scalar return + * r & cls filled with reg and irclass of each scalar return, + * for struct, r2off filled with byte offset within struct for 2nd reg * big struct -> returns 0, is passed via hidden pointer argument, * r[0] contains register for returning said pointer or -1, * r[1] contains register for hidden pointer argument, * *ni is set to 1 if said register is the first ABI integer argument */ - int (*abiret)(short r[2], uchar cls[2], int *ni, union irtype); + int (*abiret)(short r[2], uchar cls[2], uchar *r2off, int *ni, union irtype); /* abiarg: lower argument type: * scalar/small struct -> returns number of regs (1..2), * r & cls filled with reg and irclass of each scalar arg + * for struct, r2off filled with byte offset within struct for 2nd reg * if reg == -1 -> stack * big struct -> returns 0, * if passed in stack cls[0] == 0, r[0] == negative SP offset * if passed by pointer cls[0] == KPTR, r[0] contains integer register * or negative SP offset if stack */ - int (*abiarg)(short r[2], uchar cls[2], int *ni, int *nf, int *ns, union irtype); + int (*abiarg)(short r[2], uchar cls[2], uchar *r2off, int *ni, int *nf, int *ns, union irtype); void (*vastart)(struct function *, struct block *, int *curi); void (*vaarg)(struct function *, struct block *, int *curi); void (*isel)(struct function *); -- cgit v1.2.3