summaryrefslogtreecommitdiff
path: root/6
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-09-25 00:04:27 -0700
committerOri Bernstein <ori@eigenstate.org>2015-09-25 00:04:27 -0700
commitb1481c67d3e7709020bdb3a107602ab6ac80624f (patch)
tree760efa2193ca8206eab9516bf6fb80a866f6a64f /6
parent2c078158d4d8207ac978f4f86e8f3e18e47793eb (diff)
downloadmc-b1481c67d3e7709020bdb3a107602ab6ac80624f.tar.gz
Refer to captured vars through env ptr
The other half to populate an env pointer isn't there, so we haven't enabled this.
Diffstat (limited to '6')
-rw-r--r--6/asm.h4
-rw-r--r--6/gengas.c4
-rw-r--r--6/genp9.c2
-rw-r--r--6/isel.c5
-rw-r--r--6/simp.c41
5 files changed, 42 insertions, 14 deletions
diff --git a/6/asm.h b/6/asm.h
index 8f558bc..3f59700 100644
--- a/6/asm.h
+++ b/6/asm.h
@@ -135,7 +135,8 @@ struct Func {
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 @@ struct Isel {
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 */
diff --git a/6/gengas.c b/6/gengas.c
index 583dbd5..71f0bf7 100644
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -340,12 +340,13 @@ static void writeblob(FILE *fd, Blob *b)
/* 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;
@@ -356,7 +357,6 @@ void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
writeasm(fd, &is, fn);
}
-
void gentype(FILE *fd, Type *ty)
{
Blob *b;
diff --git a/6/genp9.c b/6/genp9.c
index 168e1f7..1d23777 100644
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -357,6 +357,7 @@ static size_t writeblob(FILE *fd, Blob *b, size_t off, char *lbl)
}
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 @@ static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
is.reglocs = mkht(varhash, vareq);
is.stkoff = fn->stkoff;
+ is.envoff = fn->envoff;
is.globls = globls;
is.ret = fn->ret;
is.cfg = fn->cfg;
diff --git a/6/isel.c b/6/isel.c
index 28454f7..22495cb 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -97,9 +97,14 @@ static Loc *varloc(Isel *s, Node *n)
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));
diff --git a/6/simp.c b/6/simp.c
index 865d3fa..8c1f20a 100644
--- 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 @@ struct Simp {
size_t nblobs;
Htab *globls;
- Htab *_stkoff;
+ Htab *stkoff;
+ Htab *envoff;
size_t stksz;
Node **args;
@@ -170,7 +170,7 @@ static Node *mul(Node *a, Node *b)
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 @@ static void forcelocal(Simp *s, Node *n)
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 @@ static Node *slicelen(Simp *s, Node *sl)
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 @@ static int isexport(Node *dcl)
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 @@ static Func *simpfn(Simp *s, char *name, Node *dcl)
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 @@ void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, s
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;