shithub: mc

Download patch

ref: 36ce95316220f7b7bf4bcb205533b919a65ef750
parent: 36a3a5fa99dc4887ca46c7807436ad44da19422f
author: Ori Bernstein <[email protected]>
date: Fri May 4 18:37:53 EDT 2012

Start work on isntruction selection.

    Fix instruction printing, do some very crude instruction
    selection (broken, not working, etc, etc.)

--- a/8/asm.h
+++ b/8/asm.h
@@ -7,7 +7,7 @@
 } AsmOp;
 
 typedef enum {
-#define Reg(r, name) r,
+#define Reg(r, name, mode) r,
 #include "regs.def"
 #undef Reg 
 } Reg;
@@ -52,5 +52,7 @@
 struct Insn {
     AsmOp op;
     Loc args[MaxArg];
-    int nloc;
+    int narg;
 };
+
+void genasm(Node **nl, int nn);
--- a/8/insns.def
+++ b/8/insns.def
@@ -14,13 +14,16 @@
    */
 
 /* Note, the mov instruction is specified in an overly general manner. */
-Insn(Imov,      "mov%m %x,%x",          0)
-Insn(Imovz,     "movz%0m%1m %x,%x",     0)
-Insn(Imovs,     "movs%0m%1m %x,%x",     0)
+Insn(Imov,      "\tmov%t %x,%x\n",          0)
+Insn(Imovz,     "\tmovz%0t%1t %x,%x\n",     0)
+Insn(Imovs,     "\tmovs%0t%1t %x,%x\n",     0)
 
 /* arithmetic instructions. */
-Insn(Iadd,      "add%m %r,%x",          0)
-Insn(Iret,      "ret",                  0)
+Insn(Iadd,      "\tadd%t %r,%x\n",          0)
 
+/* flow instructions */
+Insn(Ijmp,      "\tjmp %v\n",               0)
+Insn(Iret,      "\tret\n",                  0)
+
 /* not really an insn... */
-Insn(Ilbl,      "%s:",                  0)
+Insn(Ilbl,      "%v:\n",                  0)
--- a/8/isel.c
+++ b/8/isel.c
@@ -1,6 +1,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdarg.h>
 #include <ctype.h>
 #include <string.h>
 #include <assert.h>
@@ -20,11 +21,17 @@
 };
 
 char *regnames[] = {
-#define Reg(r, name) name,
+#define Reg(r, name, mode) name,
 #include "regs.def"
 #undef Reg
 };
 
+Mode regmodes[] = {
+#define Reg(r, name, mode) mode,
+#include "regs.def"
+#undef Reg
+};
+
 char *insnfmts[] = {
 #define Insn(val, fmt, attr) fmt,
 #include "insns.def"
@@ -31,38 +38,202 @@
 #undef Insn
 };
 
-void selexpr(Node *n)
+
+Loc *loclbl(Loc *l, char *lbl)
 {
+    l->type = Loclbl;
+    l->mode = ModeL;
+    l->lbl = strdup(lbl);
+    return l;
+}
+
+Loc *locreg(Loc *l, Reg r)
+{
+    l->type = Locreg;
+    l->mode = regmodes[r];
+    l->reg = r;
+    return l;
+}
+
+Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode)
+{
+    l->type = Locmem;
+    l->mode = mode;
+    l->mem.constdisp = disp;
+    l->mem.base = base;
+    l->mem.idx = idx;
+    return l;
+}
+
+Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode)
+{
+    l->type = Locmem;
+    l->mode = mode;
+    l->mem.lbldisp = strdup(disp);
+    l->mem.base = base;
+    l->mem.idx = idx;
+    return l;
+}
+
+Loc *loclit(Loc *l, long val)
+{
+    l->type = Loclit;
+    l->mode = ModeL; /* FIXME: what do we do for mode? */
+    l->lit = val;
+    return l;
+}
+
+Insn *mkinsnv(AsmOp op, va_list ap)
+{
+    Loc *l;
+    Insn *i;
+    int n;
+
+    n = 0;
+    i = malloc(sizeof(Insn));
+    i->op = op;
+    while ((l = va_arg(ap, Loc*)) != NULL)
+        i->args[n++] = *l;
+    i->narg = n;
+    return i;
+}
+
+Insn *mkinsn(AsmOp op, ...)
+{
+    va_list ap;
+    Insn *i;
+
+    va_start(ap, op);
+    i = mkinsnv(op, ap);
+    va_end(ap);
+    return i;
+}
+
+void g(Isel *s, AsmOp op, ...)
+{
+    va_list ap;
+    Insn *i;
+
+    va_start(ap, op);
+    i = mkinsnv(op, ap);
+    va_end(ap);
+    lappend(&s->il, &s->ni, i);
+}
+
+void selexpr(Isel *s, Node *n)
+{
+    Loc a, b;
+    Node **args;
+
+    args = n->expr.args;
     switch (exprop(n)) {
-        case Obad:
         case Oadd:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Osub:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Omul:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Odiv:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Omod:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Oneg:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+
         case Obor:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Oband:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Obxor:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Obsl:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Obsr:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Obnot:
-        case Opreinc:
-        case Opostinc:
-        case Opredec:
-        case Opostdec:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+
         case Oaddr:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Oderef:
-        case Olor:
-        case Oland:
-        case Olnot:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+
         case Oeq:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case One:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Ogt:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Oge:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Olt:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
         case Ole:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+
         case Oasn:
+            g(s, Imov, locreg(&b, Rebx), locreg(&a, Reax), NULL);
+            break;
+        case Oidx:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Oslice:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Osize:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Ocall:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Ocast:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Ojmp:
+            g(s, Ijmp, loclbl(&a, args[0]->lbl.name), NULL);
+            break;
+        case Ocjmp:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Ovar:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Olit:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+        case Olbl:
+            die("Unimplemented op %s", opstr(exprop(n)));
+            break;
+
+        case Obad:
+        case Oret:
+        case Opreinc:
+        case Opostinc:
+        case Opredec:
+        case Opostdec:
+        case Olor:
+        case Oland:
+        case Olnot:
         case Oaddeq:
         case Osubeq:
         case Omuleq:
@@ -73,26 +244,12 @@
         case Obxoreq:
         case Obsleq:
         case Obsreq:
-        case Oidx:
-        case Oslice:
         case Omemb:
-        case Osize:
-        case Ocall:
-        case Ocast:
-        case Oret:
-        case Ojmp:
-        case Ocjmp:
-        case Ovar:
-        case Olit:
-        case Olbl:
+            die("Should not see %s in isel", opstr(exprop(n)));
             break;
     }
 }
 
-void ilbl(Isel *s, char *name)
-{
-}
-
 void locprint(FILE *fd, Loc *l)
 {
 
@@ -138,6 +295,7 @@
     int modeidx;
     
     p = insnfmts[insn->op];
+    i = 0;
     for (; *p; p++) {
         if (*p !=  '%') {
             fputc(*p, fd);
@@ -158,12 +316,15 @@
                 i++;
                 break;
             case 't':
+                modeidx = 0;
             default:
                 if (isdigit(*p))
                     modeidx = strtol(p, &p, 10);
+
+                if (*p == 't')
+                    modeprint(fd, &insn->args[modeidx]);
                 else
-                    modeidx = 0;
-                modeprint(fd, &insn->args[modeidx]);
+                    die("Invalid %%-specifier '%c'", *p);
                 break;
         }
     }
@@ -174,12 +335,15 @@
 void isel(Node *n)
 {
     struct Isel is = {0,};
+    Loc lbl;
+    int i;
+
     switch (n->type) {
         case Nlbl:
-            ilbl(&is, n->lbl.name);
+            g(&is, Ilbl, loclbl(&lbl, n->lbl.name), NULL);
             break;
         case Nexpr:
-            selexpr(n);
+            selexpr(&is, n);
             break;
         case Ndecl:
             break;
@@ -187,4 +351,14 @@
             die("Bad node type in isel()");
             break;
     }
+    for (i = 0; i < is.ni; i++)
+        iprintf(stdout, is.il[i]);
+}
+
+void genasm(Node **nl, int nn)
+{
+    int i;
+
+    for (i = 0; i < nn; i++)
+        isel(nl[i]);
 }
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -143,17 +143,20 @@
 
     for (i = 0; i < n->block.nstmts; i++) {
         e = simp(s, n->block.stmts[i]);
-        append(s, e);
+        if (e)
+            append(s, e);
     }
 }
 
 Node *simpexpr(Simp *s, Node *n)
 {
-    Node *r, *t;
+    Node *r, *t, *v;
     int i;
 
+    r = NULL;
     switch (exprop(n)) {
         case Ovar:
+            r = n;
             break;
         case Oret:
             if (n->expr.args[0]) {
@@ -164,16 +167,17 @@
             break;
         default:
             if (isimpure(n)) {
-                r = simp(s, n);
-                t = storetmp(r);
+                v = simp(s, n);
+                t = storetmp(v);
                 append(s, t);
-                return t;
+                r = t;
             } else {
                 for (i = 0; i < n->expr.nargs; i++)
                     n->expr.args[i] = simp(s, n->expr.args[i]);
+                r = n;
             }
     }
-    return n;
+    return r;
 }
 
 Node *simp(Simp *s, Node *n)
--- a/8/regs.def
+++ b/8/regs.def
@@ -1,25 +1,25 @@
-Reg(Rnone, "%NOREG")
+Reg(Rnone, "%NOREG", ModeB)
 /* byte regs */
-Reg(Ral, "%al")
-Reg(Rcl, "%cl")
-Reg(Rdl, "%dl")
-Reg(Rbl, "%bl")
+Reg(Ral, "%al", ModeB)
+Reg(Rcl, "%cl", ModeB)
+Reg(Rdl, "%dl", ModeB)
+Reg(Rbl, "%bl", ModeB)
 
 /* short regs */
-Reg(Rax, "%ax")
-Reg(Rbx, "%bx")
-Reg(Rcx, "%cx")
-Reg(Rdx, "%dx")
-Reg(Rsi, "%si")
-Reg(Rdi, "%di")
+Reg(Rax, "%ax", ModeS)
+Reg(Rbx, "%bx", ModeS)
+Reg(Rcx, "%cx", ModeS)
+Reg(Rdx, "%dx", ModeS)
+Reg(Rsi, "%si", ModeS)
+Reg(Rdi, "%di", ModeS)
 
 /* long regs */
-Reg(Reax, "%eax")
-Reg(Recx, "%ecx")
-Reg(Redx, "%edx")
-Reg(Rebx, "%ebx")
-Reg(Resi, "%esi")
-Reg(Redi, "%edi")
-Reg(Resp, "%esp")
-Reg(Rebp, "%ebp")
+Reg(Reax, "%eax", ModeL)
+Reg(Recx, "%ecx", ModeL)
+Reg(Redx, "%edx", ModeL)
+Reg(Rebx, "%ebx", ModeL)
+Reg(Resi, "%esi", ModeL)
+Reg(Redi, "%edi", ModeL)
+Reg(Resp, "%esp", ModeL)
+Reg(Rebp, "%ebp", ModeL)
 
--- a/8/simp.c
+++ b/8/simp.c
@@ -11,14 +11,9 @@
 
 #include "parse.h"
 #include "gen.h"
+#include "asm.h"
 
-static Node *lowerexpr(Comp *c, Fn *fn, Node *n);
-static void label(Comp *c, Fn *fn, Node *lbl);
-static void lowerlocal(Comp *c, Fn *fn, Node *init);
 static void lowerglobl(Comp *c, char *name, Node *init);
-static void lowerif(Comp *c, Fn *fn, Node *cond);
-static void lowerloop(Comp *c, Fn *fn, Node *loop);
-void lowerblock(Comp *c, Fn *fn, Node *blk);
 static void lowerfn(Comp *c, char *name, Node *n);
 
 Fn *mkfn(char *name)
@@ -28,13 +23,6 @@
     f = zalloc(sizeof(Fn));
     f->name = strdup(name);
 
-    f->start = mkbb();
-    f->cur = mkbb();
-    f->end = mkbb();
-
-    edge(f->start, f->cur);
-    edge(f->cur, f->end);
-
     return f;
 }
 
@@ -58,147 +46,11 @@
     return s;
 }
 
-
-Bb *mkbb()
-{
-    static int bbid;
-    Bb *bb;
-
-    bb = zalloc(sizeof(Bb));
-    bb->id = bbid++;
-
-    return bb;
-}
-
-void edge(Bb *from, Bb *to)
-{
-    lappend(&from->out, &from->nout, to);
-    lappend(&to->in, &to->nin, to);
-}
-
-static Node *genlbl()
-{
-    static int lblid;
-    static char buf[128];
-
-    /* generate a local label */
-    snprintf(buf, 128, ".L%d", lblid++);
-    return mklbl(-1, strdup(buf));
-}
-
-static void jmp(Comp *c, Fn *fn, Node *targ)
-{
-}
-
-static void cjmp(Comp *c, Fn *fn, Node *cond, Node *iftrue, Node *iffalse)
-{
-}
-
 static void lowerglobl(Comp *c, char *name, Node *init)
 {
     printf("gen globl %s\n", name);
 }
 
-static void lowerlocal(Comp *c, Fn *fn, Node *dcl)
-{
-    printf("gen local");
-}
-
-static Node *lowerexpr(Comp *c, Fn *fn, Node *n)
-{
-    lappend(&fn->cur->n, &fn->cur->nn, n);
-    return n;
-}
-
-static void lowerif(Comp *c, Fn *fn, Node *cond)
-{
-    lowerexpr(c, fn, cond->ifstmt.cond);
-    label(c, fn, genlbl());
-    lowerexpr(c, fn, cond->ifstmt.iftrue);
-    label(c, fn, genlbl());
-    lowerexpr(c, fn, cond->ifstmt.iffalse);
-}
-
-static void lowerloop(Comp *c, Fn *fn, Node *loop)
-{
-    Node *start;
-    Node *test;
-    Node *end;
-    Node *cond;
-
-    /* structure of loop:
-          init
-          jmp test (if for/while, otherwise, fall through)
-        start:
-          body
-          inc
-        test:
-          test
-          cjmp cond start end
-        end:
-    */
-    start = genlbl();
-    test = genlbl();
-    end = genlbl();
-
-    jmp(c, fn, start);
-    /* init */
-    if (loop->loopstmt.init->type == Ndecl)
-        lowerlocal(c, fn, loop->loopstmt.init);
-    else
-        lowerexpr(c, fn, loop->loopstmt.init);
-    label(c, fn, start);
-
-    /* body and inc */
-    lowerexpr(c, fn, loop->loopstmt.body);
-    lowerexpr(c, fn, loop->loopstmt.step);
-
-    /* test */
-    label(c, fn, test);
-    cond = lowerexpr(c, fn, loop->loopstmt.cond);
-    cjmp(c, fn, cond, start, end);
-    label(c, fn, end);
-}
-
-static void label(Comp *c, Fn *fn, Node *lbl)
-{
-    lappend(&fn->fixup, &fn->nfixup, fn->cur);
-    fn->cur = mkbb();
-}
-
-void lowerblock(Comp *c, Fn *fn, Node *blk)
-{
-    Node **n;
-    size_t nn;
-    int i;
-
-    assert(blk && blk->type == Nblock);
-    n = blk->block.stmts;
-    nn = blk->block.nstmts;
-    for (i = 0; i < nn; i++) {
-        switch (n[i]->type) {
-            case Ndecl:
-                lowerlocal(c, fn, n[i]);
-                break;
-            case Nexpr:
-                lowerexpr(c, fn, n[i]);
-                break;
-            case Nifstmt:
-                lowerif(c, fn, n[i]);
-                break;
-            case Nloopstmt:
-                lowerloop(c, fn, n[i]);
-                break;
-            case Nlbl:
-                label(c, fn, n[i]);
-                break;
-            default:
-                die("Bad node %s in block", nodestr(n[i]->type));
-                break;
-        }
-    }
-}
-
 static void lowerfn(Comp *c, char *name, Node *n)
 {
     Fn *fn;
@@ -221,6 +73,8 @@
     for (i = 0; i < nn; i++) {
         dump(nl[i], stdout);
     }
+
+    genasm(nl, nn);
 }
 
 int isconstfn(Sym *s)
@@ -243,51 +97,6 @@
     fprintf(fd, "\n");
 }
 
-void bbdump(Bb *bb, FILE *fd)
-{
-    int i;
-    char *sep = "";
-
-    fprintf(fd, "\t\tbb %d\n", bb->id);
-    fprintf(fd, "\t\t\tin = [ ");
-    for (i = 0; i < bb->nin; i++) {
-        fprintf(fd, "%s%d ", sep, bb->in[i]->id);
-        sep = ",";
-    }
-    fprintf(fd, "]\n");
-    sep = "";
-    fprintf(fd, "\t\t\tout = [ ");
-    for (i = 0; i < bb->nout; i++) {
-        fprintf(fd, "%s%d ", sep, bb->out[i]->id);
-        sep = ",";
-    }
-    fprintf(fd, "]\n");
-
-    for (i = 0; i < bb->nn; i++)
-        dump(bb->n[i], fd);
-}
-
-void fndump(Fn *f, FILE *fd)
-{
-    int i;
-
-    fprintf(fd, "\tfn %s\n", f->name);
-    for (i = 0; i < f->nbb; i++)
-        bbdump(f->bb[i], fd);
-}
-
-void compdump(Comp *c, FILE *fd)
-{
-    int i;
-
-    fprintf(fd, "** globals **:\n");
-    for (i = 0; i < c->nglobl; i++)
-        blobdump(c->globl[i], fd);
-    fprintf(fd, "** funcs **:\n");
-    for (i = 0; i < c->nfunc; i++)
-        fndump(c->func[i], fd);
-}
-
 void gen(Node *file, char *out)
 {
     Node **n;
@@ -320,10 +129,4 @@
                 break;
         }
     }
-    compdump(c, stdout);
-
-    /*
-    isel();
-    regalloc();
-    */
 }