ref: fa492d6d9f5addf0231506d9c8f97308152eca23
parent: 00b71aa9ba7d44b7231da3c139eec45c22844a81
author: Ori Bernstein <[email protected]>
date: Sun May 6 14:00:58 EDT 2012
More work towards instruction selection working. Reduce more instructions to their primitive form, and select more instruction types.
--- a/8/insns.def
+++ b/8/insns.def
@@ -36,13 +36,13 @@
Insn(Isetge, "\tsetge\n", 0)
/* branch instructions */
-Insn(Ijmp, "\tjmp\n", 0)
-Insn(Ijz, "\tjz\n", 0)
-Insn(Ijnz, "\tjnz\n", 0)
-Insn(Ijlt, "\tjlt\n", 0)
-Insn(Ijle, "\tjle\n", 0)
-Insn(Ijgt, "\tjgt\n", 0)
-Insn(Ijge, "\tjge\n", 0)
+Insn(Ijmp, "\tjmp %v\n", 0)
+Insn(Ijz, "\tjz %v\n", 0)
+Insn(Ijnz, "\tjnz %v\n", 0)
+Insn(Ijlt, "\tjlt %v\n", 0)
+Insn(Ijle, "\tjle %v\n", 0)
+Insn(Ijgt, "\tjgt %v\n", 0)
+Insn(Ijge, "\tjge %v\n", 0)
Insn(Iret, "\tret\n", 0)
/* not really an insn... */
--- a/8/isel.c
+++ b/8/isel.c
@@ -48,6 +48,7 @@
AsmOp jmp;
AsmOp getflag;
} reloptab[Numops] = {
+ [Olnot] = {Itest, Ijz, Isetz},
[Oeq] = {Itest, Ijnz, Isetnz},
[One] = {Itest, Ijz, Isetz},
[Ogt] = {Icmp, Ijgt, Isetgt},
@@ -61,11 +62,12 @@
Loc selexpr(Isel *s, Node *n);
-Loc *loclbl(Loc *l, char *lbl)
+Loc *loclbl(Loc *l, Node *lbl)
{
+ assert(lbl->type = Nlbl);
l->type = Loclbl;
l->mode = ModeL;
- l->lbl = strdup(lbl);
+ l->lbl = strdup(lbl->lbl.name);
return l;
}
@@ -248,8 +250,8 @@
}
/* the jump targets will always be evaluated the same way */
- l1 = selexpr(s, args[1]); /* if true */
- l2 = selexpr(s, args[2]); /* if false */
+ loclbl(&l1, args[1]); /* if true */
+ loclbl(&l2, args[2]); /* if false */
g(s, cond, &a, &b, NULL);
g(s, jmp, &l1, NULL);
@@ -293,6 +295,15 @@
case Oaddr: die("Unimplemented op %s", opstr(exprop(n))); break;
case Oderef: die("Unimplemented op %s", opstr(exprop(n))); 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);
+ break;
+
case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
a = selexpr(s, args[0]);
b = selexpr(s, args[1]);
@@ -300,7 +311,7 @@
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);
+ g(s, Imovz, &c, &r, NULL);
return r;
case Oasn:
@@ -313,7 +324,7 @@
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);
+ g(s, Ijmp, loclbl(&a, args[0]), NULL);
break;
case Ocjmp:
selcjmp(s, n, args);
@@ -320,6 +331,8 @@
break;
case Olit: /* fall through */
+ r = loc(s, n);
+ break;
case Ovar:
b = loc(s, n);
a = getreg(s, mode(args[0]));
@@ -327,14 +340,14 @@
r = b;
break;
case Olbl:
- loclbl(&r, args[0]->lbl.name);
- break;
+ loclbl(&r, args[0]);
+ break;
/* These operators should never show up in the reduced trees,
* since they should have been replaced with more primitive
* expressions by now */
case Obad: case Oret: case Opreinc: case Opostinc: case Opredec:
- case Opostdec: case Olor: case Oland: case Olnot: case Oaddeq:
+ case Opostdec: case Olor: case Oland: case Oaddeq:
case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
case Oslice: case Oidx: case Osize: case Numops:
@@ -435,7 +448,7 @@
switch (n->type) {
case Nlbl:
- g(s, Ilbl, loclbl(&lbl, n->lbl.name), NULL);
+ g(s, Ilbl, loclbl(&lbl, n), NULL);
break;
case Nexpr:
selexpr(s, n);
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -23,8 +23,14 @@
struct Simp {
Node **blk;
size_t nblk;
+
+ /* return handling */
Node *endlbl;
Node *retval;
+
+ /* pre/postinc handling */
+ Node **incqueue;
+ size_t nqueue;
};
Node *simp(Simp *s, Node *n);
@@ -152,9 +158,72 @@
{
Node *r, *t, *v;
int i;
+ Node **args;
+ const Op fusedmap[] = {
+ [Osubeq] = Osub,
+ [Omuleq] = Omul,
+ [Odiveq] = Odiv,
+ [Omodeq] = Omod,
+ [Oboreq] = Obor,
+ [Obandeq] = Oband,
+ [Obxoreq] = Obxor,
+ [Obsleq] = Obsl,
+ };
+
r = NULL;
+ args = n->expr.args;
switch (exprop(n)) {
+ case Obad:
+ case Olor: case Oland: case Oaddeq:
+ case Obsreq: case Omemb:
+ case Oslice: case Oidx: case Osize:
+ die("Have not implemented lowering op %s", opstr(exprop(n)));
+ break;
+
+ /* fused ops:
+ * foo ?= blah
+ * =>
+ * foo = foo ? blah*/
+ case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
+ case Obandeq: case Obxoreq: case Obsleq:
+ v = mkexpr(-1, fusedmap[exprop(n)], args[0], args[1], NULL);
+ r = mkexpr(-1, Oasn, args[0], v, NULL);
+ break;
+
+ /* ++expr(x)
+ * => x = x + 1
+ * expr(x) */
+ case Opreinc:
+ t = simp(s, args[0]);
+ v = mkexpr(-1, Oadd, mkint(-1, 1), args[0], NULL);
+ r = mkexpr(-1, Oasn, args[0], v, NULL);
+ lappend(&s->incqueue, &s->nqueue, t);
+ break;
+ case Opredec:
+ t = simp(s, args[0]);
+ v = mkexpr(-1, Oadd, mkint(-1, -1), args[0], NULL);
+ r = mkexpr(-1, Oasn, args[0], v, NULL);
+ lappend(&s->incqueue, &s->nqueue, t);
+ break;
+
+ /* expr(x++)
+ * =>
+ * expr
+ * x = x + 1
+ */
+ case Opostinc:
+ r = simp(s, args[0]);
+ v = mkexpr(-1, Oadd, mkint(-1, 1), r, NULL);
+ t = mkexpr(-1, Oasn, args[0], v, NULL);
+ lappend(&s->incqueue, &s->nqueue, t);
+ break;
+ case Opostdec:
+ r = simp(s, args[0]);
+ v = mkexpr(-1, Osub, mkint(-1, -1), args[0], NULL);
+ t = mkexpr(-1, Oasn, args[0], v, NULL);
+ lappend(&s->incqueue, &s->nqueue, t);
+ break;
case Ovar:
r = n;
break;
@@ -221,31 +290,11 @@
s.nblk = 0;
s.endlbl = genlbl();
s.retval = NULL;
- switch (n->type) {
- /* these should never be inside functions */
- case Nnone:
- case Nfile:
- die("Bad node type in func");
- break;
- case Nfunc:
- die("FIXME: generate thunks");
- break;
- /* no code generated */
- case Nuse:
- break;
- /* complex nodes */
- case Nblock:
- simp(&s, n);
- break;
- case Nifstmt:
- case Nloopstmt:
- case Nexpr:
- case Nlit:
- case Nname:
- case Ndecl:
- case Nlbl:
- break;
- }
+ if (n->type == Nblock)
+ simp(&s, n);
+ else
+ die("Got a non-block (%s) to reduce", nodestr(n->type));
+
append(&s, s.endlbl);
*ret_nn = s.nblk;
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -302,7 +302,6 @@
Node *mkuse(int line, char *use, int islocal);
Node *mkexpr(int line, Op op, ...); /* NULL terminated */
Node *mkcall(int line, Node *fn, Node **args, size_t nargs);
-Node *mklit(int line, Littype lt, void *val);
Node *mkif(int line, Node *cond, Node *iftrue, Node *iffalse);
Node *mkloop(int line, Node *init, Node *cond, Node *incr, Node *body);
Node *mkblock(int line, Stab *scope);