diff options
| author | 2025-11-12 17:58:51 +0100 | |
|---|---|---|
| committer | 2025-11-12 18:03:42 +0100 | |
| commit | 82a3c1cd8d00bc342752c31116c497c52f6d8933 (patch) | |
| tree | 9b4256a83c68b6569a75d08307a50a5662f2cfb2 | |
| parent | 070bf6f223b6cc6f3d7a6c28c1afce8c0bc8a72e (diff) | |
implement argument passing in stack
| -rw-r--r-- | amd64/isel.c | 24 | ||||
| -rw-r--r-- | ir/abi0.c | 1 | ||||
| -rw-r--r-- | ir/ir.h | 1 |
3 files changed, 20 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) { @@ -276,6 +276,7 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi) if (call->vararg == i) vararg = i2; i2 += ret; } + call->argstksiz = ns; /* adjust return */ if (call->ret.isagg) { ins->cls = 0; @@ -46,6 +46,7 @@ struct call { union irtype ret; ushort narg; short vararg; /* first variadic arg or -1 */ + ushort argstksiz; struct abiarg *abiarg; struct abiarg abiret[2]; }; |