ref: 720cc29f19477550800adf5539837fec15296bbc
parent: d8b909066008d478a8abd30cb329c88d44194730
author: Quentin Carbonneaux <quentin@c9x.me>
date: Sat Jan 20 08:07:34 EST 2018
Cheap enums.
--- a/6/isel.c
+++ b/6/isel.c
@@ -63,7 +63,7 @@
tymode(Type *t)
{
/* FIXME: What should the mode for, say, structs be when we have no
- * intention of loading /through/ the pointer? For now, we'll just say it'
+ * intention of loading /through/ the pointer? For now, we'll just say it's
* the pointer mode, since we expect to address through the pointer */
t = tybase(t);
switch (t->type) {
@@ -128,6 +128,7 @@
loc(Isel *s, Node *n)
{
Node *v;
+ Ucon *uc;
Loc *l;
if (n->type == Ndecl) {
@@ -137,6 +138,10 @@
case Ovar:
l = varloc(s, n);
break;
+ case Oucon:
+ uc = finducon(exprtype(n), n->expr.args[0]);
+ l = loclit(uc->id, mode(n));
+ break;
case Olit:
v = n->expr.args[0];
switch (v->lit.littype) {
@@ -858,6 +863,9 @@
case Ovjmp:
selvjmp(s, n, args);
break;
+ case Oucon:
+ assert(isenum(tybase(exprtype(n))));
+ /* fallthrough */
case Olit:
r = loc(s, n);
break;
@@ -936,7 +944,7 @@
case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
- case Oucon: case Otup: case Oarr: case Ostruct:
+ case Otup: case Oarr: case Ostruct:
case Oslice: case Oidx: case Osize: case Otupget:
case Obreak: case Ocontinue:
case Numops:
--- a/6/simp.c
+++ b/6/simp.c
@@ -338,8 +338,11 @@
Ucon *uc;
n = rval(s, n, NULL);
- if (exprop(n) != Oucon)
+ if (exprop(n) != Oucon) {
+ if (isenum(tybase(exprtype(n))))
+ return n;
return load(addr(s, n, mktype(n->loc, Tyuint)));
+ }
uc = finducon(exprtype(n), n->expr.args[0]);
return word(uc->loc, uc->id);
@@ -539,12 +542,6 @@
case Ostruct: r = rval(s, n, NULL); break;
case Oucon: r = rval(s, n, NULL); break;
case Oarr: r = rval(s, n, NULL); break;
- case Ogap: r = temp(s, n); break;
-
- /* not actually expressible as lvalues in syntax, but we generate them */
- case Oudata: r = rval(s, n, NULL); break;
- case Outag: r = rval(s, n, NULL); break;
- case Otupget: r = rval(s, n, NULL); break;
default:
fatal(n, "%s cannot be an lvalue", opstr[exprop(n)]);
break;
@@ -840,17 +837,11 @@
Node *r;
Type *ty;
Ucon *uc;
- size_t i, o;
+ size_t o;
/* find the ucon we're constructing here */
- ty = tybase(n->expr.type);
- uc = NULL;
- for (i = 0; i < ty->nmemb; i++) {
- if (!strcmp(namestr(n->expr.args[0]), namestr(ty->udecls[i]->name))) {
- uc = ty->udecls[i];
- break;
- }
- }
+ ty = tybase(exprtype(n));
+ uc = finducon(ty, n->expr.args[0]);
if (!uc)
die("Couldn't find union constructor");
@@ -858,6 +849,13 @@
tmp = dst;
else
tmp = temp(s, n);
+
+ if (isenum(ty)) {
+ /* enums are treated as integers
+ * by the backend */
+ append(s, set(tmp, n));
+ return tmp;
+ }
/* Set the tag on the ucon */
u = addr(s, tmp, mktype(n->loc, Tyuint));
--- a/mbld/libs.myr
+++ b/mbld/libs.myr
@@ -22,7 +22,7 @@
incs : byte[:][:] -> void)
;;
-const Abiversion = 16
+const Abiversion = 17
const builtlib = {b, mt, dep, dyndep
var ldep, l, u
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -631,10 +631,6 @@
case Oarr: r = rval(s, n); break;
case Ogap: r = temp(s, n); break;
- /* not actually expressible as lvalues in syntax, but we generate them */
- case Oudata: r = rval(s, n); break;
- case Outag: r = rval(s, n); break;
- case Otupget: r = rval(s, n); break;
default:
fatal(n, "%s cannot be an lvalue", opstr[exprop(n)]);
break;
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -1,4 +1,4 @@
-#define Abiversion 16
+#define Abiversion 17
typedef struct Srcloc Srcloc;
typedef struct Tysubst Tysubst;
@@ -158,6 +158,7 @@
};
char hasparams; /* cache for whether this type has params */
+ char isenum; /* Tyunion: see isenum(), it is lazily set there */
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. */
@@ -470,6 +471,7 @@
int isproto);
Ucon *finducon(Type *t, Node *name);
int isstacktype(Type *t);
+int isenum(Type *t);
int istysigned(Type *t);
int istyunsigned(Type *t);
int istyfloat(Type *t);
--- a/parse/type.c
+++ b/parse/type.c
@@ -44,7 +44,37 @@
int
isstacktype(Type *t)
{
- return stackness[tybase(t)->type];
+ t = tybase(t);
+ if (t->type == Tyunion)
+ return !isenum(t);
+ return stackness[t->type];
+}
+
+int
+isenum(Type *t)
+{
+ size_t i;
+ char isenum;
+
+ assert(t->type == Tyunion);
+
+ /* t->isenum is lazily set:
+ * a value of 0 means that it was not computed,
+ * a value of 1 means that the type is an enum
+ * (i.e., it only has nullary constructors)
+ * a value of 2 means that the type is not an enum
+ */
+ if (t->isenum == 0) {
+ /* initialize it */
+ isenum = 1;
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype) {
+ isenum = 2;
+ break;
+ }
+ t->isenum = isenum;
+ }
+ return t->isenum == 1;
}
Type *
--- a/parse/use.c
+++ b/parse/use.c
@@ -361,9 +361,7 @@
}
}
-/* Writes types to a file. Errors on
- * internal only types like Tyvar that
- * will not be meaningful in another file */
+/* Reads types from a file. */
static Type *
tyunpickle(FILE *fd)
{