ref: c74b0bc06994e9a4921131696a5714cf83642acc
parent: bb4ff654b3f0ce2e067e707f83310af5ebc50679
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Sep 26 19:47:46 EDT 2015
Separate out the concepts of code and func ptrs. In order to pass around functions with environments for closures, we need to refer to the type of a function pointer, as well as the type of code. This is ugly. When I rewrite the backend I should change it.
--- a/6/asm.h
+++ b/6/asm.h
@@ -267,6 +267,7 @@
char *genlocallblstr(char *buf, size_t sz);
char *genlblstr(char *buf, size_t sz);
+Type *codetype(Type *ft);
Node *genlbl(Srcloc loc);
Loc *loclbl(Node *lbl);
Loc *locstrlbl(char *lbl);
@@ -303,8 +304,6 @@
size_t size(Node *n);
ssize_t tyoffset(Type *ty, Node *memb);
ssize_t offset(Node *aggr, Node *memb);
-int stacktype(Type *t);
-int floattype(Type *t);
int stacknode(Node *n);
int floatnode(Node *n);
void breakhere();
--- a/6/gen.c
+++ b/6/gen.c
@@ -25,6 +25,8 @@
k = htkeys(st->dcl, &nk);
for (i = 0; i < nk; i++) {
s = htget(st->dcl, k[i]);
+ if (isconstfn(s))
+ s->decl.type = codetype(s->decl.type);
htput(globls, s, asmname(s));
}
free(k);
@@ -42,6 +44,18 @@
free(ns);
}
+Type *codetype(Type *ft)
+{
+ ft = tybase(ft);
+ if (ft->type == Tycode)
+ return ft;
+ assert(ft->type == Tyfunc);
+ ft = tydup(ft);
+ ft->type = Tycode;
+ return ft;
+}
+
+
static int islocal(Node *dcl)
{
if (dcl->decl.vis != Visintern)
@@ -70,6 +84,7 @@
int isconstfn(Node *n)
{
Node *d;
+ Type *t;
if (n->type == Nexpr) {
if (exprop(n) != Ovar)
@@ -78,8 +93,9 @@
} else {
d = n;
}
+ t = tybase(decltype(d));
if (d && d->decl.isconst && d->decl.isglobl)
- return tybase(decltype(d))->type == Tyfunc;
+ return t->type == Tyfunc || t->type == Tycode;
return 0;
}
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -51,6 +51,7 @@
tyvoid = mktype(Zloc, Tyvoid);
ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
+ ty->type = Tycode;
name = mknsname(Zloc, "_rt", "abort_oob");
dcl = mkdecl(Zloc, name, ty);
dcl->decl.isconst = 1;
--- a/6/isel.c
+++ b/6/isel.c
@@ -68,7 +68,7 @@
case Tyflt32: return ModeF; break;
case Tyflt64: return ModeD; break;
default:
- if (stacktype(t))
+ if (isstacktype(t))
return ModeQ;
switch (tysize(t)) {
case 1: return ModeB; break;
@@ -485,6 +485,7 @@
if (isconstfn(n)) {
op = Icall;
+ assert(tybase(exprtype(n))->type == Tycode);
f = locmeml(htget(s->globls, n), NULL, NULL, mode(n));
} else {
op = Icallind;
@@ -499,7 +500,7 @@
t = tybase(t);
nargs = t->nsub - 1;
- if (stacktype(t->sub[0]))
+ if (isstacktype(t->sub[0]))
nargs++;
/* valists are replaced with hidden type parameter,
* which we want on the stack for ease of ABI */
@@ -521,10 +522,10 @@
rsp = locphysreg(Rrsp);
t = exprtype(n);
- if (tybase(t)->type == Tyvoid || stacktype(t)) {
+ if (tybase(t)->type == Tyvoid || isstacktype(t)) {
retloc = NULL;
ret = NULL;
- } else if (floattype(t)) {
+ } else if (istyfloat(t)) {
retloc = coreg(Rxmm0d, mode(n));
ret = locreg(mode(n));
} else {
@@ -981,7 +982,7 @@
rbp = locphysreg(Rrbp);
if (s->ret) {
ret = loc(s, s->ret);
- if (floattype(exprtype(s->ret)))
+ if (istyfloat(exprtype(s->ret)))
g(s, Imovs, ret, coreg(Rxmm0d, ret->mode), NULL);
else
g(s, Imov, ret, coreg(Rax, ret->mode), NULL);
--- a/6/main.c
+++ b/6/main.c
@@ -237,9 +237,9 @@
} else {
gentemp(buf, sizeof buf, ctx.args[i], ".s");
}
+ genuse(ctx.args[i]);
gen(file, buf);
assemble(buf, ctx.args[i]);
- genuse(ctx.args[i]);
}
return 0;
--- a/6/simp.c
+++ b/6/simp.c
@@ -171,33 +171,20 @@
return stacknode(a);
}
-int stacktype(Type *t)
-{
- /* the types are arranged in types.def such that this is true */
- t = tybase(t);
- return t->type >= Tyslice;
-}
-
-int floattype(Type *t)
-{
- t = tybase(t);
- return t->type == Tyflt32 || t->type == Tyflt64;
-}
-
int stacknode(Node *n)
{
if (n->type == Nexpr)
- return stacktype(n->expr.type);
+ return isstacktype(n->expr.type);
else
- return stacktype(n->decl.type);
+ return isstacktype(n->decl.type);
}
int floatnode(Node *n)
{
if (n->type == Nexpr)
- return floattype(n->expr.type);
+ return istyfloat(n->expr.type);
else
- return floattype(n->decl.type);
+ return istyfloat(n->decl.type);
}
static void forcelocal(Simp *s, Node *n)
@@ -226,7 +213,7 @@
n = mkexpr(a->loc, Oaddr, a, NULL);
if (!addressable(s, a))
- forcelocal(s, a);
+ forcelocal(s, a);
if (!bt)
n->expr.type = mktyptr(a->loc, a->expr.type);
else
@@ -557,6 +544,7 @@
/* Never supported */
case Tyvoid: case Tybad: case Tyvalist: case Tyvar:
case Typaram: case Tyunres: case Tyname: case Ntypes:
+ case Tyfunc: case Tycode:
die("Unsupported type for pattern");
break;
/* only valid for string literals */
@@ -565,7 +553,7 @@
case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint:
case Tyint64: case Tyuint64:
case Tyflt32: case Tyflt64:
- case Typtr: case Tyfunc:
+ case Typtr:
v = mkexpr(pat->loc, Oeq, pat, val, NULL);
v->expr.type = mktype(pat->loc, Tybool);
cjmp(s, v, iftrue, iffalse);
@@ -925,7 +913,6 @@
case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
case Tyuint: case Tychar: case Tybyte:
case Typtr:
- case Tyfunc:
r = intconvert(s, val, to, 0);
break;
case Tyflt32: case Tyflt64:
@@ -1157,7 +1144,7 @@
return tmp;
elt = rval(s, n->expr.args[1], NULL);
u = addk(u, Wordsz);
- if (stacktype(uc->etype)) {
+ if (isstacktype(uc->etype)) {
elt = addr(s, elt, uc->etype);
sz = disp(n->loc, tysize(uc->etype));
r = mkexpr(n->loc, Oblit, u, elt, sz, NULL);
@@ -1341,6 +1328,21 @@
return f;
}
+static Node *getcode(Simp *s, Node *n)
+{
+ Node *r, *d;
+
+ if (isconstfn(n)) {
+ d = decls[n->expr.did];
+ r = mkexpr(n->loc, Ovar, n->expr.args[0], NULL);
+ r->expr.did = d->decl.did;
+ r->expr.type = codetype(exprtype(n));
+ } else {
+ r = rval(s, n, NULL);
+ }
+ return r;
+}
+
static Node *simpcall(Simp *s, Node *n, Node *dst)
{
size_t i, nargs;
@@ -1351,7 +1353,7 @@
ft = tybase(exprtype(n->expr.args[0]));
if (exprtype(n)->type == Tyvoid)
r = NULL;
- else if (stacktype(exprtype(n)) && dst)
+ else if (isstacktype(exprtype(n)) && dst)
r = dst;
else
r = temp(s, n);
@@ -1358,9 +1360,9 @@
args = NULL;
nargs = 0;
- lappend(&args, &nargs, rval(s, n->expr.args[0], NULL));
+ lappend(&args, &nargs, getcode(s, n->expr.args[0]));
- if (exprtype(n)->type != Tyvoid && stacktype(exprtype(n)))
+ if (exprtype(n)->type != Tyvoid && isstacktype(exprtype(n)))
lappend(&args, &nargs, addr(s, r, exprtype(n)));
for (i = 1; i < n->expr.nargs; i++) {
@@ -1379,7 +1381,7 @@
call = mkexprl(n->loc, Ocall, args, nargs);
call->expr.type = exprtype(n);
- if (r && !stacktype(exprtype(n))) {
+ if (r && !isstacktype(exprtype(n))) {
append(s, set(r, call));
} else {
append(s, call);
@@ -1704,7 +1706,7 @@
/* make a temp for the return type */
ty = f->func.type->sub[0];
- if (stacktype(ty)) {
+ if (isstacktype(ty)) {
s->isbigret = 1;
s->ret = gentemp(s, f->loc, mktyptr(f->loc, ty), &dcl);
declarearg(s, dcl);
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -119,7 +119,7 @@
lappend(&sub, &nsub, bt);
switch (ty->type) {
case Ntypes: case Tyvar: case Tybad: case Typaram:
- case Tygeneric: case Tyunres:
+ case Tygeneric: case Tycode: case Tyunres:
die("invalid type in tydesc"); break;
/* atomic types -- nothing else to do */
@@ -246,7 +246,7 @@
case Tychar: /* utf32 */
return 4;
- case Typtr: case Tyfunc:
+ case Typtr:
case Tyvalist: /* ptr to first element of valist */
return Ptrsz;
@@ -260,6 +260,10 @@
case Tyflt64:
return 8;
+ case Tyfunc:
+ return Ptrsz;
+ case Tycode:
+ return Ptrsz;
case Tyslice:
return 2*Ptrsz; /* len; ptr */
case Tyname:
--- a/mi/dfcheck.c
+++ b/mi/dfcheck.c
@@ -118,7 +118,7 @@
Type *ft;
ft = tybase(decltype(cfg->fn));
- assert(ft->type == Tyfunc);
+ assert(ft->type == Tyfunc || ft->type == Tycode);
if (ft->sub[0]->type == Tyvoid)
return;
--- a/mi/match.c
+++ b/mi/match.c
@@ -75,14 +75,15 @@
/* complex types */
case Typtr: return 1; break;
- case Tyfunc: return 0; break;
case Tyarray: return 1; break;
case Tytuple: return 1; break;
case Tystruct: return 1;
case Tyunion: return t->nmemb; break;
case Tyslice: return ~0ULL; break;
+
case Tyvar: case Typaram: case Tyunres: case Tyname:
case Tybad: case Tyvalist: case Tygeneric: case Ntypes:
+ case Tyfunc: case Tycode:
die("Invalid constructor type %s in match", tystr(t));
break;
}
@@ -204,6 +205,7 @@
if (pat == NULL)
return t;
+ pat = fold(pat, 1);
switch (exprop(pat)) {
case Ovar:
dcl = decls[pat->expr.did];
--- a/parse/names.c
+++ b/parse/names.c
@@ -50,7 +50,7 @@
};
char *tidstr[] = {
-#define Ty(t, n) n,
+#define Ty(t, n, stk) n,
#include "types.def"
#undef Ty
};
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -55,7 +55,7 @@
} Littype;
typedef enum {
-#define Ty(t, n) t,
+#define Ty(t, n, stk) t,
#include "types.def"
#undef Ty
Ntypes
@@ -520,6 +520,7 @@
Trait *mktrait(Srcloc l, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto);
Type *mktylike(Srcloc l, Ty ty); /* constrains tyvar t like it was builtin ty */
Ucon *finducon(Type *t, Node *name);
+int isstacktype(Type *t);
int istysigned(Type *t);
int istyunsigned(Type *t);
int istyfloat(Type *t);
--- a/parse/type.c
+++ b/parse/type.c
@@ -29,6 +29,19 @@
static Trait *traits[Ntypes + 1][4];
static int tybfmt(char *buf, size_t len, Type *t);
+
+char stackness[] = {
+#define Ty(t, n, stk) \
+ stk,
+#include "types.def"
+#undef Ty
+};
+
+int isstacktype(Type *t)
+{
+ return stackness[tybase(t)->type];
+}
+
Type *mktype(Srcloc loc, Ty ty)
{
Type *t;
@@ -324,12 +337,8 @@
int istyfloat(Type *t)
{
- switch (tybase(t)->type) {
- case Tyflt32: case Tyflt64:
- return 1;
- default:
- return 0;
- }
+ t = tybase(t);
+ return t->type == Tyflt32 || t->type == Tyflt64;
}
int istyprimitive(Type *t)
@@ -562,6 +571,7 @@
p += bprintf(p, end - p, "[]");
}
break;
+ case Tycode:
case Tyfunc:
p += bprintf(p, end - p, "(");
for (i = 1; i < t->nsub; i++) {
@@ -803,6 +813,13 @@
p += bprintf(p, end - p, "$s");
p += tyidfmt(p, end - p, ty->sub[0]);
break;
+ case Tycode:
+ p += bprintf(p, end - p, "$F");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ p += bprintf(p, end - p, "$");
+ }
+ break;
case Tyfunc:
p += bprintf(p, end - p, "$f");
for (i = 0; i < ty->nsub; i++) {
@@ -889,7 +906,7 @@
/* Definining and registering the types has to go after we define the
* constraints, otherwise they will have no constraints set on them. */
-#define Ty(t, n) \
+#define Ty(t, n, stk) \
if (t != Ntypes) {\
ty = mktype(Zloc, t); \
if (n) { \
--- a/parse/types.def
+++ b/parse/types.def
@@ -1,46 +1,48 @@
-Ty(Tybad, NULL)
-Ty(Tyvoid, "void")
+/* type, pretty, stack */
+Ty(Tybad, NULL, 0)
+Ty(Tyvoid, "void", 0)
/* start integer types.
* Keep them ordered between start
* and end for faster
* comparisons.*/
-Ty(Tybool, "bool")
-Ty(Tychar, "char")
+Ty(Tybool, "bool", 0)
+Ty(Tychar, "char", 0)
-Ty(Tyint8, "int8")
-Ty(Tyint16, "int16")
-Ty(Tyint, "int")
-Ty(Tyint32, "int32")
-Ty(Tyint64, "int64")
+Ty(Tyint8, "int8", 0)
+Ty(Tyint16, "int16", 0)
+Ty(Tyint, "int", 0)
+Ty(Tyint32, "int32", 0)
+Ty(Tyint64, "int64", 0)
-Ty(Tybyte, "byte")
-Ty(Tyuint8, "uint8")
-Ty(Tyuint16, "uint16")
-Ty(Tyuint, "uint")
-Ty(Tyuint32, "uint32")
-Ty(Tyuint64, "uint64")
+Ty(Tybyte, "byte", 0)
+Ty(Tyuint8, "uint8", 0)
+Ty(Tyuint16, "uint16", 0)
+Ty(Tyuint, "uint", 0)
+Ty(Tyuint32, "uint32", 0)
+Ty(Tyuint64, "uint64", 0)
/*end integer types*/
-Ty(Tyflt32, "flt32")
-Ty(Tyflt64, "flt64")
+Ty(Tyflt32, "flt32", 0)
+Ty(Tyflt64, "flt64", 0)
/* end primitive types */
-Ty(Tyvalist, NULL)
+Ty(Tyvalist, NULL, 0)
/* end atomic types */
-Ty(Typtr, NULL)
-Ty(Tyfunc, NULL)
+Ty(Typtr, NULL, 0)
+Ty(Tyfunc, NULL, 0)
/* these types live on the stack */
-Ty(Tyslice, NULL)
-Ty(Tyarray, NULL)
-Ty(Tytuple, NULL)
-Ty(Tystruct, NULL)
-Ty(Tyunion, NULL)
+Ty(Tyslice, NULL, 1)
+Ty(Tyarray, NULL, 1)
+Ty(Tytuple, NULL, 1)
+Ty(Tystruct, NULL, 1)
+Ty(Tyunion, NULL, 1)
/* these have no memory repr */
-Ty(Tyvar, NULL)
-Ty(Typaram, NULL)
-Ty(Tyunres, NULL) /* unresolved */
-Ty(Tyname, NULL)
-Ty(Tygeneric, NULL)
+Ty(Tyvar, NULL, 1)
+Ty(Typaram, NULL, 1)
+Ty(Tyunres, NULL, 1) /* unresolved */
+Ty(Tyname, NULL, 1)
+Ty(Tygeneric, NULL, 1)
+Ty(Tycode, NULL, 0)