summaryrefslogtreecommitdiff
path: root/opt
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2014-09-05 10:53:28 -0400
committerOri Bernstein <ori@eigenstate.org>2014-09-05 10:53:28 -0400
commite34aa646c03869642a8d9b699356f5036cdd2c48 (patch)
tree66a7763b75780df4ef78f59e97549cd90d7990fb /opt
parent6b823d1993cb4bf0b01fca63cb926f8979580ce2 (diff)
downloadmc-e34aa646c03869642a8d9b699356f5036cdd2c48.tar.gz
Move 'mi/' directory to 'opt/'.
This is to free the 'mi/' name for machine independent code generation bits. Eg: debug information, register allocation, and other common stuff.
Diffstat (limited to 'opt')
-rw-r--r--opt/Makefile8
-rw-r--r--opt/cfg.c196
-rw-r--r--opt/df.c40
-rw-r--r--opt/fold.c215
-rw-r--r--opt/opt.h34
5 files changed, 493 insertions, 0 deletions
diff --git a/opt/Makefile b/opt/Makefile
new file mode 100644
index 0000000..b0ac3a6
--- /dev/null
+++ b/opt/Makefile
@@ -0,0 +1,8 @@
+LIB=libmi.a
+OBJ=cfg.o \
+ fold.o \
+ df.o \
+
+DEPS=../parse/libparse.a
+
+include ../mk/c.mk
diff --git a/opt/cfg.c b/opt/cfg.c
new file mode 100644
index 0000000..1e1497e
--- /dev/null
+++ b/opt/cfg.c
@@ -0,0 +1,196 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "opt.h"
+
+
+static Bb *mkbb(Cfg *cfg)
+{
+ Bb *bb;
+
+ bb = zalloc(sizeof(Bb));
+ bb->id = cfg->nextbbid++;
+ bb->pred = mkbs();
+ bb->succ = mkbs();
+ lappend(&cfg->bb, &cfg->nbb, bb);
+ return bb;
+}
+
+static char *lblstr(Node *n)
+{
+ assert(exprop(n) == Olit);
+ assert(n->expr.args[0]->type == Nlit);
+ assert(n->expr.args[0]->lit.littype == Llbl);
+ return n->expr.args[0]->lit.lblval;
+}
+
+static void label(Cfg *cfg, Node *lbl, Bb *bb)
+{
+ htput(cfg->lblmap, lblstr(lbl), bb);
+ lappend(&bb->lbls, &bb->nlbls, lblstr(lbl));
+}
+
+static int addnode(Cfg *cfg, Bb *bb, Node *n)
+{
+ switch (exprop(n)) {
+ case Ojmp:
+ case Ocjmp:
+ lappend(&bb->nl, &bb->nnl, n);
+ lappend(&cfg->fixjmp, &cfg->nfixjmp, n);
+ lappend(&cfg->fixblk, &cfg->nfixblk, bb);
+ return 1;
+ break;
+ default:
+ lappend(&bb->nl, &bb->nnl, n);
+ break;
+ }
+ return 0;
+}
+
+static int islabel(Node *n)
+{
+ Node *l;
+ if (n->type != Nexpr)
+ return 0;
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->type != Nlit)
+ return 0;
+ if (l->lit.littype != Llbl)
+ return 0;
+ return 1;
+}
+
+static Bb *addlabel(Cfg *cfg, Bb *bb, Node **nl, size_t i)
+{
+ /* if the current block assumes fall-through, insert an explicit jump */
+ if (i > 0 && nl[i - 1]->type == Nexpr) {
+ if (exprop(nl[i - 1]) != Ocjmp && exprop(nl[i - 1]) != Ojmp)
+ addnode(cfg, bb, mkexpr(-1, Ojmp, mklbl(-1, lblstr(nl[i])), NULL));
+ }
+ if (bb->nnl)
+ bb = mkbb(cfg);
+ label(cfg, nl[i], bb);
+ return bb;
+}
+
+Cfg *mkcfg(Node **nl, size_t nn)
+{
+ Cfg *cfg;
+ Bb *pre, *post;
+ Bb *bb, *targ;
+ Node *a, *b;
+ size_t i;
+
+ cfg = zalloc(sizeof(Cfg));
+ cfg->lblmap = mkht(strhash, streq);
+ pre = mkbb(cfg);
+ bb = mkbb(cfg);
+ for (i = 0; i < nn; i++) {
+ switch (nl[i]->type) {
+ case Nexpr:
+ if (islabel(nl[i]))
+ bb = addlabel(cfg, bb, nl, i);
+ else if (addnode(cfg, bb, nl[i]))
+ bb = mkbb(cfg);
+ break;
+ break;
+ case Ndecl:
+ break;
+ default:
+ die("Invalid node type %s in mkcfg", nodestr(nl[i]->type));
+ }
+ }
+ post = mkbb(cfg);
+ bsput(pre->succ, cfg->bb[1]->id);
+ bsput(cfg->bb[1]->pred, pre->id);
+ bsput(cfg->bb[cfg->nbb - 2]->succ, post->id);
+ bsput(post->pred, cfg->bb[cfg->nbb - 2]->id);
+ for (i = 0; i < cfg->nfixjmp; i++) {
+ bb = cfg->fixblk[i];
+ switch (exprop(cfg->fixjmp[i])) {
+ case Ojmp:
+ a = cfg->fixjmp[i]->expr.args[0];
+ b = NULL;
+ break;
+ case Ocjmp:
+ a = cfg->fixjmp[i]->expr.args[1];
+ b = cfg->fixjmp[i]->expr.args[2];
+ break;
+ default:
+ die("Bad jump fix thingy");
+ break;
+ }
+ if (a) {
+ targ = htget(cfg->lblmap, lblstr(a));
+ if (!targ)
+ die("No bb with label \"%s\"", lblstr(a));
+ bsput(bb->succ, targ->id);
+ bsput(targ->pred, bb->id);
+ }
+ if (b) {
+ targ = htget(cfg->lblmap, lblstr(b));
+ if (!targ)
+ die("No bb with label \"%s\"", lblstr(b));
+ bsput(bb->succ, targ->id);
+ bsput(targ->pred, bb->id);
+ }
+ }
+ return cfg;
+}
+
+void dumpcfg(Cfg *cfg, FILE *fd)
+{
+ size_t i, j;
+ Bb *bb;
+ char *sep;
+
+ for (j = 0; j < cfg->nbb; j++) {
+ bb = cfg->bb[j];
+ fprintf(fd, "\n");
+ fprintf(fd, "Bb: %d labels=(", bb->id);
+ sep = "";
+ for (i = 0; i < bb->nlbls; i++) {;
+ fprintf(fd, "%s%s", bb->lbls[i], sep);
+ sep = ",";
+ }
+ fprintf(fd, ")\n");
+
+ /* in edges */
+ fprintf(fd, "Pred: ");
+ sep = "";
+ for (i = 0; i < bsmax(bb->pred); i++) {
+ if (bshas(bb->pred, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
+
+ /* out edges */
+ fprintf(fd, "Succ: ");
+ sep = "";
+ for (i = 0; i < bsmax(bb->succ); i++) {
+ if (bshas(bb->succ, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
+
+ for (i = 0; i < bb->nnl; i++)
+ dump(bb->nl[i], fd);
+ fprintf(fd, "\n");
+ }
+}
diff --git a/opt/df.c b/opt/df.c
new file mode 100644
index 0000000..ff2ecd2
--- /dev/null
+++ b/opt/df.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "opt.h"
+
+/*
+static void nodeuse(Node *n, Bitset *bs)
+{
+}
+
+static void nodedef(Node *n, Bitset *bs)
+{
+}
+
+static void bbuse(Bb *bb, Bitset *bs)
+{
+}
+
+static void bbdef(Bb *bb, Bitset *bs)
+{
+}
+*/
+
+void flow(Cfg *cfg)
+{
+}
+
+void checkret(Cfg *cfg)
+{
+}
diff --git a/opt/fold.c b/opt/fold.c
new file mode 100644
index 0000000..fdc49b7
--- /dev/null
+++ b/opt/fold.c
@@ -0,0 +1,215 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "opt.h"
+
+static int islit(Node *n, vlong *v)
+{
+ Node *l;
+
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->lit.littype != Lint)
+ return 0;
+ *v = l->lit.intval;
+ return 1;
+}
+
+static int isval(Node *n, vlong val)
+{
+ vlong v;
+
+ if (!islit(n, &v))
+ return 0;
+ return v == val;
+}
+
+static Node *val(int line, vlong val, Type *t)
+{
+ Node *n;
+
+ n = mkint(line, val);
+ n = mkexpr(line, Olit, n, NULL);
+ n->expr.type = t;
+ return n;
+}
+
+static int issmallconst(Node *dcl)
+{
+ Type *t;
+
+ if (!dcl->decl.isconst)
+ return 0;
+ if (!dcl->decl.init)
+ return 0;
+ t = tybase(exprtype(dcl->decl.init));
+ if (t->type <= Tyfloat64)
+ return 1;
+ return 0;
+}
+
+static Node *foldcast(Node *n)
+{
+ Type *to, *from;
+ Node *sub;
+
+ sub = n->expr.args[0];
+ to = exprtype(n);
+ from = exprtype(sub);
+
+ switch (tybase(to)->type) {
+ case Tybool:
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyint: case Tyuint: case Tylong: case Tyulong:
+ case Tychar: case Tybyte:
+ case Typtr:
+ switch (tybase(from)->type) {
+ case Tybool:
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyint: case Tyuint: case Tylong: case Tyulong:
+ case Tychar: case Tybyte:
+ case Typtr:
+ if (exprop(sub) == Olit || tybase(from)->type == tybase(to)->type) {
+ sub->expr.type = to;
+ return sub;
+ } else {
+ return n;
+ }
+ default:
+ return n;
+ }
+ default:
+ return n;
+ }
+ return n;
+}
+
+
+
+Node *fold(Node *n, int foldvar)
+{
+ Node **args, *r;
+ Type *t;
+ vlong a, b;
+ size_t i;
+
+ if (!n)
+ return NULL;
+ if (n->type != Nexpr)
+ return n;
+
+ r = NULL;
+ args = n->expr.args;
+ for (i = 0; i < n->expr.nargs; i++)
+ args[i] = fold(args[i], foldvar);
+ switch (exprop(n)) {
+ case Ovar:
+ if (foldvar && issmallconst(decls[n->expr.did]))
+ r = fold(decls[n->expr.did]->decl.init, foldvar);
+ break;
+ case Oadd:
+ /* x + 0 = 0 */
+ if (isval(args[0], 0))
+ r = args[1];
+ if (isval(args[1], 0))
+ r = args[0];
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a + b, exprtype(n));
+ break;
+ case Osub:
+ /* x - 0 = 0 */
+ if (isval(args[1], 0))
+ r = args[0];
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a - b, exprtype(n));
+ break;
+ case Omul:
+ /* 1 * x = x */
+ if (isval(args[0], 1))
+ r = args[1];
+ if (isval(args[1], 1))
+ r = args[0];
+ /* 0 * x = 0 */
+ if (isval(args[0], 0))
+ r = args[0];
+ if (isval(args[1], 0))
+ r = args[1];
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a * b, exprtype(n));
+ break;
+ case Odiv:
+ /* x/1 = x */
+ if (isval(args[1], 1))
+ r = args[0];
+ /* 0/x = 0 */
+ if (isval(args[1], 0))
+ r = args[1];
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a / b, exprtype(n));
+ break;
+ case Omod:
+ /* x%1 = x */
+ if (isval(args[1], 0))
+ r = args[0];
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a % b, exprtype(n));
+ break;
+ case Oneg:
+ if (islit(args[0], &a))
+ r = val(n->line, -a, exprtype(n));
+ break;
+ case Obsl:
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a << b, exprtype(n));
+ break;
+ case Obsr:
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a >> b, exprtype(n));
+ break;
+ case Obor:
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a | b, exprtype(n));
+ break;
+ case Oband:
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a & b, exprtype(n));
+ break;
+ case Obxor:
+ if (islit(args[0], &a) && islit(args[1], &b))
+ r = val(n->line, a ^ b, exprtype(n));
+ break;
+ case Omemb:
+ t = tybase(exprtype(args[0]));
+ /* we only fold lengths right now */
+ if (t->type == Tyarray && !strcmp(namestr(args[1]), "len"))
+ r = t->asize;
+ break;
+ case Ocast:
+ r = foldcast(n);
+ break;
+ default:
+ break;
+ }
+
+ if (r && n->expr.idx)
+ r->expr.idx = n->expr.idx;
+
+ if (r)
+ return r;
+ else
+ return n;
+}
+
diff --git a/opt/opt.h b/opt/opt.h
new file mode 100644
index 0000000..7179cb4
--- /dev/null
+++ b/opt/opt.h
@@ -0,0 +1,34 @@
+typedef struct Cfg Cfg;
+typedef struct Bb Bb;
+
+struct Cfg {
+ Bb **bb;
+ Bb *start;
+ Bb *end;
+ size_t nbb;
+
+ /* for building bb */
+ int nextbbid;
+ Htab *lblmap; /* label => Bb mapping */
+ Node **fixjmp;
+ size_t nfixjmp;
+ Bb **fixblk;
+ size_t nfixblk;
+};
+
+struct Bb {
+ int id;
+ char **lbls;
+ size_t nlbls;
+ Node **nl;
+ size_t nnl;
+ Bitset *pred;
+ Bitset *succ;
+};
+
+/* expression folding */
+Node *fold(Node *n, int foldvar);
+/* Takes a reduced block, and returns a flow graph. */
+Cfg *mkcfg(Node **nl, size_t nn);
+void dumpcfg(Cfg *c, FILE *fd);
+void flow(Cfg *cfg);