shithub: mc

Download patch

ref: ec6e403c3fbefc7929f52610aecb85300e7ad17a
parent: 83ac0784c67f15c98b62cdacc660be63c447474a
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Jul 1 13:38:51 EDT 2018

Drain increment queues before jumping in matches.

--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -58,6 +58,7 @@
 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 @@
 	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 @@
 	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 @@
 		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 @@
 	Node *ldec;
 	Node *lcond;
 	Node *lstep;
-	size_t i;
 
 	lbody = genlbl(n->loc);
 	ldec = genlbl(n->loc);
@@ -760,15 +773,11 @@
 	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 */
+	draininc(s, NULL, 1);
 
-	for (i = 0; i < s->nqueue; i++)
-		append(s, s->incqueue[i]);
-	lfree(&s->incqueue, &s->nqueue);
-
 	s->inloop--;
 	s->loop = l;
 	s->curst = b;
@@ -781,7 +790,6 @@
 {
 	Node *l1, *l2, *l3;
 	Node *iftrue, *iffalse;
-	size_t i;
 
 	l1 = genlbl(n->loc);
 	l2 = genlbl(n->loc);
@@ -795,15 +803,12 @@
 
 	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 @@
 	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 @@
 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 *