shithub: mc

Download patch

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