shithub: mc

Download patch

ref: b1481c67d3e7709020bdb3a107602ab6ac80624f
parent: 2c078158d4d8207ac978f4f86e8f3e18e47793eb
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Sep 24 20:04:27 EDT 2015

Refer to captured vars through env ptr

    The other half to populate an env pointer isn't there,
    so we haven't enabled this.

--- a/6/asm.h
+++ b/6/asm.h
@@ -135,7 +135,8 @@
 
     Node **args;  /* argument list */
     size_t nargs; /* number of args, including hidden ones */
-    Htab *stkoff; /* Loc* -> int stackoff map */
+    Htab *stkoff; /* Loc* -> int stkoff map */
+    Htab *envoff; /* Loc* -> int envoff map */
     size_t stksz; /* stack size */
     Node *ret;    /* return value */
 
@@ -169,6 +170,7 @@
     Htab *spillslots;   /* reg id  => int stkoff */
     Htab *reglocs;      /* decl id => Loc *reg */
     Htab *stkoff;       /* decl id => int stkoff */
+    Htab *envoff;       /* decl id => int envoff */
     Htab *globls;       /* decl id => char *globlname */
 
     /* increased when we spill */
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -340,12 +340,13 @@
 /* genfunc requires all nodes in 'nl' to map cleanly to operations that are
  * natively supported, as promised in the output of reduce().  No 64-bit
  * operations on x32, no structures, and so on. */
-void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
+static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
 {
     Isel is = {0,};
 
     is.reglocs = mkht(varhash, vareq);
     is.stkoff = fn->stkoff;
+    is.envoff = fn->envoff;
     is.globls = globls;
     is.ret = fn->ret;
     is.cfg = fn->cfg;
@@ -355,7 +356,6 @@
         writeasm(stdout, &is, fn);
     writeasm(fd, &is, fn);
 }
-
 
 void gentype(FILE *fd, Type *ty)
 {
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -357,6 +357,7 @@
     }
     return n;
 }
+
 /* genfunc requires all nodes in 'nl' to map cleanly to operations that are
  * natively supported, as promised in the output of reduce().  No 64-bit
  * operations on x32, no structures, and so on. */
@@ -366,6 +367,7 @@
 
     is.reglocs = mkht(varhash, vareq);
     is.stkoff = fn->stkoff;
+    is.envoff = fn->envoff;
     is.globls = globls;
     is.ret = fn->ret;
     is.cfg = fn->cfg;
--- a/6/isel.c
+++ b/6/isel.c
@@ -97,9 +97,14 @@
     ssize_t stkoff;
     Loc *l, *rip;
 
+    /* we need to try getting it from the stack first, in case we
+     * forced it to stack for addressing */
     if (hthas(s->globls, n)) {
         rip = locphysreg(Rrip);
         l = locmeml(htget(s->globls, n), rip, NULL, mode(n));
+    } else if (hthas(s->envoff, n)) {
+        stkoff = ptoi(htget(s->envoff, n));
+        l = locmem(-stkoff, locphysreg(Rrax), NULL, mode(n));
     } else if (hthas(s->stkoff, n)) {
         stkoff = ptoi(htget(s->stkoff, n));
         l = locmem(-stkoff, locphysreg(Rrbp), NULL, mode(n));
--- a/6/simp.c
+++ b/6/simp.c
@@ -25,7 +25,6 @@
 typedef struct Simp Simp;
 struct Simp {
     int isglobl;
-    Bitset *env;
 
     Node **stmts;
     size_t nstmts;
@@ -50,7 +49,8 @@
     size_t nblobs;
     Htab *globls;
 
-    Htab *_stkoff;
+    Htab *stkoff;
+    Htab *envoff;
     size_t stksz;
 
     Node **args;
@@ -170,7 +170,7 @@
 static int addressable(Simp *s, Node *a)
 {
     if (a->type == Ndecl || (a->type == Nexpr && exprop(a) == Ovar))
-        return hthas(s->_stkoff, a) || hthas(s->globls, a);
+        return hthas(s->envoff, a) || hthas(s->stkoff, a) || hthas(s->globls, a);
     else
         return stacknode(a);
 }
@@ -213,7 +213,7 @@
         dump(n, stdout);
         printf("declared at %zd, size = %zd\n", s->stksz, size(n));
     }
-    htput(s->_stkoff, n, itop(s->stksz));
+    htput(s->stkoff, n, itop(s->stksz));
 }
 
 static void declarelocal(Simp *s, Node *n)
@@ -348,8 +348,6 @@
 
 Node *loadvar(Simp *s, Node *n)
 {
-    if (bshas(s->env, n->expr.did))
-        fatal(n, "closure environment capture has not yet been implemented");
     return n;
 }
 
@@ -1680,15 +1678,34 @@
     return 0;
 }
 
+static int envcmp(const void *pa, const void *pb)
+{
+    const Node *a, *b;
+
+    a = *(const Node**)pa;
+    b = *(const Node**)pb;
+    return b->decl.did - a->decl.did;
+}
+
 static void collectenv(Simp *s, Node *fn)
 {
     size_t nenv, i;
     Node **env;
+    size_t off;
 
-    s->env = mkbs();
     env = getclosure(fn->func.scope, &nenv);
-    for (i = 0; i < nenv; i++)
-        bsput(s->env, env[i]->decl.did);
+    /*
+     we need these in a deterministic order so that we can
+     put them in the right place both when we use them and
+     when we capture them.
+     */
+    qsort(env, nenv, sizeof(Node*), envcmp);
+    off = Ptrsz;    /* we start with the size of the env */
+    for (i = 0; i < nenv; i++) {
+        off = alignto(off, decltype(env[i]));
+        htput(s->envoff, env[i], itop(off));
+        off += size(env[i]);
+    }
     free(env);
 }
 
@@ -1738,7 +1755,8 @@
     fn->type = dcl->decl.type;
     fn->isexport = isexport(dcl);
     fn->stksz = align(s->stksz, 8);
-    fn->stkoff = s->_stkoff;
+    fn->stkoff = s->stkoff;
+    fn->envoff = s->envoff;
     fn->ret = s->ret;
     fn->args = s->args;
     fn->nargs = s->nargs;
@@ -1814,7 +1832,8 @@
 
     if (ismain(dcl))
         dcl->decl.vis = Vishidden;
-    s._stkoff = mkht(varhash, vareq);
+    s.stkoff = mkht(varhash, vareq);
+    s.envoff = mkht(varhash, vareq);
     s.globls = globls;
     s.blobs = *blob;
     s.nblobs = *nblob;