summaryrefslogtreecommitdiff
path: root/6
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-10-18 22:00:30 -0700
committerOri Bernstein <ori@eigenstate.org>2015-10-19 01:49:22 -0700
commit14d4a8e93c6804eb049eec51a5102c9d8b10c1c5 (patch)
treee595a03b1fcacc4ae6ea7b3552f38c58da097dea /6
parent0b0fb103248ec7b12b3a2b94d88b1fe7a0b4403e (diff)
downloadmc-14d4a8e93c6804eb049eec51a5102c9d8b10c1c5.tar.gz
Work towards better match statements.
Generate decision trees from mi/match.c. Still slightly broken, so not enabled.
Diffstat (limited to '6')
-rw-r--r--6/isel.c6
-rw-r--r--6/simp.c57
2 files changed, 45 insertions, 18 deletions
diff --git a/6/isel.c b/6/isel.c
index 7eee71c..9197e1a 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -885,9 +885,9 @@ Loc *selexpr(Isel *s, Node *n)
case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
case Oucon: case Otup: case Oarr: case Ostruct:
- case Oslice: case Oidx: case Osize:
- case Obreak: case Ocontinue:
- case Numops:
+ case Oslice: case Oidx: case Osize: case Otupget:
+ case Obreak: case Ocontinue:
+ case Numops:
dump(n, stdout);
die("Should not see %s in isel", opstr[exprop(n)]);
break;
diff --git a/6/simp.c b/6/simp.c
index dadc28a..06a744a 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -1049,29 +1049,51 @@ static Node *visit(Simp *s, Node *n)
return r;
}
+static Node *tupget(Simp *s, Node *tup, size_t idx, Node *dst)
+{
+ Node *plv, *prv, *sz, *stor, *dcl;
+ size_t off, i;
+ Type *ty;
+
+ off = 0;
+ ty = exprtype(tup);
+ for (i = 0; i < ty->nsub; i++) {
+ off = alignto(off, ty->sub[i]);
+ if (i == idx)
+ break;
+ off += tysize(ty->sub[i]);
+ }
+
+ if (!dst) {
+ dst = gentemp(s, tup->loc, ty->sub[idx], &dcl);
+ if (isstacktype(ty->sub[idx]))
+ declarelocal(s, dcl);
+ }
+ prv = add(addr(s, tup, ty->sub[i]), disp(tup->loc, off));
+ if (stacknode(dst)) {
+ sz = disp(dst->loc, size(dst));
+ plv = addr(s, dst, exprtype(dst));
+ stor = mkexpr(dst->loc, Oblit, plv, prv, sz, NULL);
+ } else {
+ stor = set(dst, load(prv));
+ }
+ append(s, stor);
+ return dst;
+}
+
/* Takes a tuple and binds the i'th element of it to the
* i'th name on the rhs of the assignment. */
static Node *destructure(Simp *s, Node *lhs, Node *rhs)
{
- Node *plv, *prv, *lv, *sz, *stor, **args;
- size_t off, i;
+ Node *lv, *rv, **args;
+ size_t i;
args = lhs->expr.args;
rhs = rval(s, rhs, NULL);
- off = 0;
for (i = 0; i < lhs->expr.nargs; i++) {
lv = lval(s, args[i]);
- off = alignto(off, exprtype(lv));
- prv = add(addr(s, rhs, exprtype(args[i])), disp(rhs->loc, off));
- if (stacknode(args[i])) {
- sz = disp(lhs->loc, size(lv));
- plv = addr(s, lv, exprtype(lv));
- stor = mkexpr(lhs->loc, Oblit, plv, prv, sz, NULL);
- } else {
- stor = set(lv, load(prv));
- }
- append(s, stor);
- off += size(lv);
+ rv = tupget(s, rhs, i, lv);
+ assert(rv == lv);
}
return NULL;
@@ -1469,6 +1491,7 @@ static Node *rval(Simp *s, Node *n, Node *dst)
Node **args;
size_t i;
Type *ty;
+
const Op fusedmap[Numops] = {
[Oaddeq] = Oadd,
[Osubeq] = Osub,
@@ -1513,7 +1536,7 @@ static Node *rval(Simp *s, Node *n, Node *dst)
r = simpucon(s, n, dst);
break;
case Outag:
- die("union tags not yet supported\n");
+ r = uconid(s, args[0]);
break;
case Oudata:
r = simpuget(s, n, dst);
@@ -1680,6 +1703,10 @@ static Node *rval(Simp *s, Node *n, Node *dst)
case Ogt: case Oge: case Olt: case Ole:
r = compare(s, n, 0);
break;
+ case Otupget:
+ assert(exprop(args[0]) == Olit);
+ i = args[0]->expr.args[0]->lit.intval;
+ r = tupget(s, args[0], i, dst);
case Obad:
die("bad operator");
break;