aboutsummaryrefslogtreecommitdiffhomepage
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
parentfe81f55cf6bcddb2cd02ea7327fce1616dd763c2 (diff)
encode calls a different way in the IR
-rw-r--r--abi0.c153
-rw-r--r--amd64/sysv.c2
-rw-r--r--ir.c21
-rw-r--r--ir.h15
-rw-r--r--irdump.c73
-rw-r--r--op.def1
-rw-r--r--parse.c33
-rw-r--r--regalloc.c28
-rw-r--r--test/test.c10
9 files changed, 158 insertions, 178 deletions
diff --git a/abi0.c b/abi0.c
index c3673e4..3547f64 100644
--- a/abi0.c
+++ b/abi0.c
@@ -2,6 +2,9 @@
/** This pass adds in ABI arguments/returns register mappings
** and lowers aggregate params/args/returns into scalars
+ **
+ ** invariant: all `call` instructions when doing this pass shall be preceded by
+ ** exactly narg `arg` instructions with no other instructions in between
**/
struct abiargsvec { vec_of(struct abiarg); };
@@ -103,25 +106,29 @@ patchparam(struct function *fn, int *start, int param, int tydat, int to, struct
}
static int
-patcharg(union ref newargs[2], union irtype newtyps[2], struct block *blk, int *icall,
- struct call *call, int arg, int nabi, struct abiarg abi[2])
+patcharg(struct block *blk, int *icall, struct call *call,
+ int argidx, int nabi, struct abiarg abi[2])
{
- if (call->typs[arg].isagg) {
- /* originally aggregate argument */
+ 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 */
{
- newargs[0] = call->args[arg];
- newtyps[0] = call->typs[arg];
+ return 1;
} else { /* aggregate in registers */
- union ref src = call->args[arg];
+ union ref src = arg->r;
/* deconstruct into
* %a = load* %x
* (%b = load* %x + N)
*/
+ delinstr(blk, arginst);
for (int i = 0; i < nabi; ++i) {
/* XXX this can generate unaligned loads */
struct instr ins = {0};
+ union ref temp;
switch (ins.cls = abi[i].ty.cls) {
default: assert(0);
case KI4: ins.op = Oloadu4; break;
@@ -132,20 +139,19 @@ patcharg(union ref newargs[2], union irtype newtyps[2], struct block *blk, int *
if (i == 0)
ins.l = src;
else
- ins.l = insertinstr(blk, (*icall)++ - 1,
+ ins.l = insertinstr(blk, arginst++,
mkinstr(Oadd, KPTR, src,
mkref(RICON, cls2siz[abi[0].ty.cls])));
- newtyps[i] = (union irtype) { .cls = ins.cls };
- newargs[i] = insertinstr(blk, (*icall)++ - 1, ins);
+ temp = insertinstr(blk, arginst++, ins);
+ insertinstr(blk, arginst++, mkarginstr(abi[i].ty, temp));
}
+ *icall += arginst - (call->narg - argidx);
return nabi;
}
} else {
/* normal scalar argument */
- newargs[0] = call->args[arg];
- newtyps[0] = call->typs[arg];
+ return 1;
}
- return 1;
}
void
@@ -215,10 +221,6 @@ abi0(struct function *fn)
for (int iinstr = 0; iinstr < blk->ins.n; ++iinstr) {
struct instr *ins = &instrtab[blk->ins.p[iinstr]];
struct call *call = &calltab.p[ins->r.i];
- static union ref newargsbuf[32];
- static union irtype newtypsbuf[32];
- vec_of(union ref) newargs = VINIT(newargsbuf, arraylength(newargsbuf));
- vec_of(union irtype) newtyps = VINIT(newtypsbuf, arraylength(newtypsbuf));
bool structbyval;
int vararg;
@@ -226,58 +228,56 @@ abi0(struct function *fn)
vararg = call->vararg;
vinit(&abiargs, abiargsbuf, arraylength(abiargsbuf));
- if (!(structbyval = call->sret))
- for (int i = 0; i < call->narg; ++i)
- if ((structbyval = call->typs[i].isagg))
+ if (!(structbyval = call->ret.isagg))
+ for (int i = iinstr - call->narg; i < iinstr; ++i)
+ if ((structbyval = ref2type(instrtab[blk->ins.p[i]].l).isagg))
break;
ni = nf = ns = 0;
memset(call->abiret, 0, sizeof call->abiret);
- if (call->sret) {
- union irtype retty = call->typs[call->narg];
+ if (call->ret.isagg) { /* adjust struct return */
+ union ref temp;
+ union irtype retty = call->ret;
+ struct instr alloca = { .cls = KPTR };
+ struct typedata *td = &typedata[retty.dat];
int ret = abiret(call->abiret, &abiargs, &ni, retty);
- if (retty.isagg) {
- union ref temp;
- struct instr alloca = { .cls = KPTR };
- struct typedata *td = &typedata[retty.dat];
- sretarghidden = ni == 0;
- alloca.op = Oalloca8 + (td->align == 16);
- alloca.l = mkref(RICON, td->align == 16 ? 1 : td->siz / 8);
- temp = insertinstr(blk, iinstr++, alloca);
- replref(fn, blk, iinstr, mkref(RTMP, ins - instrtab), temp);
- if (!ret) { /* hidden pointer argument */
- vpush(&newargs, temp);
- vpush(&newtyps, (union irtype) {.cls = KPTR});
- ins->cls = 0;
- } else {
- union ref call2r;
- int to = iinstr + 1;
- assert(in_range(ret, 1, 2));
- ins->cls = call->abiret[0].ty.cls;
- if (ret == 2)
- call2r = insertinstr(blk, to++, mkinstr(Ocall2r, call->abiret[1].ty.cls,
- mkref(RTMP, ins - instrtab)));
- for (int i = 0; i < ret; ++i) {
- uchar cls;
- struct instr store = {0};
- /* XXX this can generate unaligned stores */
- switch (cls = call->abiret[i].ty.cls) {
- default: assert(0);
- case KF4: case KI4: store.op = Ostore4; break;
- case KI8: case KF8: store.op = Ostore8; break;
- }
- if (i == 0) {
- store.l = temp;
- store.r = mkref(RTMP, ins - instrtab);
- } else {
- store.l = insertinstr(blk, to++,
- mkinstr(Oadd, KPTR, temp,
- mkref(RICON, cls2siz[call->abiret[0].ty.cls])));
- store.r = call2r;
- }
- insertinstr(blk, to++, store);
+ sretarghidden = ni == 0;
+ alloca.op = Oalloca8 + (td->align == 16);
+ alloca.l = mkref(RICON, td->align == 16 ? 1 : td->siz / 8);
+ temp = insertinstr(blk, iinstr++ - call->narg, alloca);
+ replref(fn, blk, iinstr, mkref(RTMP, ins - instrtab), temp);
+ if (!ret) { /* hidden pointer argument */
+ insertinstr(blk, iinstr++ - call->narg,
+ mkarginstr((union irtype){.cls = KPTR}, temp));
+ ins->cls = 0;
+ } else { /* aggregate returned in regs */
+ union ref call2r;
+ int to = iinstr + 1;
+ assert(in_range(ret, 1, 2));
+ ins->cls = call->abiret[0].ty.cls;
+ if (ret == 2)
+ call2r = insertinstr(blk, to++, mkinstr(Ocall2r, call->abiret[1].ty.cls,
+ mkref(RTMP, ins - instrtab)));
+ for (int i = 0; i < ret; ++i) {
+ uchar cls;
+ struct instr store = {0};
+ /* XXX this can generate unaligned stores */
+ switch (cls = call->abiret[i].ty.cls) {
+ default: assert(0);
+ case KF4: case KI4: store.op = Ostore4; break;
+ case KI8: case KF8: store.op = Ostore8; break;
}
+ if (i == 0) {
+ store.l = temp;
+ store.r = mkref(RTMP, ins - instrtab);
+ } else {
+ store.l = insertinstr(blk, to++,
+ mkinstr(Oadd, KPTR, temp,
+ mkref(RICON, cls2siz[call->abiret[0].ty.cls])));
+ store.r = call2r;
+ }
+ insertinstr(blk, to++, store);
}
}
} else if (ins->cls) {
@@ -286,35 +286,20 @@ abi0(struct function *fn)
}
for (int i = 0; i < call->narg; ++i) {
- union irtype pty = call->typs[i];
+ union irtype pty = ref2type(instrtab[blk->ins.p[iinstr - call->narg + i]].l);
int thisi = sretarghidden + ni + nf + ns;
int first = abiargs.n;
int ret = abiarg(&abiargs, &ni, &nf, &ns, pty);
- union ref argss[2];
- union irtype typss[2];
- ret = patcharg(argss, typss, blk, &iinstr, call, i, ret, &abiargs.p[first]);
- if (structbyval) {
- vpushn(&newargs, argss, ret);
- vpushn(&newtyps, typss, ret);
- }
+ ret = patcharg(blk, &iinstr, call, i, ret, &abiargs.p[first]);
if (call->vararg == i)
vararg = thisi;
}
- call->sret = 0;
+ if (call->ret.isagg) call->ret = (union irtype){0};
call->vararg = vararg;
- if (structbyval && newargs.n != call->narg) {
- call->args = alloc(&fn->arena, newargs.n * (sizeof *newargs.p + sizeof *newtyps.p), 0);
- call->typs = (union irtype *)((char *)call->args + newargs.n * sizeof *newargs.p);
- }
- memcpy(call->typs, newtyps.p, newtyps.n * sizeof *call->typs);
- if (structbyval)
- memcpy(call->args, newargs.p, newargs.n * sizeof *call->args);
call->abiargregs = alloc(&fn->arena, abiargs.n * sizeof *call->abiargregs, 0);
for (int i = 0; i < abiargs.n; ++i) call->abiargregs[i] = abiargs.p[i].reg;
call->narg = abiargs.n;
vfree(&abiargs);
- vfree(&newargs);
- vfree(&newtyps);
}
/* adjust returns */
@@ -344,10 +329,10 @@ abi0(struct function *fn)
/* aggregate return (arg[0] is pointer to return value) */
if (rvovar == -1) {
/* 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, mkintrin(fn, INstructcopy, 0, 2, args, typ));
+ union irtype typ = mkirtype(fn->retty);
+ insertinstr(blk, blk->ins.n, mkarginstr(typ, sret));
+ insertinstr(blk, blk->ins.n, mkarginstr(typ, blk->jmp.arg[0]));
+ insertinstr(blk, blk->ins.n, mkintrin(fn, INstructcopy, 0, 2));
} else assert(blk->jmp.arg[0].bits == mkref(RTMP, rvovar).bits);
if (fn->abiret[0].ty.cls) blk->jmp.arg[0] = rvovar == -1 ? sret : mkref(RTMP, rvovar);
else memset(blk->jmp.arg, 0, sizeof blk->jmp.arg);
diff --git a/amd64/sysv.c b/amd64/sysv.c
index e2f5b7b..f909067 100644
--- a/amd64/sysv.c
+++ b/amd64/sysv.c
@@ -48,7 +48,7 @@ classify(uchar cls[2], const struct typedata *td, uint off)
if (!cls[(fld->off + off)/8])
cls[(fld->off + off)/8] = KF8;
} else { /* INTEGER */
- assert(isint(fld->t) || chld.t == TYPTR);
+ assert(isint(fld->t) || fld->t.t == TYPTR);
cls[(fld->off + off)/8] = KI8;
}
}
diff --git a/ir.c b/ir.c
index 96877e2..1d937cf 100644
--- a/ir.c
+++ b/ir.c
@@ -119,8 +119,7 @@ conputdat(struct irdat *dat, uint off, enum typetag t, const void *src)
union irtype
mkirtype(union type t)
{
- assert(t.t != TYVOID);
- if (isscalar(t)) return (union irtype) { .cls = type2cls[t.t] };
+ if (t.t == TYVOID || isscalar(t)) return (union irtype) { .cls = type2cls[t.t] };
assert(isagg(t));
return (union irtype) { .isagg = 1, .dat = t.dat };
}
@@ -179,17 +178,10 @@ mkalloca(uint siz, uint align)
}
union ref
-mkcallarg(struct function *fn, bool sret, uint narg, int vararg, union ref *args, union irtype *typs)
+mkcallarg(struct function *fn, union irtype ret, uint narg, int vararg)
{
- struct call call = { .sret=sret, .narg=narg, .vararg=vararg };
-
+ struct call call = { .ret=ret, .narg=narg, .vararg=vararg };
assert((long) vararg <= narg);
- if (narg) {
- call.args = alloc(&fn->arena, narg*sizeof *args + (narg+sret)*sizeof(union irtype), 0);
- call.typs = (union irtype *)((char *)call.args + narg*sizeof *args);
- memcpy(call.args, args, narg*sizeof *args);
- memcpy(call.typs, typs, (narg+sret)*sizeof *typs);
- }
vpush(&calltab, call);
return mkref(RMORE, calltab.n-1);
}
@@ -359,13 +351,6 @@ replref(struct function *fn, struct block *blk, int i0, union ref from, union re
for (int i = 0; i < 2; ++i) {
union ref *r = &(&ins->l)[i];
if (r->bits == from.bits) *r = to;
- else if (r->t == RMORE) {
- struct call *call = &calltab.p[r->i];
- assert(ins->op == Ocall || ins->op == Ointrin);
- for (int i = 0; i < call->narg; ++i)
- if (call->args[i].bits == from.bits)
- call->args[i] = to;
- }
}
}
i0 = 0;
diff --git a/ir.h b/ir.h
index c871fa7..2b6267a 100644
--- a/ir.h
+++ b/ir.h
@@ -48,11 +48,9 @@ struct abiarg {
};
struct call {
- ushort narg : 15;
- ushort sret : 1;
+ union irtype ret;
+ ushort narg;
short vararg; /* first variadic arg or -1 */
- union ref *args;
- union irtype *typs;
short *abiargregs;
struct abiarg abiret[2];
};
@@ -71,7 +69,7 @@ enum refkind {
RXCON, /* other constants (incl. external symbols) */
RDAT, /* reference to irdat */
RMORE, /* reference to extra data for Ocall and Ophi */
- RREG, /* machine register */
+ RTYPE, /* irtype */
};
union ref {
@@ -167,7 +165,10 @@ extern struct dattab {vec_of(struct irdat);} dattab;
#define NOREF ((union ref) {0})
#define ZEROREF ((union ref) {{ RICON, 0 }})
#define mkref(t, x) ((union ref) {{ (t), (x) }})
+#define mktyperef(t) ((union ref) {{ RTYPE, (t).bits }})
+#define ref2type(r) ((union irtype) {.bits = (r).i})
#define mkinstr(O, C, ...) ((struct instr) { .op = (O), .cls = (C), .reg=0, __VA_ARGS__ })
+#define mkarginstr(ty, x) mkinstr(Oarg, 0, mktyperef(ty), (x))
void irinit(struct function *);
void irfini(struct function *);
union irtype mkirtype(union type);
@@ -177,8 +178,8 @@ union ref mksymref(struct function *, const char *);
union ref mkdatref(struct function *, uint siz, uint align, const void *, uint n);
struct instr mkalloca(uint siz, uint align);
void conputdat(struct irdat *, uint off, enum typetag t, const void *dat);
-union ref mkcallarg(struct function *, bool sret, uint narg, int vararg, union ref *, union irtype *);
-#define mkintrin(F, B, C, N, A, T) mkinstr(Ointrin, C, {.t=RICON,B}, mkcallarg(F,0,N,-1,A,T))
+union ref mkcallarg(struct function *, union irtype ret, uint narg, int vararg);
+#define mkintrin(F, B, C, N) mkinstr(Ointrin, C, {.t=RICON,B}, mkcallarg(F,(union irtype){{0}},N,-1))
union ref addinstr(struct function *, struct instr);
union ref insertinstr(struct block *, int idx, struct instr);
void delinstr(struct block *, int idx);
diff --git a/irdump.c b/irdump.c
index d437fc4..0b6424b 100644
--- a/irdump.c
+++ b/irdump.c
@@ -76,7 +76,12 @@ dumpref(enum op o, union ref ref)
{
struct xcon *con;
switch (ref.t) {
- case RTMP: efmt("%%%d", ref.i); break;
+ case RTMP:
+ if (instrtab[ref.i].reg)
+ efmt("%s", mctarg->rnames[instrtab[ref.i].reg - 1]);
+ else
+ efmt("%%%d", ref.i);
+ break;
case RPARAM: efmt("%%param%d", ref.i); break;
case RICON:
if (o == Ointrin) efmt("\"%s\"", intrinname[ref.i]);
@@ -97,39 +102,32 @@ dumpref(enum op o, union ref ref)
case RDAT:
efmt("$^%d", ref.i);
break;
+ case RTYPE:
+ prityp(ref2type(ref));
+ break;
case RMORE:
- if (o == Ocall || o == Ointrin) {
- struct call *call = &calltab.p[ref.i];
- if (call->sret) {
- efmt("sret ");
- prityp(call->typs[call->narg]);
- }
- for (int i = 0; i < call->narg; ++i) {
- if (i > 0 || call->sret) efmt(", ");
- if (call->vararg == i)
- efmt("..., ");
- if (call->abiargregs) {
- short r = call->abiargregs[i];
- efmt("(%ls) ", r != -1 ? mctarg->rnames[r] : "<stk>");
- }
- prityp(call->typs[i]);
- efmt(" ");
- dumpref(0, call->args[i]);
- }
- } else if (o == Ophi) {
- struct phi *phi = &phitab.p[ref.i];
- for (int i = 0; i < phi->n; ++i) {
- if (i > 0) efmt(", ");
- efmt("[@%d ", phi->blk[i]->id);
- dumpref(0, phi->ref[i]);
- efmt("]");
- }
- } else assert(0);
+ assert(0);
break;
default: assert(!"ref");
}
}
+static void
+dumpcall(struct call *call)
+{
+ if (call->ret.isagg) {
+ efmt("sret ");
+ prityp(call->ret);
+ efmt(", ");
+ }
+ if (call->vararg < 0) {
+ efmt("#%d", call->narg);
+ } else {
+ assert(call->vararg <= call->narg);
+ efmt("#%d, ... #%d", call->vararg, call->narg - call->vararg);
+ }
+}
+
static const char *opname[] = {
"?\??",
#define _(o,...) #o,
@@ -148,15 +146,22 @@ dumpinst(const struct instr *ins)
{
int i;
efmt(" ");
- if (ins->cls) {
+ if (ins->reg) {
+ if (ins->cls)
+ efmt("%s ", clsname[ins->cls]);
+ efmt("%s = ", mctarg->rnames[ins->reg - 1]);
+ } else if (ins->cls) {
efmt("%s %%%d", clsname[ins->cls], ins - instrtab);
- if (ins->reg) efmt("(%ls)", mctarg->rnames[ins->reg - 1]);
efmt(" = ");
}
efmt("%s ", opname[ins->op]);
for (i = 0; i < opnarg[ins->op]; ++i) {
if (i) efmt(", ");
- dumpref(ins->op, (&ins->l)[i]);
+ if (i == 1 && (ins->op == Ocall || ins->op == Ointrin)) {
+ dumpcall(&calltab.p[ins->r.i]);
+ } else {
+ dumpref(ins->op, (&ins->l)[i]);
+ }
}
efmt("\n");
}
@@ -203,7 +208,7 @@ irdump(struct function *fn, const char *fname)
for (int i = 0; i < fn->nabiarg; ++i) {
if (i > 0) efmt(", ");
if (fn->abiarg[i].reg != -1) {
- efmt("%ls", mctarg->rnames[fn->abiarg[i].reg]);
+ efmt("%s", mctarg->rnames[fn->abiarg[i].reg]);
} else {
prityp(fn->abiarg[i].ty);
efmt(" <stk>");
@@ -211,9 +216,9 @@ irdump(struct function *fn, const char *fname)
}
efmt(")");
if (fn->retty.t != TYVOID) {
- efmt(" -> %ls", mctarg->rnames[fn->abiret[0].reg]);
+ efmt(" -> %s", mctarg->rnames[fn->abiret[0].reg]);
if (fn->nabiret > 1)
- efmt(", %ls", mctarg->rnames[fn->abiret[1].reg]);
+ efmt(", %s", mctarg->rnames[fn->abiret[1].reg]);
}
efmt("\n");
}
diff --git a/op.def b/op.def
index 55d2159..d04f4ed 100644
--- a/op.def
+++ b/op.def
@@ -57,6 +57,7 @@ _(store1, 2)
_(store2, 2)
_(store4, 2)
_(store8, 2)
+_(arg, 2)
_(call, 2)
_(call2r, 1)
_(intrin, 2)
diff --git a/parse.c b/parse.c
index 4fb44ec..1ea9dbd 100644
--- a/parse.c
+++ b/parse.c
@@ -987,10 +987,10 @@ expreffects(struct function *fn, const struct expr *ex)
static void
structcopy(struct function *fn, union type ty, union ref dst, union ref src)
{
- union ref args[2] = { dst, src };
- union irtype typs[2] = { mkirtype(ty) };
- typs[1] = typs[0];
- addinstr(fn, mkintrin(fn, INstructcopy, 0, 2, args, typs));
+ union irtype typ = mkirtype(ty);
+ addinstr(fn, mkarginstr(typ, dst));
+ addinstr(fn, mkarginstr(typ, src));
+ addinstr(fn, mkintrin(fn, INstructcopy, 0, 2));
}
static union ref
@@ -1289,10 +1289,8 @@ compilecall(struct function *fn, const struct expr *ex)
struct instr ins = {0};
struct expr *sub = ex->sub;
const struct typedata *td = &typedata[sub[0].ty.dat];
- union ref argsbuf[10];
- union irtype typbuf[10];
- vec_of(union ref) args = VINIT(argsbuf, arraylength(argsbuf));
- vec_of(union irtype) typs = VINIT(typbuf, arraylength(typbuf));
+ struct instr insnsbuf[10];
+ vec_of(struct instr) insns = VINIT(insnsbuf, arraylength(insnsbuf));
ins.op = Ocall;
if (isagg(ex->ty)) {
@@ -1302,21 +1300,16 @@ compilecall(struct function *fn, const struct expr *ex)
ins.cls = type2cls[ex->ty.t];
}
ins.l = exprvalue(fn, &sub[0]);
- vresize(&args, ex->narg);
- vresize(&typs, ex->narg);
- /* backwards because of RTL call stack order */
- for (int i = ex->narg - 1; i >= 0; --i) {
+ for (int i = 0; i < ex->narg; ++i) {
struct expr *arg = &sub[i+1];
union type ty = i < td->nmemb ? td->param[i] : argpromote(arg->ty);
- args.p[i] = cvt(fn, ty.t, arg->ty.t, exprvalue(fn, arg));
- typs.p[i] = mkirtype(ty);
+ union ref r = cvt(fn, ty.t, arg->ty.t, exprvalue(fn, arg));
+ vpush(&insns, mkarginstr(mkirtype(ty), r));
}
- if (isagg(ex->ty))
- vpush(&typs, mkirtype(ex->ty));
- ins.r = mkcallarg(fn, isagg(ex->ty), ex->narg, td->variadic ? td->nmemb : td->kandr ? 0 : -1,
- args.p, typs.p);
- vfree(&args);
- vfree(&typs);
+ for (int i = 0; i < insns.n; ++i)
+ addinstr(fn, insns.p[i]);
+ vfree(&insns);
+ ins.r = mkcallarg(fn, mkirtype(ex->ty), ex->narg, td->variadic ? td->nmemb : td->kandr ? 0 : -1);
return addinstr(fn, ins);
}
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);
diff --git a/test/test.c b/test/test.c
index 40b59e6..e429104 100644
--- a/test/test.c
+++ b/test/test.c
@@ -51,18 +51,18 @@ void silly(struct pair *p, struct quad *q)
*q = quad(1,2,3,4);
}
-void test2(struct big *b) {
+int test2(struct big *b) {
struct big s = *b;
- extern void h(int, struct big, float);
+ extern int h(int,float, struct big, float);
s.x[5] += 2;
- h(0, s, 0);
+ return h(0, -.5f, s, 0);
}
struct f2 { float f,g; };
struct f2 f2test(struct f2 *r) {
return *r;
}
-
+#if 0
void fill(char *p, int c, unsigned long n)
{
int t;
@@ -93,5 +93,5 @@ struct f{
union { int x,y;} ;
char flex[];
};
-
+#endif
//