shithub: mc

Download patch

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)