ref: ac3d02cdfbafe7b887cbd8738d3df9b17c5c82c9
parent: 1520007d5fd0238f7ea3bf7aa7269043976bf3d6
author: Ori Bernstein <ori@eigenstate.org>
date: Mon May 18 06:26:33 EDT 2015
Improve type generation code. This should be simpler to port to plan 9, and the data should be more compact.
--- a/6/asm.h
+++ b/6/asm.h
@@ -12,6 +12,7 @@
typedef struct Blob Blob;
typedef struct Isel Isel;
typedef struct Asmbb Asmbb;
+typedef struct Blob Blob;
typedef enum {
#define Insn(val, gasfmt, p9fmt, use, def) val,
@@ -59,6 +60,35 @@
Plan9,
} Asmsyntax;
+typedef enum {
+ Bti8,
+ Bti16,
+ Bti32,
+ Bti64,
+ Btimin, /* byte-packed uint */
+ Btref,
+ Btbytes,
+ Btseq,
+} Blobtype;
+
+struct Blob {
+ Blobtype type;
+ char *lbl; /* may be null */
+ char isglobl;
+ union {
+ uint64_t ival;
+ char *ref;
+ struct {
+ size_t len;
+ char *buf;
+ } bytes;
+ struct {
+ size_t nsub;
+ Blob **sub;
+ } seq;
+ };
+};
+
/* a register, label, or memory location */
struct Loc {
Loctype type; /* the type of loc */
@@ -205,6 +235,7 @@
void gen(Node *file, char *out);
void gengas(Node *file, char *out);
void genp9(Node *file, char *out);
+Blob *tydescblob(Type *t);
/* location generation */
extern size_t maxregid;
@@ -237,7 +268,6 @@
/* register allocation */
void regalloc(Isel *s);
Rclass rclass(Loc *l);
-
/* useful functions */
size_t tysize(Type *t);
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -40,7 +40,6 @@
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)
{
@@ -490,131 +489,73 @@
writeasm(fd, &is, fn);
}
-void gennamevec(FILE *fd, Node *n)
+static void encodemin(FILE *fd, uint64_t val)
{
- if (n->name.ns) {
- fprintf(fd, "\t.quad %zd\n", strlen(n->name.name) + strlen(n->name.ns) + 1);
- fprintf(fd, "\t.ascii \"%s.%s\"\n", n->name.ns, n->name.name);
- } else {
- fprintf(fd, "\t.quad %zd\n", strlen(n->name.name));
- fprintf(fd, "\t.ascii \"%s\"\n", n->name.name);
+ size_t i, shift;
+ uint8_t b;
+
+ for (i = 1; i < 8; i++)
+ if (val < 1ULL << (7*i))
+ break;
+ shift = 8 - i + 1;
+ b = ~0 << shift;
+ b |= val & ((1 << shift) - 1);
+ fprintf(fd, "\t.byte %u\n", b);
+ val >>= shift;
+ while (val != 0) {
+ fprintf(fd, "\t.byte %u\n", (uint)val & 0xff);
+ val >>= 8;
}
}
-static void genstructmemb(FILE *fd, Node *sdecl)
+static void gentyblob(FILE *fd, Blob *b)
{
- gennamevec(fd, sdecl->decl.name);
- gentydesc(fd, sdecl->decl.type);
-}
-
-static void genunionmemb(FILE *fd, Ucon *ucon)
-{
- gennamevec(fd, ucon->name);
- if (ucon->etype)
- gentydesc(fd, ucon->etype);
- else
- fprintf(fd, "\t.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];
- uint8_t tt;
- Node *sz;
size_t i;
- /* names are pulled out of line */
- tt = ty->type;
- /* tyvars can get tagged, but aren't desired */
- if (ty->type == Tyvar)
+ if (!b)
return;
- if (ty->type == Tyname)
- tt |= Tdindirect;
- fprintf(fd, "\t.byte %d\n", tt);
- 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:
+ if (b->lbl) {
+ if (b->isglobl)
+ fprintf(fd, ".globl %s%s\n", Symprefix, b->lbl);
+ fprintf(fd, "%s%s:\n", Symprefix, b->lbl);
+ }
+ switch (b->type) {
+ case Bti8:
+ fprintf(fd, "\t.byte %zd\n", b->ival);
break;
-
- case Typtr:
- gentydesc(fd, ty->sub[0]);
+ case Bti16:
+ fprintf(fd, "\t.short %zd\n", b->ival);
break;
- case Tyslice:
- gentydesc(fd, ty->sub[0]);
+ case Bti32:
+ fprintf(fd, "\t.long %zd\n", b->ival);
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, "\t.quad %lld /* array size */\n", (vlong)sz->lit.intval);
- } else {
- fprintf(fd, "\t.quad -1 /* array size */\n");
- }
-
- gentydesc(fd, ty->sub[0]);
+ case Bti64:
+ fprintf(fd, "\t.quad %zd\n", b->ival);
break;
- case Tyfunc:
- fprintf(fd, "\t.byte %zd /* nargs + ret */\n", ty->nsub);
- for (i = 0; i < ty->nsub; i++)
- gentydesc(fd, ty->sub[i]);
+ case Btimin:
+ encodemin(fd, b->ival);
break;
- case Tytuple:
- fprintf(fd, "\t.byte %zd\n", ty->nsub);
- for (i = 0; i < ty->nsub; i++)
- gentydesc(fd, ty->sub[i]);
+ case Btref:
+ fprintf(fd, "\t.quad %s%s\n", Symprefix, b->ref);
break;
- case Tystruct:
- fprintf(fd, "\t.quad %zd\n", ty->nmemb);
- for (i = 0; i < ty->nmemb; i++)
- genstructmemb(fd, ty->sdecls[i]);
+ case Btbytes:
+ writebytes(fd, b->bytes.buf, b->bytes.len);
break;
- case Tyunion:
- fprintf(fd, "\t.quad %zd\n", ty->nmemb);
- for (i = 0; i < ty->nmemb; i++)
- genunionmemb(fd, ty->udecls[i]);
+ case Btseq:
+ for (i = 0; i < b->seq.nsub; i++)
+ gentyblob(fd, b->seq.sub[i]);
break;
- case Tyname:
- fprintf(fd, "\t.quad %s%s\n", Symprefix, tydescid(buf, sizeof buf, ty));
- break;
}
}
-static void gentype(FILE *fd, Type *ty)
+void gentype(FILE *fd, Type *ty)
{
- char buf[512];
+ Blob *b;
- tydescid(buf, sizeof buf, ty);
- if (ty->type == Tyname) {
- if (hasparams(ty))
- return;
- if (ty->vis == Visexport)
- fprintf(fd, ".globl %s%s /* tid: %d */\n", Symprefix, buf, ty->tid);
- }
- fprintf(fd, "%s%s:\n", Symprefix, buf);
- fprintf(fd, "\t.quad %s$data\n", buf);
- fprintf(fd, "\t.quad %s$end - %s$data\n", buf, buf);
- fprintf(fd, "%s$data:\n", buf);
- if (ty->type == Tyname) {
- fprintf(fd, "\t.byte %d\n", ty->type);
- gennamevec(fd, ty->name);
- gentydesc(fd, ty->sub[0]);
- } else {
- gentydesc(fd, ty);
- }
- fprintf(fd, "%s$end:\n\n", buf);
+ if (ty->type == Tyvar)
+ return;
+ b = tydescblob(ty);
+ gentyblob(fd, b);
}
void gengas(Node *file, char *out)
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -15,7 +15,231 @@
#include "asm.h"
#include "../config.h"
+#define Tdindirect 0x80
+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)
+{
+ Blob *b;
+
+ b = zalloc(sizeof(Blob));
+ b->type = Btref;
+ b->ref = strdup(lbl);
+ return b;
+}
+
+static size_t blobsz(Blob *b)
+{
+ size_t n;
+ size_t i;
+
+ switch (b->type) {
+ case Bti8: return 1; break;
+ case Bti16: return 2; break;
+ case Bti32: return 4; break;
+ case Bti64: return 8; break;
+ case Btref: return 8; break;
+ case Btbytes: return b->bytes.len; break;
+ case Btimin:
+ if (b->ival >= 1ULL << 56)
+ die("packed int too big");
+
+ for (i = 1; i < 8; i++)
+ if (b->ival < 1ULL << (7*i))
+ return i;
+ die("impossible blob size");
+ break;
+ case Btseq:
+ n = 0;
+ for (i = 0; i < b->seq.nsub; i++)
+ n += blobsz(b->seq.sub[i]);
+ return n;
+ break;
+ default:
+ die("unknown blob type");
+ }
+}
+
+void namevec(Blob ***sub, size_t *nsub, Node *n)
+{
+ char *buf;
+ size_t len;
+
+ if (n->name.ns) {
+ len = strlen(n->name.name) + strlen(n->name.ns) + 1;
+ buf = xalloc(len + 1);
+ snprintf(buf, len, "%s.%s", n->name.ns, n->name.name);
+ } else {
+ len = strlen(n->name.name);
+ buf = xalloc(len + 1);
+ snprintf(buf, len, "%s", n->name.name);
+ }
+ lappend(sub, nsub, mkblobi(Btimin, len));
+ lappend(sub, nsub, mkblobbytes(buf, len));
+}
+
+static void structmemb(Blob ***sub, size_t *nsub, Node *sdecl)
+{
+ Blob *b;
+
+ namevec(sub, nsub, sdecl->decl.name);
+ b = tydescsub(sdecl->decl.type);
+ lappend(sub, nsub, b);
+}
+
+static void unionmemb(Blob ***sub, size_t *nsub, Ucon *ucon)
+{
+ namevec(sub, nsub, ucon->name);
+ if (ucon->etype)
+ lappend(sub, nsub, tydescsub(ucon->etype));
+ else
+ lappend(sub, nsub, mkblobi(Bti8, Tybad));
+}
+
+Blob *tydescsub(Type *ty)
+{
+ Blob **sub, *sz, *bt, *b;
+ size_t i, nsub;
+ char buf[512];
+ uint8_t tt;
+ Node *len;
+
+ sub = NULL;
+ nsub = 0;
+ /* names are pulled out of line */
+ tt = ty->type;
+ /* tyvars can get tagged, but aren't desired */
+ if (ty->type == Tyvar)
+ return NULL;
+
+ if (ty->type == Tyname)
+ tt |= Tdindirect;
+ sz = mkblobi(Btimin, 0);
+ bt = mkblobi(Bti8, tt);
+ lappend(&sub, &nsub, bt);
+ switch (ty->type) {
+ case Ntypes: case Tyvar: case Tybad: case Typaram:
+ case Tygeneric: case Tyunres:
+ die("invalid type in tydesc"); break;
+
+ /* atomic types -- nothing else to do */
+ 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:
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ break;
+ case Tyslice:
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ break;
+ case Tyarray:
+ ty->asize = fold(ty->asize, 1);
+ len = ty->asize;
+ if (len) {
+ assert(len->type == Nexpr);
+ len = len->expr.args[0];
+ assert(len->type == Nlit && len->lit.littype == Lint);
+ lappend(&sub, &nsub, mkblobi(Btimin, len->lit.intval));
+ } else {
+ lappend(&sub, &nsub, mkblobi(Btimin, 0));
+ }
+
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ break;
+ case Tyfunc:
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nsub));
+ for (i = 0; i < ty->nsub; i++)
+ lappend(&sub, &nsub, tydescsub(ty->sub[i]));
+ break;
+ case Tytuple:
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nsub));
+ for (i = 0; i < ty->nsub; i++)
+ lappend(&sub, &nsub, tydescsub(ty->sub[i]));
+ break;
+ case Tystruct:
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nmemb));
+ for (i = 0; i < ty->nmemb; i++)
+ structmemb(&sub, &nsub, ty->sdecls[i]);
+ break;
+ case Tyunion:
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nmemb));
+ for (i = 0; i < ty->nmemb; i++)
+ unionmemb(&sub, &nsub, ty->udecls[i]);
+ break;
+ case Tyname:
+ i = snprintf(buf, sizeof buf, "%s", Symprefix);
+ tydescid(buf + i, sizeof buf - i, ty);
+ lappend(&sub, &nsub, mkblobref(buf));
+ break;
+ }
+ b = mkblobseq(sub, nsub);
+ sz->ival = blobsz(b);
+ linsert(&b->seq.sub, &b->seq.nsub, 0, sz);
+ return b;
+}
+
+Blob *tydescblob(Type *ty)
+{
+ char buf[512];
+ Blob *b, *sz, *sub;
+
+ if (ty->type == Tyname && hasparams(ty))
+ return NULL;
+
+ if (ty->type == Tyname) {
+ b = mkblobseq(NULL, 0);
+ sz = mkblobi(Btimin, 0);
+ sub = tydescsub(ty->sub[0]);
+ sz->ival = blobsz(sub);
+ lappend(&b->seq.sub, &b->seq.nsub, mkblobi(Bti8, Tyname));
+ lappend(&b->seq.sub, &b->seq.nsub, sz);
+ lappend(&b->seq.sub, &b->seq.nsub, sub);
+ if (ty->vis == Visexport)
+ b->isglobl = 1;
+ } else {
+ b = tydescsub(ty);
+ }
+ tydescid(buf, sizeof buf, ty);
+ b->lbl = strdup(buf);
+ return b;
+}
size_t tysize(Type *t)
{
size_t sz;