shithub: mc

Download patch

ref: a16c4e637079bb3d7f1cb93ae9b2348d710c003f
parent: fa8e0920764f9f298d6b6ac9471c862aec024e01
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Jun 27 09:38:48 EDT 2015

Factor out blob generation.

    The logic for our type layout is common between platforms.

--- a/6/Makefile
+++ b/6/Makefile
@@ -1,5 +1,6 @@
 INSTBIN=6m
 OBJ= \
+	blob.o \
 	gen.o \
 	gengas.o \
 	genp9.o \
--- a/6/asm.h
+++ b/6/asm.h
@@ -68,6 +68,7 @@
     Btref,
     Btbytes,
     Btseq,
+    Btpad,
 } Blobtype;
 
 struct Blob {
@@ -75,10 +76,12 @@
     char *lbl;  /* may be null */
     char isglobl;
     union {
+        uint64_t npad;
         uint64_t ival;
         struct {
             char *str;
             char isextern;
+            size_t off;
         } ref;
         struct {
             size_t len;
@@ -238,7 +241,17 @@
 void gen(Node *file, char *out);
 void gengas(Node *file, char *out);
 void genp9(Node *file, char *out);
+
+/* blob stuff */
+Blob *mkblobpad(size_t sz);
+Blob *mkblobi(Blobtype type, uint64_t ival);
+Blob *mkblobbytes(char *buf, size_t len);
+Blob *mkblobseq(Blob **sub, size_t nsub);
+Blob *mkblobref(char *lbl, size_t off, int isextern);
+void blobfree(Blob *b);
+
 Blob *tydescblob(Type *t);
+Blob *litblob(Htab *globls, Htab *strtab, Node *n);
 size_t blobsz(Blob *b);
 
 /* location generation */
--- /dev/null
+++ b/6/blob.c
@@ -1,0 +1,272 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "mi.h"
+#include "asm.h"
+#include "../config.h"
+
+static size_t blobrec(Blob *b, Htab *globls, Htab *strtab, Node *n);
+
+Blob *mkblobi(Blobtype type, uint64_t ival)
+{
+    Blob *b;
+
+    b = zalloc(sizeof(Blob));
+    b->type = type;
+    b->ival = ival;
+    return b;
+}
+
+Blob *mkblobpad(size_t sz)
+{
+    Blob *b;
+
+    b = zalloc(sizeof(Blob));
+    b->type = Btpad;
+    b->npad = sz;
+    return b;
+}
+
+Blob *mkblobbytes(char *buf, size_t len)
+{
+    Blob *b;
+
+    b = zalloc(sizeof(Blob));
+    b->type = Btbytes;
+    b->bytes.buf = buf;
+    b->bytes.len = len;
+    return b;
+}
+
+Blob *mkblobseq(Blob **sub, size_t nsub)
+{
+    Blob *b;
+
+    b = zalloc(sizeof(Blob));
+    b->type = Btseq;
+    b->seq.sub = sub;
+    b->seq.nsub = nsub;
+    return b;
+}
+
+Blob *mkblobref(char *lbl, size_t off, int isextern)
+{
+    Blob *b;
+
+    b = zalloc(sizeof(Blob));
+    b->type = Btref;
+    b->ref.str = strdup(lbl);
+    b->ref.isextern = isextern;
+    b->ref.off = off;
+    return b;
+}
+
+void blobfree(Blob *b)
+{
+    size_t i;
+
+    switch (b->type) {
+        case Btref:
+            free(b->lbl);
+            break;
+        case Btseq:
+            for (i = 0; i < b->seq.nsub; i++)
+                blobfree(b->seq.sub[i]);
+            break;
+        default:
+            break;
+    }
+    free(b);
+}
+
+static size_t getintlit(Node *n, char *failmsg)
+{
+    if (exprop(n) != Olit)
+        fatal(n, "%s", failmsg);
+    n = n->expr.args[0];
+    if (n->lit.littype != Lint)
+        fatal(n, "%s", failmsg);
+    return n->lit.intval;
+}
+
+void b(Blob *b, Blob *n)
+{
+    lappend(&b->seq.sub, &b->seq.nsub, n);
+}
+
+static size_t blobpad(Blob *seq, size_t sz)
+{
+    b(seq, mkblobpad(sz));
+    return sz;
+}
+
+static size_t bloblit(Blob *seq, Htab *strtab, Node *v, Type *ty)
+{
+    char buf[128];
+    char *lbl;
+    size_t sz;
+    Blobtype intsz[] = {
+        [1] = Bti8,
+        [2] = Bti16,
+        [4] = Bti32,
+        [8] = Bti64
+    };
+    union {
+        float fv;
+        double dv;
+        uint64_t qv;
+        uint32_t lv;
+    } u;
+
+    assert(v->type == Nlit);
+    sz = tysize(ty);
+    switch (v->lit.littype) {
+        case Lint:      b(seq, mkblobi(intsz[sz], v->lit.intval));    break;
+        case Lbool:     b(seq, mkblobi(Bti8, v->lit.boolval));     break;
+        case Lchr:      b(seq, mkblobi(Bti32, v->lit.chrval));     break;
+        case Lflt:
+                if (tybase(v->lit.type)->type == Tyflt32) {
+                    u.fv = v->lit.fltval;
+                    b(seq, mkblobi(Bti32, u.lv));
+                } else if (tybase(v->lit.type)->type == Tyflt64) {
+                    u.dv = v->lit.fltval;
+                    b(seq, mkblobi(Bti64, u.qv));
+                }
+                break;
+        case Lstr:
+           if (hthas(strtab, &v->lit.strval)) {
+               lbl = htget(strtab, &v->lit.strval);
+           } else {
+               lbl = genlocallblstr(buf, sizeof buf);
+               htput(strtab, &v->lit.strval, strdup(lbl));
+           }
+           b(seq, mkblobref(lbl, 0, 0));
+           b(seq, mkblobi(Bti64, v->lit.strval.len));
+           break;
+        case Lfunc:
+            die("Generating this shit ain't ready yet ");
+            break;
+        case Llbl:
+            die("Can't generate literal labels, ffs. They're not data.");
+            break;
+    }
+    return sz;
+}
+
+static size_t blobslice(Blob *seq,  Htab *globls, Htab *strtab, Node *n)
+{
+    Node *base, *lo, *hi;
+    ssize_t loval, hival, sz;
+    char *lbl;
+
+    base = n->expr.args[0];
+    lo = n->expr.args[1];
+    hi = n->expr.args[2];
+
+    /* by this point, all slicing operations should have had their bases
+     * pulled out, and we should have vars with their pseudo-decls in their
+     * place */
+    if (exprop(base) != Ovar || !base->expr.isconst)
+        fatal(base, "slice base is not a constant value");
+    loval = getintlit(lo, "lower bound in slice is not constant literal");
+    hival = getintlit(hi, "upper bound in slice is not constant literal");
+    sz = tysize(tybase(exprtype(base))->sub[0]);
+
+    lbl = htget(globls, base);
+    b(seq, mkblobref(lbl, loval*sz, 0));
+    b(seq, mkblobi(Bti64, (hival - loval)));
+    return 16;
+}
+
+static Node *structmemb(Node *n, char *dcl)
+{
+    size_t i;
+
+    for (i = 0; i < n->expr.nargs; i++)
+        if (!strcmp(namestr(n->expr.args[i]->expr.idx), dcl))
+            return n->expr.args[i];
+    return NULL;
+}
+
+static size_t blobstruct(Blob *seq, Htab *globls, Htab *strtab, Node *n)
+{
+    size_t i, sz, pad, end, ndcl;
+    Node **dcl, *m;
+    Type *t;
+
+    sz = 0;
+    t = tybase(exprtype(n));
+    assert(t->type == Tystruct);
+    dcl = t->sdecls;
+    ndcl = t->nmemb;
+
+    for (i = 0; i < ndcl; i++) {
+        pad = alignto(sz, decltype(dcl[i]));
+        m = structmemb(n, declname(dcl[i]));
+        sz += blobpad(seq, pad - sz);
+        if (m)
+            sz += blobrec(seq, globls, strtab, m);
+        else
+            sz += blobpad(seq, size(dcl[i]));
+    }
+    end = alignto(sz, t);
+    sz += blobpad(seq, end - sz);
+    return sz;
+}
+
+static size_t blobucon(Blob *seq, Htab *globls, Htab *strtab, Node *n)
+{
+    size_t sz;
+    Ucon *uc;
+
+    sz = 4;
+    uc = finducon(exprtype(n), n->expr.args[0]);
+    b(seq, mkblobi(Bti32, uc->id));
+    if (n->expr.nargs > 1)
+        sz += blobrec(seq, globls, strtab, n->expr.args[1]);
+    sz += blobpad(seq, size(n) - sz);
+    return sz;
+}
+
+
+static size_t blobrec(Blob *b, Htab *globls, Htab *strtab, Node *n)
+{
+    size_t i, sz;
+
+    switch(exprop(n)) {
+        case Oucon:     sz = blobucon(b, globls, strtab, n);  break;
+        case Oslice:    sz = blobslice(b, globls, strtab, n); break;
+        case Ostruct:   sz = blobstruct(b, globls, strtab, n);        break;
+        case Olit:      sz = bloblit(b, strtab, n->expr.args[0], exprtype(n));        break;
+        case Otup:
+        case Oarr:
+                        sz = 0;
+                        for (i = 0; i < n->expr.nargs; i++)
+                            sz += blobrec(b, globls, strtab, n->expr.args[i]);
+                        break;
+        default:
+                        dump(n, stdout);
+                        die("Nonliteral initializer for global");
+                        break;
+    }
+    return sz;
+}
+
+Blob *litblob(Htab *globls, Htab *strtab, Node *n)
+{
+    Blob *b;
+
+    b = mkblobseq(NULL, 0);
+    blobrec(b, globls, strtab, n);
+    return b;
+}
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -38,7 +38,6 @@
   [ModeD] = "d"
 };
 
-static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
 static void locprint(FILE *fd, Loc *l, char spec);
 
 static void fillglobls(Stab *st, Htab *globls)
@@ -260,169 +259,6 @@
     }
 }
 
-static size_t writelit(FILE *fd, Htab *strtab, Node *v, Type *ty)
-{
-    char buf[128];
-    char *lbl;
-    size_t sz;
-    char *intsz[] = {
-        [1] = ".byte",
-        [2] = ".short",
-        [4] = ".long",
-        [8] = ".quad"
-    };
-    union {
-        float fv;
-        double dv;
-        uint64_t qv;
-        uint32_t lv;
-    } u;
-
-    assert(v->type == Nlit);
-    sz = tysize(ty);
-    switch (v->lit.littype) {
-        case Lint:      fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval);    break;
-        case Lbool:     fprintf(fd, "\t.byte %d\n", v->lit.boolval);     break;
-        case Lchr:      fprintf(fd, "\t.long %d\n",  v->lit.chrval);     break;
-        case Lflt:
-                if (tybase(v->lit.type)->type == Tyflt32) {
-                    u.fv = v->lit.fltval;
-                    fprintf(fd, "\t.long 0x%llx\n", (vlong)u.lv);
-                } else if (tybase(v->lit.type)->type == Tyflt64) {
-                    u.dv = v->lit.fltval;
-                    fprintf(fd, "\t.quad 0x%llx\n", (vlong)u.qv);
-                }
-                break;
-        case Lstr:
-           if (hthas(strtab, &v->lit.strval)) {
-               lbl = htget(strtab, &v->lit.strval);
-           } else {
-               lbl = genlocallblstr(buf, sizeof buf);
-               htput(strtab, &v->lit.strval, strdup(lbl));
-           }
-           fprintf(fd, "\t.quad %s\n", lbl);
-           fprintf(fd, "\t.quad %zd\n", v->lit.strval.len);
-           break;
-        case Lfunc:
-            die("Generating this shit ain't ready yet ");
-            break;
-        case Llbl:
-            die("Can't generate literal labels, ffs. They're not data.");
-            break;
-    }
-    return sz;
-}
-
-static size_t writepad(FILE *fd, size_t sz)
-{
-    assert((ssize_t)sz >= 0);
-    if (sz > 0)
-        fprintf(fd, "\t.fill %zd,1,0\n", sz);
-    return sz;
-}
-
-static size_t getintlit(Node *n, char *failmsg)
-{
-    if (exprop(n) != Olit)
-        fatal(n, "%s", failmsg);
-    n = n->expr.args[0];
-    if (n->lit.littype != Lint)
-        fatal(n, "%s", failmsg);
-    return n->lit.intval;
-}
-
-static size_t writeucon(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
-    size_t sz;
-    Ucon *uc;
-
-    sz = 4;
-    uc = finducon(exprtype(n), n->expr.args[0]);
-    fprintf(fd, ".long %zd\n", uc->id);
-    if (n->expr.nargs > 1)
-        sz += writeblob(fd, globls, strtab, n->expr.args[1]);
-    return writepad(fd, size(n) - sz);
-}
-
-static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
-    Node *base, *lo, *hi;
-    ssize_t loval, hival, sz;
-    char *lbl;
-
-    base = n->expr.args[0];
-    lo = n->expr.args[1];
-    hi = n->expr.args[2];
-
-    /* by this point, all slicing operations should have had their bases
-     * pulled out, and we should have vars with their pseudo-decls in their
-     * place */
-    if (exprop(base) != Ovar || !base->expr.isconst)
-        fatal(base, "slice base is not a constant value");
-    loval = getintlit(lo, "lower bound in slice is not constant literal");
-    hival = getintlit(hi, "upper bound in slice is not constant literal");
-    sz = tysize(tybase(exprtype(base))->sub[0]);
-
-    lbl = htget(globls, base);
-    fprintf(fd, "\t.quad %s + (%zd*%zd)\n", lbl, loval, sz);
-    fprintf(fd, "\t.quad %zd\n", (hival - loval));
-    return size(n);
-}
-
-static size_t writestruct(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
-    Type *t;
-    Node **dcl;
-    int found;
-    size_t i, j;
-    size_t sz, pad, end;
-    size_t ndcl;
-
-    sz = 0;
-    t = tybase(exprtype(n));
-    assert(t->type == Tystruct);
-    dcl = t->sdecls;
-    ndcl = t->nmemb;
-    for (i = 0; i < ndcl; i++) {
-        pad = alignto(sz, decltype(dcl[i]));
-        sz += writepad(fd, pad - sz);
-        found = 0;
-        for (j = 0; j < n->expr.nargs; j++)
-            if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
-                found = 1;
-                sz += writeblob(fd, globls, strtab, n->expr.args[j]);
-            }
-        if (!found)
-            sz += writepad(fd, size(dcl[i]));
-    }
-    end = alignto(sz, t);
-    sz += writepad(fd, end - sz);
-    return sz;
-}
-
-static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
-    size_t i, sz;
-
-    switch(exprop(n)) {
-        case Oucon:     sz = writeucon(fd, globls, strtab, n);  break;
-        case Oslice:    sz = writeslice(fd, globls, strtab, n); break;
-        case Ostruct:   sz = writestruct(fd, globls, strtab, n);        break;
-        case Olit:      sz = writelit(fd, strtab, n->expr.args[0], exprtype(n));        break;
-        case Otup:
-        case Oarr:
-            sz = 0;
-            for (i = 0; i < n->expr.nargs; i++)
-                sz += writeblob(fd, globls, strtab, n->expr.args[i]);
-            break;
-        default:
-            dump(n, stdout);
-            die("Nonliteral initializer for global");
-            break;
-    }
-    return sz;
-}
-
 void genstrings(FILE *fd, Htab *strtab)
 {
     void **k;
@@ -454,42 +290,6 @@
     }
 }
 
-void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
-{
-    char *lbl;
-
-    /* lits and such also get wrapped in decls */
-    assert(blob->type == Ndecl);
-
-    lbl = htget(globls, blob);
-    if (blob->decl.vis != Visintern)
-        fprintf(fd, ".globl %s\n", lbl);
-    fprintf(fd, "%s:\n", lbl);
-    if (blob->decl.init)
-        writeblob(fd, globls, strtab, blob->decl.init);
-    else
-        writepad(fd, size(blob));
-}
-
-/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
- * natively supported, as promised in the output of reduce().  No 64-bit
- * operations on x32, no structures, and so on. */
-void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
-{
-    Isel is = {0,};
-
-    is.reglocs = mkht(varhash, vareq);
-    is.stkoff = fn->stkoff;
-    is.globls = globls;
-    is.ret = fn->ret;
-    is.cfg = fn->cfg;
-
-    selfunc(&is, fn, globls, strtab);
-    if (debugopt['i'])
-        writeasm(stdout, &is, fn);
-    writeasm(fd, &is, fn);
-}
-
 static void encodemin(FILE *fd, uint64_t val)
 {
     size_t i, shift;
@@ -514,7 +314,7 @@
     }
 }
 
-static void gentyblob(FILE *fd, Blob *b)
+static void writeblob(FILE *fd, Blob *b)
 {
     size_t i;
 
@@ -542,7 +342,7 @@
             encodemin(fd, b->ival);
             break;
         case Btref:
-            fprintf(fd, "\t.quad %s%s\n", b->ref.str, b->ref.isextern ? "g" : "");
+            fprintf(fd, "\t.quad %s%s + %zd\n", b->ref.str, b->ref.isextern ? "g" : "", b->ref.off);
             break;
         case Btbytes:
             writebytes(fd, b->bytes.buf, b->bytes.len);
@@ -549,11 +349,36 @@
             break;
         case Btseq:
             for (i = 0; i < b->seq.nsub; i++)
-                gentyblob(fd, b->seq.sub[i]);
+                writeblob(fd, b->seq.sub[i]);
             break;
+        case Btpad:
+            for (i = 0; i < b->npad; i++)
+                fprintf(fd, "\t.byte 0\n");
+            break;
+
     }
 }
 
+/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
+ * natively supported, as promised in the output of reduce().  No 64-bit
+ * operations on x32, no structures, and so on. */
+void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
+{
+    Isel is = {0,};
+
+    is.reglocs = mkht(varhash, vareq);
+    is.stkoff = fn->stkoff;
+    is.globls = globls;
+    is.ret = fn->ret;
+    is.cfg = fn->cfg;
+
+    selfunc(&is, fn, globls, strtab);
+    if (debugopt['i'])
+        writeasm(stdout, &is, fn);
+    writeasm(fd, &is, fn);
+}
+
+
 void gentype(FILE *fd, Type *ty)
 {
     Blob *b;
@@ -561,7 +386,28 @@
     if (ty->type == Tyvar)
         return;
     b = tydescblob(ty);
-    gentyblob(fd, b);
+    writeblob(fd, b);
+    blobfree(b);
+}
+
+void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
+{
+    char *lbl;
+    Blob *b;
+
+    /* lits and such also get wrapped in decls */
+    assert(blob->type == Ndecl);
+
+    lbl = htget(globls, blob);
+    if (blob->decl.vis != Visintern)
+        fprintf(fd, ".globl %s\n", lbl);
+    fprintf(fd, "%s:\n", lbl);
+    if (blob->decl.init)
+        b = litblob(globls, strtab, blob->decl.init);
+    else
+        b = mkblobpad(size(blob));
+    writeblob(fd, b);
+    blobfree(b);
 }
 
 void gengas(Node *file, char *out)
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -37,7 +37,6 @@
   [ModeD] = "D"
 };
 
-static size_t writeblob(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *blob);
 static void locprint(FILE *fd, Loc *l, char spec);
 
 static void fillglobls(Stab *st, Htab *globls)
@@ -262,169 +261,6 @@
     return sz;
 }
 
-static size_t writelit(FILE *fd, char *name, size_t off, Htab *strtab, Node *v, Type *ty)
-{
-    char buf[128];
-    char *lbl;
-    size_t sz;
-    union {
-        float fv;
-        double dv;
-        uint64_t qv;
-        uint32_t lv;
-    } u;
-
-    assert(v->type == Nlit);
-    sz = tysize(ty);
-    switch (v->lit.littype) {
-        case Lint:
-            fprintf(fd, "DATA %s+%zd(SB)/%zd,$%lld\n", name, off, sz, v->lit.intval);
-            break;
-        case Lbool:
-            fprintf(fd, "DATA %s+%zd(SB)/%zd,$%d\n", name, off, sz, v->lit.boolval);
-            break;
-        case Lchr:
-            fprintf(fd, "DATA %s+%zd(SB)/%zd,$%d\n", name, off, sz, v->lit.chrval);
-            break;
-        case Lflt:
-            if (tybase(v->lit.type)->type == Tyflt32) {
-                u.fv = v->lit.fltval;
-                fprintf(fd, "DATA %s+%zd(SB)/%zd, $0x%llx\n", name, off, sz, (vlong)u.lv);
-            } else if (tybase(v->lit.type)->type == Tyflt64) {
-                u.dv = v->lit.fltval;
-                fprintf(fd, "DATA %s+%zd(SB)/%zd, $0x%llx\n", name, off, sz, (vlong)u.qv);
-            }
-            break;
-        case Lstr:
-           if (hthas(strtab, &v->lit.strval)) {
-               lbl = htget(strtab, &v->lit.strval);
-           } else {
-               lbl = genlocallblstr(buf, sizeof buf);
-               htput(strtab, &v->lit.strval, strdup(lbl));
-           }
-           if (v->lit.strval.len > 0)
-               fprintf(fd, "DATA %s+%zd(SB)/8,$%s+0(SB)\n", name, off, lbl);
-           else
-               fprintf(fd, "DATA %s+%zd(SB)/8,$0\n", name, off);
-           fprintf(fd, "DATA %s+%zd(SB)/8,$%zd\n", name, off+8, v->lit.strval.len);
-           break;
-        case Lfunc:
-            die("Generating this shit ain't ready yet ");
-            break;
-        case Llbl:
-            die("Can't generate literal labels, ffs. They're not data.");
-            break;
-    }
-    return sz;
-}
-
-static size_t writepad(FILE *fd, char *name, size_t off, size_t sz)
-{
-    size_t n;
-
-    assert((ssize_t)sz >= 0);
-    while (sz > 0) {
-        n = min(sz, 8);
-        fprintf(fd, "DATA %s+%zd(SB)/%zd,$0\n", name, off, n);
-        sz -= n;
-    }
-    return sz;
-}
-
-static size_t getintlit(Node *n, char *failmsg)
-{
-    if (exprop(n) != Olit)
-        fatal(n, "%s", failmsg);
-    n = n->expr.args[0];
-    if (n->lit.littype != Lint)
-        fatal(n, "%s", failmsg);
-    return n->lit.intval;
-}
-
-static size_t writeslice(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *n)
-{
-    Node *base, *lo, *hi;
-    ssize_t loval, hival, sz;
-    char *lbl;
-
-    base = n->expr.args[0];
-    lo = n->expr.args[1];
-    hi = n->expr.args[2];
-
-    /* by this point, all slicing operations should have had their bases
-     * pulled out, and we should have vars with their pseudo-decls in their
-     * place */
-    if (exprop(base) != Ovar || !base->expr.isconst)
-        fatal(base, "slice base is not a constant value");
-    loval = getintlit(lo, "lower bound in slice is not constant literal");
-    hival = getintlit(hi, "upper bound in slice is not constant literal");
-    sz = tysize(tybase(exprtype(base))->sub[0]);
-
-    lbl = htget(globls, base);
-    fprintf(fd, "DATA %s+%zd(SB)/8,$%s+%zd(SB)\n", name, off, lbl, loval*sz);
-    fprintf(fd, "DATA %s+%zd(SB)/8,$%zd\n", name, off + Ptrsz, (hival - loval));
-    return size(n);
-}
-
-static size_t writestruct(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *n)
-{
-    Type *t;
-    Node **dcl;
-    int found;
-    size_t i, j;
-    size_t pad, start, end;
-    size_t ndcl;
-
-    start = off;
-    t = tybase(exprtype(n));
-    assert(t->type == Tystruct);
-    dcl = t->sdecls;
-    ndcl = t->nmemb;
-    for (i = 0; i < ndcl; i++) {
-        pad = alignto(off, decltype(dcl[i]));
-        off += writepad(fd, name, off, pad - off);
-        found = 0;
-        for (j = 0; j < n->expr.nargs; j++)
-            if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
-                found = 1;
-                off += writeblob(fd, name, off, globls, strtab, n->expr.args[j]);
-            }
-        if (!found)
-            off += writepad(fd, name, off, size(dcl[i]));
-    }
-    end = alignto(off, t);
-    off += writepad(fd, name, off, end - off);
-    return off - start;
-}
-
-static size_t writeblob(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *n)
-{
-    size_t i, sz;
-
-    switch(exprop(n)) {
-        case Otup:
-        case Oarr:
-            sz = 0;
-            for (i = 0; i < n->expr.nargs; i++)
-                sz += writeblob(fd, name, off + sz, globls, strtab, n->expr.args[i]);
-            break;
-        case Ostruct:
-            sz = writestruct(fd, name, off, globls, strtab, n);
-            break;
-        case Olit:
-            sz = writelit(fd, name, off, strtab, n->expr.args[0], exprtype(n));
-            break;
-        case Oslice:
-            sz = writeslice(fd, name, off, globls, strtab, n);
-            break;
-        default:
-            dump(n, stdout);
-            die("Nonliteral initializer for global");
-            break;
-    }
-    return sz;
-}
-
 static void genstrings(FILE *fd, Htab *strtab)
 {
     void **k;
@@ -464,40 +300,6 @@
     }
 }
 
-static void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
-{
-    char *lbl;
-
-    /* lits and such also get wrapped in decls */
-    assert(blob->type == Ndecl);
-
-    lbl = htget(globls, blob);
-    fprintf(fd, "GLOBL %s+0(SB),$%zd\n", lbl, size(blob));
-    if (blob->decl.init)
-        writeblob(fd, lbl, 0, globls, strtab, blob->decl.init);
-    else
-        writepad(fd, lbl, 0, size(blob));
-}
-
-/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
- * natively supported, as promised in the output of reduce().  No 64-bit
- * operations on x32, no structures, and so on. */
-static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
-{
-    Isel is = {0,};
-
-    is.reglocs = mkht(varhash, vareq);
-    is.stkoff = fn->stkoff;
-    is.globls = globls;
-    is.ret = fn->ret;
-    is.cfg = fn->cfg;
-
-    selfunc(&is, fn, globls, strtab);
-    if (debugopt['i'])
-        writeasm(stdout, &is, fn);
-    writeasm(fd, &is, fn);
-}
-
 static size_t encodemin(FILE *fd, uint64_t val, size_t off, char *lbl)
 {
     size_t i, shift, n;
@@ -526,7 +328,7 @@
     return i;
 }
 
-static size_t gentyblob(FILE *fd, Blob *b, size_t off, char *lbl)
+static size_t writeblob(FILE *fd, Blob *b, size_t off, char *lbl)
 {
     size_t i, n;
 
@@ -555,9 +357,11 @@
             break;
         case Btref:
             if (b->ref.isextern)
-                fprintf(fd, "DATA %s+%zd(SB)/8,$%s+0(SB)\n", lbl, off+n, b->ref.str);
+                fprintf(fd, "DATA %s+%zd(SB)/8,$%s+%zd(SB)\n",
+                        lbl, off+n, b->ref.str, b->ref.off);
             else
-                fprintf(fd, "DATA %s+%zd(SB)/8,$%s<>+0(SB)\n", lbl, off+n, b->ref.str);
+                fprintf(fd, "DATA %s+%zd(SB)/8,$%s<>+%zd(SB)\n",
+                        lbl, off+n, b->ref.str, b->ref.off);
             n += 8;
             break;
         case Btbytes:
@@ -565,12 +369,35 @@
             break;
         case Btseq:
             for (i = 0; i < b->seq.nsub; i++)
-                n += gentyblob(fd, b->seq.sub[i], off+n, lbl);
+                n += writeblob(fd, b->seq.sub[i], off+n, lbl);
             break;
+        case Btpad:
+            for (i = 0; i < b->npad; i++)
+                fprintf(fd, "DATA %s+%zd(SB)/1,$0\n", lbl, off+n+i);
+            n += b->npad;
+            break;
     }
     return n;
 }
+/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
+ * natively supported, as promised in the output of reduce().  No 64-bit
+ * operations on x32, no structures, and so on. */
+static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
+{
+    Isel is = {0,};
 
+    is.reglocs = mkht(varhash, vareq);
+    is.stkoff = fn->stkoff;
+    is.globls = globls;
+    is.ret = fn->ret;
+    is.cfg = fn->cfg;
+
+    selfunc(&is, fn, globls, strtab);
+    if (debugopt['i'])
+        writeasm(stdout, &is, fn);
+    writeasm(fd, &is, fn);
+}
+
 static void gentype(FILE *fd, Type *ty)
 {
     Blob *b;
@@ -588,7 +415,24 @@
         fprintf(fd, "GLOBL %s%s<>+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
         snprintf(lbl, sizeof lbl, "%s%s<>", Symprefix, b->lbl);
     }
-    gentyblob(fd, b, 0, lbl);
+    writeblob(fd, b, 0, lbl);
+}
+
+static void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
+{
+    char *lbl;
+    Blob *b;
+
+    /* lits and such also get wrapped in decls */
+    assert(blob->type == Ndecl);
+
+    lbl = htget(globls, blob);
+    fprintf(fd, "GLOBL %s+0(SB),$%zd\n", lbl, size(blob));
+    if (blob->decl.init)
+        b = litblob(globls, strtab, blob->decl.init);
+    else
+        b = mkblobpad(size(blob));
+    writeblob(fd, b, 0, lbl);
 }
 
 void genp9(Node *file, char *out)
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -19,49 +19,6 @@
 
 Blob *tydescsub(Type *ty);
 
-static Blob *mkblobi(Blobtype type, uint64_t ival)
-{
-    Blob *b;
-
-    b = zalloc(sizeof(Blob));
-    b->type = type;
-    b->ival = ival;
-    return b;
-}
-
-static Blob *mkblobbytes(char *buf, size_t len)
-{
-    Blob *b;
-
-    b = zalloc(sizeof(Blob));
-    b->type = Btbytes;
-    b->bytes.len = len;
-    b->bytes.buf = buf;
-    return b;
-}
-
-static Blob *mkblobseq(Blob **sub, size_t nsub)
-{
-    Blob *b;
-
-    b = zalloc(sizeof(Blob));
-    b->type = Btseq;
-    b->seq.nsub = nsub;
-    b->seq.sub = sub;
-    return b;
-}
-
-static Blob *mkblobref(char *lbl, int isextern)
-{
-    Blob *b;
-
-    b = zalloc(sizeof(Blob));
-    b->type = Btref;
-    b->ref.str = strdup(lbl);
-    b->ref.isextern = isextern;
-    return b;
-}
-
 size_t blobsz(Blob *b)
 {
     size_t n;
@@ -220,7 +177,7 @@
         case Tyname:
             i = snprintf(buf, sizeof buf, "%s", Symprefix);
             tydescid(buf + i, sizeof buf - i, ty);
-            lappend(&sub, &nsub, mkblobref(buf, ty->isimport || ty->vis == Visexport));
+            lappend(&sub, &nsub, mkblobref(buf, 0, ty->isimport || ty->vis == Visexport));
             break;
     }
     b = mkblobseq(sub, nsub);