shithub: mc

Download patch

ref: 90cb266f109bb3ed87c2306e3d3def1325dc313a
parent: aa1fc1c605dde3cc533e353a25343dd344ea4ba8
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Feb 25 08:19:25 EST 2015

Implement type description dumping.

--- a/6/gengas.c
+++ b/6/gengas.c
@@ -38,6 +38,7 @@
 
 static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
 static void locprint(FILE *fd, Loc *l, char spec);
+static void gentydesc(FILE *fd, Type *ty);
 
 static void fillglobls(Stab *st, Htab *globls)
 {
@@ -433,7 +434,6 @@
     }
 }
 
-
 static void writeasm(FILE *fd, Isel *s, Func *fn)
 {
     size_t i, j;
@@ -487,6 +487,120 @@
     writeasm(fd, &is, fn);
 }
 
+static char *tydescid(char *buf, size_t bufsz, Type *ty)
+{
+    char *sep, *ns;
+
+    sep = "";
+    ns = "";
+    if (ty->name->name.ns) {
+        ns = ty->name->name.ns;
+        sep = "$";
+    }
+    if (ty->vis == Visexport || ty->isimport)
+        snprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
+    else
+        snprintf(buf, bufsz, "_tydesc$%zd$%s%s%s", ty->tid, ns, sep, ty->name->name.name);
+    return buf;
+}
+
+static void genstructmemb(FILE *fd, Node *sdecl)
+{
+    fprintf(fd, ".ascii \"%s\" /* struct member */\n", namestr(sdecl->decl.name));
+    gentydesc(fd, sdecl->decl.type);
+}
+
+static void genunionmemb(FILE *fd, Ucon *ucon)
+{
+    fprintf(fd, ".ascii \"%s\" /* union constructor */\n", namestr(ucon->name));
+    if (ucon->etype)
+        gentydesc(fd, ucon->etype);
+    else
+        fprintf(fd, ".byte %d /* no union type */\n", Tybad);
+}
+
+/* on x86, unaligned pointers are cheap. we shouldn't be introspecting too
+ * much, so tentatively, we'll just generate packed data.
+ */
+static void gentydesc(FILE *fd, Type *ty)
+{
+    char buf[512];
+    Node *sz;
+    size_t i;
+
+    fprintf(fd, ".byte %d /* type: %s */\n", ty->type, tidstr[ty->type]);
+    switch (ty->type) {
+        case Ntypes: case Tyvar: case Tybad: case Typaram:
+        case Tygeneric: case Tyunres:
+            die("invalid type in tydesc");    break;
+
+        case Tyvoid: case Tychar: case Tybool: case Tyint8:
+        case Tyint16: case Tyint: case Tyint32: case Tyint64:
+        case Tylong: case Tybyte: case Tyuint8: case Tyuint16:
+        case Tyuint: case Tyuint32: case Tyuint64: case Tyulong:
+        case Tyflt32: case Tyflt64: case Tyvalist:
+            break;
+
+        case Typtr:
+            gentydesc(fd, ty->sub[0]);
+            break;
+        case Tyslice:
+            gentydesc(fd, ty->sub[0]);
+            break;
+        case Tyarray:
+            ty->asize = fold(ty->asize, 1);
+            sz = ty->asize;
+            if (sz) {
+                assert(sz->type == Nexpr);
+                sz = sz->expr.args[0];
+                assert(sz->type == Nlit && sz->lit.littype == Lint);
+                fprintf(fd, ".quad %lld /* array size */\n", (vlong)sz->lit.intval);
+            } else {
+                fprintf(fd, ".quad -1 /* array size */\n");
+            }
+
+            gentydesc(fd, ty->sub[0]);
+            break;
+        case Tyfunc:
+            fprintf(fd, ".byte %zd /* nargs + ret */\n", ty->nsub);
+            for (i = 0; i < ty->nsub; i++)
+                gentydesc(fd, ty->sub[i]);
+            break;
+        case Tytuple:
+            for (i = 0; i < ty->nsub; i++)
+                gentydesc(fd, ty->sub[i]);
+            break;
+        case Tystruct:
+            for (i = 0; i < ty->nmemb; i++)
+                genstructmemb(fd, ty->sdecls[i]);
+            break;
+        case Tyunion:
+            for (i = 0; i < ty->nmemb; i++)
+                genunionmemb(fd, ty->udecls[i]);
+            break;
+        case Tyname:
+            fprintf(fd, ".quad %s\n", tydescid(buf, sizeof buf, ty));
+            break;
+    }
+}
+
+void gentype(FILE *fd, Type *ty)
+{
+    char buf[512];
+
+    if (ty->type == Tyname) {
+        if (hasparams(ty))
+            return;
+        tydescid(buf, sizeof buf, ty);
+        if (ty->vis == Visexport)
+            fprintf(fd, ".globl %s\n", buf);
+        fprintf(fd, "%s:\n", buf);
+        gentydesc(fd, ty->sub[0]);
+    } else {
+        gentydesc(fd, ty);
+    }
+}
+
 void gengas(Node *file, char *out)
 {
     Htab *globls, *strtab;
@@ -540,6 +654,8 @@
     fprintf(fd, ".text\n");
     for (i = 0; i < nfn; i++)
         genfunc(fd, fn[i], globls, strtab);
+    for (i = 0; i < file->file.ntydefs; i++)
+        gentype(fd, file->file.tydefs[i]);
     genstrings(fd, strtab);
     fclose(fd);
 }
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -281,7 +281,7 @@
         ;
 
 package : Tpkg optident Tasn pkgbody Tendblk {
-                if (file->file.globls->_name)
+                if (file->file.globls->name)
                     lfatal($1->loc, "Package already declared\n");
                 if ($2) {
                     updatens(file->file.globls, $2->id);
@@ -406,6 +406,7 @@
                 $$ = $2;
                 if ($$.nparams == 0) {
                     $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
+                    lappend(&file->file.tydefs, &file->file.ntydefs, $$.type);
                 } else {
                     $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
                 }
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1471,8 +1471,8 @@
            to do namespace dependent comparisons for specializing, we need to set the
            namespace here.
          */
-        if (file->file.globls->_name)
-            setns(dcl->decl.name, file->file.globls->_name);
+        if (file->file.globls->name)
+            setns(dcl->decl.name, file->file.globls->name);
         for (j = 0; j < t->nfuncs; j++) {
             if (nameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
                 proto = t->funcs[j];
@@ -1703,11 +1703,13 @@
         for (i = 0; i < t->nsub; i++)
             t->sub[i] = tyfix(st, ctx, t->sub[i]);
     }
+
     if (t->type == Tyvar) {
         if (debugopt['T'])
             dump(file, stdout);
         lfatal(t->loc, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(st, ctx));
     }
+
     if (debugopt['u'] && !tyeq(orig, t)) {
         from = tystr(orig);
         to = tystr(t);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -123,7 +123,7 @@
 
 struct Stab {
     Stab *super;
-    char *_name;
+    char *name;
 
     /* Contents of stab.
      * types and values are in separate namespaces. */
@@ -166,9 +166,11 @@
         Node **sdecls;  /* Tystruct: decls in struct */
         Ucon **udecls;  /* Tyunion: decls in union */
     };
-    char  issynth;       /* Tyname: whether this is synthesized or not */
-    char  ishidden;      /* Tyname: whether this is hidden or not */
-    char  ispkglocal;    /* Tyname: whether this is package local or not */
+
+    char issynth;       /* Tyname: whether this is synthesized or not */
+    char ishidden;      /* Tyname: whether this is hidden or not */
+    char ispkglocal;    /* Tyname: whether this is package local or not */
+    char isimport;      /* Tyname: whether tyis type was imported. */
 };
 
 struct Ucon {
@@ -211,6 +213,8 @@
             Node **stmts;
             size_t nstmts;
             Stab  *globls;
+            size_t ntydefs;
+            Type **tydefs;
         } file;
 
         struct {
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -52,6 +52,7 @@
             htput(tsmap, t, ret);
             for (i = 0; i < t->ngparam; i++)
                 lappend(&ret->arg, &ret->narg, tyspecialize(t->gparam[i], tsmap, delayed));
+            lappend(&file->file.tydefs, &file->file.ntydefs, ret);
             break;
         case Tyname:
             arg = NULL;
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -191,7 +191,7 @@
     Stab *s;
 
     do {
-        if (streq(st->_name, name))
+        if (streq(st->name, name))
             return st;
         if ((s = htget(st->ns, name)))
             return s;
@@ -263,8 +263,8 @@
 }
 
 void forcedcl (Stab *st, Node *s) {
-    if (st->_name)
-        setns(s->decl.name, st->_name);
+    if (st->name)
+        setns(s->decl.name, st->name);
     htput(st->dcl, s->decl.name, s);
     assert(htget(st->dcl, s->decl.name) != NULL);
 }
@@ -304,10 +304,10 @@
     Tydefn *td;
     Type *ty;
 
-    if (st->_name)
-        setns(n, st->_name);
-    if (st->_name && t && t->name)
-        setns(t->name, st->_name);
+    if (st->name)
+        setns(n, st->name);
+    if (st->name && t && t->name)
+        setns(t->name, st->name);
 
     ty = gettype(st, n);
     if (!ty) {
@@ -387,8 +387,8 @@
         fatal(n, "Trait %s already implemented over %s at %s:%d",
               namestr(n->impl.traitname), tystr(n->impl.type),
               fname(n->loc), lnum(n->loc));
-    if (st->_name)
-        setns(n->impl.traitname, st->_name);
+    if (st->name)
+        setns(n->impl.traitname, st->name);
     htput(st->impl, n, n);
 }
 
@@ -408,10 +408,10 @@
 {
     Stab *s;
 
-    s = getns_str(st, scope->_name);
+    s = getns_str(st, scope->name);
     if (s)
-        lfatal(Zloc, "Namespace %s already defined", st->_name);
-    htput(st->ns, scope->_name, scope);
+        lfatal(Zloc, "Namespace %s already defined", st->name);
+    htput(st->ns, scope->name, scope);
 }
 
 /*
@@ -425,9 +425,9 @@
     size_t i, nk;
     Tydefn *td;
 
-    if (st->_name)
-        die("Stab %s already has namespace; Can't set to %s", st->_name, name);
-    st->_name = strdup(name);
+    if (st->name)
+        die("Stab %s already has namespace; Can't set to %s", st->name, name);
+    st->name = strdup(name);
     k = htkeys(st->dcl, &nk);
     for (i = 0; i < nk; i++)
         setns(k[i], name);
--- a/parse/use.c
+++ b/parse/use.c
@@ -48,7 +48,7 @@
     size_t n, i;
     void **keys;
 
-    wrstr(fd, val->_name);
+    wrstr(fd, val->name);
 
     /* write decls */
     keys = htkeys(val->dcl, &n);
@@ -86,7 +86,7 @@
 
     /* read dcls */
     st = mkstab();
-    st->_name = rdstr(fd);
+    st->name = rdstr(fd);
     n = rdint(fd);
     for (i = 0; i < n; i++)
         putdcl(st, rdsym(fd, NULL));
@@ -340,6 +340,7 @@
 
     t = rdbyte(fd);
     ty = mktype(Zloc, t);
+    ty->isimport = 1;
     if (rdbyte(fd) == Vishidden)
         ty->ishidden = 1;
     /* tid is generated; don't write */
@@ -704,7 +705,7 @@
     Stab *s;
 
     if (!pkg) {
-        if (!st->_name)
+        if (!st->name)
             return st;
         else
             return NULL;
@@ -713,7 +714,7 @@
     s = getns_str(st, pkg);
     if (!s) {
         s = mkstab();
-        s->_name = strdup(pkg);
+        s->name = strdup(pkg);
         putns(st, s);
     }
     return s;
@@ -827,8 +828,8 @@
     /* if the package names match up, or the usefile has no declared
      * package, then we simply add to the current stab. Otherwise,
      * we add a new stab under the current one */
-    if (st->_name) {
-        if (pkg && !strcmp(pkg, st->_name)) {
+    if (st->name) {
+        if (pkg && !strcmp(pkg, st->name)) {
             s = st;
         } else {
             s = findstab(st, pkg);
@@ -841,7 +842,7 @@
         }
     }
     if (!s) {
-        printf("could not find matching package for merge: %s\n", st->_name);
+        printf("could not find matching package for merge: %s\n", st->name);
         exit(1);
     }
     tidmap = mkht(ptrhash, ptreq);
@@ -964,8 +965,8 @@
     /* usefile name */
     wrbyte(f, 'U');
     wrint(f, Useversion);        /* use version */
-    if (st->_name)
-        wrstr(f, st->_name);
+    if (st->name)
+        wrstr(f, st->name);
     else
         wrstr(f, NULL);