diff options
| author | 2025-11-27 21:35:12 +0100 | |
|---|---|---|
| committer | 2025-11-27 21:35:12 +0100 | |
| commit | ba40fd10d0c6066c07cd651c25cefba8d75df9e0 (patch) | |
| tree | e3185169d71d04e5e30674791e435d69e5acd061 | |
| parent | cba84f37bc9b1d939c04ed31beec5b803ee4da5a (diff) | |
abi/isel: aggregate args in stack wip
| -rw-r--r-- | amd64/isel.c | 17 | ||||
| -rw-r--r-- | ir/abi0.c | 40 |
2 files changed, 42 insertions, 15 deletions
diff --git a/amd64/isel.c b/amd64/isel.c index 7bb0a06..1b10de5 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -136,18 +136,21 @@ selcall(struct function *fn, struct instr *ins, struct block *blk, int *curi) break; } - assert(!abi.ty.isagg); if (!abi.isstk) { 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 = abi.stk}); - *arg = mkinstr(Ostore8+ilog2(cls2siz[abi.ty.cls]), 0, adr, arg->r); int iargsave = iarg; - if (isaddrcon(arg->r,1) || arg->r.t == RADDR) - arg->r = insertinstr(blk, iarg++, mkinstr(Ocopy, abi.ty.cls, arg->r)); - else - fixarg(&ins->r, ins, blk, &iarg); + if (!abi.ty.isagg) { /* scalar arg in stack */ + *arg = mkinstr(Ostore8+ilog2(cls2siz[abi.ty.cls]), 0, adr, arg->r); + if (isaddrcon(arg->r,1) || arg->r.t == RADDR) + arg->r = insertinstr(blk, iarg++, mkinstr(Ocopy, abi.ty.cls, arg->r)); + else + fixarg(&ins->r, ins, blk, &iarg); + } else { /* aggregate arg in stack, callee stack frame destination address */ + *arg = mkinstr(Ocopy, KPTR, adr); + } *curi += iarg - iargsave; } } @@ -423,6 +426,8 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) } if (ins->l.t != RTMP && ins->l.t != RREG) ins->l = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ins->cls, ins->l)); + else + fixarg(&ins->l, ins, blk, curi); fixarg(&ins->r, ins, blk, curi); break; case Odiv: case Oudiv: case Orem: case Ourem: @@ -63,13 +63,15 @@ copyparam(struct function *fn, int *curi, int param, struct abiarg abi) if (!abi.isstk) { /* reg */ assert(!abi.ty.isagg); return par; - } else if (!abi.ty.isagg) { /* scalar in stack */ + } + par.r = mktyperef((union irtype){.cls = KPTR}); + if (!abi.ty.isagg) { /* scalar in stack */ enum op ld; par.cls = KPTR; if (abi.ty.cls == KPTR) abi.ty.cls = siz2intcls[cls2siz[abi.ty.cls]]; switch (abi.ty.cls) { default: assert(0); - case KI32: ld = Oloadu32; break; + case KI32: ld = Oloads32; break; case KI64: ld = Oloadi64; break; case KF32: ld = Oloadf32; break; case KF64: ld = Oloadf64; break; @@ -207,23 +209,43 @@ patcharg(struct block *blk, int *icall, struct call *call, int arginst = *icall - (call->narg - argidx); struct instr *arg = &instrtab[blk->ins.p[arginst]]; assert(arg->op == Oarg && arg->l.t == RTYPE); - if (ref2type(arg->l).isagg) { - /* aggregate argument */ - if (abi[0].ty.isagg /* aggregate in stack */ - || abi[0].ty.cls == KPTR) /* aggregate by pointer */ - { + if (ref2type(arg->l).isagg) { /* aggregate argument */ + if (abi[0].ty.isagg) { /* aggregate in stack */ + /* XXX do this better.. */ + /* ptr %dst = arg <stk dst> */ + /* (blit %dst, %src) */ + union ref dst = mkref(RTMP, arg - instrtab); + uint align = typedata[abi->ty.dat].align, siz = typedata[abi->ty.dat].siz; + union ref src = arg->r; + if (src.t == RTMP && oisalloca(instrtab[src.i].op)) { + align = 1 << (instrtab[src.i].op - Oalloca1); + } + assert(align <= 8); + arg->cls = KPTR; + arg->r = mkref(RICON, abi->stk); + for (uint off = 0; off < siz; off += align) { + union ref sadr = off == 0 ? src : insertinstr(blk, ++arginst, mkinstr(Oadd, KPTR, src, mkref(RICON, off))); + union ref tmp = insertinstr(blk, ++arginst, mkinstr(Oloads8+2*ilog2(align), align < 8 ? KI32 : KI64, sadr)); + union ref dadr = off == 0 ? dst : insertinstr(blk, ++arginst, mkinstr(Oadd, KPTR, dst, mkref(RICON, off))); + insertinstr(blk, ++arginst, mkinstr(Ostore8+ilog2(align), 0, dadr, tmp)); + } + *icall = arginst + (call->narg - argidx); + return 1; + } else if (abi[0].ty.cls == KPTR) { /* aggregate by pointer */ + arg->cls = KPTR; return 1; } else { /* aggregate in registers */ union ref r[2]; delinstr(blk, arginst); load2regs(r, ref2type(arg->l), arg->r, nabi, abi, blk, &arginst); for (int i = 0; i < nabi; ++i) - insertinstr(blk, arginst++, mkarginstr(abi[i].ty, r[i])); + insertinstr(blk, arginst++, mkinstr(Oarg, 0, mktyperef(abi[i].ty), r[i])); *icall = arginst + (call->narg - argidx - 1); return nabi; } - } else /* normal scalar argument */ + } else { /* normal scalar argument */ return 1; + } } static struct abiarg abiargsbuf[32]; |