diff options
author | Ori Bernstein <ori@eigenstate.org> | 2018-07-01 17:38:51 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2018-07-01 17:40:28 -0700 |
commit | ec6e403c3fbefc7929f52610aecb85300e7ad17a (patch) | |
tree | d420a2c60d441ae25d655ed02ac12a94ee193c52 /mi | |
parent | 83ac0784c67f15c98b62cdacc660be63c447474a (diff) | |
download | mc-ec6e403c3fbefc7929f52610aecb85300e7ad17a.tar.gz |
Drain increment queues before jumping in matches.
Diffstat (limited to 'mi')
-rw-r--r-- | mi/flatten.c | 66 |
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 * |