aboutsummaryrefslogtreecommitdiffhomepage
path: root/amd64
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-11-12 17:58:51 +0100
committerlemon <lsof@mailbox.org>2025-11-12 18:03:42 +0100
commit82a3c1cd8d00bc342752c31116c497c52f6d8933 (patch)
tree9b4256a83c68b6569a75d08307a50a5662f2cfb2 /amd64
parent070bf6f223b6cc6f3d7a6c28c1afce8c0bc8a72e (diff)
implement argument passing in stack
Diffstat (limited to 'amd64')
-rw-r--r--amd64/isel.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/amd64/isel.c b/amd64/isel.c
index 8108ec4..c0c6054 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -106,20 +106,32 @@ selcall(struct function *fn, struct instr *ins, struct block *blk, int *curi)
const struct call *call = &calltab.p[ins->r.i];
int iarg = *curi - 1;
enum irclass cls;
+ uint argstksiz = alignup(call->argstksiz, 16);
for (int i = call->narg - 1; i >= 0; --i) {
+ struct abiarg abi = call->abiarg[i];
struct instr *arg;
- for (;;) {
- assert(i >= 0 && "arg?");
- if ((arg = &instrtab[blk->ins.p[iarg--]])->op == Oarg)
+ for (;; --iarg) {
+ assert(iarg >= 0 && i >= 0 && "arg?");
+ if ((arg = &instrtab[blk->ins.p[iarg]])->op == Oarg)
break;
}
- if (call->abiarg[i].reg >= 0) {
- assert(!call->abiarg[i].ty.isagg);
- *arg = mkinstr(Omove, call->abiarg[i].ty.cls, mkref(RREG, call->abiarg[i].reg), arg->r);
+ assert(!abi.ty.isagg);
+ if (abi.reg >= 0) {
+ assert(!abi.ty.isagg);
+ *arg = mkinstr(Omove, call->abiarg[i].ty.cls, mkref(RREG, abi.reg), arg->r);
+ } else {
+ union ref adr = mkaddr((struct addr){mkref(RREG, RSP), .disp = argstksiz+abi.stk});
+ *arg = mkinstr(Ostore1+ilog2(cls2siz[abi.ty.cls]), 0, adr, arg->r);
}
}
+ if (call->argstksiz) {
+ union ref disp = mkref(RICON, argstksiz);
+ insertinstr(blk, iarg--, (struct instr){Osub, KPTR, .keep=1, .reg = RSP+1, .l=mkref(RREG,RSP), disp});
+ ++*curi;
+ insertinstr(blk, *curi+1, (struct instr){Oadd, KPTR, .keep=1, .reg = RSP+1, .l=mkref(RREG,RSP), disp});
+ }
cls = ins->cls;
ins->cls = 0;
if (cls) {