aboutsummaryrefslogtreecommitdiffhomepage
path: root/ir/ir.h
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-12-06 18:59:53 +0100
committerlemon <lsof@mailbox.org>2025-12-06 18:59:53 +0100
commitf7d68175fc2b52230b8f78bf78145c7f1d0ad9c5 (patch)
tree099243c78aaef479daee0b2ab5e8dc8215cea9e3 /ir/ir.h
parentd82f3052c813f671561362126d0fbe08568542d3 (diff)
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).
Diffstat (limited to 'ir/ir.h')
-rw-r--r--ir/ir.h9
1 files changed, 6 insertions, 3 deletions
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 *);