shithub: mc

Download patch

ref: 637b1e8cb316cff76682b868012904e77040f034
parent: c4336db289bfad5a3e9274bf181282be86bc6ce7
author: Ori Bernstein <[email protected]>
date: Wed Jun 13 13:18:20 EDT 2012

Put the location allocation into shape

    For register allocation, we need to assign pseudos. Do this.

    This breaks every fucking test we have.

--- a/8/asm.h
+++ b/8/asm.h
@@ -17,7 +17,6 @@
     Locnone,
     Loclbl,  /* label */
     Locreg,  /* register */
-    Locpseu, /* pseudo-reg */
     Locmem,  /* reg offset mem */
     Locmeml, /* label offset mem */
     Loclit,
@@ -50,8 +49,10 @@
     Mode mode;
     union {
         char *lbl;
-        Reg   reg;
-        long  pseudo;
+        struct {
+            long  pseudo;
+            Reg   colour;
+        } reg;
         long  lit;
         /* disp(base + index) */
         struct {
@@ -58,9 +59,9 @@
             /* only one of lbldisp and constdisp may be used */
             char *lbldisp;
             long constdisp;
-            int scale;
-            Reg base;
-            Reg idx;
+            int scale; /* 0,1,2,4, or 8 */
+            Loc *base; /* needed */
+            Loc *idx;  /* optional */
         } mem;
     };
 };
@@ -67,7 +68,7 @@
 
 struct Insn {
     AsmOp op;
-    Loc args[MaxArg];
+    Loc *args[MaxArg];
     int narg;
 };
 
@@ -89,6 +90,8 @@
     Htab *locs; /* decl id => int stkoff */
     Htab *globls; /* decl id => char *globlname */
 
+    /* increased when we spill */
+    Loc *stksz;
     /* 6 general purpose regs */
     int rtaken[Nreg];
 };
@@ -98,22 +101,20 @@
 void gen(Node *file, char *out);
 
 /* location generation */
-Loc *loclbl(Loc *l, Node *lbl);
-Loc *locstrlbl(Loc *l, char *lbl);
-Loc *locreg(Loc *l, Reg r);
-Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode);
-Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode);
-Loc *locmems(Loc *l, long disp, Reg base, Reg idx, int scale, Mode mode);
-Loc *locmemls(Loc *l, char *disp, Reg base, Reg idx, int scale, Mode mode);
-Loc *loclit(Loc *l, long val);
+Loc *loclbl(Node *lbl);
+Loc *locstrlbl(char *lbl);
+Loc *locreg(Mode m);
+Loc *locphysreg(Reg r);
+Loc *locmem(long disp, Loc *base, Loc *idx, Mode mode);
+Loc *locmeml(char *disp, Loc *base, Loc *idx, Mode mode);
+Loc *locmems(long disp, Loc *base, Loc *idx, int scale, Mode mode);
+Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode);
+Loc *loclit(long val);
+
 void locprint(FILE *fd, Loc *l);
 void iprintf(FILE *fd, Insn *insn);
 
 /* register allocation */
-Loc getreg(Isel *s, Mode m);
-void freeloc(Isel *s, Loc l);
-Loc claimreg(Isel *s, Reg r);
-void freereg(Isel *s, Reg r);
 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);
+Loc *selexpr(Isel *s, Node *n);
 
 /* used to decide which operator is appropriate
  * for implementing various conditional operators */
@@ -48,9 +48,9 @@
 };
 
 
-static Loc loc(Isel *s, Node *n)
+static Loc *loc(Isel *s, Node *n)
 {
-    Loc l;
+    Loc *l;
     Node *v;
     size_t stkoff;
 
@@ -58,9 +58,9 @@
         case Ovar:
             if (hthas(s->locs, (void*)n->expr.did)) {
                 stkoff = (size_t)htget(s->locs, (void*)n->expr.did);
-                locmem(&l, -stkoff, Rebp, Rnone, ModeL);
+                l = locmem(-stkoff, locphysreg(Rebp), NULL, ModeL);
             } else if (hthas(s->globls, (void*)n->expr.did)) {
-                locstrlbl(&l, htget(s->globls, (void*)n->expr.did));
+                l = locstrlbl(htget(s->globls, (void*)n->expr.did));
             } else {
                 die("%s (id=%ld) not found", namestr(n->expr.args[0]), n->expr.did);
             }
@@ -68,9 +68,9 @@
         case Olit:
             v = n->expr.args[0];
             switch (v->lit.littype) {
-                case Lchr:      loclit(&l, v->lit.chrval); break;
-                case Lbool:     loclit(&l, v->lit.boolval); break;
-                case Lint:      loclit(&l, v->lit.intval); break;
+                case Lchr:      l = loclit(v->lit.chrval); break;
+                case Lbool:     l = loclit(v->lit.boolval); break;
+                case Lint:      l = loclit(v->lit.intval); break;
                 default:
                                 die("Literal type %s should be blob", litstr(v->lit.littype));
             }
@@ -87,10 +87,8 @@
     return ModeL;
 }
 
-static Loc coreg(Loc r, Mode m)
+static Loc *coreg(Reg r, Mode m)
 {
-    Loc l;
-
     Reg crtab[][Nmode + 1] = {
         [Ral] = {Rnone, Ral, Rax, Reax},
         [Rcl] = {Rnone, Rcl, Rcx, Recx},
@@ -111,10 +109,9 @@
         [Resi] = {Rnone, Rnone, Rsi, Resi},
         [Redi] = {Rnone, Rnone, Rdi, Redi},
     };
-    if (r.type != Locreg)
-        die("Non-reg passed to coreg()");
-    locreg(&l, crtab[r.reg][m]);
-    return l;
+
+    assert(crtab[r][m] != Rnone);
+    return locphysreg(crtab[r][m]);
 }
 
 static Insn *mkinsnv(AsmOp op, va_list ap)
@@ -127,7 +124,7 @@
     i = malloc(sizeof(Insn));
     i->op = op;
     while ((l = va_arg(ap, Loc*)) != NULL)
-        i->args[n++] = *l;
+        i->args[n++] = l;
     i->narg = n;
     return i;
 }
@@ -145,43 +142,43 @@
 
 static void load(Isel *s, Loc *a, Loc *b)
 {
-    Loc l;
+    Loc *l;
     assert(b->type == Locreg);
     if (a->type == Locreg)
-        locmem(&l, 0, b->reg, Rnone, a->mode);
+        locmem(0, b, Rnone, a->mode);
     else
-        l = *a;
-    g(s, Imov, &l, b, NULL);
+        l = a;
+    g(s, Imov, l, b, NULL);
 }
 
 static void stor(Isel *s, Loc *a, Loc *b)
 {
-    Loc l;
+    Loc *l;
 
     assert(a->type == Locreg || a->type == Loclit);
     if (b->type == Locreg)
-        locmem(&l, 0, b->reg, Rnone, b->mode);
+        locmem(0, b, Rnone, b->mode);
     else
-        l = *b;
-    g(s, Imov, a, &l, NULL);
+        l = b;
+    g(s, Imov, a, l, NULL);
 }
 
 /* ensures that a location is within a reg */
-static Loc inr(Isel *s, Loc a)
+static Loc *inr(Isel *s, Loc *a)
 {
-    Loc r;
+    Loc *r;
 
-    if (a.type == Locreg)
+    if (a->type == Locreg)
         return a;
-    r = getreg(s, a.mode);
-    load(s, &a, &r);
+    r = locreg(a->mode);
+    load(s, a, r);
     return r;
 }
 
 /* ensures that a location is within a reg or an imm */
-static Loc inri(Isel *s, Loc a)
+static Loc *inri(Isel *s, Loc *a)
 {
-    if (a.type == Locreg || a.type == Loclit)
+    if (a->type == Locreg || a->type == Loclit)
         return a;
     else
         return inr(s, a);
@@ -188,9 +185,9 @@
 }
 
 /* ensures that a location is within a reg or an imm */
-static Loc inrm(Isel *s, Loc a)
+static Loc *inrm(Isel *s, Loc *a)
 {
-    if (a.type == Locreg || a.type == Locmem)
+    if (a->type == Locreg || a->type == Locmem)
         return a;
     else
         return inr(s, a);
@@ -207,8 +204,8 @@
  * directly */
 static void selcjmp(Isel *s, Node *n, Node **args)
 {
-    Loc a, b;
-    Loc l1, l2;
+    Loc *a, *b;
+    Loc *l1, *l2;
     AsmOp cond, jmp;
 
     cond = reloptab[exprop(args[0])].test;
@@ -227,23 +224,22 @@
     }
 
     /* the jump targets will always be evaluated the same way */
-    loclbl(&l1, args[1]); /* if true */
-    loclbl(&l2, args[2]); /* if false */
+    l1 = loclbl(args[1]); /* if true */
+    l2 = loclbl(args[2]); /* if false */
 
-    g(s, cond, &a, &b, NULL);
-    g(s, jmp, &l1, NULL);
-    g(s, Ijmp, &l2, NULL);
+    g(s, cond, a, b, NULL);
+    g(s, jmp, l1, NULL);
+    g(s, Ijmp, l2, NULL);
 }
 
-static Loc binop(Isel *s, AsmOp op, Node *x, Node *y)
+static Loc *binop(Isel *s, AsmOp op, Node *x, Node *y)
 {
-    Loc a, b;
+    Loc *a, *b;
 
     a = selexpr(s, x);
     b = selexpr(s, y);
     a = inr(s, a);
-    g(s, op, &b, &a, NULL);
-    freeloc(s, b);
+    g(s, op, b, a, NULL);
     return a;
 }
 
@@ -276,10 +272,10 @@
     return 1;
 }
 
-static Loc memloc(Isel *s, Node *e, Mode m)
+static Loc *memloc(Isel *s, Node *e, Mode m)
 {
     Node **args;
-    Loc l, b, o; /* location, base, offset */
+    Loc *l, *b, *o; /* location, base, offset */
     int scale;
 
     scale = 0;
@@ -290,33 +286,32 @@
             o = selexpr(s, args[1]->expr.args[0]);
         else
             o = selexpr(s, args[1]);
-        if (b.type != Locreg)
+        if (b->type != Locreg)
             b = inr(s, b);
-        if (o.type == Loclit) {
-            locmem(&l, o.lit, b.reg, Rnone, m);
-        } else if (o.type == Locreg) {
+        if (o->type == Loclit) {
+            locmem(o->lit, b, Rnone, m);
+        } else if (o->type == Locreg) {
             b = inr(s, b);
-            locmems(&l, 0, b.reg, o.reg, scale, m);
+            l = locmems(0, b, o, scale, m);
         }
     } else {
         l = selexpr(s, e);
-        if (l.type == Locreg)
-            locmem(&l, 0, l.reg, Rnone, m);
+        if (l->type == Locreg)
+            locmem(0, l, Rnone, m);
     }
     return l;
 }
 
-static Loc gencall(Isel *s, Node *n)
+static Loc *gencall(Isel *s, Node *n)
 {
     int argsz, argoff;
     size_t i;
-    Loc eax, esp;       /* hard-coded registers */
-    Loc stkbump;        /* calculated stack offset */
-    Loc dst, arg, fn;   /* values we reduced */
+    Loc *eax, *esp;       /* hard-coded registers */
+    Loc *stkbump;        /* calculated stack offset */
+    Loc *dst, *arg, *fn;   /* values we reduced */
 
-    locreg(&esp, Resp);
-    locreg(&eax, Reax);
-    claimreg(s, Reax);
+    esp = locphysreg(Resp);
+    eax = locphysreg(Reax);
     argsz = 0;
     /* Have to calculate the amount to bump the stack
      * pointer by in one pass first, otherwise if we push
@@ -326,9 +321,9 @@
      * We skip the first operand, since it's the function itself */
     for (i = 1; i < n->expr.nargs; i++)
         argsz += size(n->expr.args[i]);
-    loclit(&stkbump, argsz);
+    stkbump = loclit(argsz);
     if (argsz)
-        g(s, Isub, &stkbump, &esp, NULL);
+        g(s, Isub, stkbump, esp, NULL);
 
     /* Now, we can evaluate the arguments */
     argoff = 0;
@@ -335,56 +330,56 @@
     for (i = 1; i < n->expr.nargs; i++) {
         arg = selexpr(s, n->expr.args[i]);
         arg = inri(s, arg);
-        locmem(&dst, argoff, Resp, Rnone, arg.mode);
-        stor(s, &arg, &dst);
+        dst = locmem(argoff, esp, NULL, arg->mode);
+        stor(s, arg, dst);
         argsz += size(n->expr.args[i]);
     }
     fn = selexpr(s, n->expr.args[0]);
-    g(s, Icall, &fn, NULL);
+    g(s, Icall, fn, NULL);
     if (argsz)
-        g(s, Iadd, &stkbump, &esp, NULL);
+        g(s, Iadd, stkbump, esp, NULL);
     return eax;
 }
 
-static void blit(Isel *s, Loc a, Loc b, int sz)
+static void blit(Isel *s, Loc *a, Loc *b, int sz)
 {
     int i;
-    Reg sp, dp; /* pointers to src, dst */
-    Loc tmp, src, dst; /* source memory, dst memory */
+    Loc *sp, *dp; /* pointers to src, dst */
+    Loc *tmp, src, dst; /* source memory, dst memory */
 
-    sp = inr(s, a).reg;
-    dp = inr(s, b).reg;
+    sp = inr(s, a);
+    dp = inr(s, b);
 
     /* Slightly funny loop condition: We might have trailing bytes
      * that we can't blit word-wise. */
-    tmp = getreg(s, ModeL);
+    tmp = locreg(ModeL);
     for (i = 0; i + 4 <= sz; i+= 4) {
-        locmem(&src, i, sp, Rnone, ModeL);
-        locmem(&dst, i, dp, Rnone, ModeL);
-        g(s, Imov, &src, &tmp, NULL);
-        g(s, Imov, &tmp, &dst, NULL);
+        locmem(i, sp, NULL, ModeL);
+        locmem(i, dp, NULL, ModeL);
+        g(s, Imov, src, tmp, NULL);
+        g(s, Imov, tmp, dst, NULL);
     }
     /* now, the trailing bytes */
-    tmp = coreg(tmp, ModeB);
+    tmp = locreg(ModeB);
     for (; i < sz; i++) {
-        locmem(&src, i, sp, Rnone, ModeB);
-        locmem(&dst, i, dp, Rnone, ModeB);
-        g(s, Imov, &src, &tmp, NULL);
-        g(s, Imov, &tmp, &dst, NULL);
+        locmem(i, sp, NULL, ModeB);
+        locmem(i, dp, NULL, ModeB);
+        g(s, Imov, src, tmp, NULL);
+        g(s, Imov, tmp, dst, NULL);
     }
 }
 
-Loc selexpr(Isel *s, Node *n)
+Loc *selexpr(Isel *s, Node *n)
 {
-    Loc a, b, c, r;
-    Loc eax, edx, cl; /* x86 wanst some hard-coded regs */
+    Loc *a, *b, *c, *r;
+    Loc *eax, *edx, *cl; /* x86 wanst some hard-coded regs */
     Node **args;
 
     args = n->expr.args;
-    r = (Loc){Locnone, };
-    locreg(&eax, Reax);
-    locreg(&edx, Redx);
-    locreg(&cl, Rcl);
+    r = NULL;
+    eax = locphysreg(Reax);
+    edx = locphysreg(Redx);
+    cl = locphysreg(Rcl);
     switch (exprop(n)) {
         case Oadd:      r = binop(s, Iadd, args[0], args[1]); break;
         case Osub:      r = binop(s, Isub, args[0], args[1]); break;
@@ -394,30 +389,24 @@
 
         case Omul:
             /* these get clobbered by the mul insn */
-            claimreg(s, Reax);
-            claimreg(s, Redx);
             a = selexpr(s, args[0]);
             b = selexpr(s, args[1]);
             b = inr(s, b);
-            c = coreg(eax, mode(n));
-            g(s, Imov, &a, &c, NULL);
-            g(s, Imul, &b, NULL);
-            freereg(s, Redx);
+            c = coreg(Reax, mode(n));
+            g(s, Imov, a, c, NULL);
+            g(s, Imul, b, NULL);
             r = eax;
             break;
         case Odiv:
         case Omod:
             /* these get clobbered by the div insn */
-            claimreg(s, Reax);
-            claimreg(s, Redx);
             a = selexpr(s, args[0]);
             b = selexpr(s, args[1]);
             b = inr(s, b);
-            c = coreg(eax, mode(n));
-            g(s, Imov, &a, &c, NULL);
-            g(s, Ixor, &edx, &edx, NULL);
-            g(s, Idiv, &b, NULL);
-            freereg(s, Redx);
+            c = coreg(Reax, mode(n));
+            g(s, Imov, a, c, NULL);
+            g(s, Ixor, edx, edx, NULL);
+            g(s, Idiv, b, NULL);
             if (exprop(n) == Odiv)
                 r = eax;
             else
@@ -426,56 +415,53 @@
         case Oneg:
             r = selexpr(s, args[0]);
             r = inr(s, r);
-            g(s, Ineg, &r, NULL);
+            g(s, Ineg, r, NULL);
             break;
 
         case Obsl:
         case Obsr:
-            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);
+            c = coreg(Rcl, b->mode);
+            g(s, Imov, b, c, NULL);
             if (exprop(n) == Obsr) {
                 if (istysigned(n->expr.type))
-                    g(s, Isar, &cl, &a, NULL);
+                    g(s, Isar, cl, a, NULL);
                 else
-                    g(s, Ishr, &cl, &a, NULL);
+                    g(s, Ishr, cl, a, NULL);
             } else {
-                g(s, Ishl, &cl, &a, NULL);
+                g(s, Ishl, cl, a, NULL);
             }
-            freeloc(s, cl);
-            freeloc(s, b);
             r = a;
             break;
         case Obnot:
             r = selexpr(s, args[0]);
             r = inrm(s, r);
-            g(s, Inot, &r, NULL);
+            g(s, Inot, r, NULL);
             break;
 
         case Oderef:
             a = selexpr(s, args[0]);
             a = inr(s, a);
-            r = getreg(s, a.mode);
-            locmem(&c, 0, a.reg, Rnone, a.mode);
-            g(s, Imov, &c, &r, NULL);
+            r = locreg(a->mode);
+            c = locmem(0, a, Rnone, a->mode);
+            g(s, Imov, c, r, NULL);
             break;
 
         case Oaddr:
             a = selexpr(s, args[0]);
-            r = getreg(s, ModeL);
-            g(s, Ilea, &a, &r, NULL);
+            r = locreg(ModeL);
+            g(s, Ilea, a, r, NULL);
             break;
 
         case Olnot:
             a = selexpr(s, args[0]);
-            b = getreg(s, ModeB);
-            r = coreg(b, mode(n));
-            g(s, reloptab[exprop(n)].test, &a, &a, NULL);
-            g(s, reloptab[exprop(n)].getflag, &b, NULL);
-            g(s, Imovz, &b, &r, NULL);
+            b = locreg(ModeB);
+            r = locreg(mode(n));
+            g(s, reloptab[exprop(n)].test, a, a, NULL);
+            g(s, reloptab[exprop(n)].getflag, b, NULL);
+            g(s, Imovz, b, r, NULL);
             break;
 
         case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
@@ -482,11 +468,11 @@
             a = selexpr(s, args[0]);
             b = selexpr(s, args[1]);
             b = inr(s, b);
-            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);
+            c = locreg(ModeB);
+            r = locreg(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;
 
         case Oasn:  /* relabel */
@@ -496,13 +482,13 @@
             a = memloc(s, args[0], mode(n));
             b = selexpr(s, args[1]);
             b = inri(s, b);
-            g(s, Imov, &b, &a, NULL);
+            g(s, Imov, b, a, NULL);
             r = b;
             break;
         case Oload: /* mem -> reg */
             b = memloc(s, args[0], mode(n));
-            r = getreg(s, mode(n));
-            g(s, Imov, &b, &r, NULL);
+            r = locreg(mode(n));
+            g(s, Imov, b, r, NULL);
             break;
 
         case Ocall:
@@ -510,7 +496,7 @@
             break;
         case Ocast: die("Unimplemented op %s", opstr(exprop(n))); break;
         case Ojmp:
-            g(s, Ijmp, loclbl(&a, args[0]), NULL);
+            g(s, Ijmp, a = loclbl(args[0]), NULL);
             break;
         case Ocjmp:
             selcjmp(s, n, args);
@@ -521,7 +507,7 @@
             r = loc(s, n);
             break;
         case Olbl:
-            loclbl(&r, args[0]);
+            r = loclbl(args[0]);
             break;
         case Oblit:
             b = selexpr(s, args[0]);
@@ -532,12 +518,12 @@
         case Oslbase:
             a = selexpr(s, args[0]);
             a = inr(s, a);
-            locmem(&r, 0, a.reg, Rnone, ModeL);
+            locmem(0, a, Rnone, ModeL);
             break;
         case Osllen:
             a = selexpr(s, args[0]);
             a = inr(s, a);
-            locmem(&r, 4, a.reg, Rnone, ModeL);
+            locmem(4, a, Rnone, ModeL);
             break;
 
         /* These operators should never show up in the reduced trees,
@@ -563,13 +549,10 @@
             fprintf(fd, "%s", l->lbl);
             break;
         case Locreg:
-            fprintf(fd, "%s", regnames[l->reg]);
-            break;
-        case Locpseu:
-            if (debug)
-              fprintf(fd, "%c%lu", modenames[l->mode], l->pseudo);
+            if (l->reg.colour == Rnone)
+                fprintf(fd, "%%P.%ld", l->reg.pseudo);
             else
-              die("Trying to print pseudoreg %lu", l->pseudo);
+                fprintf(fd, "%s", regnames[l->reg.colour]);
             break;
         case Locmem:
         case Locmeml:
@@ -580,10 +563,12 @@
                 if (l->mem.lbldisp)
                     fprintf(fd, "%s", l->mem.lbldisp);
             }
-            if (l->mem.base)
-                fprintf(fd, "(%s", regnames[l->mem.base]);
-            if (l->mem.idx)
-                fprintf(fd, ",%s", regnames[l->mem.idx]);
+            fprintf(fd, "(");
+            locprint(fd, l->mem.base);
+            if (l->mem.idx) {
+                fprintf(fd, ",");
+                locprint(fd, l->mem.idx);
+            }
             if (l->mem.scale)
                 fprintf(fd, ",%d", l->mem.scale);
             if (l->mem.base)
@@ -622,7 +607,7 @@
             case 'l':
             case 'x':
             case 'v':
-                locprint(fd, &insn->args[i]);
+                locprint(fd, insn->args[i]);
                 i++;
                 break;
             case 't':
@@ -632,7 +617,7 @@
                     modeidx = strtol(p, &p, 10);
 
                 if (*p == 't')
-                    fputc(modenames[insn->args[modeidx].mode], fd);
+                    fputc(modenames[insn->args[modeidx]->mode], fd);
                 else
                     die("Invalid %%-specifier '%c'", *p);
                 break;
@@ -644,11 +629,11 @@
 
 static void isel(Isel *s, Node *n)
 {
-    Loc lbl;
+    Loc *lbl;
 
     switch (n->type) {
         case Nlbl:
-            g(s, Ilbl, loclbl(&lbl, n), NULL);
+            g(s, Ilbl, lbl = loclbl(n), NULL);
             break;
         case Nexpr:
             selexpr(s, n);
@@ -663,32 +648,33 @@
 
 static void prologue(Isel *s, size_t sz)
 {
-    Loc esp;
-    Loc ebp;
-    Loc stksz;
+    Loc *esp;
+    Loc *ebp;
+    Loc *stksz;
 
-    locreg(&esp, Resp);
-    locreg(&ebp, Rebp);
-    loclit(&stksz, sz);
-    g(s, Ipush, &ebp, NULL);
-    g(s, Imov, &esp, &ebp, NULL);
-    g(s, Isub, &stksz, &esp, NULL);
+    esp = locphysreg(Resp);
+    ebp = locphysreg(Rebp);
+    stksz = loclit(sz);
+    g(s, Ipush, ebp, NULL);
+    g(s, Imov, esp, ebp, NULL);
+    g(s, Isub, stksz, esp, NULL);
+    s->stksz = stksz; /* need to update if we spill */
 }
 
 static void epilogue(Isel *s)
 {
-    Loc esp, ebp, eax;
-    Loc ret;
+    Loc *esp, *ebp, *eax;
+    Loc *ret;
 
-    locreg(&esp, Resp);
-    locreg(&ebp, Rebp);
-    locreg(&eax, Reax);
+    esp = locphysreg(Resp);
+    ebp = locphysreg(Rebp);
+    eax = locphysreg(Reax);
     if (s->ret) {
         ret = loc(s, s->ret);
-        g(s, Imov, &ret, &eax, NULL);
+        g(s, Imov, ret, eax, NULL);
     }
-    g(s, Imov, &ebp, &esp, NULL);
-    g(s, Ipop, &ebp, NULL);
+    g(s, Imov, ebp, esp, NULL);
+    g(s, Ipop, ebp, NULL);
     g(s, Iret, NULL);
 }
 
--- a/8/regalloc.c
+++ b/8/regalloc.c
@@ -52,8 +52,11 @@
     [Rebp] = {Rebp},
 };
 
-Loc *locstrlbl(Loc *l, char *lbl)
+Loc *locstrlbl(char *lbl)
 {
+    Loc *l;
+
+    l = zalloc(sizeof(Loc));
     l->type = Loclbl;
     l->mode = ModeL;
     l->lbl = strdup(lbl);
@@ -60,22 +63,38 @@
     return l;
 }
 
-Loc *loclbl(Loc *l, Node *lbl)
+Loc *loclbl(Node *lbl)
 {
     assert(lbl->type = Nlbl);
-    return locstrlbl(l, lbl->lbl.name);
+    return locstrlbl(lbl->lbl.name);
 }
 
-Loc *locreg(Loc *l, Reg r)
+Loc *locreg(Mode m)
 {
+    Loc *l;
+    static long nextpseudo;
+
+    l = zalloc(sizeof(Loc));
     l->type = Locreg;
-    l->mode = regmodes[r];
-    l->reg = r;
+    l->mode = m;
+    l->reg.pseudo = nextpseudo++;
     return l;
 }
 
-Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode)
+Loc *locphysreg(Reg r)
 {
+    Loc *l;
+
+    l = locreg(regmodes[r]);
+    l->reg.colour = r;
+    return l;
+}
+
+Loc *locmem(long disp, Loc *base, Loc *idx, Mode mode)
+{
+    Loc *l;
+
+    l = zalloc(sizeof(Loc));
     l->type = Locmem;
     l->mode = mode;
     l->mem.constdisp = disp;
@@ -85,15 +104,20 @@
     return l;
 }
 
-Loc *locmems(Loc *l, long disp, Reg base, Reg idx, int scale, Mode mode)
+Loc *locmems(long disp, Loc *base, Loc *idx, int scale, Mode mode)
 {
-    locmem(l, disp, base, idx, mode);
+    Loc *l;
+
+    l = locmem(disp, base, idx, mode);
     l->mem.scale = scale;
     return l;
 }
 
-Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode)
+Loc *locmeml(char *disp, Loc *base, Loc *idx, Mode mode)
 {
+    Loc *l;
+
+    l = zalloc(sizeof(Loc));
     l->type = Locmem;
     l->mode = mode;
     l->mem.lbldisp = strdup(disp);
@@ -103,67 +127,23 @@
     return l;
 }
 
-Loc *locmemls(Loc *l, char *disp, Reg base, Reg idx, int scale, Mode mode)
+Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode)
 {
-    locmeml(l, disp, base, idx, mode);
+    Loc *l;
+
+    l = locmeml(disp, base, idx, mode);
     l->mem.scale = scale;
     return l;
 }
 
 
-Loc *loclit(Loc *l, long val)
+Loc *loclit(long val)
 {
+    Loc *l;
+
+    l = zalloc(sizeof(Loc));
     l->type = Loclit;
     l->mode = ModeL; /* FIXME: what do we do for mode? */
     l->lit = val;
     return l;
-}
-
-Loc getreg(Isel *s, Mode m)
-{
-
-    Loc l;
-    int i;
-
-    assert(m != ModeNone);
-    l.reg = Rnone;
-    for (i = 0; i < Nreg; i++) {
-        if (!s->rtaken[i] && regmodes[i] == m) {
-            locreg(&l, i);
-            break;
-        }
-    }
-    if (l.reg == Rnone)
-        die("Not enough registers. Please split your expression and try again (FIXME: implement spilling)");
-    for (i = 0; i < Nmode; i++)
-        s->rtaken[reginterferes[l.reg][i]] = 1;
-
-    return l;
-}
-
-Loc claimreg(Isel *s, Reg r)
-{
-    Loc l;
-    int i;
-
-    if (s->rtaken[r])
-        die("Reg %s is already taken", regnames[r]);
-    for (i = 0; i < Nmode; i++)
-        s->rtaken[reginterferes[r][i]] = 1;
-    locreg(&l, r);
-    return l;
-}
-
-void freereg(Isel *s, Reg r)
-{
-    int i;
-
-    for (i = 0; i < Nmode; i++)
-        s->rtaken[reginterferes[r][i]] = 0;
-}
-
-void freeloc(Isel *s, Loc l)
-{
-    if (l.type == Locreg)
-        freereg(s, l.reg);
 }