summaryrefslogtreecommitdiff
path: root/mi
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2018-07-01 17:38:51 -0700
committerOri Bernstein <ori@eigenstate.org>2018-07-01 17:40:28 -0700
commitec6e403c3fbefc7929f52610aecb85300e7ad17a (patch)
treed420a2c60d441ae25d655ed02ac12a94ee193c52 /mi
parent83ac0784c67f15c98b62cdacc660be63c447474a (diff)
downloadmc-ec6e403c3fbefc7929f52610aecb85300e7ad17a.tar.gz
Drain increment queues before jumping in matches.
Diffstat (limited to 'mi')
-rw-r--r--mi/flatten.c66
1 files changed, 34 insertions, 32 deletions
diff --git a/mi/flatten.c b/mi/flatten.c
index fa4bdc1..b746804 100644
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -58,6 +58,7 @@ static Node *flatten(Flattenctx *s, Node *n);
static Node *rval(Flattenctx *s, Node *n);
static Node *lval(Flattenctx *s, Node *n);
static Node *assign(Flattenctx *s, Node *lhs, Node *rhs);
+static Node *draininc(Flattenctx *c, Node *protect, int free);
static void
append(Flattenctx *s, Node *n)
@@ -457,6 +458,30 @@ assign(Flattenctx *s, Node *lhs, Node *rhs)
return r;
}
+/*
+ * If protect is not null, returns a node with the
+ * unmodified value.
+ */
+static Node*
+draininc(Flattenctx *fc, Node *protect, int free)
+{
+ Node *tmp;
+ size_t i;
+
+ tmp = NULL;
+ if (!fc->nqueue)
+ return protect;
+ if (protect) {
+ tmp = temp(fc, protect);
+ append(fc, assign(fc, tmp, protect));
+ }
+ for (i = 0; i < fc->nqueue; i++)
+ append(fc, fc->incqueue[i]);
+ if (free)
+ lfree(&fc->incqueue, &fc->nqueue);
+ return tmp;
+}
+
/* returns 1 when the exit jump needs to be emitted */
static int
exitscope(Flattenctx *s, Stab *stop, Srcloc loc, Exit x)
@@ -488,7 +513,6 @@ rval(Flattenctx *s, Node *n)
Node *t, *u, *v; /* temporary nodes */
Node *r; /* expression result */
Node **args;
- size_t i;
Type *ty;
const Op fusedmap[Numops] = {
@@ -607,18 +631,8 @@ rval(Flattenctx *s, Node *n)
r = n;
break;;
case Oret:
- /* drain the increment queue before we return */
v = rval(s, args[0]);
- if (!s->nqueue) {
- t = v;
- } else {
- t = temp(s, v);
- u = assign(s, t, v);
- append(s, u);
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
- lfree(&s->incqueue, &s->nqueue);
- }
+ t = draininc(s, v, 1);
if (!s->tret)
s->tret = temp(s, v);
flatten(s, asn(lval(s, s->tret), t));
@@ -734,7 +748,6 @@ flattenloop(Flattenctx *s, Node *n)
Node *ldec;
Node *lcond;
Node *lstep;
- size_t i;
lbody = genlbl(n->loc);
ldec = genlbl(n->loc);
@@ -760,14 +773,10 @@ flattenloop(Flattenctx *s, Node *n)
flatten(s, lcond); /* test lbl */
flattencond(s, n->loopstmt.cond, ldec, lend); /* repeat? */
flatten(s, ldec); /* drain decrements */
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
+ draininc(s, NULL, 0);
jmp(s, lbody); /* goto test */
flatten(s, lend); /* exit */
-
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
- lfree(&s->incqueue, &s->nqueue);
+ draininc(s, NULL, 1);
s->inloop--;
s->loop = l;
@@ -781,7 +790,6 @@ flattenif(Flattenctx *s, Node *n, Node *exit)
{
Node *l1, *l2, *l3;
Node *iftrue, *iffalse;
- size_t i;
l1 = genlbl(n->loc);
l2 = genlbl(n->loc);
@@ -795,15 +803,12 @@ flattenif(Flattenctx *s, Node *n, Node *exit)
flattencond(s, n->ifstmt.cond, l1, l2);
flatten(s, l1);
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
+ draininc(s, NULL, 0);
/* goto test */
flatten(s, iftrue);
jmp(s, l3);
flatten(s, l2);
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
- lfree(&s->incqueue, &s->nqueue);
+ draininc(s, NULL, 1);
/* because lots of bunched up end labels are ugly,
* coalesce them by handling 'elif'-like construct
* separately */
@@ -1007,14 +1012,15 @@ flatteniter(Flattenctx *s, Node *n)
default: flattentraititer(s, n); break;
}
}
+
static void
flattenmatch(Flattenctx *fc, Node *n)
{
- Node *val;
- Node **match;
+ Node *val, **match;
size_t i, nmatch;
val = rval(fc, n->matchstmt.val);
+ val = draininc(fc, val, 1);
match = NULL;
nmatch = 0;
@@ -1027,19 +1033,15 @@ static void
flattenexpr(Flattenctx *fc, Node *n)
{
Node *r;
- size_t i;
if (islbl(n)) {
append(fc, n);
return;
}
-
r = rval(fc, n);
if (r)
append(fc, r);
- for (i = 0; i < fc->nqueue; i++)
- append(fc, fc->incqueue[i]);
- lfree(&fc->incqueue, &fc->nqueue);
+ draininc(fc, NULL, 1);
}
static Node *