shithub: mc

Download patch

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)
 {