aboutsummaryrefslogtreecommitdiffhomepage
path: root/regalloc.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-05 15:57:57 +0200
committerlemon <lsof@mailbox.org>2023-06-05 15:57:57 +0200
commitfb3e9ae04d86cd7e80e8d4db3c1c444bfe7f7168 (patch)
tree665d5051bd27b2ee1c7cd7add85cc7fc04eebe32 /regalloc.c
parentfe81f55cf6bcddb2cd02ea7327fce1616dd763c2 (diff)
encode calls a different way in the IR
Diffstat (limited to 'regalloc.c')
-rw-r--r--regalloc.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/regalloc.c b/regalloc.c
index d7fadf6..5833ed4 100644
--- a/regalloc.c
+++ b/regalloc.c
@@ -36,11 +36,7 @@ use(struct block *blk, enum op op, int hint, union ref *ref)
{
struct instr *ins;
if (ref->t == RMORE) {
- if (op == Ocall || op == Ointrin) {
- struct call *call = &calltab.p[ref->i];
- for (int i = 0; i < call->narg; ++i)
- use(blk, 0, op == Ocall ? call->abiargregs[i] : -1, &call->args[i]);
- } else if (op == Ophi) {
+ if (op == Ophi) {
struct phi *phi = &phitab.p[ref->i];
for (int i = 0; i < phi->n; ++i)
use(blk, 0, hint, &phi->ref[i]);
@@ -57,7 +53,6 @@ use(struct block *blk, enum op op, int hint, union ref *ref)
/* result of comparison instr is only used to conditionally branch,
* doesn't usually need a reg (handled by isel) */
return;
- /* TODO implement actual constraints and stuff */
if (ins->op == Ocall) {
struct call *call = &calltab.p[ins->r.i];
hint = call->abiret[0].reg;
@@ -105,9 +100,24 @@ regalloc(struct function *fn)
int hint0 = -1, hint1 = -1;
ins = &instrtab[blk->ins.p[i]];
def(ins);
- if (ins->op == Ocopy) hint0 = ins->reg - 1;
- if (ins->l.t) use(blk, ins->op, hint0, &ins->l);
- if (ins->r.t) use(blk, ins->op, hint1, &ins->r);
+ if (ins->op != Ocall) {
+ if (ins->op == Ocopy) hint0 = ins->reg - 1;
+ if (ins->l.t) use(blk, ins->op, hint0, &ins->l);
+ if (ins->r.t) use(blk, ins->op, hint1, &ins->r);
+ } else {
+ struct call *call = &calltab.p[ins->r.i];
+ for (int iarg = 0; iarg < call->narg; ++iarg) {
+ struct instr *arg = &instrtab[blk->ins.p[i - call->narg + iarg]];
+ int reg = call->abiargregs[iarg];
+ assert(arg->op == Oarg);
+ if (reg != -1) {
+ assert(!bstest(taken, reg) && "nyi spill");
+ arg->reg = reg + 1;
+ bsset(taken, reg);
+ }
+ }
+ use(blk, ins->op, hint0, &ins->l);
+ }
}
} while ((blk = blk->lprev) != last);