ref: d532e561e36b997684354cd7bce46dad074a00ca
parent: 3c49faca8d3bb0dd12065897dd2efb6b8f234420
author: Ori Bernstein <[email protected]>
date: Wed Jun 13 07:07:06 EDT 2012
Implement spilling. TODO: fix fib()
--- a/8/asm.h
+++ b/8/asm.h
@@ -91,6 +91,7 @@
/* register and spill states */
size_t stksz;
+ Loc stkszloc;
int rtaken[Nreg];
Node *rcontains[Nreg];
Loc *locmap;
@@ -117,6 +118,7 @@
Loc claimreg(Isel *s, Reg r);
void freeloc(Isel *s, Loc l);
void freereg(Isel *s, Reg r);
+void in(Isel *s, Node *n, Loc l);
extern const char *regnames[];
extern const Mode regmodes[];
--- a/8/isel.c
+++ b/8/isel.c
@@ -29,7 +29,7 @@
};
/* forward decls */
-Loc selexpr(Isel *s, Node *n);
+void selexpr(Isel *s, Node *n);
/* used to decide which operator is appropriate
* for implementing various conditional operators */
@@ -47,7 +47,6 @@
[Ole] = {Icmp, Ijle, Isetle}
};
-
static Loc loc(Isel *s, Node *n)
{
Loc l;
@@ -82,6 +81,17 @@
return l;
}
+static Loc getloc(Isel *s, Node *n)
+{
+ if (s->locmap[n->nid].type != Locnone)
+ return s->locmap[n->nid];
+ else if (exprop(n) == Ndecl)
+ return loc(s, n);
+ else
+ die("Unevaluated node %s", opstr(exprop(n)));
+ return (Loc){Locnone,};
+}
+
static Mode mode(Node *n)
{
return ModeL;
@@ -216,13 +226,15 @@
/* if we have a cond, we're knocking off the redundant test,
* and want to eval the children */
if (cond) {
- a = selexpr(s, args[0]->expr.args[1]);
- b = selexpr(s, args[0]->expr.args[0]);
- b = inr(s, b);
+ selexpr(s, args[0]->expr.args[1]);
+ selexpr(s, args[0]->expr.args[0]);
+ a = getloc(s, args[0]->expr.args[1]);
+ b = inr(s, getloc(s, args[0]->expr.args[0]));
} else {
cond = Itest;
jmp = Ijnz;
- a = inr(s, selexpr(s, args[0])); /* cond */
+ selexpr(s, args[0]);
+ a = inr(s, getloc(s, args[0])); /* cond */
b = a;
}
@@ -239,9 +251,10 @@
{
Loc a, b;
- a = selexpr(s, x);
- b = selexpr(s, y);
- a = inr(s, a);
+ selexpr(s, x);
+ selexpr(s, y);
+ a = inr(s, getloc(s, x));
+ b = getloc(s, y);
g(s, op, &b, &a, NULL);
freeloc(s, b);
return a;
@@ -285,13 +298,16 @@
scale = 0;
if (exprop(e) == Oadd) {
args = e->expr.args;
- b = selexpr(s, args[0]);
- if (ismergablemul(args[1], &scale))
- o = selexpr(s, args[1]->expr.args[0]);
- else
- o = selexpr(s, args[1]);
- if (b.type != Locreg)
- b = inr(s, b);
+ selexpr(s, args[0]);
+ if (ismergablemul(args[1], &scale)) {
+ selexpr(s, args[1]->expr.args[0]);
+ o = getloc(s, args[1]->expr.args[0]);
+ } else {
+ selexpr(s, args[1]);
+ o = getloc(s, args[1]);
+ }
+
+ b = inr(s, getloc(s, args[0]));
if (o.type == Loclit) {
locmem(&l, o.lit, b.reg, Rnone, m);
} else if (o.type == Locreg) {
@@ -299,7 +315,8 @@
locmems(&l, 0, b.reg, o.reg, scale, m);
}
} else {
- l = selexpr(s, e);
+ selexpr(s, e);
+ l = getloc(s, e);
if (l.type == Locreg)
locmem(&l, 0, l.reg, Rnone, m);
}
@@ -316,7 +333,6 @@
locreg(&esp, Resp);
locreg(&eax, Reax);
- claimreg(s, Reax);
argsz = 0;
/* Have to calculate the amount to bump the stack
* pointer by in one pass first, otherwise if we push
@@ -333,13 +349,15 @@
/* Now, we can evaluate the arguments */
argoff = 0;
for (i = 1; i < n->expr.nargs; i++) {
- arg = selexpr(s, n->expr.args[i]);
- arg = inri(s, arg);
+ selexpr(s, n->expr.args[i]);
+ arg = inri(s, getloc(s, n->expr.args[i]));
locmem(&dst, argoff, Resp, Rnone, arg.mode);
stor(s, &arg, &dst);
argsz += size(n->expr.args[i]);
}
- fn = selexpr(s, n->expr.args[0]);
+ selexpr(s, n->expr.args[0]);
+ fn = getloc(s, n->expr.args[0]);
+ claimreg(s, Reax);
g(s, Icall, &fn, NULL);
if (argsz)
g(s, Iadd, &stkbump, &esp, NULL);
@@ -374,7 +392,7 @@
}
}
-Loc selexpr(Isel *s, Node *n)
+void selexpr(Isel *s, Node *n)
{
Loc a, b, c, r;
Loc eax, edx, cl; /* x86 wanst some hard-coded regs */
@@ -394,11 +412,12 @@
case Omul:
/* these get clobbered by the mul insn */
+ selexpr(s, args[0]);
+ selexpr(s, args[1]);
claimreg(s, Reax);
claimreg(s, Redx);
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- b = inr(s, b);
+ a = getloc(s, args[0]);
+ b = inr(s, getloc(s, args[1]));
c = coreg(eax, mode(n));
g(s, Imov, &a, &c, NULL);
g(s, Imul, &b, NULL);
@@ -408,11 +427,12 @@
case Odiv:
case Omod:
/* these get clobbered by the div insn */
+ selexpr(s, args[0]);
+ selexpr(s, args[1]);
claimreg(s, Reax);
claimreg(s, Redx);
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- b = inr(s, b);
+ a = getloc(s, args[0]);
+ b = inr(s, getloc(s, args[1]));
c = coreg(eax, mode(n));
g(s, Imov, &a, &c, NULL);
g(s, Ixor, &edx, &edx, NULL);
@@ -424,17 +444,19 @@
r = edx;
break;
case Oneg:
- r = selexpr(s, args[0]);
- r = inr(s, r);
+ selexpr(s, args[0]);
+ r = inr(s, getloc(s, args[0]));
g(s, Ineg, &r, NULL);
break;
case Obsl:
case Obsr:
+ selexpr(s, args[0]);
+ selexpr(s, args[1]);
+ a = inr(s, getloc(s, args[0]));
+ b = getloc(s, args[1]);
+ /* FIXME: we can shift by constants */
claimreg(s, Rcl); /* shift requires cl as it's arg. stupid. */
- a = selexpr(s, args[0]);
- a = inr(s, a);
- b = selexpr(s, args[1]);
c = coreg(cl, b.mode);
g(s, Imov, &b, &c, NULL);
if (exprop(n) == Obsr) {
@@ -450,14 +472,14 @@
r = a;
break;
case Obnot:
- r = selexpr(s, args[0]);
- r = inrm(s, r);
+ selexpr(s, args[0]);
+ r = inrm(s, getloc(s, args[0]));
g(s, Inot, &r, NULL);
break;
case Oderef:
- a = selexpr(s, args[0]);
- a = inr(s, a);
+ selexpr(s, args[0]);
+ a = inr(s, getloc(s, args[0]));
r = getreg(s, a.mode);
locmem(&c, 0, a.reg, Rnone, a.mode);
g(s, Imov, &c, &r, NULL);
@@ -464,13 +486,15 @@
break;
case Oaddr:
- a = selexpr(s, args[0]);
+ selexpr(s, args[0]);
+ a = getloc(s, args[0]);
r = getreg(s, ModeL);
g(s, Ilea, &a, &r, NULL);
break;
case Olnot:
- a = selexpr(s, args[0]);
+ selexpr(s, args[0]);
+ a = getloc(s, args[0]);
b = getreg(s, ModeB);
r = coreg(b, mode(n));
g(s, reloptab[exprop(n)].test, &a, &a, NULL);
@@ -479,23 +503,24 @@
break;
case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- b = inr(s, b);
+ selexpr(s, args[0]);
+ selexpr(s, args[1]);
+ a = getloc(s, args[0]);
+ b = inr(s, getloc(s, args[1]));
c = getreg(s, ModeB);
r = coreg(c, mode(n));
g(s, reloptab[exprop(n)].test, &a, &b, NULL);
g(s, reloptab[exprop(n)].getflag, &c, NULL);
g(s, Imovz, &c, &r, NULL);
- return r;
+ break;
case Oasn: /* relabel */
die("Unimplemented op %s", opstr(exprop(n)));
break;
case Ostor: /* reg -> mem */
+ selexpr(s, args[1]);
a = memloc(s, args[0], mode(n));
- b = selexpr(s, args[1]);
- b = inri(s, b);
+ b = inri(s, getloc(s, args[1]));
g(s, Imov, &b, &a, NULL);
r = b;
break;
@@ -524,19 +549,21 @@
loclbl(&r, args[0]);
break;
case Oblit:
- b = selexpr(s, args[0]);
- a = selexpr(s, args[1]);
+ selexpr(s, args[0]);
+ selexpr(s, args[1]);
+ b = getloc(s, args[0]);
+ a = getloc(s, args[1]);
blit(s, a, b, args[2]->expr.args[0]->lit.intval);
r = b;
break;
case Oslbase:
- a = selexpr(s, args[0]);
- a = inr(s, a);
+ selexpr(s, args[0]);
+ a = inr(s, getloc(s, args[0]));
locmem(&r, 0, a.reg, Rnone, ModeL);
break;
case Osllen:
- a = selexpr(s, args[0]);
- a = inr(s, a);
+ selexpr(s, args[0]);
+ a = inr(s, getloc(s, args[0]));
locmem(&r, 4, a.reg, Rnone, ModeL);
break;
@@ -552,7 +579,7 @@
die("Should not see %s in isel", opstr(exprop(n)));
break;
}
- return r;
+ in(s, n, r);
}
void locprint(FILE *fd, Loc *l)
@@ -661,18 +688,17 @@
}
}
-static void prologue(Isel *s, size_t sz)
+static void prologue(Isel *s)
{
Loc esp;
Loc ebp;
- Loc stksz;
locreg(&esp, Resp);
locreg(&ebp, Rebp);
- loclit(&stksz, sz);
+ loclit(&s->stkszloc, s->stksz);
g(s, Ipush, &ebp, NULL);
g(s, Imov, &esp, &ebp, NULL);
- g(s, Isub, &stksz, &esp, NULL);
+ g(s, Isub, &s->stkszloc, &esp, NULL);
}
static void epilogue(Isel *s)
@@ -714,8 +740,10 @@
is.locs = fn->locs;
is.globls = globls;
is.ret = fn->ret;
+ is.stksz = fn->stksz;
+ is.locmap = zalloc(maxnid * sizeof(Loc));
- prologue(&is, fn->stksz);
+ prologue(&is);
for (i = 0; i < fn->nn; i++) {
bzero(is.rtaken, sizeof is.rtaken);
isel(&is, fn->nl[i]);
--- a/8/regalloc.c
+++ b/8/regalloc.c
@@ -126,9 +126,9 @@
Node *n;
for (i = 0; i < Nmode; i++) {
- if (!s->rcontains[i])
+ n = s->rcontains[reginterferes[r][i]];
+ if (!n)
continue;
- n = s->rcontains[i];
if (exprop(n) != Ovar) {
s->stksz += tysize(exprtype(n));
locmem(&s->locmap[n->nid], s->stksz, Rebp, Rnone, ModeL);
@@ -138,6 +138,13 @@
}
}
+void in(Isel *s, Node *n, Loc l)
+{
+ s->locmap[n->nid] = l;
+ if (l.type == Locreg)
+ s->rcontains[l.reg] = n;
+}
+
Loc getreg(Isel *s, Mode m)
{
@@ -177,8 +184,10 @@
{
int i;
- for (i = 0; i < Nmode; i++)
+ for (i = 0; i < Nmode; i++) {
s->rtaken[reginterferes[r][i]] = 0;
+ s->rcontains[reginterferes[r][i]] = NULL;
+ }
}
void freeloc(Isel *s, Loc l)
--- a/parse/node.c
+++ b/parse/node.c
@@ -12,11 +12,14 @@
#include "parse.h"
+int maxnid;
+
Node *mknode(int line, Ntype nt)
{
Node *n;
n = zalloc(sizeof(Node));
+ n->nid = maxnid++;
n->type = nt;
n->line = line;
return n;
@@ -226,7 +229,7 @@
Type *exprtype(Node *n)
{
- assert(n->type == Ndecl);
+ assert(n->type == Nexpr);
return nodetype(n);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -219,6 +219,7 @@
extern int ntypes;
extern Cstr **cstrtab; /* int -> cstr map */
extern int ncstrs;
+extern int maxnid; /* the maximum node id generated so far */
extern Type *littypes[]; /* literal type -> type map */
extern int ispureop[];
--- a/test/mul.myr
+++ b/test/mul.myr
@@ -1,3 +1,3 @@
const main = {
- -> 42 * 2
+ -> 7 * 2 * 3
}
--- a/test/tests
+++ b/test/tests
@@ -15,7 +15,7 @@
# evident.
B main E 0
B add E 53
-B mul E 84
+B mul E 42
B div E 42
B mod E 6
B bsr E 5