aboutsummaryrefslogtreecommitdiffhomepage
path: root/abistruct.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-03 21:51:28 +0200
committerlemon <lsof@mailbox.org>2023-06-04 10:20:19 +0200
commit2ca24f83c35b253593b5aa8775d37923c8383149 (patch)
tree09fc86a228b81ac574233a922758953c4c460861 /abistruct.c
parent65ace14e184807df026e985e073b3b5c5aaf576c (diff)
abi lowering pass
Diffstat (limited to 'abistruct.c')
-rw-r--r--abistruct.c148
1 files changed, 0 insertions, 148 deletions
diff --git a/abistruct.c b/abistruct.c
deleted file mode 100644
index 36b686b..0000000
--- a/abistruct.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include "common.h"
-#include "ir.h"
-
-/* This pass lowers aggregate params/args/returns into scalars, according to abi */
-
-/* RARG can only appear in the entry block (prologue), each RARG can only appear once
- * this function patches arg starting at instruction no. *start according to cls
- * to redirect it to use arg no. `to' (and maybe also `to + 1')
- */
-static void
-patcharg(struct function *fn, int *start, int arg, int tydat, int to, uchar cls[2])
-{
- struct block *blk = fn->entry;
- assert(!blk->phi.n);
- while((*start)++ < blk->ins.n) {
- struct instr *ins = &instrtab[blk->ins.p[*start - 1]];
- if (ins->op == Ocopy && ins->l.t == RARG && ins->l.i == arg) {
- /* originally aggregate argument */
- assert(tydat != -1);
- if (!cls[0]) { /* memory class */
- ins->l.i = to;
- } else { /* aggregate in registers */
- const struct typedata *td = &typedata[tydat];
- /* transform
- * %x = copy %argX
- * into
- * %x = alloca...
- * store* %x, %argN
- * store* %x + I, %argM
- */
- assert(td->siz <= 16 && td->align <= 16);
- ins->op = Oalloca8 + (td->align == 16);
- ins->l = mkref(RICON, td->align == 16 ? 1 : td->siz / 8);
- insertinstr(blk, *start, mkinstr(Ostore1 + ilog2(cls2siz[cls[0]]), 0,
- mkref(RTMP, ins - instrtab), mkref(RARG, to)));
- *start += 1;
- if (cls[1]) {
- struct instr tmp = mkinstr(Oadd, KPTR,
- mkref(RTMP, ins - instrtab), mkref(RICON, cls2siz[cls[0]]));
- insertinstr(blk, *start+1, mkinstr(Ostore1 + ilog2(cls2siz[cls[1]]), 0,
- insertinstr(blk, *start, tmp), mkref(RARG, to+1)));
- *start += 2;
- }
- }
- break;
- } else if (oisstore(ins->op) && ins->r.t == RARG && ins->r.i == arg) {
- /* normal scalar argument */
- assert(tydat == -1);
- ins->r.i = to;
- break;
- }
- }
-}
-
-void
-abistruct(struct function *fn)
-{
- uint nparam = typedata[fn->fnty.dat].nmemb;
- const union type *paramty = typedata[fn->fnty.dat].param;
- vec_of(struct abiarg) abiargs = {0};
- int retreg = 0;
- struct abiarg retval[2];
- int ni = 0, nf = 0, mi = 0, istart = 0;
- short r[2];
- uchar cls[2];
- struct block *blk;
- union ref sret;
-
- if (isagg(fn->retty)) {
- retreg = mctarg->abi_retregs(r, cls, mkirtype(fn->retty));
- if (!retreg) {
- /* return location is first (pointer) argument */
- vpush(&abiargs, ((struct abiarg) { {.cls = KPTR}, r[0] }));
- ++ni;
- sret = insertinstr(fn->entry, 0, mkinstr(Ocopy, KPTR, mkref(RARG, 0)));
- ++istart;
- } else for (int i = 0; i < retreg; ++i) {
- /* return in 1 or 2 registers */
- retval[i].ty = (union irtype) {.cls = cls[i]};
- retval[i].reg = r[i];
- }
- }
- memcpy(fn->abiret, retval, sizeof retval);
- fn->nabiret = retreg;
-
- /* adjust params */
- for (int i = 0, newi; i < nparam; ++i) {
- union irtype pty = mkirtype(paramty[i]);
- int ret;
- assert(mctarg->abi_argregs);
- newi = ni + nf + mi;
- ret = mctarg->abi_argregs(r, cls, &ni, &nf, pty);
- if (!ret) { /* memory */
- vpush(&abiargs, ((struct abiarg) { pty, -1 }));
- ++mi;
- } else {
- vpush(&abiargs, ((struct abiarg) { {.cls = cls[0]}, r[0] }));
- if (ret == 2)
- vpush(&abiargs, ((struct abiarg) { {.cls = cls[1]}, r[1] }));
- }
- if (i != newi || (pty.isagg && ret))
- patcharg(fn, &istart, i, pty.isagg ? pty.dat : -1, newi, cls);
- }
- fn->abiarg = abiargs.p;
- fn->nabiarg = abiargs.n;
-
- /* adjust calls and returns */
- blk = fn->entry;
- do {
- for (int i = 0; i < blk->ins.n; ++i) {
- struct instr *ins = &instrtab[blk->ins.p[i]];
- }
- if (isagg(fn->retty) && blk->jmp.t == Jret && blk->jmp.arg[0].t) {
- /* aggregate return (arg[0] is pointer to return value) */
- assert(!blk->jmp.arg[1].t);
- if (retreg) {
- union ref src = blk->jmp.arg[0];
- for (int i = 0; i < retreg; ++i) {
- /* XXX this can generate unaligned loads */
- struct instr ins = {0};
- switch (ins.cls = retval[i].ty.cls) {
- default: assert(0);
- case KI4: ins.op = Oloadu4; break;
- case KI8: ins.op = Oloadi8; break;
- case KF4: ins.op = Oloadf4; break;
- case KF8: ins.op = Oloadf8; break;
- }
- if (i == 0)
- ins.l = src;
- else
- ins.l = insertinstr(blk, blk->ins.n,
- mkinstr(Oadd, KPTR, src,
- mkref(RICON, cls2siz[retval[0].ty.cls])));
- blk->jmp.arg[i] = insertinstr(blk, blk->ins.n, ins);
- }
- } else {
- /* blit %sret, %arg */
- union ref args[2] = { sret, blk->jmp.arg[0] };
- union irtype typ[2] = { mkirtype(fn->retty) };
- typ[1] = typ[0];
- insertinstr(blk, blk->ins.n, mkbuiltin(fn, BTstructcopy, 0, 2, args, typ));
- memset(&blk->jmp.arg[0], 0, sizeof(union ref));
- }
- }
- } while ((blk = blk->lnext) != fn->entry);
-}
-
-/* vim:set ts=3 sw=3 expandtab: */