shithub: mc

Download patch

ref: 91d7d2a303319f8a0fd2d2be1426bf4b03590bf0
parent: ccee477034a0a63df7a5864b375a243f8e4f246a
author: Ori Bernstein <ori@eigenstate.org>
date: Wed May 6 16:48:08 EDT 2015

A huge amount of work on checking.

    We now check for return types, and have a partly fleshed out
    use-before-def analysis.

--- a/mi/dfcheck.c
+++ b/mi/dfcheck.c
@@ -13,26 +13,166 @@
 #include "parse.h"
 #include "mi.h"
 
-/*
-static void nodeuse(Node *n, Bitset *bs)
+static void nodevars(Node *n, Bitset *bs)
 {
+    size_t i;
+
+    if (!n || n->type != Nexpr)
+        return;
+    switch (exprop(n)) {
+        case Ovar:
+            bsput(bs, n->expr.did);
+            break;
+        default:
+            nodevars(n->expr.idx, bs);
+            for (i = 0; i < n->expr.nargs; i++)
+                nodevars(n->expr.args[i], bs);
+            break;
+    }
 }
+void nodedef(Node *n, Bitset *bs)
+{
+    Node *p;
+    size_t i;
 
-static void nodedef(Node *n, Bitset *bs)
+    switch(exprop(n)) {
+        case Oset:
+        case Oasn: case Oaddeq:
+        case Osubeq: case Omuleq:
+        case Odiveq: case Omodeq:
+        case Oboreq: case Obandeq:
+        case Obxoreq: case Obsleq:
+        case Obsreq:
+            nodevars(n->expr.args[0], bs);
+            break;
+            /* for the sake of less noise: assume that f(&var) inits the var. */
+        case Ocall:
+            for (i = 1; i < n->expr.nargs; i++) {
+                p = n->expr.args[i];
+                if (exprop(p) == Oaddr && exprop(p->expr.args[0]) == Ovar)
+                    nodevars(p, bs);
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+static void checkdefined(Node *n, Bitset *def)
 {
+    size_t i;
+    Node *d;
+
+    if (!n || n->type != Nexpr)
+        return;
+    switch (exprop(n)) {
+        case Ovar:
+            d = decls[n->expr.did];
+            if (!bshas(def, n->expr.did) && !d->decl.isglobl)
+                fatal(n, "%s used before definition", namestr(n->expr.args[0]));
+            break;
+        default:
+            nodevars(n->expr.idx, def);
+            for (i = 0; i < n->expr.nargs; i++)
+                checkdefined(n->expr.args[i], def);
+            break;
+    }
 }
 
-static void bbuse(Bb *bb, Bitset *bs)
+static void checkuse(Bb *bb, Bitset *def)
 {
+    size_t i;
+    Node *n;
+
+    if (!bb)
+        return;
+    for (i = 0; i < bb->nnl; i++) {
+        n = bb->nl[i];
+        switch(exprop(n)) {
+            case Oset:
+            case Oasn:
+                checkdefined(n->expr.args[1], def);
+                break;
+            default:
+                checkdefined(n, def);
+        }
+        nodedef(n, def);
+    }
 }
 
 static void bbdef(Bb *bb, Bitset *bs)
 {
+    size_t i;
+
+    if (!bb)
+        return;
+    for (i = 0; i < bb->nnl; i++)
+        nodedef(bb->nl[i], bs);
 }
-*/
 
+static Bitset *indef(Cfg *cfg, Bb *bb, Bitset **outdef)
+{
+    size_t j;
+    Bitset *def;
+
+    j = 0;
+    if (!bsiter(bb->pred, &j))
+        return mkbs();
+    def = bsdup(outdef[j]);
+    for (; bsiter(bb->pred, &j); j++)
+        bsintersect(def, outdef[j]);
+    return def;
+}
+
 static void checkreach(Cfg *cfg)
 {
+    Bitset **outdef;
+    Bitset *def;
+    size_t i, j;
+    int changed;
+    Bb *bb;
+
+    outdef = xalloc(sizeof(Bitset*) * cfg->nbb);
+
+    def = mkbs();
+
+    for (i = 0; i < cfg->nbb; i++) {
+        outdef[i] = mkbs();
+        bbdef(cfg->bb[i], outdef[i]);
+    }
+
+    dumpcfg(cfg, stdout);
+    for (i = 0; i < cfg->nbb; i++)
+        for (j= 0; bsiter(outdef[i], &j); j++)
+            printf("bb %zd defines %s\n", i, declname(decls[j]));
+
+    do {
+        changed = 0;
+        for (i = 0; i < cfg->nbb; i++) {
+            bb = cfg->bb[i];
+
+            def = indef(cfg, bb, outdef);
+            bsunion(def, outdef[i]);
+
+            if (!bseq(outdef[i], def)) {
+                changed = 1;
+                bsfree(outdef[i]);
+                outdef[i] = def;
+            }
+
+        }
+    } while (changed);
+
+
+
+    printf("---\n");
+    for (i = 0; i < cfg->nbb; i++) {
+        for (j= 0; bsiter(outdef[i], &j); j++)
+            printf("bb %zd defines %s\n", i, declname(decls[j]));
+        def = indef(cfg, bb, outdef);
+        checkuse(cfg->bb[i], def);
+        bsfree(def);
+    }
 }
 
 static void checkpredret(Cfg *cfg, Bb *bb)
@@ -69,5 +209,6 @@
 void check(Cfg *cfg)
 {
     checkret(cfg);
-    checkreach(cfg);
+    if (0) /* Not quite ready yet. */
+        checkreach(cfg);
 }
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -56,7 +56,7 @@
 O(Oarr,	        1,	OTmisc, NULL)
 
 /* all below this point are backend-only */
-O(Odead,        0,      OTmisc, "DEAD")         /* unreachable code */
+O(Odead,        0,      OTmisc, "DEAD")         /*  code */
 O(Ocjmp,	1,	OTmisc, "CJMP")         /* conditional jump */
 O(Ojtab,	1,	OTmisc, "JTAB")		/* jump table */
 O(Oset,	        1,	OTbin,  "=")            /* store to var */