shithub: mc

Download patch

ref: 3792aa38235a273f449d25c4fe813de01bce3093
parent: 3435783cac36d00e147a7cc6f76cf2fa9d484cc4
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Jan 20 19:31:56 EST 2016

Add labels before linking them up.

	Forward jumps were broken since we were looking up labels
	before adding them. Oops.

--- a/parse/gram.y
+++ b/parse/gram.y
@@ -581,8 +581,11 @@
 	;
 
 goto    : Tgoto Tident {
-		$$ = mkexpr($1->loc, Ojmp, mklbl($2->loc, ""), NULL);
-		$$->expr.args[0]->lit.lblname = strdup($2->id);
+		Node *lbl;
+
+		lbl = mklbl($2->loc, "");
+		lbl->expr.args[0]->lit.lblname = strdup($2->id);
+		$$ = mkexpr($1->loc, Ojmp, lbl, NULL);
 	}
 	;
 
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1563,7 +1563,15 @@
 			   /* FIXME: env capture means this is non-const */
 			   n->expr.isconst = 1;
 			   break;
-		   default: n->expr.isconst = 1; break;
+		   case Llbl:
+			   s = getlbl(curstab(), args[0]->loc, args[0]->lit.lblname);
+			   if (!s)
+				   fatal(n, "unable to find label %s in function scope\n", args[0]->lit.lblname);
+			   *np = s;
+			   break;
+		   default: 
+			   n->expr.isconst = 1;
+			   break;
 		   }
 		   settype(st, n, type(st, args[0]));
 		   break;
@@ -1758,6 +1766,20 @@
 	free(k);
 }
 
+static void addlbl(Inferstate *st, Node *n)
+{
+	Node *lit;
+
+	if (n->type != Nexpr)
+		return;
+	if (exprop(n) != Olit)
+		return;
+	lit = n->expr.args[0];
+	if (lit->lit.littype != Llbl)
+		return;
+	putlbl(curstab(), lit->lit.lblname, n);
+}
+
 static void infernode(Inferstate *st, Node **np, Type *ret, int *sawret)
 {
 	size_t i, nbound;
@@ -1793,9 +1815,10 @@
 		setsuper(n->block.scope, curstab());
 		pushstab(n->block.scope);
 		inferstab(st, n->block.scope);
-		for (i = 0; i < n->block.nstmts; i++) {
+		for (i = 0; i < n->block.nstmts; i++)
+			addlbl(st, n->block.stmts[i]);
+		for (i = 0; i < n->block.nstmts; i++)
 			infernode(st, &n->block.stmts[i], ret, sawret);
-		}
 		popstab();
 		break;
 	case Nifstmt:
@@ -1865,9 +1888,6 @@
 		specializeimpl(st, n);
 		break;
 	case Nlit:
-		if (n->lit.littype == Llbl)
-			putlbl(curstab(), n->lit.lblname, n);
-		break;
 	case Nname:
 	case Nuse:
 		break;
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -114,6 +114,7 @@
 		st->lbl = mkht(strhash, streq);
 	}
 	st->impl = mkht(implhash, impleq);
+	st->isfunc = isfunc;
 	return st;
 }
 
@@ -182,7 +183,7 @@
 
 void putlbl(Stab *st, char *name, Node *lbl)
 {
-	while (!st->isfunc && st->super)
+	while (st && !st->isfunc)
 		st = st->super;
 	if (!st) 
 		fatal(lbl, "label %s defined outside function\n", name);
@@ -193,10 +194,10 @@
 
 Node *getlbl(Stab *st, Srcloc loc, char *name)
 {
-	while (!st->isfunc && st->super)
+	while (st && !st->isfunc)
 		st = st->super;
 	if (!st || !hthas(st->lbl, name))
-		lfatal(loc, "unable to find label %s in function scope\n", name);
+		return NULL;
 	return htget(st->lbl, name);
 }