From 8b79b61ae78c91c069447331ed64d400187bdd77 Mon Sep 17 00:00:00 2001 From: lemon Date: Wed, 8 Apr 2026 10:26:18 +0200 Subject: Implement basic aarch64 struct arg passing ABI - Missing: vaargs, >2 member HFAs - Reworked the way stack allocation references are lowered. Now RSTACK persists throughout all passes until emit. This allows deferring stack frame layouting until the end in a less messy way than before, which was emiting frame-pointer relative addresses @ isel time and patching them up later in emit to account for actual stack frame layout. --- src/ir_abi0.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/ir_abi0.c') diff --git a/src/ir_abi0.c b/src/ir_abi0.c index dd8bc40..b8ae90f 100644 --- a/src/ir_abi0.c +++ b/src/ir_abi0.c @@ -91,18 +91,18 @@ static void patchparam(Function *fn, int *curi, int *param, int tydat, int nabi, ABIArg abi[2], uchar r2off) { Block *blk = fn->entry; - assert(in_range(nabi,1,2)); for (; *curi < blk->ins.n; ++*curi) { Instr *ins = &instrtab[blk->ins.p[*curi]]; if (ins->op != Oparam) continue; assert(ins->r.t == RTYPE && ins->r.i == (tydat < 0 ? abi[0].ty : (IRType){.isagg=1, .dat=tydat}).bits); - if (abi[0].ty.isagg || tydat < 0) { + if (abi[0].ty.isagg || tydat < 0 || abi[0].ty.bits == cls2type(KPTR).bits) { /* aggregate in stack or scalar, just copy */ - assert(nabi == 1); + assert(nabi < 2); *ins = copyparam(fn, curi, *param, abi[0]); } else { /* aggregate in registers, materialize */ + assert(nabi >= 1); Ref alloc, r[2]; Instr st; const TypeData *td; @@ -120,13 +120,13 @@ patchparam(Function *fn, int *curi, int *param, int tydat, int nabi, ABIArg abi[ if (nabi > 1) r[1] = insertinstr(blk, ++*curi, copyparam(fn, NULL, ++*param, abi[1])); /* transform - * %x = copy %p + * %x = param %p * into * %x = alloca... * store* %x, %a * store* %x + N, %b */ - st = mkinstr2(cls2store[abi[0].ty.cls], 0, alloc, r[0]); + st = mkinstr2(cls2store[abi[0].ty.isagg ? KPTR : abi[0].ty.cls], 0, alloc, r[0]); insertinstr(blk, ++*curi, st); if (nabi > 1) { Instr tmp = mkinstr2(Oadd, KPTR, alloc, mkref(RICON, r2off)); @@ -174,7 +174,6 @@ load2regs(Ref out[2], IRType typ, Ref src, int nabi, ABIArg abi[2], uchar r2off, ins.l = insertinstr(blk, (*curi)++, adr); } temp = insertinstr(blk, (*curi)++, ins); - //insertinstr(blk, (*curi)++, mkarginstr(abi[i].ty, temp)); out[i] = temp; } } else { @@ -200,7 +199,6 @@ load2regs(Ref out[2], IRType typ, Ref src, int nabi, ABIArg abi[2], uchar r2off, reg = temp; } } - //insertinstr(blk, arginst++, mkarginstr(abi[i].ty, reg)); out[i] = reg; } } @@ -215,6 +213,7 @@ patcharg(Block *blk, int *icall, IRCall *call, assert(arg->op == Oarg && arg->l.t == RTYPE); if (ref2type(arg->l).isagg) { /* aggregate argument */ if (abi[0].ty.isagg) { /* aggregate in stack */ + assert(nabi == 0); /* XXX do this better.. */ /* ptr %dst = arg */ /* (blit %dst, %src) */ @@ -236,9 +235,12 @@ patcharg(Block *blk, int *icall, IRCall *call, *icall = arginst + (call->narg - argidx); return 1; } else if (abi[0].ty.cls == KPTR) { /* aggregate by pointer */ + /* XXX make a copy */ + assert(nabi == -1 || nabi == 1); arg->cls = KPTR; return 1; } else { /* aggregate in registers */ + assert(nabi > 0); Ref r[2]; IRType typ = ref2type(arg->l); delinstr(blk, arginst); @@ -249,6 +251,7 @@ patcharg(Block *blk, int *icall, IRCall *call, return nabi; } } else { /* normal scalar argument */ + assert(nabi >= 0); return 1; } } @@ -383,7 +386,7 @@ abi0(Function *fn) int first = abiargs.n; uchar r2off; int ret = abiarg(&abiargs, &r2off, &ni, &nf, &ns, pty); - patchparam(fn, &istart, ¶m, pty.isagg ? pty.dat : -1, ret+!ret, &abiargs.p[first], r2off); + patchparam(fn, &istart, ¶m, pty.isagg ? pty.dat : -1, ret, &abiargs.p[first], r2off); } fn->abiarg = alloccopy(fn->arena, abiargs.p, abiargs.n * sizeof *abiargs.p, 0); fn->nabiarg = abiargs.n; -- cgit v1.2.3