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;