ref: 334532827595c538c638dcae7ebecb4d857573f5
parent: 0cae8df980a684eb9334e167765596b8e12b5728
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Dec 26 21:21:46 EST 2013
Move towards automatically creating hidden exports. Right now, this only works muse, since the probing is only done when generating usefiles. However, with a bit of work it should be usable for exporting symbols in assembly as well
--- a/6/isel.c
+++ b/6/isel.c
@@ -1039,7 +1039,7 @@
assert(blob->type == Ndecl);
lbl = htget(globls, blob);
- if (blob->decl.isexport)
+ if (blob->decl.vis != Visintern)
fprintf(fd, ".globl %s\n", lbl);
fprintf(fd, "%s:\n", lbl);
if (blob->decl.init)
--- a/6/simp.c
+++ b/6/simp.c
@@ -1435,7 +1435,7 @@
append(s, s->endlbl);
}
-static Func *simpfn(Simp *s, char *name, Node *n, int export)
+static Func *simpfn(Simp *s, char *name, Node *n, Vis vis)
{
size_t i;
Func *fn;
@@ -1476,7 +1476,8 @@
fn = zalloc(sizeof(Func));
fn->name = strdup(name);
- fn->isexport = export;
+ if (vis != Visintern)
+ fn->isexport = 1;
fn->stksz = align(s->stksz, 8);
fn->stkoff = s->stkoff;
fn->ret = s->ret;
@@ -1544,7 +1545,7 @@
if (dcl->decl.isextern || dcl->decl.isgeneric)
return;
if (isconstfn(dcl)) {
- f = simpfn(&s, name, dcl->decl.init, dcl->decl.isexport);
+ f = simpfn(&s, name, dcl->decl.init, dcl->decl.vis);
lappend(fn, nfn, f);
} else {
simpconstinit(&s, dcl);
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -137,8 +137,8 @@
outnode(n->file.stmts[i], fd, depth + 1);
break;
case Ndecl:
- fprintf(fd, "(did = %zd, isconst = %d, isgeneric = %d, isextern = %d, isexport = %d)\n",
- n->decl.did, n->decl.isconst, n->decl.isgeneric, n->decl.isextern, n->decl.isexport);
+ fprintf(fd, "(did = %zd, isconst = %d, isgeneric = %d, isextern = %d, vis = %d)\n",
+ n->decl.did, n->decl.isconst, n->decl.isgeneric, n->decl.isextern, n->decl.vis);
outsym(n, fd, depth + 1);
outnode(n->decl.init, fd, depth + 1);
break;
--- a/parse/htab.c
+++ b/parse/htab.c
@@ -103,16 +103,21 @@
while (ht->hashes[i] && !ht->dead[i]) {
/* second insertion overwrites first. nb, we shouldn't touch the
* keys for dead values */
- if (ht->hashes[i] == h && (ht->dead[i] || ht->cmp(ht->keys[i], k)))
+ if (ht->hashes[i] == h) {
+ if (ht->dead[i])
break;
+ else if (ht->cmp(ht->keys[i], k))
+ goto conflicted;
+ }
di++;
i = (h + di) & (ht->sz - 1);
}
+ ht->nelt++;
+conflicted:
ht->hashes[i] = h;
ht->keys[i] = k;
ht->vals[i] = v;
ht->dead[i] = 0;
- ht->nelt++;
if (ht->sz < ht->nelt*2)
grow(ht, ht->sz*2);
return 1;
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -842,6 +842,8 @@
{
Type *t;
+ if (s->decl.ishidden)
+ fatal(n->line, "attempting to refer to hidden decl %s", ctxstr(st, n));
if (s->decl.isgeneric)
t = tyfreshen(st, tf(st, s->decl.type));
else
@@ -1277,10 +1279,9 @@
if (d->type == Ndecl) {
s = getdcl(file->file.exports, d->decl.name);
if (s) {
- d->decl.isexport = 1;
- s->decl.isexport = 1;
- s->decl.init = d->decl.init;
+ d->decl.vis = Visexport;
unify(st, d, type(st, d), s->decl.type);
+ forcedcl(file->file.exports, d);
}
}
}
@@ -1533,7 +1534,8 @@
k = htkeys(s->dcl, &n);
for (i = 0; i < n; i++) {
d = getdcl(s, k[i]);
- d->decl.type = tyfix(st, d, d->decl.type);
+ if (d)
+ d->decl.type = tyfix(st, d, d->decl.type);
}
free(k);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -237,11 +237,12 @@
struct {
size_t did;
+ char vis;
char isglobl;
- char isexport;
char isconst;
char isgeneric;
char isextern;
+ char ishidden;
Node *name;
Type *type;
Node *init;
@@ -341,6 +342,7 @@
void putcstr(Stab *st, Node *n, Cstr *cstr);
void updatetype(Stab *st, Node *n, Type *t);
void putdcl(Stab *st, Node *dcl);
+void forcedcl(Stab *st, Node *dcl);
void putucon(Stab *st, Ucon *uc);
Stab *getns(Stab *st, Node *n);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -92,7 +92,8 @@
orig = st;
do {
- if ((s = htget(st->dcl, n))) {
+ s = htget(st->dcl, n);
+ if (s) {
/* record that this is in the closure of this scope */
if (!st->closure)
st->closure = mkht(nsnamehash, nsnameeq);
@@ -177,9 +178,14 @@
d = htget(st->dcl, s->decl.name);
if (d)
fatal(s->line, "%s already declared (on line %d)", namestr(s->decl.name), d->line);
+ forcedcl(st, s);
+}
+
+void forcedcl (Stab *st, Node *s) {
if (st->name)
setns(s->decl.name, namestr(st->name));
htput(st->dcl, s->decl.name, s);
+ assert(htget(st->dcl, s->decl.name) != NULL);
}
void updatetype(Stab *st, Node *n, Type *t)
--- a/parse/use.c
+++ b/parse/use.c
@@ -78,7 +78,7 @@
st->name = unpickle(fd);
n = rdint(fd);
for (i = 0; i < n; i++)
- putdcl(st, rdsym(fd));
+ putdcl(st, rdsym(fd));
/* read types */
n = rdint(fd);
@@ -141,6 +141,7 @@
wrtype(fd, val->decl.type);
/* symflags */
+ wrint(fd, val->decl.vis);
wrbool(fd, val->decl.isconst);
wrbool(fd, val->decl.isgeneric);
wrbool(fd, val->decl.isextern);
@@ -160,6 +161,8 @@
n = mkdecl(line, name, NULL);
rdtype(fd, &n->decl.type);
+ if (rdint(fd) == Vishidden)
+ n->decl.ishidden = 1;
n->decl.isconst = rdbool(fd);
n->decl.isgeneric = rdbool(fd);
n->decl.isextern = rdbool(fd);
@@ -780,9 +783,10 @@
}
}
-static void nodetag(Node *n)
+static void nodetag(Stab *st, Node *n, int ingeneric)
{
size_t i;
+ Node *d;
if (!n)
return;
@@ -789,50 +793,58 @@
switch (n->type) {
case Nblock:
for (i = 0; i < n->block.nstmts; i++)
- nodetag(n->block.stmts[i]);
+ nodetag(st, n->block.stmts[i], ingeneric);
break;
case Nifstmt:
- nodetag(n->ifstmt.cond);
- nodetag(n->ifstmt.iftrue);
- nodetag(n->ifstmt.iffalse);
+ nodetag(st, n->ifstmt.cond, ingeneric);
+ nodetag(st, n->ifstmt.iftrue, ingeneric);
+ nodetag(st, n->ifstmt.iffalse, ingeneric);
break;
case Nloopstmt:
- nodetag(n->loopstmt.init);
- nodetag(n->loopstmt.cond);
- nodetag(n->loopstmt.step);
- nodetag(n->loopstmt.body);
+ nodetag(st, n->loopstmt.init, ingeneric);
+ nodetag(st, n->loopstmt.cond, ingeneric);
+ nodetag(st, n->loopstmt.step, ingeneric);
+ nodetag(st, n->loopstmt.body, ingeneric);
break;
case Nmatchstmt:
- nodetag(n->matchstmt.val);
+ nodetag(st, n->matchstmt.val, ingeneric);
for (i = 0; i < n->matchstmt.nmatches; i++)
- nodetag(n->matchstmt.matches[i]);
+ nodetag(st, n->matchstmt.matches[i], ingeneric);
break;
case Nmatch:
- nodetag(n->match.pat);
- nodetag(n->match.block);
+ nodetag(st, n->match.pat, ingeneric);
+ nodetag(st, n->match.block, ingeneric);
break;
case Nexpr:
- nodetag(n->expr.idx);
+ nodetag(st, n->expr.idx, ingeneric);
taghidden(n->expr.type);
for (i = 0; i < n->expr.nargs; i++)
- nodetag(n->expr.args[i]);
+ nodetag(st, n->expr.args[i], ingeneric);
+ /* generics need to have the decls they refer to exported. */
+ if (ingeneric && exprop(n) == Ovar) {
+ d = decls[n->expr.did];
+ if (d->decl.isglobl && d->decl.vis == Visintern) {
+ d->decl.vis = Vishidden;
+ putdcl(st, d);
+ }
+ }
break;
case Nlit:
taghidden(n->lit.type);
if (n->lit.littype == Lfunc)
- nodetag(n->lit.fnval);
+ nodetag(st, n->lit.fnval, ingeneric);
break;
case Ndecl:
taghidden(n->decl.type);
/* generics export their body. */
if (n->decl.isgeneric)
- nodetag(n->decl.init);
+ nodetag(st, n->decl.init, n->decl.isgeneric);
break;
case Nfunc:
taghidden(n->func.type);
for (i = 0; i < n->func.nargs; i++)
- nodetag(n->func.args[i]);
- nodetag(n->func.body);
+ nodetag(st, n->func.args[i], ingeneric);
+ nodetag(st, n->func.body, ingeneric);
break;
case Nuse: case Nname:
@@ -868,7 +880,7 @@
k = htkeys(st->dcl, &n);
for (i = 0; i < n; i++) {
s = getdcl(st, k[i]);
- nodetag(s);
+ nodetag(st, s, 0);
}
}
@@ -905,7 +917,7 @@
k = htkeys(st->dcl, &n);
for (i = 0; i < n; i++) {
s = getdcl(st, k[i]);
- if (s->decl.isgeneric)
+ if (s && s->decl.isgeneric)
wrbyte(f, 'G');
else
wrbyte(f, 'D');