summaryrefslogtreecommitdiff
path: root/6/simp.c
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-11-17 20:53:32 -0800
committerOri Bernstein <ori@eigenstate.org>2015-11-17 20:53:32 -0800
commit8531896f8d21ba1e727262aaf5cd96043590b480 (patch)
tree7c01441755f56ab66d33c37d3ac41642ddc46c0b /6/simp.c
parentc20862cda53c711fe476f6c7d0f6631af47a4933 (diff)
downloadmc-8531896f8d21ba1e727262aaf5cd96043590b480.tar.gz
MEGAPATCH: Tabification.
Tabs > spaces. By 4 spaces, to be precise. Let's use them.
Diffstat (limited to '6/simp.c')
-rw-r--r--6/simp.c2886
1 files changed, 1443 insertions, 1443 deletions
diff --git a/6/simp.c b/6/simp.c
index dd06dff..59a12e9 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -24,42 +24,42 @@
*/
typedef struct Simp Simp;
struct Simp {
- int isglobl;
-
- Node **stmts;
- size_t nstmts;
-
- /* return handling */
- Node *endlbl;
- Node *ret;
- int hasenv;
- int isbigret;
-
- /* the array we're indexing for context within [] */
- Node **idxctx;
- size_t nidxctx;
-
- /* pre/postinc handling */
- Node **incqueue;
- size_t nqueue;
-
- /* break/continue handling */
- Node **loopstep;
- size_t nloopstep;
- Node **loopexit;
- size_t nloopexit;
-
- /* location handling */
- Node **blobs;
- size_t nblobs;
- Htab *globls;
-
- Htab *stkoff;
- Htab *envoff;
- size_t stksz;
-
- Node **args;
- size_t nargs;
+ int isglobl;
+
+ Node **stmts;
+ size_t nstmts;
+
+ /* return handling */
+ Node *endlbl;
+ Node *ret;
+ int hasenv;
+ int isbigret;
+
+ /* the array we're indexing for context within [] */
+ Node **idxctx;
+ size_t nidxctx;
+
+ /* pre/postinc handling */
+ Node **incqueue;
+ size_t nqueue;
+
+ /* break/continue handling */
+ Node **loopstep;
+ size_t nloopstep;
+ Node **loopexit;
+ size_t nloopexit;
+
+ /* location handling */
+ Node **blobs;
+ size_t nblobs;
+ Htab *globls;
+
+ Htab *stkoff;
+ Htab *envoff;
+ size_t stksz;
+
+ Node **args;
+ size_t nargs;
};
static int envcmp(const void *pa, const void *pb);
@@ -83,309 +83,309 @@ Node *abortoob;
static void append(Simp *s, Node *n)
{
- lappend(&s->stmts, &s->nstmts, n);
+ lappend(&s->stmts, &s->nstmts, n);
}
static int ispure(Node *n)
{
- return opispure[exprop(n)];
+ return opispure[exprop(n)];
}
size_t alignto(size_t sz, Type *t)
{
- size_t a;
- size_t i;
-
- t = tybase(t);
- a = 0;
- switch (t->type) {
- case Tyarray:
- a = alignto(1, t->sub[0]);
- case Tytuple:
- for (i = 0; i < t->nsub; i++)
- a = max(alignto(1, t->sub[i]), a);
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- a = max(alignto(1, decltype(t->sdecls[i])), a);
- break;
- default:
- a = tysize(t);
- break;
- }
-
- return align(sz, min(a, Ptrsz));
+ size_t a;
+ size_t i;
+
+ t = tybase(t);
+ a = 0;
+ switch (t->type) {
+ case Tyarray:
+ a = alignto(1, t->sub[0]);
+ case Tytuple:
+ for (i = 0; i < t->nsub; i++)
+ a = max(alignto(1, t->sub[i]), a);
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ a = max(alignto(1, decltype(t->sdecls[i])), a);
+ break;
+ default:
+ a = tysize(t);
+ break;
+ }
+
+ return align(sz, min(a, Ptrsz));
}
static Type *base(Type *t)
{
- assert(t->nsub == 1);
- return t->sub[0];
+ assert(t->nsub == 1);
+ return t->sub[0];
}
static Node *add(Node *a, Node *b)
{
- Node *n;
+ Node *n;
- assert(size(a) == size(b));
- n = mkexpr(a->loc, Oadd, a, b, NULL);
- n->expr.type = a->expr.type;
- return n;
+ assert(size(a) == size(b));
+ n = mkexpr(a->loc, Oadd, a, b, NULL);
+ n->expr.type = a->expr.type;
+ return n;
}
static Node *addk(Node *n, uvlong v)
{
- Node *k;
+ Node *k;
- k = mkintlit(n->loc, v);
- k->expr.type = exprtype(n);
- return add(n, k);
+ k = mkintlit(n->loc, v);
+ k->expr.type = exprtype(n);
+ return add(n, k);
}
static Node *sub(Node *a, Node *b)
{
- Node *n;
+ Node *n;
- n = mkexpr(a->loc, Osub, a, b, NULL);
- n->expr.type = a->expr.type;
- return n;
+ n = mkexpr(a->loc, Osub, a, b, NULL);
+ n->expr.type = a->expr.type;
+ return n;
}
static Node *subk(Node *n, uvlong v)
{
- Node *k;
+ Node *k;
- k = mkintlit(n->loc, v);
- k->expr.type = exprtype(n);
- return sub(n, k);
+ k = mkintlit(n->loc, v);
+ k->expr.type = exprtype(n);
+ return sub(n, k);
}
static Node *mul(Node *a, Node *b)
{
- Node *n;
+ Node *n;
- n = mkexpr(a->loc, Omul, a, b, NULL);
- n->expr.type = a->expr.type;
- return n;
+ n = mkexpr(a->loc, Omul, a, b, NULL);
+ n->expr.type = a->expr.type;
+ return n;
}
static int addressable(Simp *s, Node *a)
{
- if (a->type == Ndecl || (a->type == Nexpr && exprop(a) == Ovar))
- return hthas(s->envoff, a) || hthas(s->stkoff, a) || hthas(s->globls, a);
- else
- return stacknode(a);
+ if (a->type == Ndecl || (a->type == Nexpr && exprop(a) == Ovar))
+ return hthas(s->envoff, a) || hthas(s->stkoff, a) || hthas(s->globls, a);
+ else
+ return stacknode(a);
}
int stacknode(Node *n)
{
- if (n->type == Nexpr)
- return isstacktype(n->expr.type);
- else
- return isstacktype(n->decl.type);
+ if (n->type == Nexpr)
+ return isstacktype(n->expr.type);
+ else
+ return isstacktype(n->decl.type);
}
int floatnode(Node *n)
{
- if (n->type == Nexpr)
- return istyfloat(n->expr.type);
- else
- return istyfloat(n->decl.type);
+ if (n->type == Nexpr)
+ return istyfloat(n->expr.type);
+ else
+ return istyfloat(n->decl.type);
}
static void forcelocal(Simp *s, Node *n)
{
- assert(n->type == Ndecl || (n->type == Nexpr && exprop(n) == Ovar));
- s->stksz += size(n);
- s->stksz = align(s->stksz, min(size(n), Ptrsz));
- if (debugopt['i']) {
- dump(n, stdout);
- printf("declared at %zd, size = %zd\n", s->stksz, size(n));
- }
- htput(s->stkoff, n, itop(s->stksz));
+ assert(n->type == Ndecl || (n->type == Nexpr && exprop(n) == Ovar));
+ s->stksz += size(n);
+ s->stksz = align(s->stksz, min(size(n), Ptrsz));
+ if (debugopt['i']) {
+ dump(n, stdout);
+ printf("declared at %zd, size = %zd\n", s->stksz, size(n));
+ }
+ htput(s->stkoff, n, itop(s->stksz));
}
static void declarelocal(Simp *s, Node *n)
{
- if (stacknode(n))
- forcelocal(s, n);
+ if (stacknode(n))
+ forcelocal(s, n);
}
/* takes the address of a node, possibly converting it to
* a pointer to the base type 'bt' */
static Node *addr(Simp *s, Node *a, Type *bt)
{
- Node *n;
+ Node *n;
- n = mkexpr(a->loc, Oaddr, a, NULL);
- if (!addressable(s, a))
- forcelocal(s, a);
- if (!bt)
- n->expr.type = mktyptr(a->loc, a->expr.type);
- else
- n->expr.type = mktyptr(a->loc, bt);
- return n;
+ n = mkexpr(a->loc, Oaddr, a, NULL);
+ if (!addressable(s, a))
+ forcelocal(s, a);
+ if (!bt)
+ n->expr.type = mktyptr(a->loc, a->expr.type);
+ else
+ n->expr.type = mktyptr(a->loc, bt);
+ return n;
}
static Node *load(Node *a)
{
- Node *n;
+ Node *n;
- assert(a->expr.type->type == Typtr);
- n = mkexpr(a->loc, Oderef, a, NULL);
- n->expr.type = base(a->expr.type);
- return n;
+ assert(a->expr.type->type == Typtr);
+ n = mkexpr(a->loc, Oderef, a, NULL);
+ n->expr.type = base(a->expr.type);
+ return n;
}
static Node *deref(Node *a, Type *t)
{
- Node *n;
+ Node *n;
- assert(a->expr.type->type == Typtr);
- n = mkexpr(a->loc, Oderef, a, NULL);
- if (t)
- n->expr.type = t;
- else
- n->expr.type = base(a->expr.type);
- return n;
+ assert(a->expr.type->type == Typtr);
+ n = mkexpr(a->loc, Oderef, a, NULL);
+ if (t)
+ n->expr.type = t;
+ else
+ n->expr.type = base(a->expr.type);
+ return n;
}
static Node *set(Node *a, Node *b)
{
- Node *n;
+ Node *n;
- assert(a != NULL && b != NULL);
- assert(exprop(a) == Ovar || exprop(a) == Oderef);
- n = mkexpr(a->loc, Oset, a, b, NULL);
- n->expr.type = exprtype(a);
- return n;
+ assert(a != NULL && b != NULL);
+ assert(exprop(a) == Ovar || exprop(a) == Oderef);
+ n = mkexpr(a->loc, Oset, a, b, NULL);
+ n->expr.type = exprtype(a);
+ return n;
}
static void def(Simp *s, Node *var)
{
- Node *d;
+ Node *d;
- d = mkexpr(var->loc, Odef, var, NULL);
- d->expr.type = mktype(var->loc, Tyvoid);
- append(s, d);
+ d = mkexpr(var->loc, Odef, var, NULL);
+ d->expr.type = mktype(var->loc, Tyvoid);
+ append(s, d);
}
static Node *disp(Srcloc loc, uint v)
{
- Node *n;
+ Node *n;
- n = mkintlit(loc, v);
- n->expr.type = tyintptr;
- return n;
+ n = mkintlit(loc, v);
+ n->expr.type = tyintptr;
+ return n;
}
static Node *word(Srcloc loc, uint v)
{
- Node *n;
+ Node *n;
- n = mkintlit(loc, v);
- n->expr.type = tyword;
- return n;
+ n = mkintlit(loc, v);
+ n->expr.type = tyword;
+ return n;
}
static Node *temp(Simp *simp, Node *e)
{
- Node *t, *dcl;
+ Node *t, *dcl;
- assert(e->type == Nexpr);
- t = gentemp(e->loc, e->expr.type, &dcl);
- if (stacknode(e))
- declarelocal(simp, dcl);
- return t;
+ assert(e->type == Nexpr);
+ t = gentemp(e->loc, e->expr.type, &dcl);
+ if (stacknode(e))
+ declarelocal(simp, dcl);
+ return t;
}
static void jmp(Simp *s, Node *lbl)
{
- append(s, mkexpr(lbl->loc, Ojmp, lbl, NULL));
+ append(s, mkexpr(lbl->loc, Ojmp, lbl, NULL));
}
static void cjmp(Simp *s, Node *cond, Node *iftrue, Node *iffalse)
{
- Node *jmp;
+ Node *jmp;
- jmp = mkexpr(cond->loc, Ocjmp, cond, iftrue, iffalse, NULL);
- append(s, jmp);
+ jmp = mkexpr(cond->loc, Ocjmp, cond, iftrue, iffalse, NULL);
+ append(s, jmp);
}
static Node *slicelen(Simp *s, Node *sl)
{
- /* *(&sl + sizeof(size_t)) */
- return load(addk(addr(s, sl, tyintptr), Ptrsz));
+ /* *(&sl + sizeof(size_t)) */
+ return load(addk(addr(s, sl, tyintptr), Ptrsz));
}
Node *loadvar(Simp *s, Node *n, Node *dst)
{
- Node *p, *f, *r;
+ Node *p, *f, *r;
- if (isconstfn(n)) {
- if (dst)
- r = dst;
- else
- r = temp(s, n);
- f = getcode(s, n);
- p = addr(s, r, exprtype(n));
- assignat(s, p, Ptrsz, f);
- } else {
- r = n;
- }
- return r;
+ if (isconstfn(n)) {
+ if (dst)
+ r = dst;
+ else
+ r = temp(s, n);
+ f = getcode(s, n);
+ p = addr(s, r, exprtype(n));
+ assignat(s, p, Ptrsz, f);
+ } else {
+ r = n;
+ }
+ return r;
}
static Node *seqlen(Simp *s, Node *n, Type *ty)
{
- Node *t, *r;
+ Node *t, *r;
- if (exprtype(n)->type == Tyslice) {
- t = slicelen(s, n);
- r = simpcast(s, t, ty);
- } else if (exprtype(n)->type == Tyarray) {
- t = exprtype(n)->asize;
- r = simpcast(s, t, ty);
- } else {
- r = NULL;
- }
- return r;
+ if (exprtype(n)->type == Tyslice) {
+ t = slicelen(s, n);
+ r = simpcast(s, t, ty);
+ } else if (exprtype(n)->type == Tyarray) {
+ t = exprtype(n)->asize;
+ r = simpcast(s, t, ty);
+ } else {
+ r = NULL;
+ }
+ return r;
}
/* if foo; bar; else baz;;
* => cjmp (foo) :bar :baz */
static void simpif(Simp *s, Node *n, Node *exit)
{
- Node *l1, *l2, *l3;
- Node *iftrue, *iffalse;
-
- l1 = genlbl(n->loc);
- l2 = genlbl(n->loc);
- if (exit)
- l3 = exit;
- else
- l3 = genlbl(n->loc);
-
- iftrue = n->ifstmt.iftrue;
- iffalse = n->ifstmt.iffalse;
-
- simpcond(s, n->ifstmt.cond, l1, l2);
- simp(s, l1);
- simp(s, iftrue);
- jmp(s, l3);
- simp(s, l2);
- /* because lots of bunched up end labels are ugly,
- * coalesce them by handling 'elif'-like constructs
- * separately */
- if (iffalse && iffalse->type == Nifstmt) {
- simpif(s, iffalse, exit);
- } else {
- simp(s, iffalse);
- jmp(s, l3);
- }
-
- if (!exit)
- simp(s, l3);
+ Node *l1, *l2, *l3;
+ Node *iftrue, *iffalse;
+
+ l1 = genlbl(n->loc);
+ l2 = genlbl(n->loc);
+ if (exit)
+ l3 = exit;
+ else
+ l3 = genlbl(n->loc);
+
+ iftrue = n->ifstmt.iftrue;
+ iffalse = n->ifstmt.iffalse;
+
+ simpcond(s, n->ifstmt.cond, l1, l2);
+ simp(s, l1);
+ simp(s, iftrue);
+ jmp(s, l3);
+ simp(s, l2);
+ /* because lots of bunched up end labels are ugly,
+ * coalesce them by handling 'elif'-like constructs
+ * separately */
+ if (iffalse && iffalse->type == Nifstmt) {
+ simpif(s, iffalse, exit);
+ } else {
+ simp(s, iffalse);
+ jmp(s, l3);
+ }
+
+ if (!exit)
+ simp(s, l3);
}
/* init; while cond; body;;
@@ -401,31 +401,31 @@ static void simpif(Simp *s, Node *n, Node *exit)
*/
static void simploop(Simp *s, Node *n)
{
- Node *lbody;
- Node *lend;
- Node *lcond;
- Node *lstep;
+ Node *lbody;
+ Node *lend;
+ Node *lcond;
+ Node *lstep;
- lbody = genlbl(n->loc);
- lcond = genlbl(n->loc);
- lstep = genlbl(n->loc);
- lend = genlbl(n->loc);
+ lbody = genlbl(n->loc);
+ lcond = genlbl(n->loc);
+ lstep = genlbl(n->loc);
+ lend = genlbl(n->loc);
- lappend(&s->loopstep, &s->nloopstep, lstep);
- lappend(&s->loopexit, &s->nloopexit, lend);
+ lappend(&s->loopstep, &s->nloopstep, lstep);
+ lappend(&s->loopexit, &s->nloopexit, lend);
- simp(s, n->loopstmt.init); /* init */
- jmp(s, lcond); /* goto test */
- simp(s, lbody); /* body lbl */
- simp(s, n->loopstmt.body); /* body */
- simp(s, lstep); /* test lbl */
- simp(s, n->loopstmt.step); /* step */
- simp(s, lcond); /* test lbl */
- simpcond(s, n->loopstmt.cond, lbody, lend); /* repeat? */
- simp(s, lend); /* exit */
+ simp(s, n->loopstmt.init); /* init */
+ jmp(s, lcond); /* goto test */
+ simp(s, lbody); /* body lbl */
+ simp(s, n->loopstmt.body); /* body */
+ simp(s, lstep); /* test lbl */
+ simp(s, n->loopstmt.step); /* step */
+ simp(s, lcond); /* test lbl */
+ simpcond(s, n->loopstmt.cond, lbody, lend); /* repeat? */
+ simp(s, lend); /* exit */
- s->nloopstep--;
- s->nloopexit--;
+ s->nloopstep--;
+ s->nloopexit--;
}
/* pat; seq;
@@ -448,554 +448,554 @@ static void simploop(Simp *s, Node *n)
*/
static void simpiter(Simp *s, Node *n)
{
- Node *lbody, *lload, *lstep, *lcond, *lmatch, *lend;
- Node *idx, *len, *dcl, *seq, *val, *done;
- Node **cap, **out;
- size_t i, ncap, nout;
- Node *zero;
-
- lbody = genlbl(n->loc);
- lload = genlbl(n->loc);
- lstep = genlbl(n->loc);
- lcond = genlbl(n->loc);
- lmatch = genlbl(n->loc);
- lend = genlbl(n->loc);
-
- lappend(&s->loopstep, &s->nloopstep, lstep);
- lappend(&s->loopexit, &s->nloopexit, lend);
-
- zero = mkintlit(n->loc, 0);
- zero->expr.type = tyintptr;
-
- seq = rval(s, n->iterstmt.seq, NULL);
- idx = gentemp(n->loc, tyintptr, &dcl);
- declarelocal(s, dcl);
-
- /* setup */
- append(s, assign(s, idx, zero));
- jmp(s, lcond);
- simp(s, lbody);
-
- /* body */
- simp(s, n->iterstmt.body);
- /* step */
- simp(s, lstep);
- simp(s, assign(s, idx, addk(idx, 1)));
- /* condition */
- simp(s, lcond);
- len = seqlen(s, seq, tyintptr);
- done = mkexpr(n->loc, Olt, idx, len, NULL);
- cjmp(s, done, lmatch, lend);
- simp(s, lmatch);
- val = load(idxaddr(s, seq, idx));
-
- /* pattern match */
- out = NULL;
- nout = 0;
- cap = NULL;
- ncap = 0;
- genonematch(n->iterstmt.elt, val, lload, lstep, &out, &nout, &cap, &ncap);
- for (i = 0; i < nout; i++)
- simp(s, out[i]);
- simp(s, lload);
- for (i = 0; i < ncap; i++)
- simp(s, cap[i]);
- jmp(s, lbody);
- simp(s, lend);
-
- s->nloopstep--;
- s->nloopexit--;
+ Node *lbody, *lload, *lstep, *lcond, *lmatch, *lend;
+ Node *idx, *len, *dcl, *seq, *val, *done;
+ Node **cap, **out;
+ size_t i, ncap, nout;
+ Node *zero;
+
+ lbody = genlbl(n->loc);
+ lload = genlbl(n->loc);
+ lstep = genlbl(n->loc);
+ lcond = genlbl(n->loc);
+ lmatch = genlbl(n->loc);
+ lend = genlbl(n->loc);
+
+ lappend(&s->loopstep, &s->nloopstep, lstep);
+ lappend(&s->loopexit, &s->nloopexit, lend);
+
+ zero = mkintlit(n->loc, 0);
+ zero->expr.type = tyintptr;
+
+ seq = rval(s, n->iterstmt.seq, NULL);
+ idx = gentemp(n->loc, tyintptr, &dcl);
+ declarelocal(s, dcl);
+
+ /* setup */
+ append(s, assign(s, idx, zero));
+ jmp(s, lcond);
+ simp(s, lbody);
+
+ /* body */
+ simp(s, n->iterstmt.body);
+ /* step */
+ simp(s, lstep);
+ simp(s, assign(s, idx, addk(idx, 1)));
+ /* condition */
+ simp(s, lcond);
+ len = seqlen(s, seq, tyintptr);
+ done = mkexpr(n->loc, Olt, idx, len, NULL);
+ cjmp(s, done, lmatch, lend);
+ simp(s, lmatch);
+ val = load(idxaddr(s, seq, idx));
+
+ /* pattern match */
+ out = NULL;
+ nout = 0;
+ cap = NULL;
+ ncap = 0;
+ genonematch(n->iterstmt.elt, val, lload, lstep, &out, &nout, &cap, &ncap);
+ for (i = 0; i < nout; i++)
+ simp(s, out[i]);
+ simp(s, lload);
+ for (i = 0; i < ncap; i++)
+ simp(s, cap[i]);
+ jmp(s, lbody);
+ simp(s, lend);
+
+ s->nloopstep--;
+ s->nloopexit--;
}
static Node *uconid(Simp *s, Node *n)
{
- Ucon *uc;
+ Ucon *uc;
- n = rval(s, n, NULL);
- if (exprop(n) != Oucon)
- return load(addr(s, n, mktype(n->loc, Tyuint)));
+ n = rval(s, n, NULL);
+ if (exprop(n) != Oucon)
+ return load(addr(s, n, mktype(n->loc, Tyuint)));
- uc = finducon(exprtype(n), n->expr.args[0]);
- return word(uc->loc, uc->id);
+ uc = finducon(exprtype(n), n->expr.args[0]);
+ return word(uc->loc, uc->id);
}
static void simpblk(Simp *s, Node *n)
{
- size_t i;
+ size_t i;
- for (i = 0; i < n->block.nstmts; i++) {
- n->block.stmts[i] = fold(n->block.stmts[i], 0);
- simp(s, n->block.stmts[i]);
- }
+ for (i = 0; i < n->block.nstmts; i++) {
+ n->block.stmts[i] = fold(n->block.stmts[i], 0);
+ simp(s, n->block.stmts[i]);
+ }
}
static Node *geninitdecl(Node *init, Type *ty, Node **dcl)
{
- Node *n, *d, *r;
- char lbl[128];
+ Node *n, *d, *r;
+ char lbl[128];
- n = mkname(init->loc, genlblstr(lbl, 128, ""));
- d = mkdecl(init->loc, n, ty);
- r = mkexpr(init->loc, Ovar, n, NULL);
+ n = mkname(init->loc, genlblstr(lbl, 128, ""));
+ d = mkdecl(init->loc, n, ty);
+ r = mkexpr(init->loc, Ovar, n, NULL);
- d->decl.init = init;
- d->decl.type = ty;
- d->decl.isconst = 1;
- d->decl.isglobl = 1;
+ d->decl.init = init;
+ d->decl.type = ty;
+ d->decl.isconst = 1;
+ d->decl.isglobl = 1;
- r->expr.did = d->decl.did;
- r->expr.type = ty;
- r->expr.isconst = 1;
- if (dcl)
- *dcl = d;
- return r;
+ r->expr.did = d->decl.did;
+ r->expr.type = ty;
+ r->expr.isconst = 1;
+ if (dcl)
+ *dcl = d;
+ return r;
}
static Node *simpcode(Simp *s, Node *fn)
{
- Node *r, *d;
+ Node *r, *d;
- r = geninitdecl(fn, codetype(exprtype(fn)), &d);
- htput(s->globls, d, asmname(d));
- lappend(&file->file.stmts, &file->file.nstmts, d);
- return r;
+ r = geninitdecl(fn, codetype(exprtype(fn)), &d);
+ htput(s->globls, d, asmname(d));
+ lappend(&file->file.stmts, &file->file.nstmts, d);
+ return r;
}
static Node *simpblob(Simp *s, Node *blob)
{
- Node *r, *d;
+ Node *r, *d;
- r = geninitdecl(blob, exprtype(blob), &d);
- htput(s->globls, d, asmname(d));
- lappend(&s->blobs, &s->nblobs, d);
- return r;
+ r = geninitdecl(blob, exprtype(blob), &d);
+ htput(s->globls, d, asmname(d));
+ lappend(&s->blobs, &s->nblobs, d);
+ return r;
}
static Node *ptrsized(Simp *s, Node *v)
{
- if (size(v) == Ptrsz)
- return v;
- else if (size(v) < Ptrsz)
- v = mkexpr(v->loc, Ozwiden, v, NULL);
- else if (size(v) > Ptrsz)
- v = mkexpr(v->loc, Otrunc, v, NULL);
- v->expr.type = tyintptr;
- return v;
+ if (size(v) == Ptrsz)
+ return v;
+ else if (size(v) < Ptrsz)
+ v = mkexpr(v->loc, Ozwiden, v, NULL);
+ else if (size(v) > Ptrsz)
+ v = mkexpr(v->loc, Otrunc, v, NULL);
+ v->expr.type = tyintptr;
+ return v;
}
static Node *membaddr(Simp *s, Node *n)
{
- Node *t, *u, *r;
- Node **args;
- Type *ty;
+ Node *t, *u, *r;
+ Node **args;
+ Type *ty;
- args = n->expr.args;
- ty = tybase(exprtype(args[0]));
- if (ty->type == Typtr) {
- t = lval(s, args[0]);
- } else {
- t = addr(s, lval(s, args[0]), exprtype(n));
- }
- u = disp(n->loc, offset(args[0], args[1]));
- r = add(t, u);
- r->expr.type = mktyptr(n->loc, n->expr.type);
- return r;
+ args = n->expr.args;
+ ty = tybase(exprtype(args[0]));
+ if (ty->type == Typtr) {
+ t = lval(s, args[0]);
+ } else {
+ t = addr(s, lval(s, args[0]), exprtype(n));
+ }
+ u = disp(n->loc, offset(args[0], args[1]));
+ r = add(t, u);
+ r->expr.type = mktyptr(n->loc, n->expr.type);
+ return r;
}
static void checkidx(Simp *s, Node *len, Node *idx)
{
- Node *cmp, *die;
- Node *ok, *fail;
+ Node *cmp, *die;
+ Node *ok, *fail;
- if (!len)
- return;
- /* create expressions */
- cmp = mkexpr(idx->loc, Olt, ptrsized(s, idx), ptrsized(s, len), NULL);
- cmp->expr.type = mktype(len->loc, Tybool);
- ok = genlbl(len->loc);
- fail = genlbl(len->loc);
- die = mkexpr(idx->loc, Ocall, abortoob, NULL);
- die->expr.type = mktype(len->loc, Tyvoid);
+ if (!len)
+ return;
+ /* create expressions */
+ cmp = mkexpr(idx->loc, Olt, ptrsized(s, idx), ptrsized(s, len), NULL);
+ cmp->expr.type = mktype(len->loc, Tybool);
+ ok = genlbl(len->loc);
+ fail = genlbl(len->loc);
+ die = mkexpr(idx->loc, Ocall, abortoob, NULL);
+ die->expr.type = mktype(len->loc, Tyvoid);
- /* insert them */
- cjmp(s, cmp, ok, fail);
- append(s, fail);
- append(s, die);
- append(s, ok);
+ /* insert them */
+ cjmp(s, cmp, ok, fail);
+ append(s, fail);
+ append(s, die);
+ append(s, ok);
}
static Node *idxaddr(Simp *s, Node *seq, Node *idx)
{
- Node *a, *t, *u, *v, *w; /* temps */
- Node *r; /* result */
- Type *ty;
- size_t sz;
-
- a = rval(s, seq, NULL);
- ty = exprtype(seq)->sub[0];
- if (exprtype(seq)->type == Tyarray) {
- t = addr(s, a, ty);
- w = exprtype(a)->asize;
- } else if (seq->expr.type->type == Tyslice) {
- t = load(addr(s, a, mktyptr(seq->loc, ty)));
- w = slicelen(s, a);
- } else {
- die("Can't index type %s\n", tystr(seq->expr.type));
- }
- assert(t->expr.type->type == Typtr);
- u = rval(s, idx, NULL);
- u = ptrsized(s, u);
- checkidx(s, w, u);
- sz = tysize(ty);
- v = mul(u, disp(seq->loc, sz));
- r = add(t, v);
- return r;
+ Node *a, *t, *u, *v, *w; /* temps */
+ Node *r; /* result */
+ Type *ty;
+ size_t sz;
+
+ a = rval(s, seq, NULL);
+ ty = exprtype(seq)->sub[0];
+ if (exprtype(seq)->type == Tyarray) {
+ t = addr(s, a, ty);
+ w = exprtype(a)->asize;
+ } else if (seq->expr.type->type == Tyslice) {
+ t = load(addr(s, a, mktyptr(seq->loc, ty)));
+ w = slicelen(s, a);
+ } else {
+ die("Can't index type %s\n", tystr(seq->expr.type));
+ }
+ assert(t->expr.type->type == Typtr);
+ u = rval(s, idx, NULL);
+ u = ptrsized(s, u);
+ checkidx(s, w, u);
+ sz = tysize(ty);
+ v = mul(u, disp(seq->loc, sz));
+ r = add(t, v);
+ return r;
}
static Node *slicebase(Simp *s, Node *n, Node *off)
{
- Node *u, *v;
- Type *ty;
- int sz;
-
- u = NULL;
- ty = tybase(exprtype(n));
- switch (ty->type) {
- case Typtr: u = n; break;
- case Tyarray: u = addr(s, n, base(exprtype(n))); break;
- case Tyslice: u = load(addr(s, n, mktyptr(n->loc, base(exprtype(n))))); break;
- default: die("Unslicable type %s", tystr(n->expr.type));
- }
- /* safe: all types we allow here have a sub[0] that we want to grab */
- if (off) {
- off = ptrsized(s, rval(s, off, NULL));
- sz = tysize(n->expr.type->sub[0]);
- v = mul(off, disp(n->loc, sz));
- return add(u, v);
- } else {
- return u;
- }
+ Node *u, *v;
+ Type *ty;
+ int sz;
+
+ u = NULL;
+ ty = tybase(exprtype(n));
+ switch (ty->type) {
+ case Typtr: u = n; break;
+ case Tyarray: u = addr(s, n, base(exprtype(n))); break;
+ case Tyslice: u = load(addr(s, n, mktyptr(n->loc, base(exprtype(n))))); break;
+ default: die("Unslicable type %s", tystr(n->expr.type));
+ }
+ /* safe: all types we allow here have a sub[0] that we want to grab */
+ if (off) {
+ off = ptrsized(s, rval(s, off, NULL));
+ sz = tysize(n->expr.type->sub[0]);
+ v = mul(off, disp(n->loc, sz));
+ return add(u, v);
+ } else {
+ return u;
+ }
}
static Node *loadidx(Simp *s, Node *arr, Node *idx)
{
- Node *v, *a;
+ Node *v, *a;
- a = rval(s, arr, NULL);
- lappend(&s->idxctx, &s->nidxctx, a);
- v = deref(idxaddr(s, a, idx), NULL);
- lpop(&s->idxctx, &s->nidxctx);
- return v;
+ a = rval(s, arr, NULL);
+ lappend(&s->idxctx, &s->nidxctx, a);
+ v = deref(idxaddr(s, a, idx), NULL);
+ lpop(&s->idxctx, &s->nidxctx);
+ return v;
}
static Node *lval(Simp *s, Node *n)
{
- Node *r;
- Node **args;
-
- args = n->expr.args;
- switch (exprop(n)) {
- case Ovar: r = loadvar(s, n, NULL); break;
- case Oidx: r = loadidx(s, args[0], args[1]); break;
- case Oderef: r = deref(rval(s, args[0], NULL), NULL); break;
- case Omemb: r = rval(s, n, NULL); break;
- case Ostruct: r = rval(s, n, NULL); break;
- case Oucon: r = rval(s, n, NULL); break;
- case Oarr: r = rval(s, n, NULL); break;
- case Ogap: r = temp(s, n); break;
-
- /* not actually expressible as lvalues in syntax, but we generate them */
- case Oudata: r = rval(s, n, NULL); break;
- case Outag: r = rval(s, n, NULL); break;
- case Otupget: r = rval(s, n, NULL); break;
- default:
- fatal(n, "%s cannot be an lvalue", opstr[exprop(n)]);
- break;
- }
- return r;
+ Node *r;
+ Node **args;
+
+ args = n->expr.args;
+ switch (exprop(n)) {
+ case Ovar: r = loadvar(s, n, NULL); break;
+ case Oidx: r = loadidx(s, args[0], args[1]); break;
+ case Oderef: r = deref(rval(s, args[0], NULL), NULL); break;
+ case Omemb: r = rval(s, n, NULL); break;
+ case Ostruct: r = rval(s, n, NULL); break;
+ case Oucon: r = rval(s, n, NULL); break;
+ case Oarr: r = rval(s, n, NULL); break;
+ case Ogap: r = temp(s, n); break;
+
+ /* not actually expressible as lvalues in syntax, but we generate them */
+ case Oudata: r = rval(s, n, NULL); break;
+ case Outag: r = rval(s, n, NULL); break;
+ case Otupget: r = rval(s, n, NULL); break;
+ default:
+ fatal(n, "%s cannot be an lvalue", opstr[exprop(n)]);
+ break;
+ }
+ return r;
}
static void simpcond(Simp *s, Node *n, Node *ltrue, Node *lfalse)
{
- Node **args;
- Node *v, *lnext;
-
- args = n->expr.args;
- switch (exprop(n)) {
- case Oland:
- lnext = genlbl(n->loc);
- simpcond(s, args[0], lnext, lfalse);
- append(s, lnext);
- simpcond(s, args[1], ltrue, lfalse);
- break;
- case Olor:
- lnext = genlbl(n->loc);
- simpcond(s, args[0], ltrue, lnext);
- append(s, lnext);
- simpcond(s, args[1], ltrue, lfalse);
- break;
- case Olnot:
- simpcond(s, args[0], lfalse, ltrue);
- break;
- default:
- v = rval(s, n, NULL);
- cjmp(s, v, ltrue, lfalse);
- break;
- }
+ Node **args;
+ Node *v, *lnext;
+
+ args = n->expr.args;
+ switch (exprop(n)) {
+ case Oland:
+ lnext = genlbl(n->loc);
+ simpcond(s, args[0], lnext, lfalse);
+ append(s, lnext);
+ simpcond(s, args[1], ltrue, lfalse);
+ break;
+ case Olor:
+ lnext = genlbl(n->loc);
+ simpcond(s, args[0], ltrue, lnext);
+ append(s, lnext);
+ simpcond(s, args[1], ltrue, lfalse);
+ break;
+ case Olnot:
+ simpcond(s, args[0], lfalse, ltrue);
+ break;
+ default:
+ v = rval(s, n, NULL);
+ cjmp(s, v, ltrue, lfalse);
+ break;
+ }
}
static Node *intconvert(Simp *s, Node *from, Type *to, int issigned)
{
- Node *r;
- size_t fromsz, tosz;
+ Node *r;
+ size_t fromsz, tosz;
- fromsz = size(from);
- tosz = tysize(to);
- r = rval(s, from, NULL);
- if (fromsz > tosz) {
- r = mkexpr(from->loc, Otrunc, r, NULL);
- } else if (tosz > fromsz) {
- if (issigned)
- r = mkexpr(from->loc, Oswiden, r, NULL);
- else
- r = mkexpr(from->loc, Ozwiden, r, NULL);
- }
- r->expr.type = to;
- return r;
+ fromsz = size(from);
+ tosz = tysize(to);
+ r = rval(s, from, NULL);
+ if (fromsz > tosz) {
+ r = mkexpr(from->loc, Otrunc, r, NULL);
+ } else if (tosz > fromsz) {
+ if (issigned)
+ r = mkexpr(from->loc, Oswiden, r, NULL);
+ else
+ r = mkexpr(from->loc, Ozwiden, r, NULL);
+ }
+ r->expr.type = to;
+ return r;
}
static Node *simpcast(Simp *s, Node *val, Type *to)
{
- Node *r;
- Type *t;
-
- r = NULL;
- /* do the type conversion */
- switch (tybase(to)->type) {
- case Tybool:
- case Tyint8: case Tyint16: case Tyint32: case Tyint64:
- case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
- case Tyint: case Tyuint: case Tychar: case Tybyte:
- case Typtr:
- t = tybase(exprtype(val));
- switch (t->type) {
- /* ptr -> slice conversion is disallowed */
- case Tyslice:
- /* FIXME: we should only allow casting to pointers. */
- if (tysize(to) != Ptrsz)
- fatal(val, "bad cast from %s to %s", tystr(exprtype(val)), tystr(to));
- val = rval(s, val, NULL);
- r = slicebase(s, val, NULL);
- break;
- case Tyfunc:
- if (to->type != Typtr)
- fatal(val, "bad cast from %s to %s", tystr(exprtype(val)), tystr(to));
- r = getcode(s, val);
- break;
- /* signed conversions */
- case Tyint8: case Tyint16: case Tyint32: case Tyint64:
- case Tyint:
- r = intconvert(s, val, to, 1);
- break;
- /* unsigned conversions */
- case Tybool:
- case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
- case Tyuint: case Tychar: case Tybyte:
- case Typtr:
- r = intconvert(s, val, to, 0);
- break;
- case Tyflt32: case Tyflt64:
- if (tybase(to)->type == Typtr)
- fatal(val, "bad cast from %s to %s",
- tystr(exprtype(val)), tystr(to));
- r = mkexpr(val->loc, Oflt2int, rval(s, val, NULL), NULL);
- r->expr.type = to;
- break;
- default:
- fatal(val, "bad cast from %s to %s",
- tystr(exprtype(val)), tystr(to));
- }
- break;
- case Tyflt32: case Tyflt64:
- t = tybase(exprtype(val));
- switch (t->type) {
- case Tyint8: case Tyint16: case Tyint32: case Tyint64:
- case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
- case Tyint: case Tyuint: case Tychar: case Tybyte:
- r = mkexpr(val->loc, Oint2flt, rval(s, val, NULL), NULL);
- r->expr.type = to;
- break;
- case Tyflt32: case Tyflt64:
- r = mkexpr(val->loc, Oflt2flt, rval(s, val, NULL), NULL);
- r->expr.type = to;
- break;
- default:
- fatal(val, "bad cast from %s to %s",
- tystr(exprtype(val)), tystr(to));
- break;
- }
- break;
- /* no other destination types are handled as things stand */
- default:
- fatal(val, "bad cast from %s to %s",
- tystr(exprtype(val)), tystr(to));
- }
- return r;
+ Node *r;
+ Type *t;
+
+ r = NULL;
+ /* do the type conversion */
+ switch (tybase(to)->type) {
+ case Tybool:
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyint: case Tyuint: case Tychar: case Tybyte:
+ case Typtr:
+ t = tybase(exprtype(val));
+ switch (t->type) {
+ /* ptr -> slice conversion is disallowed */
+ case Tyslice:
+ /* FIXME: we should only allow casting to pointers. */
+ if (tysize(to) != Ptrsz)
+ fatal(val, "bad cast from %s to %s", tystr(exprtype(val)), tystr(to));
+ val = rval(s, val, NULL);
+ r = slicebase(s, val, NULL);
+ break;
+ case Tyfunc:
+ if (to->type != Typtr)
+ fatal(val, "bad cast from %s to %s", tystr(exprtype(val)), tystr(to));
+ r = getcode(s, val);
+ break;
+ /* signed conversions */
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyint:
+ r = intconvert(s, val, to, 1);
+ break;
+ /* unsigned conversions */
+ case Tybool:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyuint: case Tychar: case Tybyte:
+ case Typtr:
+ r = intconvert(s, val, to, 0);
+ break;
+ case Tyflt32: case Tyflt64:
+ if (tybase(to)->type == Typtr)
+ fatal(val, "bad cast from %s to %s",
+ tystr(exprtype(val)), tystr(to));
+ r = mkexpr(val->loc, Oflt2int, rval(s, val, NULL), NULL);
+ r->expr.type = to;
+ break;
+ default:
+ fatal(val, "bad cast from %s to %s",
+ tystr(exprtype(val)), tystr(to));
+ }
+ break;
+ case Tyflt32: case Tyflt64:
+ t = tybase(exprtype(val));
+ switch (t->type) {
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyint: case Tyuint: case Tychar: case Tybyte:
+ r = mkexpr(val->loc, Oint2flt, rval(s, val, NULL), NULL);
+ r->expr.type = to;
+ break;
+ case Tyflt32: case Tyflt64:
+ r = mkexpr(val->loc, Oflt2flt, rval(s, val, NULL), NULL);
+ r->expr.type = to;
+ break;
+ default:
+ fatal(val, "bad cast from %s to %s",
+ tystr(exprtype(val)), tystr(to));
+ break;
+ }
+ break;
+ /* no other destination types are handled as things stand */
+ default:
+ fatal(val, "bad cast from %s to %s",
+ tystr(exprtype(val)), tystr(to));
+ }
+ return r;
}
/* Simplifies taking a slice of an array, pointer,
* or other slice down to primitive pointer operations */
static Node *simpslice(Simp *s, Node *n, Node *dst)
{
- Node *t;
- Node *start, *end;
- Node *seq, *base, *sz, *len;
- Node *stbase, *stlen;
-
- if (dst)
- t = dst;
- else
- t = temp(s, n);
- seq = rval(s, n->expr.args[0], NULL);
- if (tybase(exprtype(seq))->type != Typtr)
- lappend(&s->idxctx, &s->nidxctx, seq);
- /* *(&slice) = (void*)base + off*sz */
- base = slicebase(s, seq, n->expr.args[1]);
- start = ptrsized(s, rval(s, n->expr.args[1], NULL));
- end = ptrsized(s, rval(s, n->expr.args[2], NULL));
- len = sub(end, start);
- /* we can be storing through a pointer, in the case
- * of '*foo = bar'. */
- if (tybase(exprtype(t))->type == Typtr) {
- stbase = set(simpcast(s, t, mktyptr(t->loc, tyintptr)), base);
- sz = addk(simpcast(s, t, mktyptr(t->loc, tyintptr)), Ptrsz);
- } else {
- stbase = set(deref(addr(s, t, tyintptr), NULL), base);
- sz = addk(addr(s, t, tyintptr), Ptrsz);
- }
- if (tybase(exprtype(seq))->type != Typtr)
- lpop(&s->idxctx, &s->nidxctx);
- /* *(&slice + ptrsz) = len */
- stlen = set(deref(sz, NULL), len);
- append(s, stbase);
- append(s, stlen);
- return t;
+ Node *t;
+ Node *start, *end;
+ Node *seq, *base, *sz, *len;
+ Node *stbase, *stlen;
+
+ if (dst)
+ t = dst;
+ else
+ t = temp(s, n);
+ seq = rval(s, n->expr.args[0], NULL);
+ if (tybase(exprtype(seq))->type != Typtr)
+ lappend(&s->idxctx, &s->nidxctx, seq);
+ /* *(&slice) = (void*)base + off*sz */
+ base = slicebase(s, seq, n->expr.args[1]);
+ start = ptrsized(s, rval(s, n->expr.args[1], NULL));
+ end = ptrsized(s, rval(s, n->expr.args[2], NULL));
+ len = sub(end, start);
+ /* we can be storing through a pointer, in the case
+ * of '*foo = bar'. */
+ if (tybase(exprtype(t))->type == Typtr) {
+ stbase = set(simpcast(s, t, mktyptr(t->loc, tyintptr)), base);
+ sz = addk(simpcast(s, t, mktyptr(t->loc, tyintptr)), Ptrsz);
+ } else {
+ stbase = set(deref(addr(s, t, tyintptr), NULL), base);
+ sz = addk(addr(s, t, tyintptr), Ptrsz);
+ }
+ if (tybase(exprtype(seq))->type != Typtr)
+ lpop(&s->idxctx, &s->nidxctx);
+ /* *(&slice + ptrsz) = len */
+ stlen = set(deref(sz, NULL), len);
+ append(s, stbase);
+ append(s, stlen);
+ return t;
}
static Node *visit(Simp *s, Node *n)
{
- size_t i;
- Node *r;
-
- for (i = 0; i < n->expr.nargs; i++)
- n->expr.args[i] = rval(s, n->expr.args[i], NULL);
- if (ispure(n)) {
- r = n;
- } else {
- if (exprtype(n)->type == Tyvoid) {
- r = NULL;
- append(s, n);
- } else {
- r = temp(s, n);
- append(s, set(r, n));
- }
- }
- return r;
+ size_t i;
+ Node *r;
+
+ for (i = 0; i < n->expr.nargs; i++)
+ n->expr.args[i] = rval(s, n->expr.args[i], NULL);
+ if (ispure(n)) {
+ r = n;
+ } else {
+ if (exprtype(n)->type == Tyvoid) {
+ r = NULL;
+ append(s, n);
+ } else {
+ r = temp(s, n);
+ append(s, set(r, n));
+ }
+ }
+ return r;
}
static Node *tupget(Simp *s, Node *tup, size_t idx, Node *dst)
{
- Node *plv, *prv, *sz, *stor, *dcl;
- size_t off, i;
- Type *ty;
-
- off = 0;
- ty = exprtype(tup);
- for (i = 0; i < ty->nsub; i++) {
- off = alignto(off, ty->sub[i]);
- if (i == idx)
- break;
- off += tysize(ty->sub[i]);
- }
-
- if (!dst) {
- dst = gentemp(tup->loc, ty->sub[idx], &dcl);
- if (isstacktype(ty->sub[idx]))
- declarelocal(s, dcl);
- }
- prv = add(addr(s, tup, ty->sub[i]), disp(tup->loc, off));
- if (stacknode(dst)) {
- sz = disp(dst->loc, size(dst));
- plv = addr(s, dst, exprtype(dst));
- stor = mkexpr(dst->loc, Oblit, plv, prv, sz, NULL);
- } else {
- stor = set(dst, load(prv));
- }
- append(s, stor);
- return dst;
+ Node *plv, *prv, *sz, *stor, *dcl;
+ size_t off, i;
+ Type *ty;
+
+ off = 0;
+ ty = exprtype(tup);
+ for (i = 0; i < ty->nsub; i++) {
+ off = alignto(off, ty->sub[i]);
+ if (i == idx)
+ break;
+ off += tysize(ty->sub[i]);
+ }
+
+ if (!dst) {
+ dst = gentemp(tup->loc, ty->sub[idx], &dcl);
+ if (isstacktype(ty->sub[idx]))
+ declarelocal(s, dcl);
+ }
+ prv = add(addr(s, tup, ty->sub[i]), disp(tup->loc, off));
+ if (stacknode(dst)) {
+ sz = disp(dst->loc, size(dst));
+ plv = addr(s, dst, exprtype(dst));
+ stor = mkexpr(dst->loc, Oblit, plv, prv, sz, NULL);
+ } else {
+ stor = set(dst, load(prv));
+ }
+ append(s, stor);
+ return dst;
}
/* Takes a tuple and binds the i'th element of it to the
* i'th name on the rhs of the assignment. */
static Node *destructure(Simp *s, Node *lhs, Node *rhs)
{
- Node *lv, *rv, **args;
- size_t i;
+ Node *lv, *rv, **args;
+ size_t i;
- args = lhs->expr.args;
- rhs = rval(s, rhs, NULL);
- for (i = 0; i < lhs->expr.nargs; i++) {
- lv = lval(s, args[i]);
- rv = tupget(s, rhs, i, lv);
- assert(rv == lv);
- }
+ args = lhs->expr.args;
+ rhs = rval(s, rhs, NULL);
+ for (i = 0; i < lhs->expr.nargs; i++) {
+ lv = lval(s, args[i]);
+ rv = tupget(s, rhs, i, lv);
+ assert(rv == lv);
+ }
- return NULL;
+ return NULL;
}
static Node *assign(Simp *s, Node *lhs, Node *rhs)
{
- Node *t, *u, *v, *r;
-
- if (exprop(lhs) == Otup) {
- r = destructure(s, lhs, rhs);
- } else {
- t = lval(s, lhs);
- u = rval(s, rhs, t);
-
- /* if we stored the result into t, rval() should return that,
- * so we know our work is done. */
- if (u == t) {
- r = t;
- } else if (stacknode(lhs)) {
- t = addr(s, t, exprtype(lhs));
- u = addr(s, u, exprtype(lhs));
- v = disp(lhs->loc, size(lhs));
- r = mkexpr(lhs->loc, Oblit, t, u, v, NULL);
- } else {
- r = set(t, u);
- }
- }
- return r;
+ Node *t, *u, *v, *r;
+
+ if (exprop(lhs) == Otup) {
+ r = destructure(s, lhs, rhs);
+ } else {
+ t = lval(s, lhs);
+ u = rval(s, rhs, t);
+
+ /* if we stored the result into t, rval() should return that,
+ * so we know our work is done. */
+ if (u == t) {
+ r = t;
+ } else if (stacknode(lhs)) {
+ t = addr(s, t, exprtype(lhs));
+ u = addr(s, u, exprtype(lhs));
+ v = disp(lhs->loc, size(lhs));
+ r = mkexpr(lhs->loc, Oblit, t, u, v, NULL);
+ } else {
+ r = set(t, u);
+ }
+ }
+ return r;
}
static Node *assignat(Simp *s, Node *r, size_t off, Node *val)
{
- Node *pval, *pdst;
- Node *sz;
- Node *st;
+ Node *pval, *pdst;
+ Node *sz;
+ Node *st;
- pdst = add(r, disp(val->loc, off));
+ pdst = add(r, disp(val->loc, off));
- if (stacknode(val)) {
- sz = disp(val->loc, size(val));
- pval = addr(s, val, exprtype(val));
- st = mkexpr(val->loc, Oblit, pdst, pval, sz, NULL);
- } else {
- st = set(deref(pdst, val->expr.type), val);
- }
- append(s, st);
- return r;
+ if (stacknode(val)) {
+ sz = disp(val->loc, size(val));
+ pval = addr(s, val, exprtype(val));
+ st = mkexpr(val->loc, Oblit, pdst, pval, sz, NULL);
+ } else {
+ st = set(deref(pdst, val->expr.type), val);
+ }
+ append(s, st);
+ return r;
}
/* Simplify tuple construction to a stack allocated
@@ -1004,83 +1004,83 @@ static Node *assignat(Simp *s, Node *r, size_t off, Node *val)
* head of the tuple. */
static Node *simptup(Simp *s, Node *n, Node *dst)
{
- Node **args;
- Node *r;
- size_t i, off;
+ Node **args;
+ Node *r;
+ size_t i, off;
- args = n->expr.args;
- if (!dst)
- dst = temp(s, n);
- r = addr(s, dst, exprtype(dst));
+ args = n->expr.args;
+ if (!dst)
+ dst = temp(s, n);
+ r = addr(s, dst, exprtype(dst));
- off = 0;
- for (i = 0; i < n->expr.nargs; i++) {
- off = alignto(off, exprtype(args[i]));
- assignat(s, r, off, rval(s, args[i], NULL));
- off += size(args[i]);
- }
- return dst;
+ off = 0;
+ for (i = 0; i < n->expr.nargs; i++) {
+ off = alignto(off, exprtype(args[i]));
+ assignat(s, r, off, rval(s, args[i], NULL));
+ off += size(args[i]);
+ }
+ return dst;
}
static Node *simpucon(Simp *s, Node *n, Node *dst)
{
- Node *tmp, *u, *tag, *elt, *sz;
- Node *r;
- Type *ty;
- Ucon *uc;
- size_t i;
-
- /* find the ucon we're constructing here */
- ty = tybase(n->expr.type);
- uc = NULL;
- for (i = 0; i < ty->nmemb; i++) {
- if (!strcmp(namestr(n->expr.args[0]), namestr(ty->udecls[i]->name))) {
- uc = ty->udecls[i];
- break;
- }
- }
- if (!uc)
- die("Couldn't find union constructor");
-
- if (dst)
- tmp = dst;
- else
- tmp = temp(s, n);
-
- /* Set the tag on the ucon */
- u = addr(s, tmp, mktype(n->loc, Tyuint));
- tag = mkintlit(n->loc, uc->id);
- tag->expr.type = mktype(n->loc, Tyuint);
- append(s, set(deref(u, tyword), tag));
-
-
- /* fill the value, if needed */
- if (!uc->etype)
- return tmp;
- elt = rval(s, n->expr.args[1], NULL);
- u = addk(u, Wordsz);
- 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);
- } else {
- r = set(deref(u, uc->etype), elt);
- }
- append(s, r);
- return tmp;
+ Node *tmp, *u, *tag, *elt, *sz;
+ Node *r;
+ Type *ty;
+ Ucon *uc;
+ size_t i;
+
+ /* find the ucon we're constructing here */
+ ty = tybase(n->expr.type);
+ uc = NULL;
+ for (i = 0; i < ty->nmemb; i++) {
+ if (!strcmp(namestr(n->expr.args[0]), namestr(ty->udecls[i]->name))) {
+ uc = ty->udecls[i];
+ break;
+ }
+ }
+ if (!uc)
+ die("Couldn't find union constructor");
+
+ if (dst)
+ tmp = dst;
+ else
+ tmp = temp(s, n);
+
+ /* Set the tag on the ucon */
+ u = addr(s, tmp, mktype(n->loc, Tyuint));
+ tag = mkintlit(n->loc, uc->id);
+ tag->expr.type = mktype(n->loc, Tyuint);
+ append(s, set(deref(u, tyword), tag));
+
+
+ /* fill the value, if needed */
+ if (!uc->etype)
+ return tmp;
+ elt = rval(s, n->expr.args[1], NULL);
+ u = addk(u, Wordsz);
+ 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);
+ } else {
+ r = set(deref(u, uc->etype), elt);
+ }
+ append(s, r);
+ return tmp;
}
static Node *simpuget(Simp *s, Node *n, Node *dst)
{
- Node *u, *p, *l;
+ Node *u, *p, *l;
- if (!dst)
- dst = temp(s, n);
- u = rval(s, n->expr.args[0], NULL);
- p = addk(addr(s, u, exprtype(n)), Wordsz);
- l = assign(s, dst, load(p));
- append(s, l);
- return dst;
+ if (!dst)
+ dst = temp(s, n);
+ u = rval(s, n->expr.args[0], NULL);
+ p = addk(addr(s, u, exprtype(n)), Wordsz);
+ l = assign(s, dst, load(p));
+ append(s, l);
+ return dst;
}
/* simplifies
@@ -1094,583 +1094,583 @@ static Node *simpuget(Simp *s, Node *n, Node *dst)
*/
static Node *simplazy(Simp *s, Node *n)
{
- Node *r, *t, *u;
- Node *ltrue, *lfalse, *ldone;
+ Node *r, *t, *u;
+ Node *ltrue, *lfalse, *ldone;
- /* set up temps and labels */
- r = temp(s, n);
- ltrue = genlbl(n->loc);
- lfalse = genlbl(n->loc);
- ldone = genlbl(n->loc);
+ /* set up temps and labels */
+ r = temp(s, n);
+ ltrue = genlbl(n->loc);
+ lfalse = genlbl(n->loc);
+ ldone = genlbl(n->loc);
- /* simp the conditional */
- simpcond(s, n, ltrue, lfalse);
+ /* simp the conditional */
+ simpcond(s, n, ltrue, lfalse);
- /* if true */
- append(s, ltrue);
- u = mkexpr(n->loc, Olit, mkbool(n->loc, 1), NULL);
- u->expr.type = mktype(n->loc, Tybool);
- t = set(r, u);
- append(s, t);
- jmp(s, ldone);
+ /* if true */
+ append(s, ltrue);
+ u = mkexpr(n->loc, Olit, mkbool(n->loc, 1), NULL);
+ u->expr.type = mktype(n->loc, Tybool);
+ t = set(r, u);
+ append(s, t);
+ jmp(s, ldone);
- /* if false */
- append(s, lfalse);
- u = mkexpr(n->loc, Olit, mkbool(n->loc, 0), NULL);
- u->expr.type = mktype(n->loc, Tybool);
- t = set(r, u);
- append(s, t);
- jmp(s, ldone);
+ /* if false */
+ append(s, lfalse);
+ u = mkexpr(n->loc, Olit, mkbool(n->loc, 0), NULL);
+ u->expr.type = mktype(n->loc, Tybool);
+ t = set(r, u);
+ append(s, t);
+ jmp(s, ldone);
- /* finish */
- append(s, ldone);
- return r;
+ /* finish */
+ append(s, ldone);
+ return r;
}
static Node *comparecomplex(Simp *s, Node *n, Op op)
{
- fatal(n, "Complex comparisons not yet supported\n");
- return NULL;
+ fatal(n, "Complex comparisons not yet supported\n");
+ return NULL;
}
static Node *compare(Simp *s, Node *n, int fields)
{
- const Op cmpmap[Numops][3] = {
- [Oeq] = {Oeq, Oueq, Ofeq},
- [One] = {One, Oune, Ofne},
- [Ogt] = {Ogt, Ougt, Ofgt},
- [Oge] = {Oge, Ouge, Ofge},
- [Olt] = {Olt, Oult, Oflt},
- [Ole] = {Ole, Oule, Ofle}
- };
- Node *r;
- Op newop;
-
- newop = Obad;
- if (istysigned(tybase(exprtype(n->expr.args[0]))))
- newop = cmpmap[n->expr.op][0];
- else if (istyunsigned(tybase(exprtype(n->expr.args[0]))))
- newop = cmpmap[n->expr.op][1];
- else if (istyfloat(tybase(exprtype(n->expr.args[0]))))
- newop = cmpmap[n->expr.op][2];
-
- if (newop != Obad) {
- n->expr.op = newop;
- r = visit(s, n);
- } else if (fields) {
- r = comparecomplex(s, n, exprop(n));
- } else {
- fatal(n, "unsupported comparison on values");
- }
- return r;
+ const Op cmpmap[Numops][3] = {
+ [Oeq] = {Oeq, Oueq, Ofeq},
+ [One] = {One, Oune, Ofne},
+ [Ogt] = {Ogt, Ougt, Ofgt},
+ [Oge] = {Oge, Ouge, Ofge},
+ [Olt] = {Olt, Oult, Oflt},
+ [Ole] = {Ole, Oule, Ofle}
+ };
+ Node *r;
+ Op newop;
+
+ newop = Obad;
+ if (istysigned(tybase(exprtype(n->expr.args[0]))))
+ newop = cmpmap[n->expr.op][0];
+ else if (istyunsigned(tybase(exprtype(n->expr.args[0]))))
+ newop = cmpmap[n->expr.op][1];
+ else if (istyfloat(tybase(exprtype(n->expr.args[0]))))
+ newop = cmpmap[n->expr.op][2];
+
+ if (newop != Obad) {
+ n->expr.op = newop;
+ r = visit(s, n);
+ } else if (fields) {
+ r = comparecomplex(s, n, exprop(n));
+ } else {
+ fatal(n, "unsupported comparison on values");
+ }
+ return r;
}
static Node *vatypeinfo(Simp *s, Node *n)
{
- Node *ti, *tp, *td, *tn;
- Type *ft, *vt, **st;
- size_t nst, i;
- char buf[1024];
-
- st = NULL;
- nst = 0;
- ft = exprtype(n->expr.args[0]);
- /* The structure of ft->sub:
- * [return, normal, args, ...]
- *
- * The structure of n->expr.sub:
- * [fn, normal, args, , variadic, args]
- *
- * We want to start at variadic, so we want
- * to count from ft->nsub - 1, up to n->expr.nsub.
- */
- for (i = ft->nsub - 1; i < n->expr.nargs; i++)
- lappend(&st, &nst, exprtype(n->expr.args[i]));
- vt = mktytuple(n->loc, st, nst);
- vt->isreflect = 1;
-
- /* make the decl */
- tn = mkname(Zloc, tydescid(buf, sizeof buf, vt));
- td = mkdecl(Zloc, tn, mktype(n->loc, Tybyte));
- td->decl.isglobl = 1;
- td->decl.isconst = 1;
- td->decl.ishidden = 1;
-
- /* and the var */
- ti = mkexpr(Zloc, Ovar, tn, NULL);
- ti->expr.type = td->decl.type;
- ti->expr.did = td->decl.did;
-
- /* and the pointer */
- tp = mkexpr(Zloc, Oaddr, ti, NULL);
- tp->expr.type = mktyptr(n->loc, td->decl.type);
-
- htput(s->globls, td, asmname(td));
- return tp;
+ Node *ti, *tp, *td, *tn;
+ Type *ft, *vt, **st;
+ size_t nst, i;
+ char buf[1024];
+
+ st = NULL;
+ nst = 0;
+ ft = exprtype(n->expr.args[0]);
+ /* The structure of ft->sub:
+ * [return, normal, args, ...]
+ *
+ * The structure of n->expr.sub:
+ * [fn, normal, args, , variadic, args]
+ *
+ * We want to start at variadic, so we want
+ * to count from ft->nsub - 1, up to n->expr.nsub.
+ */
+ for (i = ft->nsub - 1; i < n->expr.nargs; i++)
+ lappend(&st, &nst, exprtype(n->expr.args[i]));
+ vt = mktytuple(n->loc, st, nst);
+ vt->isreflect = 1;
+
+ /* make the decl */
+ tn = mkname(Zloc, tydescid(buf, sizeof buf, vt));
+ td = mkdecl(Zloc, tn, mktype(n->loc, Tybyte));
+ td->decl.isglobl = 1;
+ td->decl.isconst = 1;
+ td->decl.ishidden = 1;
+
+ /* and the var */
+ ti = mkexpr(Zloc, Ovar, tn, NULL);
+ ti->expr.type = td->decl.type;
+ ti->expr.did = td->decl.did;
+
+ /* and the pointer */
+ tp = mkexpr(Zloc, Oaddr, ti, NULL);
+ tp->expr.type = mktyptr(n->loc, td->decl.type);
+
+ htput(s->globls, td, asmname(td));
+ return tp;
}
static Node *capture(Simp *s, Node *n, Node *dst)
{
- Node *fn, *t, *f, *e, *val, *dcl, *fp, *envsz;
- size_t nenv, nenvt, off, i;
- Type **envt;
- Node **env;
-
- f = simpcode(s, n);
- fn = n->expr.args[0];
- fn = fn->lit.fnval;
- if (!dst) {
- dst = gentemp(n->loc, closuretype(exprtype(f)), &dcl);
- forcelocal(s, dcl);
- }
- fp = addr(s, dst, exprtype(dst));
-
- env = getclosure(fn->func.scope, &nenv);
- if (env) {
- /* 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);
-
- /* make the tuple that will hold the environment */
- envt = NULL;
- nenvt = 0;
- /* reserve space for size */
- lappend(&envt, &nenvt, tyintptr);
- for (i = 0; i < nenv; i++)
- lappend(&envt, &nenvt, decltype(env[i]));
-
- t = gentemp(n->loc, mktytuple(n->loc, envt, nenvt), &dcl);
- forcelocal(s, dcl);
- e = addr(s, t, exprtype(t));
-
- off = Ptrsz; /* we start with the size of the env */
- for (i = 0; i < nenv; i++) {
- off = alignto(off, decltype(env[i]));
- val = mkexpr(n->loc, Ovar, env[i]->decl.name, NULL);
- val->expr.type = env[i]->decl.type;
- val->expr.did = env[i]->decl.did;
- assignat(s, e, off, rval(s, val, NULL));
- off += size(env[i]);
- }
- free(env);
- envsz = mkintlit(n->loc, off);
- envsz->expr.type = tyintptr;
- assignat(s, e, 0, envsz);
- assignat(s, fp, 0, e);
- }
- assignat(s, fp, Ptrsz, f);
- return dst;
+ Node *fn, *t, *f, *e, *val, *dcl, *fp, *envsz;
+ size_t nenv, nenvt, off, i;
+ Type **envt;
+ Node **env;
+
+ f = simpcode(s, n);
+ fn = n->expr.args[0];
+ fn = fn->lit.fnval;
+ if (!dst) {
+ dst = gentemp(n->loc, closuretype(exprtype(f)), &dcl);
+ forcelocal(s, dcl);
+ }
+ fp = addr(s, dst, exprtype(dst));
+
+ env = getclosure(fn->func.scope, &nenv);
+ if (env) {
+ /* 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);
+
+ /* make the tuple that will hold the environment */
+ envt = NULL;
+ nenvt = 0;
+ /* reserve space for size */
+ lappend(&envt, &nenvt, tyintptr);
+ for (i = 0; i < nenv; i++)
+ lappend(&envt, &nenvt, decltype(env[i]));
+
+ t = gentemp(n->loc, mktytuple(n->loc, envt, nenvt), &dcl);
+ forcelocal(s, dcl);
+ e = addr(s, t, exprtype(t));
+
+ off = Ptrsz; /* we start with the size of the env */
+ for (i = 0; i < nenv; i++) {
+ off = alignto(off, decltype(env[i]));
+ val = mkexpr(n->loc, Ovar, env[i]->decl.name, NULL);
+ val->expr.type = env[i]->decl.type;
+ val->expr.did = env[i]->decl.did;
+ assignat(s, e, off, rval(s, val, NULL));
+ off += size(env[i]);
+ }
+ free(env);
+ envsz = mkintlit(n->loc, off);
+ envsz->expr.type = tyintptr;
+ assignat(s, e, 0, envsz);
+ assignat(s, fp, 0, e);
+ }
+ assignat(s, fp, Ptrsz, f);
+ return dst;
}
static Node *getenvptr(Simp *s, Node *n)
{
- assert(tybase(exprtype(n))->type == Tyfunc);
- return load(addr(s, n, tyintptr));
+ assert(tybase(exprtype(n))->type == Tyfunc);
+ return load(addr(s, n, tyintptr));
}
static Node *getcode(Simp *s, Node *n)
{
- Node *r, *p, *d;
- Type *ty;
+ Node *r, *p, *d;
+ Type *ty;
- 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 {
- ty = tybase(exprtype(n));
- assert(ty->type == Tyfunc);
- p = addr(s, rval(s, n, NULL), codetype(ty));
- r = load(addk(p, Ptrsz));
- }
- return r;
+ 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 {
+ ty = tybase(exprtype(n));
+ assert(ty->type == Tyfunc);
+ p = addr(s, rval(s, n, NULL), codetype(ty));
+ r = load(addk(p, Ptrsz));
+ }
+ return r;
}
static Node *simpcall(Simp *s, Node *n, Node *dst)
{
- Node *r, *call, *fn;
- size_t i, nargs;
- Node **args;
- Type *ft;
- Op op;
-
- /* NB: If we called rval() on a const function, , we would end up with
- a stack allocated closure. We don't want to do this. */
- fn = n->expr.args[0];
- if (!isconstfn(fn))
- fn = rval(s, fn, NULL);
- ft = tybase(exprtype(fn));
- if (exprtype(n)->type == Tyvoid)
- r = NULL;
- else if (isstacktype(exprtype(n)) && dst)
- r = dst;
- else
- r = temp(s, n);
-
- args = NULL;
- nargs = 0;
- op = Ocall;
- lappend(&args, &nargs, getcode(s, fn));
- if (!isconstfn(fn)) {
- op = Ocallind;
- lappend(&args, &nargs, getenvptr(s, fn));
- }
-
- if (exprtype(n)->type != Tyvoid && isstacktype(exprtype(n)))
- lappend(&args, &nargs, addr(s, r, exprtype(n)));
-
- for (i = 1; i < n->expr.nargs; i++) {
- if (i < ft->nsub && tybase(ft->sub[i])->type == Tyvalist)
- lappend(&args, &nargs, vatypeinfo(s, n));
- lappend(&args, &nargs, rval(s, n->expr.args[i], NULL));
- if (exprop(n->expr.args[i]) == Oaddr)
- if (exprop(n->expr.args[i]->expr.args[0]) == Ovar)
- def(s, n->expr.args[i]->expr.args[0]);
- }
- if (i < ft->nsub && tybase(ft->sub[i])->type == Tyvalist)
- lappend(&args, &nargs, vatypeinfo(s, n));
-
- if (r)
- def(s, r);
-
- call = mkexprl(n->loc, op, args, nargs);
- call->expr.type = exprtype(n);
- if (r && !isstacktype(exprtype(n))) {
- append(s, set(r, call));
- } else {
- append(s, call);
- }
- return r;
+ Node *r, *call, *fn;
+ size_t i, nargs;
+ Node **args;
+ Type *ft;
+ Op op;
+
+ /* NB: If we called rval() on a const function, , we would end up with
+ a stack allocated closure. We don't want to do this. */
+ fn = n->expr.args[0];
+ if (!isconstfn(fn))
+ fn = rval(s, fn, NULL);
+ ft = tybase(exprtype(fn));
+ if (exprtype(n)->type == Tyvoid)
+ r = NULL;
+ else if (isstacktype(exprtype(n)) && dst)
+ r = dst;
+ else
+ r = temp(s, n);
+
+ args = NULL;
+ nargs = 0;
+ op = Ocall;
+ lappend(&args, &nargs, getcode(s, fn));
+ if (!isconstfn(fn)) {
+ op = Ocallind;
+ lappend(&args, &nargs, getenvptr(s, fn));
+ }
+
+ if (exprtype(n)->type != Tyvoid && isstacktype(exprtype(n)))
+ lappend(&args, &nargs, addr(s, r, exprtype(n)));
+
+ for (i = 1; i < n->expr.nargs; i++) {
+ if (i < ft->nsub && tybase(ft->sub[i])->type == Tyvalist)
+ lappend(&args, &nargs, vatypeinfo(s, n));
+ lappend(&args, &nargs, rval(s, n->expr.args[i], NULL));
+ if (exprop(n->expr.args[i]) == Oaddr)
+ if (exprop(n->expr.args[i]->expr.args[0]) == Ovar)
+ def(s, n->expr.args[i]->expr.args[0]);
+ }
+ if (i < ft->nsub && tybase(ft->sub[i])->type == Tyvalist)
+ lappend(&args, &nargs, vatypeinfo(s, n));
+
+ if (r)
+ def(s, r);
+
+ call = mkexprl(n->loc, op, args, nargs);
+ call->expr.type = exprtype(n);
+ if (r && !isstacktype(exprtype(n))) {
+ append(s, set(r, call));
+ } else {
+ append(s, call);
+ }
+ return r;
}
static Node *rval(Simp *s, Node *n, Node *dst)
{
- Node *t, *u, *v; /* temporary nodes */
- Node *r; /* expression result */
- Node **args;
- size_t i;
- Type *ty;
-
- const Op fusedmap[Numops] = {
- [Oaddeq] = Oadd,
- [Osubeq] = Osub,
- [Omuleq] = Omul,
- [Odiveq] = Odiv,
- [Omodeq] = Omod,
- [Oboreq] = Obor,
- [Obandeq] = Oband,
- [Obxoreq] = Obxor,
- [Obsleq] = Obsl,
- [Obsreq] = Obsr,
- };
-
- r = NULL;
- args = n->expr.args;
- switch (exprop(n)) {
- case Olor: case Oland:
- r = simplazy(s, n);
- break;
- case Osize:
- r = mkintlit(n->loc, size(args[0]));
- r->expr.type = exprtype(n);
- break;
- case Oslice:
- r = simpslice(s, n, dst);
- break;
- case Oidx:
- t = rval(s, n->expr.args[0], NULL);
- lappend(&s->idxctx, &s->nidxctx, t);
- u = idxaddr(s, t, n->expr.args[1]);
- lpop(&s->idxctx, &s->nidxctx);
- r = load(u);
- break;
- /* array.len slice.len are magic 'virtual' members.
- * they need to be special cased. */
- case Omemb:
- if (exprtype(args[0])->type == Tyslice || exprtype(args[0])->type == Tyarray) {
- r = seqlen(s, args[0], exprtype(n));
- } else {
- t = membaddr(s, n);
- r = load(t);
- }
- break;
- case Oucon:
- r = simpucon(s, n, dst);
- break;
- case Outag:
- r = uconid(s, args[0]);
- break;
- case Oudata:
- r = simpuget(s, n, dst);
- break;
- case Otup:
- r = simptup(s, n, dst);
- break;
- case Oarr:
- if (!dst)
- dst = temp(s, n);
- t = addr(s, dst, exprtype(dst));
- for (i = 0; i < n->expr.nargs; i++)
- assignat(s, t, size(n->expr.args[i])*i, rval(s, n->expr.args[i], NULL));
- r = dst;
- break;
- case Ostruct:
- if (!dst)
- dst = temp(s, n);
- u = mkexpr(dst->loc, Odef, dst, NULL);
- u->expr.type = mktype(u->loc, Tyvoid);
- append(s, u);
- t = addr(s, dst, exprtype(dst));
- ty = exprtype(n);
- /* we only need to clear if we don't have things fully initialized */
- if (tybase(ty)->nmemb != n->expr.nargs)
- append(s, mkexpr(n->loc, Oclear, t, mkintlit(n->loc, size(n)), NULL));
- for (i = 0; i < n->expr.nargs; i++)
- assignat(s, t, offset(n, n->expr.args[i]->expr.idx), rval(s, n->expr.args[i], NULL));
- r = dst;
- break;
- case Ocast:
- r = simpcast(s, args[0], exprtype(n));
- break;
-
- /* fused ops:
- * foo ?= blah
- * =>
- * foo = foo ? blah*/
- case Oaddeq: case Osubeq: case Omuleq: case Odiveq: case Omodeq:
- case Oboreq: case Obandeq: case Obxoreq: case Obsleq: case Obsreq:
- assert(fusedmap[exprop(n)] != Obad);
- u = lval(s, args[0]);
- v = rval(s, args[1], NULL);
- v = mkexpr(n->loc, fusedmap[exprop(n)], u, v, NULL);
- v->expr.type = u->expr.type;
- r = set(u, v);
- break;
-
- /* ++expr(x)
- * => args[0] = args[0] + 1
- * expr(x) */
- case Opreinc:
- v = assign(s, args[0], addk(args[0], 1));
- append(s, v);
- r = rval(s, args[0], NULL);
- break;
- case Opredec:
- v = assign(s, args[0], subk(args[0], 1));
- append(s, v);
- r = rval(s, args[0], NULL);
- break;
-
- /* expr(x++)
- * => expr
- * x = x + 1
- */
- case Opostinc:
- r = lval(s, args[0]);
- t = assign(s, r, addk(r, 1));
- lappend(&s->incqueue, &s->nqueue, t);
- break;
- case Opostdec:
- r = lval(s, args[0]);
- t = assign(s, r, subk(r, 1));
- lappend(&s->incqueue, &s->nqueue, t);
- break;
- case Olit:
- switch (args[0]->lit.littype) {
- case Lchr: case Lbool: case Llbl:
- r = n;
- break;
- case Lint:
- /* we can only have up to 4 byte immediates, but they
- * can be moved into 64 bit regs */
- if ((uint64_t)args[0]->lit.intval < 0x7fffffffULL)
- r = n;
- else
- r = simpblob(s, n);
- break;
- case Lstr: case Lflt:
- r = simpblob(s, n);
- break;
- case Lfunc:
- r = capture(s, n, dst);
- break;
- }
- break;
- case Ovar:
- r = loadvar(s, n, dst);
- break;
- case Oidxlen:
- if (s->nidxctx == 0)
- fatal(n, "'$' undefined outside of index or slice expression");
- return seqlen(s, s->idxctx[s->nidxctx - 1], exprtype(n));
- break;
- case Ogap:
- fatal(n, "'_' may not be an rvalue");
- break;
- case Oret:
- if (s->isbigret) {
- t = rval(s, args[0], NULL);
- t = addr(s, t, exprtype(args[0]));
- u = disp(n->loc, size(args[0]));
- v = mkexpr(n->loc, Oblit, s->ret, t, u, NULL);
- append(s, v);
- } else if (n->expr.nargs && n->expr.args[0]) {
- t = s->ret;
- /* void calls return nothing */
- if (t) {
- t = set(t, rval(s, args[0], NULL));
- append(s, t);
- }
- }
- /* drain the increment queue before we return */
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
- lfree(&s->incqueue, &s->nqueue);
- append(s, mkexpr(n->loc, Oret, NULL));
- break;
- case Oasn:
- r = assign(s, args[0], args[1]);
- break;
- case Ocall:
- r = simpcall(s, n, dst);
- break;
- case Oaddr:
- t = lval(s, args[0]);
- if (exprop(t) == Ovar) /* Ovar is the only one that doesn't return Oderef(Oaddr(...)) */
- r = addr(s, t, exprtype(t));
- else
- r = t->expr.args[0];
- break;
- case Oneg:
- if (istyfloat(exprtype(n))) {
- t =mkfloat(n->loc, -1.0);
- u = mkexpr(n->loc, Olit, t, NULL);
- t->lit.type = n->expr.type;
- u->expr.type = n->expr.type;
- v = simpblob(s, u);
- r = mkexpr(n->loc, Ofmul, v, rval(s, args[0], NULL), NULL);
- r->expr.type = n->expr.type;
- } else {
- r = visit(s, n);
- }
- break;
- case Obreak:
- if (s->nloopexit == 0)
- fatal(n, "trying to break when not in loop");
- jmp(s, s->loopexit[s->nloopexit - 1]);
- break;
- case Ocontinue:
- if (s->nloopstep == 0)
- fatal(n, "trying to continue when not in loop");
- jmp(s, s->loopstep[s->nloopstep - 1]);
- break;
- case Oeq: case One:
- r = compare(s, n, 1);
- break;
- case Ogt: case Oge: case Olt: case Ole:
- r = compare(s, n, 0);
- break;
- case Otupget:
- assert(exprop(args[1]) == Olit);
- i = args[1]->expr.args[0]->lit.intval;
- t = rval(s, args[0], NULL);
- r = tupget(s, t, i, dst);
- break;
- case Obad:
- die("bad operator");
- break;
- default:
- if (istyfloat(exprtype(n))) {
- switch (exprop(n)) {
- case Oadd: n->expr.op = Ofadd; break;
- case Osub: n->expr.op = Ofsub; break;
- case Omul: n->expr.op = Ofmul; break;
- case Odiv: n->expr.op = Ofdiv; break;
- default: break;
- }
- }
- r = visit(s, n);
- break;
- }
- return r;
+ Node *t, *u, *v; /* temporary nodes */
+ Node *r; /* expression result */
+ Node **args;
+ size_t i;
+ Type *ty;
+
+ const Op fusedmap[Numops] = {
+ [Oaddeq] = Oadd,
+ [Osubeq] = Osub,
+ [Omuleq] = Omul,
+ [Odiveq] = Odiv,
+ [Omodeq] = Omod,
+ [Oboreq] = Obor,
+ [Obandeq] = Oband,
+ [Obxoreq] = Obxor,
+ [Obsleq] = Obsl,
+ [Obsreq] = Obsr,
+ };
+
+ r = NULL;
+ args = n->expr.args;
+ switch (exprop(n)) {
+ case Olor: case Oland:
+ r = simplazy(s, n);
+ break;
+ case Osize:
+ r = mkintlit(n->loc, size(args[0]));
+ r->expr.type = exprtype(n);
+ break;
+ case Oslice:
+ r = simpslice(s, n, dst);
+ break;
+ case Oidx:
+ t = rval(s, n->expr.args[0], NULL);
+ lappend(&s->idxctx, &s->nidxctx, t);
+ u = idxaddr(s, t, n->expr.args[1]);
+ lpop(&s->idxctx, &s->nidxctx);
+ r = load(u);
+ break;
+ /* array.len slice.len are magic 'virtual' members.
+ * they need to be special cased. */
+ case Omemb:
+ if (exprtype(args[0])->type == Tyslice || exprtype(args[0])->type == Tyarray) {
+ r = seqlen(s, args[0], exprtype(n));
+ } else {
+ t = membaddr(s, n);
+ r = load(t);
+ }
+ break;
+ case Oucon:
+ r = simpucon(s, n, dst);
+ break;
+ case Outag:
+ r = uconid(s, args[0]);
+ break;
+ case Oudata:
+ r = simpuget(s, n, dst);
+ break;
+ case Otup:
+ r = simptup(s, n, dst);
+ break;
+ case Oarr:
+ if (!dst)
+ dst = temp(s, n);
+ t = addr(s, dst, exprtype(dst));
+ for (i = 0; i < n->expr.nargs; i++)
+ assignat(s, t, size(n->expr.args[i])*i, rval(s, n->expr.args[i], NULL));
+ r = dst;
+ break;
+ case Ostruct:
+ if (!dst)
+ dst = temp(s, n);
+ u = mkexpr(dst->loc, Odef, dst, NULL);
+ u->expr.type = mktype(u->loc, Tyvoid);
+ append(s, u);
+ t = addr(s, dst, exprtype(dst));
+ ty = exprtype(n);
+ /* we only need to clear if we don't have things fully initialized */
+ if (tybase(ty)->nmemb != n->expr.nargs)
+ append(s, mkexpr(n->loc, Oclear, t, mkintlit(n->loc, size(n)), NULL));
+ for (i = 0; i < n->expr.nargs; i++)
+ assignat(s, t, offset(n, n->expr.args[i]->expr.idx), rval(s, n->expr.args[i], NULL));
+ r = dst;
+ break;
+ case Ocast:
+ r = simpcast(s, args[0], exprtype(n));
+ break;
+
+ /* fused ops:
+ * foo ?= blah
+ * =>
+ * foo = foo ? blah*/
+ case Oaddeq: case Osubeq: case Omuleq: case Odiveq: case Omodeq:
+ case Oboreq: case Obandeq: case Obxoreq: case Obsleq: case Obsreq:
+ assert(fusedmap[exprop(n)] != Obad);
+ u = lval(s, args[0]);
+ v = rval(s, args[1], NULL);
+ v = mkexpr(n->loc, fusedmap[exprop(n)], u, v, NULL);
+ v->expr.type = u->expr.type;
+ r = set(u, v);
+ break;
+
+ /* ++expr(x)
+ * => args[0] = args[0] + 1
+ * expr(x) */
+ case Opreinc:
+ v = assign(s, args[0], addk(args[0], 1));
+ append(s, v);
+ r = rval(s, args[0], NULL);
+ break;
+ case Opredec:
+ v = assign(s, args[0], subk(args[0], 1));
+ append(s, v);
+ r = rval(s, args[0], NULL);
+ break;
+
+ /* expr(x++)
+ * => expr
+ * x = x + 1
+ */
+ case Opostinc:
+ r = lval(s, args[0]);
+ t = assign(s, r, addk(r, 1));
+ lappend(&s->incqueue, &s->nqueue, t);
+ break;
+ case Opostdec:
+ r = lval(s, args[0]);
+ t = assign(s, r, subk(r, 1));
+ lappend(&s->incqueue, &s->nqueue, t);
+ break;
+ case Olit:
+ switch (args[0]->lit.littype) {
+ case Lchr: case Lbool: case Llbl:
+ r = n;
+ break;
+ case Lint:
+ /* we can only have up to 4 byte immediates, but they
+ * can be moved into 64 bit regs */
+ if ((uint64_t)args[0]->lit.intval < 0x7fffffffULL)
+ r = n;
+ else
+ r = simpblob(s, n);
+ break;
+ case Lstr: case Lflt:
+ r = simpblob(s, n);
+ break;
+ case Lfunc:
+ r = capture(s, n, dst);
+ break;
+ }
+ break;
+ case Ovar:
+ r = loadvar(s, n, dst);
+ break;
+ case Oidxlen:
+ if (s->nidxctx == 0)
+ fatal(n, "'$' undefined outside of index or slice expression");
+ return seqlen(s, s->idxctx[s->nidxctx - 1], exprtype(n));
+ break;
+ case Ogap:
+ fatal(n, "'_' may not be an rvalue");
+ break;
+ case Oret:
+ if (s->isbigret) {
+ t = rval(s, args[0], NULL);
+ t = addr(s, t, exprtype(args[0]));
+ u = disp(n->loc, size(args[0]));
+ v = mkexpr(n->loc, Oblit, s->ret, t, u, NULL);
+ append(s, v);
+ } else if (n->expr.nargs && n->expr.args[0]) {
+ t = s->ret;
+ /* void calls return nothing */
+ if (t) {
+ t = set(t, rval(s, args[0], NULL));
+ append(s, t);
+ }
+ }
+ /* drain the increment queue before we return */
+ for (i = 0; i < s->nqueue; i++)
+ append(s, s->incqueue[i]);
+ lfree(&s->incqueue, &s->nqueue);
+ append(s, mkexpr(n->loc, Oret, NULL));
+ break;
+ case Oasn:
+ r = assign(s, args[0], args[1]);
+ break;
+ case Ocall:
+ r = simpcall(s, n, dst);
+ break;
+ case Oaddr:
+ t = lval(s, args[0]);
+ if (exprop(t) == Ovar) /* Ovar is the only one that doesn't return Oderef(Oaddr(...)) */
+ r = addr(s, t, exprtype(t));
+ else
+ r = t->expr.args[0];
+ break;
+ case Oneg:
+ if (istyfloat(exprtype(n))) {
+ t =mkfloat(n->loc, -1.0);
+ u = mkexpr(n->loc, Olit, t, NULL);
+ t->lit.type = n->expr.type;
+ u->expr.type = n->expr.type;
+ v = simpblob(s, u);
+ r = mkexpr(n->loc, Ofmul, v, rval(s, args[0], NULL), NULL);
+ r->expr.type = n->expr.type;
+ } else {
+ r = visit(s, n);
+ }
+ break;
+ case Obreak:
+ if (s->nloopexit == 0)
+ fatal(n, "trying to break when not in loop");
+ jmp(s, s->loopexit[s->nloopexit - 1]);
+ break;
+ case Ocontinue:
+ if (s->nloopstep == 0)
+ fatal(n, "trying to continue when not in loop");
+ jmp(s, s->loopstep[s->nloopstep - 1]);
+ break;
+ case Oeq: case One:
+ r = compare(s, n, 1);
+ break;
+ case Ogt: case Oge: case Olt: case Ole:
+ r = compare(s, n, 0);
+ break;
+ case Otupget:
+ assert(exprop(args[1]) == Olit);
+ i = args[1]->expr.args[0]->lit.intval;
+ t = rval(s, args[0], NULL);
+ r = tupget(s, t, i, dst);
+ break;
+ case Obad:
+ die("bad operator");
+ break;
+ default:
+ if (istyfloat(exprtype(n))) {
+ switch (exprop(n)) {
+ case Oadd: n->expr.op = Ofadd; break;
+ case Osub: n->expr.op = Ofsub; break;
+ case Omul: n->expr.op = Ofmul; break;
+ case Odiv: n->expr.op = Ofdiv; break;
+ default: break;
+ }
+ }
+ r = visit(s, n);
+ break;
+ }
+ return r;
}
static void declarearg(Simp *s, Node *n)
{
- assert(n->type == Ndecl || (n->type == Nexpr && exprop(n) == Ovar));
- lappend(&s->args, &s->nargs, n);
+ assert(n->type == Ndecl || (n->type == Nexpr && exprop(n) == Ovar));
+ lappend(&s->args, &s->nargs, n);
}
static int islbl(Node *n)
{
- Node *l;
- if (exprop(n) != Olit)
- return 0;
- l = n->expr.args[0];
- return l->type == Nlit && l->lit.littype == Llbl;
+ Node *l;
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ return l->type == Nlit && l->lit.littype == Llbl;
}
static void simpmatch(Simp *s, Node *n)
{
- Node *val;
- Node **match;
- size_t i, nmatch;
+ Node *val;
+ Node **match;
+ size_t i, nmatch;
- val = rval(s, n->matchstmt.val, NULL);
+ val = rval(s, n->matchstmt.val, NULL);
- match = NULL;
- nmatch = 0;
- genmatch(n, val, &match, &nmatch);
- for (i = 0; i < nmatch; i++)
- simp(s, match[i]);
+ match = NULL;
+ nmatch = 0;
+ genmatch(n, val, &match, &nmatch);
+ for (i = 0; i < nmatch; i++)
+ simp(s, match[i]);
}
static Node *simp(Simp *s, Node *n)
{
- Node *r, *t, *u;
- size_t i;
-
- if (!n)
- return NULL;
- r = NULL;
- switch (n->type) {
- case Nblock: simpblk(s, n); break;
- case Nifstmt: simpif(s, n, NULL); break;
- case Nloopstmt: simploop(s, n); break;
- case Niterstmt: simpiter(s, n); break;
- case Nmatchstmt: simpmatch(s, n); break;
- case Nexpr:
- if (islbl(n))
- append(s, n);
- else
- r = rval(s, n, NULL);
- if (r)
- append(s, r);
- /* drain the increment queue for this expr */
- for (i = 0; i < s->nqueue; i++)
- append(s, s->incqueue[i]);
- lfree(&s->incqueue, &s->nqueue);
- break;
-
- case Ndecl:
- declarelocal(s, n);
- t = mkexpr(n->loc, Ovar, n->decl.name, NULL);
- if (n->decl.init) {
- u = mkexpr(n->loc, Oasn, t, n->decl.init, NULL);
- u->expr.type = n->decl.type;
- t->expr.type = n->decl.type;
- t->expr.did = n->decl.did;
- simp(s, u);
- }
- break;
- default:
- dump(n, stderr);
- die("bad node passsed to simp()");
- break;
- }
- return r;
+ Node *r, *t, *u;
+ size_t i;
+
+ if (!n)
+ return NULL;
+ r = NULL;
+ switch (n->type) {
+ case Nblock: simpblk(s, n); break;
+ case Nloopstmt: simploop(s, n); break;
+ case Niterstmt: simpiter(s, n); break;
+ case Nifstmt: simpif(s, n, NULL); break;
+ case Nmatchstmt: simpmatch(s, n); break;
+ case Nexpr:
+ if (islbl(n))
+ append(s, n);
+ else
+ r = rval(s, n, NULL);
+ if (r)
+ append(s, r);
+ /* drain the increment queue for this expr */
+ for (i = 0; i < s->nqueue; i++)
+ append(s, s->incqueue[i]);
+ lfree(&s->incqueue, &s->nqueue);
+ break;
+
+ case Ndecl:
+ declarelocal(s, n);
+ t = mkexpr(n->loc, Ovar, n->decl.name, NULL);
+ if (n->decl.init) {
+ u = mkexpr(n->loc, Oasn, t, n->decl.init, NULL);
+ u->expr.type = n->decl.type;
+ t->expr.type = n->decl.type;
+ t->expr.did = n->decl.did;
+ simp(s, u);
+ }
+ break;
+ default:
+ dump(n, stderr);
+ die("bad node passsed to simp()");
+ break;
+ }
+ return r;
}
/*
@@ -1680,225 +1680,225 @@ static Node *simp(Simp *s, Node *n)
*/
static void flatten(Simp *s, Node *f)
{
- Node *dcl;
- Type *ty;
- size_t i;
+ Node *dcl;
+ Type *ty;
+ size_t i;
- assert(f->type == Nfunc);
- s->nstmts = 0;
- s->stmts = NULL;
- s->endlbl = genlbl(f->loc);
- s->ret = NULL;
+ assert(f->type == Nfunc);
+ s->nstmts = 0;
+ s->stmts = NULL;
+ s->endlbl = genlbl(f->loc);
+ s->ret = NULL;
- /* make a temp for the return type */
- ty = f->func.type->sub[0];
- if (isstacktype(ty)) {
- s->isbigret = 1;
- s->ret = gentemp(f->loc, mktyptr(f->loc, ty), &dcl);
- declarearg(s, dcl);
- } else if (ty->type != Tyvoid) {
- s->isbigret = 0;
- s->ret = gentemp(f->loc, ty, &dcl);
- }
+ /* make a temp for the return type */
+ ty = f->func.type->sub[0];
+ if (isstacktype(ty)) {
+ s->isbigret = 1;
+ s->ret = gentemp(f->loc, mktyptr(f->loc, ty), &dcl);
+ declarearg(s, dcl);
+ } else if (ty->type != Tyvoid) {
+ s->isbigret = 0;
+ s->ret = gentemp(f->loc, ty, &dcl);
+ }
- for (i = 0; i < f->func.nargs; i++) {
- declarearg(s, f->func.args[i]);
- }
- simp(s, f->func.body);
+ for (i = 0; i < f->func.nargs; i++) {
+ declarearg(s, f->func.args[i]);
+ }
+ simp(s, f->func.body);
- append(s, s->endlbl);
+ append(s, s->endlbl);
}
static int isexport(Node *dcl)
{
- Node *n;
+ Node *n;
- /* Vishidden should also be exported. */
- if (dcl->decl.vis != Visintern)
- return 1;
- n = dcl->decl.name;
- if (!n->name.ns && streq(n->name.name, "main"))
- return 1;
- if (streq(n->name.name, "__init__"))
- return 1;
- return 0;
+ /* Vishidden should also be exported. */
+ if (dcl->decl.vis != Visintern)
+ return 1;
+ n = dcl->decl.name;
+ if (!n->name.ns && streq(n->name.name, "main"))
+ return 1;
+ if (streq(n->name.name, "__init__"))
+ return 1;
+ return 0;
}
static int envcmp(const void *pa, const void *pb)
{
- const Node *a, *b;
+ const Node *a, *b;
- a = *(const Node**)pa;
- b = *(const Node**)pb;
- return b->decl.did - a->decl.did;
+ 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;
-
- env = getclosure(fn->func.scope, &nenv);
- if (!env)
- return;
- /*
- 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.
- */
- s->hasenv = 1;
- 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);
+ size_t nenv, i;
+ Node **env;
+ size_t off;
+
+ env = getclosure(fn->func.scope, &nenv);
+ if (!env)
+ return;
+ /*
+ 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.
+ */
+ s->hasenv = 1;
+ 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);
}
static Func *simpfn(Simp *s, char *name, Node *dcl)
{
- Node *n;
- size_t i;
- Func *fn;
- Cfg *cfg;
-
- n = dcl->decl.init;
- if(debugopt['i'] || debugopt['F'] || debugopt['f'])
- printf("\n\nfunction %s\n", name);
-
- /* set up the simp context */
- /* unwrap to the function body */
- n = n->expr.args[0];
- n = n->lit.fnval;
- collectenv(s, n);
- flatten(s, n);
-
- if (debugopt['f'] || debugopt['F'])
- for (i = 0; i < s->nstmts; i++)
- dump(s->stmts[i], stdout);
- for (i = 0; i < s->nstmts; i++) {
- if (s->stmts[i]->type != Nexpr)
- continue;
- if (debugopt['f']) {
- printf("FOLD FROM ----------\n");
- dump(s->stmts[i], stdout);
- }
- s->stmts[i] = fold(s->stmts[i], 0);
- if (debugopt['f']) {
- printf("TO ------------\n");
- dump(s->stmts[i], stdout);
- printf("DONE ----------------\n");
- }
- }
-
- cfg = mkcfg(dcl, s->stmts, s->nstmts);
- check(cfg);
- if (debugopt['t'] || debugopt['s'])
- dumpcfg(cfg, stdout);
-
- fn = zalloc(sizeof(Func));
- fn->name = strdup(name);
- fn->type = dcl->decl.type;
- fn->isexport = isexport(dcl);
- fn->stksz = align(s->stksz, 8);
- fn->stkoff = s->stkoff;
- fn->envoff = s->envoff;
- fn->ret = s->ret;
- fn->args = s->args;
- fn->nargs = s->nargs;
- fn->cfg = cfg;
- fn->hasenv = s->hasenv;
- return fn;
+ Node *n;
+ size_t i;
+ Func *fn;
+ Cfg *cfg;
+
+ n = dcl->decl.init;
+ if(debugopt['i'] || debugopt['F'] || debugopt['f'])
+ printf("\n\nfunction %s\n", name);
+
+ /* set up the simp context */
+ /* unwrap to the function body */
+ n = n->expr.args[0];
+ n = n->lit.fnval;
+ collectenv(s, n);
+ flatten(s, n);
+
+ if (debugopt['f'] || debugopt['F'])
+ for (i = 0; i < s->nstmts; i++)
+ dump(s->stmts[i], stdout);
+ for (i = 0; i < s->nstmts; i++) {
+ if (s->stmts[i]->type != Nexpr)
+ continue;
+ if (debugopt['f']) {
+ printf("FOLD FROM ----------\n");
+ dump(s->stmts[i], stdout);
+ }
+ s->stmts[i] = fold(s->stmts[i], 0);
+ if (debugopt['f']) {
+ printf("TO ------------\n");
+ dump(s->stmts[i], stdout);
+ printf("DONE ----------------\n");
+ }
+ }
+
+ cfg = mkcfg(dcl, s->stmts, s->nstmts);
+ check(cfg);
+ if (debugopt['t'] || debugopt['s'])
+ dumpcfg(cfg, stdout);
+
+ fn = zalloc(sizeof(Func));
+ fn->name = strdup(name);
+ fn->type = dcl->decl.type;
+ fn->isexport = isexport(dcl);
+ fn->stksz = align(s->stksz, 8);
+ fn->stkoff = s->stkoff;
+ fn->envoff = s->envoff;
+ fn->ret = s->ret;
+ fn->args = s->args;
+ fn->nargs = s->nargs;
+ fn->cfg = cfg;
+ fn->hasenv = s->hasenv;
+ return fn;
}
static void extractsub(Simp *s, Node *e)
{
- size_t i;
+ size_t i;
- assert(e != NULL);
- switch (exprop(e)) {
- case Oslice:
- if (exprop(e->expr.args[0]) == Oarr)
- e->expr.args[0] = simpblob(s, e->expr.args[0]);
- break;
- case Oarr:
- case Ostruct:
- for (i = 0; i < e->expr.nargs; i++)
- extractsub(s, e->expr.args[i]);
- break;
- default:
- break;
- }
+ assert(e != NULL);
+ switch (exprop(e)) {
+ case Oslice:
+ if (exprop(e->expr.args[0]) == Oarr)
+ e->expr.args[0] = simpblob(s, e->expr.args[0]);
+ break;
+ case Oarr:
+ case Ostruct:
+ for (i = 0; i < e->expr.nargs; i++)
+ extractsub(s, e->expr.args[i]);
+ break;
+ default:
+ break;
+ }
}
static void simpconstinit(Simp *s, Node *dcl)
{
- Node *e;
-
- dcl->decl.init = fold(dcl->decl.init, 1);;
- e = dcl->decl.init;
- if (e && exprop(e) == Olit) {
- if (e->expr.args[0]->lit.littype == Lfunc)
- simpcode(s, e);
- else
- lappend(&s->blobs, &s->nblobs, dcl);
- } else if (dcl->decl.isconst) {
- switch (exprop(e)) {
- case Oarr:
- case Ostruct:
- case Oslice:
- extractsub(s, e);
- lappend(&s->blobs, &s->nblobs, dcl);
- break;
- default:
- fatal(dcl, "unsupported initializer for %s", declname(dcl));
- break;
- }
- } else if (!dcl->decl.isconst && !e) {
- lappend(&s->blobs, &s->nblobs, dcl);
- } else {
- die("Non-constant initializer for %s\n", declname(dcl));
- }
+ Node *e;
+
+ dcl->decl.init = fold(dcl->decl.init, 1);;
+ e = dcl->decl.init;
+ if (e && exprop(e) == Olit) {
+ if (e->expr.args[0]->lit.littype == Lfunc)
+ simpcode(s, e);
+ else
+ lappend(&s->blobs, &s->nblobs, dcl);
+ } else if (dcl->decl.isconst) {
+ switch (exprop(e)) {
+ case Oarr:
+ case Ostruct:
+ case Oslice:
+ extractsub(s, e);
+ lappend(&s->blobs, &s->nblobs, dcl);
+ break;
+ default:
+ fatal(dcl, "unsupported initializer for %s", declname(dcl));
+ break;
+ }
+ } else if (!dcl->decl.isconst && !e) {
+ lappend(&s->blobs, &s->nblobs, dcl);
+ } else {
+ die("Non-constant initializer for %s\n", declname(dcl));
+ }
}
int ismain(Node *dcl)
{
- Node *n;
+ Node *n;
- n = dcl->decl.name;
- if (n->name.ns)
- return 0;
- return strcmp(n->name.name, "main") == 0;
+ n = dcl->decl.name;
+ if (n->name.ns)
+ return 0;
+ return strcmp(n->name.name, "main") == 0;
}
void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob)
{
- Simp s = {0,};
- char *name;
- Func *f;
-
- if (ismain(dcl))
- dcl->decl.vis = Vishidden;
- s.stkoff = mkht(varhash, vareq);
- s.envoff = mkht(varhash, vareq);
- s.globls = globls;
- s.blobs = *blob;
- s.nblobs = *nblob;
- s.hasenv = 0;
- name = asmname(dcl);
-
- if (dcl->decl.isextern || dcl->decl.isgeneric)
- return;
- if (isconstfn(dcl)) {
- f = simpfn(&s, name, dcl);
- lappend(fn, nfn, f);
- } else {
- simpconstinit(&s, dcl);
- }
- *blob = s.blobs;
- *nblob = s.nblobs;
- free(name);
+ Simp s = {0,};
+ char *name;
+ Func *f;
+
+ if (ismain(dcl))
+ dcl->decl.vis = Vishidden;
+ s.stkoff = mkht(varhash, vareq);
+ s.envoff = mkht(varhash, vareq);
+ s.globls = globls;
+ s.blobs = *blob;
+ s.nblobs = *nblob;
+ s.hasenv = 0;
+ name = asmname(dcl);
+
+ if (dcl->decl.isextern || dcl->decl.isgeneric)
+ return;
+ if (isconstfn(dcl)) {
+ f = simpfn(&s, name, dcl);
+ lappend(fn, nfn, f);
+ } else {
+ simpconstinit(&s, dcl);
+ }
+ *blob = s.blobs;
+ *nblob = s.nblobs;
+ free(name);
}