summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2018-01-20 13:07:34 -0500
committerOri Bernstein <ori@eigenstate.org>2018-01-21 14:29:38 -0800
commit720cc29f19477550800adf5539837fec15296bbc (patch)
tree34efa93381a753b3b0c06090b84116f7cc9e7967
parentd8b909066008d478a8abd30cb329c88d44194730 (diff)
downloadmc-720cc29f19477550800adf5539837fec15296bbc.tar.gz
Cheap enums.
-rw-r--r--6/isel.c12
-rw-r--r--6/simp.c30
-rw-r--r--mbld/libs.myr2
-rw-r--r--mi/flatten.c4
-rw-r--r--parse/parse.h4
-rw-r--r--parse/type.c32
-rw-r--r--parse/use.c4
7 files changed, 60 insertions, 28 deletions
diff --git a/6/isel.c b/6/isel.c
index d7ec0c0..e695096 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -63,7 +63,7 @@ static Mode
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 @@ static Loc *
loc(Isel *s, Node *n)
{
Node *v;
+ Ucon *uc;
Loc *l;
if (n->type == Ndecl) {
@@ -137,6 +138,10 @@ loc(Isel *s, Node *n)
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 @@ selexpr(Isel *s, Node *n)
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 @@ selexpr(Isel *s, Node *n)
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:
diff --git a/6/simp.c b/6/simp.c
index b43a083..0a8e15f 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -338,8 +338,11 @@ uconid(Simp *s, Node *n)
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 @@ lval(Simp *s, Node *n)
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 @@ simpucon(Simp *s, Node *n, Node *dst)
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");
@@ -859,6 +850,13 @@ simpucon(Simp *s, Node *n, Node *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));
tag = mkintlit(n->loc, uc->id);
diff --git a/mbld/libs.myr b/mbld/libs.myr
index 49e2fc6..f92d0f9 100644
--- a/mbld/libs.myr
+++ b/mbld/libs.myr
@@ -22,7 +22,7 @@ pkg bld =
incs : byte[:][:] -> void)
;;
-const Abiversion = 16
+const Abiversion = 17
const builtlib = {b, mt, dep, dyndep
var ldep, l, u
diff --git a/mi/flatten.c b/mi/flatten.c
index 1b95d0f..03f3df1 100644
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -631,10 +631,6 @@ lval(Flattenctx *s, Node *n)
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;
diff --git a/parse/parse.h b/parse/parse.h
index 1bf0029..c7b94aa 100644
--- 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 @@ struct Type {
};
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 @@ Trait *mktrait(Srcloc l, Node *name,
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);
diff --git a/parse/type.c b/parse/type.c
index c31fbbe..8674d8c 100644
--- a/parse/type.c
+++ b/parse/type.c
@@ -44,7 +44,37 @@ char stackness[] = {
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 *
diff --git a/parse/use.c b/parse/use.c
index 605b3be..c40c9bc 100644
--- a/parse/use.c
+++ b/parse/use.c
@@ -361,9 +361,7 @@ rdtrait(FILE *fd, Trait **dest, Type *ty)
}
}
-/* 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)
{