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);
}