summaryrefslogtreecommitdiff
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
parentc20862cda53c711fe476f6c7d0f6631af47a4933 (diff)
downloadmc-8531896f8d21ba1e727262aaf5cd96043590b480.tar.gz
MEGAPATCH: Tabification.
Tabs > spaces. By 4 spaces, to be precise. Let's use them.
-rw-r--r--6/asm.h316
-rw-r--r--6/blob.c378
-rw-r--r--6/gen.c220
-rw-r--r--6/gengas.c726
-rw-r--r--6/genp9.c766
-rw-r--r--6/isel.c1744
-rw-r--r--6/locs.c336
-rw-r--r--6/main.c376
-rw-r--r--6/peep.c96
-rw-r--r--6/ra.c2183
-rw-r--r--6/simp.c2886
-rw-r--r--6/typeinfo.c595
-rw-r--r--bench/runner.c84
-rw-r--r--mi/cfg.c456
-rw-r--r--mi/dfcheck.c184
-rw-r--r--mi/fold.c390
-rw-r--r--mi/match.c1288
-rw-r--r--mi/mi.h48
-rw-r--r--mi/reaching.c233
-rw-r--r--mk/lexyacc.mk2
-rw-r--r--muse/muse.c140
-rw-r--r--parse/bitset.c240
-rw-r--r--parse/dump.c408
-rw-r--r--parse/gram.y1387
-rw-r--r--parse/htab.c377
-rw-r--r--parse/infer.c4048
-rw-r--r--parse/names.c11
-rw-r--r--parse/node.c532
-rw-r--r--parse/parse.h625
-rw-r--r--parse/specialize.c832
-rw-r--r--parse/stab.c644
-rw-r--r--parse/tok.c1330
-rw-r--r--parse/type.c1341
-rw-r--r--parse/use.c1826
-rw-r--r--parse/util.c653
35 files changed, 13770 insertions, 13931 deletions
diff --git a/6/asm.h b/6/asm.h
index ceb720a..9b6dd1a 100644
--- a/6/asm.h
+++ b/6/asm.h
@@ -21,218 +21,218 @@ typedef enum {
#define Reg(r, gasname, p9name, mode) r,
#include "regs.def"
#undef Reg
- Nreg
+ Nreg
} Reg;
typedef enum {
- Locnone,
- Loclbl, /* label */
- Locreg, /* register */
- Locmem, /* reg offset mem */
- Locmeml, /* label offset mem */
- Loclit, /* literal value */
- Loclitl /* label address */
+ Locnone,
+ Loclbl, /* label */
+ Locreg, /* register */
+ Locmem, /* reg offset mem */
+ Locmeml, /* label offset mem */
+ Loclit, /* literal value */
+ Loclitl /* label address */
} Loctype;
typedef enum {
- ModeNone,
- ModeB, /* byte */
- ModeW, /* short */
- ModeL, /* long */
- ModeQ, /* quad */
- ModeF, /* float32 */
- ModeD, /* float64 */
- Nmode,
+ ModeNone,
+ ModeB, /* byte */
+ ModeW, /* short */
+ ModeL, /* long */
+ ModeQ, /* quad */
+ ModeF, /* float32 */
+ ModeD, /* float64 */
+ Nmode,
} Mode;
typedef enum {
- Classbad,
- Classint,
- Classflt,
- Nclass,
+ Classbad,
+ Classint,
+ Classflt,
+ Nclass,
} Rclass;
typedef enum {
- Gnugas,
- Plan9,
+ Gnugas,
+ Plan9,
} Asmsyntax;
typedef enum {
- Bti8,
- Bti16,
- Bti32,
- Bti64,
- Btimin, /* byte-packed uint */
- Btref,
- Btbytes,
- Btseq,
- Btpad,
+ Bti8,
+ Bti16,
+ Bti32,
+ Bti64,
+ Btimin, /* byte-packed uint */
+ Btref,
+ Btbytes,
+ Btseq,
+ Btpad,
} Blobtype;
struct Blob {
- Blobtype type;
- size_t align;
- char *lbl; /* may be null */
- char isglobl;
- union {
- uint64_t npad;
- uint64_t ival;
- struct {
- char *str;
- char isextern;
- size_t off;
- } ref;
- struct {
- size_t len;
- char *buf;
- } bytes;
- struct {
- size_t nsub;
- Blob **sub;
- } seq;
- };
+ Blobtype type;
+ size_t align;
+ char *lbl; /* may be null */
+ char isglobl;
+ union {
+ uint64_t npad;
+ uint64_t ival;
+ struct {
+ char *str;
+ char isextern;
+ size_t off;
+ } ref;
+ struct {
+ size_t len;
+ char *buf;
+ } bytes;
+ struct {
+ size_t nsub;
+ Blob **sub;
+ } seq;
+ };
};
/* a register, label, or memory location */
struct Loc {
- Loctype type; /* the type of loc */
- Mode mode; /* the mode of this location */
- void *list;
- union {
- char *lbl; /* for Loclbl, Loclitl */
- struct { /* for Locreg */
- regid id;
- Reg colour;
- } reg;
- long lit; /* for Loclit */
- /*
- * for Locmem, Locmeml.
- * address format is
- * disp(base + index)
- */
- struct {
- /* only one of lbldisp and constdisp may be used */
- char *lbldisp;
- long constdisp;
- int scale; /* 0,1,2,4, or 8 */
- Loc *base; /* needed */
- Loc *idx; /* optional */
- } mem;
- };
+ Loctype type; /* the type of loc */
+ Mode mode; /* the mode of this location */
+ void *list;
+ union {
+ char *lbl; /* for Loclbl, Loclitl */
+ struct { /* for Locreg */
+ regid id;
+ Reg colour;
+ } reg;
+ long lit; /* for Loclit */
+ /*
+ * for Locmem, Locmeml.
+ * address format is
+ * disp(base + index)
+ */
+ struct {
+ /* only one of lbldisp and constdisp may be used */
+ char *lbldisp;
+ long constdisp;
+ int scale; /* 0,1,2,4, or 8 */
+ Loc *base; /* needed */
+ Loc *idx; /* optional */
+ } mem;
+ };
};
struct Insn {
- size_t uid;
- AsmOp op;
- Loc *args[Maxarg];
- size_t nargs;
+ size_t uid;
+ AsmOp op;
+ Loc *args[Maxarg];
+ size_t nargs;
};
struct Func {
- char *name; /* function name */
- Type *type; /* type of function */
-
- Node **args; /* argument list */
- size_t nargs; /* number of args, including hidden ones */
- Htab *stkoff; /* Loc* -> int stkoff map */
- Htab *envoff; /* Loc* -> int envoff map */
- size_t stksz; /* stack size */
- Node *ret; /* return value */
-
- Cfg *cfg; /* flow graph */
- char isexport; /* is this exported from the asm? */
- char hasenv; /* do we have an environment? */
+ char *name; /* function name */
+ Type *type; /* type of function */
+
+ Node **args; /* argument list */
+ size_t nargs; /* number of args, including hidden ones */
+ Htab *stkoff; /* Loc* -> int stkoff map */
+ Htab *envoff; /* Loc* -> int envoff map */
+ size_t stksz; /* stack size */
+ Node *ret; /* return value */
+
+ Cfg *cfg; /* flow graph */
+ char isexport; /* is this exported from the asm? */
+ char hasenv; /* do we have an environment? */
};
struct Asmbb {
- int id; /* unique identifier */
- char **lbls; /* list of BB labels */
- size_t nlbls; /* number of labels */
- Insn **il; /* instructions */
- size_t ni; /* number of instructions */
-
- Bitset *pred; /* set of predecessor BB ids */
- Bitset *succ; /* set of successor BB ids */
- Bitset *use; /* registers used by this BB */
- Bitset *def; /* registers defined by this BB */
- Bitset *livein; /* variables live on entrance to BB */
- Bitset *liveout; /* variables live on exit from BB */
+ int id; /* unique identifier */
+ char **lbls; /* list of BB labels */
+ size_t nlbls; /* number of labels */
+ Insn **il; /* instructions */
+ size_t ni; /* number of instructions */
+
+ Bitset *pred; /* set of predecessor BB ids */
+ Bitset *succ; /* set of successor BB ids */
+ Bitset *use; /* registers used by this BB */
+ Bitset *def; /* registers defined by this BB */
+ Bitset *livein; /* variables live on entrance to BB */
+ Bitset *liveout; /* variables live on exit from BB */
};
/* instruction selection state */
struct Isel {
- Cfg *cfg; /* cfg built with nodes */
+ Cfg *cfg; /* cfg built with nodes */
- Asmbb **bb; /* 1:1 mappings with the Node bbs in the CFG */
- size_t nbb;
- Asmbb *curbb;
+ Asmbb **bb; /* 1:1 mappings with the Node bbs in the CFG */
+ size_t nbb;
+ Asmbb *curbb;
- Node *ret; /* we store the return into here */
- 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 */
+ Node *ret; /* we store the return into here */
+ 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 */
- Loc *envp;
+ Loc *envp;
- /* increased when we spill */
- Loc *stksz;
- Loc *calleesave[Nreg];
- size_t nsaved;
+ /* increased when we spill */
+ Loc *stksz;
+ Loc *calleesave[Nreg];
+ size_t nsaved;
- /* register allocator state */
+ /* register allocator state */
- size_t *gbits; /* igraph matrix repr */
- regid **gadj; /* igraph adj set repr */
- size_t *ngadj;
- size_t nreg; /* maxregid at time of alloc */
- int *degree; /* degree of nodes */
- int *nuses; /* number of uses of nodes */
- Loc **aliasmap; /* mapping of aliases */
+ size_t *gbits; /* igraph matrix repr */
+ regid **gadj; /* igraph adj set repr */
+ size_t *ngadj;
+ size_t nreg; /* maxregid at time of alloc */
+ int *degree; /* degree of nodes */
+ int *nuses; /* number of uses of nodes */
+ Loc **aliasmap; /* mapping of aliases */
- Bitset *shouldspill; /* the first registers we should try to spill */
- Bitset *neverspill; /* registers we should never spill */
+ Bitset *shouldspill; /* the first registers we should try to spill */
+ Bitset *neverspill; /* registers we should never spill */
- Insn ***rmoves;
- size_t *nrmoves;
+ Insn ***rmoves;
+ size_t *nrmoves;
- /* move sets */
- Insn **mcoalesced;
- size_t nmcoalesced;
+ /* move sets */
+ Insn **mcoalesced;
+ size_t nmcoalesced;
- Insn **mconstrained;
- size_t nmconstrained;
+ Insn **mconstrained;
+ size_t nmconstrained;
- Insn **mfrozen;
- size_t nmfrozen;
+ Insn **mfrozen;
+ size_t nmfrozen;
- Bitset *mactiveset;
- Insn **mactive;
- size_t nmactive;
+ Bitset *mactiveset;
+ Insn **mactive;
+ size_t nmactive;
- /* worklists */
- Bitset *wlmoveset;
- Insn **wlmove;
- size_t nwlmove;
+ /* worklists */
+ Bitset *wlmoveset;
+ Insn **wlmove;
+ size_t nwlmove;
- Loc **wlspill;
- size_t nwlspill;
+ Loc **wlspill;
+ size_t nwlspill;
- Loc **wlfreeze;
- size_t nwlfreeze;
+ Loc **wlfreeze;
+ size_t nwlfreeze;
- Loc **wlsimp;
- size_t nwlsimp;
+ Loc **wlsimp;
+ size_t nwlsimp;
- Loc **selstk;
- size_t nselstk;
+ Loc **selstk;
+ size_t nselstk;
- Bitset *coalesced;
- Bitset *spilled;
- Bitset *prepainted; /* locations that need to be a specific colour */
- Bitset *initial; /* initial set of locations used by this fn */
+ Bitset *coalesced;
+ Bitset *spilled;
+ Bitset *prepainted; /* locations that need to be a specific colour */
+ Bitset *initial; /* initial set of locations used by this fn */
};
/* globals */
diff --git a/6/blob.c b/6/blob.c
index 95e5678..df48b7e 100644
--- a/6/blob.c
+++ b/6/blob.c
@@ -19,260 +19,260 @@ static size_t blobrec(Blob *b, Htab *globls, Htab *strtab, Node *n);
Blob *mkblobi(Blobtype type, uint64_t ival)
{
- Blob *b;
+ Blob *b;
- b = zalloc(sizeof(Blob));
- b->type = type;
- b->ival = ival;
- return b;
+ b = zalloc(sizeof(Blob));
+ b->type = type;
+ b->ival = ival;
+ return b;
}
Blob *mkblobpad(size_t sz)
{
- Blob *b;
+ Blob *b;
- b = zalloc(sizeof(Blob));
- b->type = Btpad;
- b->npad = sz;
- return b;
+ b = zalloc(sizeof(Blob));
+ b->type = Btpad;
+ b->npad = sz;
+ return b;
}
Blob *mkblobbytes(char *buf, size_t len)
{
- Blob *b;
+ Blob *b;
- b = zalloc(sizeof(Blob));
- b->type = Btbytes;
- b->bytes.buf = buf;
- b->bytes.len = len;
- return b;
+ b = zalloc(sizeof(Blob));
+ b->type = Btbytes;
+ b->bytes.buf = buf;
+ b->bytes.len = len;
+ return b;
}
Blob *mkblobseq(Blob **sub, size_t nsub)
{
- Blob *b;
+ Blob *b;
- b = zalloc(sizeof(Blob));
- b->type = Btseq;
- b->seq.sub = sub;
- b->seq.nsub = nsub;
- return b;
+ b = zalloc(sizeof(Blob));
+ b->type = Btseq;
+ b->seq.sub = sub;
+ b->seq.nsub = nsub;
+ return b;
}
Blob *mkblobref(char *lbl, size_t off, int isextern)
{
- Blob *b;
-
- b = zalloc(sizeof(Blob));
- b->type = Btref;
- b->ref.str = strdup(lbl);
- b->ref.isextern = isextern;
- b->ref.off = off;
- return b;
+ Blob *b;
+
+ b = zalloc(sizeof(Blob));
+ b->type = Btref;
+ b->ref.str = strdup(lbl);
+ b->ref.isextern = isextern;
+ b->ref.off = off;
+ return b;
}
void blobfree(Blob *b)
{
- size_t i;
-
- if (!b)
- return;
- switch (b->type) {
- case Btref:
- free(b->lbl);
- break;
- case Btseq:
- for (i = 0; i < b->seq.nsub; i++)
- blobfree(b->seq.sub[i]);
- break;
- default:
- break;
- }
- free(b);
+ size_t i;
+
+ if (!b)
+ return;
+ switch (b->type) {
+ case Btref:
+ free(b->lbl);
+ break;
+ case Btseq:
+ for (i = 0; i < b->seq.nsub; i++)
+ blobfree(b->seq.sub[i]);
+ break;
+ default:
+ break;
+ }
+ free(b);
}
static size_t getintlit(Node *n, char *failmsg)
{
- if (exprop(n) != Olit)
- fatal(n, "%s", failmsg);
- n = n->expr.args[0];
- if (n->lit.littype != Lint)
- fatal(n, "%s", failmsg);
- return n->lit.intval;
+ if (exprop(n) != Olit)
+ fatal(n, "%s", failmsg);
+ n = n->expr.args[0];
+ if (n->lit.littype != Lint)
+ fatal(n, "%s", failmsg);
+ return n->lit.intval;
}
void b(Blob *b, Blob *n)
{
- lappend(&b->seq.sub, &b->seq.nsub, n);
+ lappend(&b->seq.sub, &b->seq.nsub, n);
}
static size_t blobpad(Blob *seq, size_t sz)
{
- b(seq, mkblobpad(sz));
- return sz;
+ b(seq, mkblobpad(sz));
+ return sz;
}
static size_t bloblit(Blob *seq, Htab *strtab, Node *v, Type *ty)
{
- char buf[128];
- char *lbl;
- size_t sz;
- Blobtype intsz[] = {
- [1] = Bti8,
- [2] = Bti16,
- [4] = Bti32,
- [8] = Bti64
- };
- union {
- float fv;
- double dv;
- uint64_t qv;
- uint32_t lv;
- } u;
-
- assert(v->type == Nlit);
- sz = tysize(ty);
- switch (v->lit.littype) {
- case Lint: b(seq, mkblobi(intsz[sz], v->lit.intval)); break;
- case Lbool: b(seq, mkblobi(Bti8, v->lit.boolval)); break;
- case Lchr: b(seq, mkblobi(Bti32, v->lit.chrval)); break;
- case Lflt:
- if (tybase(v->lit.type)->type == Tyflt32) {
- u.fv = v->lit.fltval;
- b(seq, mkblobi(Bti32, u.lv));
- } else if (tybase(v->lit.type)->type == Tyflt64) {
- u.dv = v->lit.fltval;
- b(seq, mkblobi(Bti64, u.qv));
- }
- break;
- case Lstr:
- if (hthas(strtab, &v->lit.strval)) {
- lbl = htget(strtab, &v->lit.strval);
- } else {
- lbl = genlocallblstr(buf, sizeof buf);
- htput(strtab, &v->lit.strval, strdup(lbl));
- }
- if (v->lit.strval.len > 0)
- b(seq, mkblobref(lbl, 0, 1));
- else
- b(seq, mkblobi(Bti64, 0));
- b(seq, mkblobi(Bti64, v->lit.strval.len));
- break;
- case Lfunc:
- die("Generating this shit ain't ready yet ");
- break;
- case Llbl:
- die("Can't generate literal labels, ffs. They're not data.");
- break;
- }
- return sz;
+ char buf[128];
+ char *lbl;
+ size_t sz;
+ Blobtype intsz[] = {
+ [1] = Bti8,
+ [2] = Bti16,
+ [4] = Bti32,
+ [8] = Bti64
+ };
+ union {
+ float fv;
+ double dv;
+ uint64_t qv;
+ uint32_t lv;
+ } u;
+
+ assert(v->type == Nlit);
+ sz = tysize(ty);
+ switch (v->lit.littype) {
+ case Lint: b(seq, mkblobi(intsz[sz], v->lit.intval)); break;
+ case Lbool: b(seq, mkblobi(Bti8, v->lit.boolval)); break;
+ case Lchr: b(seq, mkblobi(Bti32, v->lit.chrval)); break;
+ case Lflt:
+ if (tybase(v->lit.type)->type == Tyflt32) {
+ u.fv = v->lit.fltval;
+ b(seq, mkblobi(Bti32, u.lv));
+ } else if (tybase(v->lit.type)->type == Tyflt64) {
+ u.dv = v->lit.fltval;
+ b(seq, mkblobi(Bti64, u.qv));
+ }
+ break;
+ case Lstr:
+ if (hthas(strtab, &v->lit.strval)) {
+ lbl = htget(strtab, &v->lit.strval);
+ } else {
+ lbl = genlocallblstr(buf, sizeof buf);
+ htput(strtab, &v->lit.strval, strdup(lbl));
+ }
+ if (v->lit.strval.len > 0)
+ b(seq, mkblobref(lbl, 0, 1));
+ else
+ b(seq, mkblobi(Bti64, 0));
+ b(seq, mkblobi(Bti64, v->lit.strval.len));
+ break;
+ case Lfunc:
+ die("Generating this shit ain't ready yet ");
+ break;
+ case Llbl:
+ die("Can't generate literal labels, ffs. They're not data.");
+ break;
+ }
+ return sz;
}
static size_t blobslice(Blob *seq, Htab *globls, Htab *strtab, Node *n)
{
- Node *base, *lo, *hi;
- ssize_t loval, hival, sz;
- char *lbl;
-
- base = n->expr.args[0];
- lo = n->expr.args[1];
- hi = n->expr.args[2];
-
- /* by this point, all slicing operations should have had their bases
- * pulled out, and we should have vars with their pseudo-decls in their
- * place */
- if (exprop(base) != Ovar || !base->expr.isconst)
- fatal(base, "slice base is not a constant value");
- loval = getintlit(lo, "lower bound in slice is not constant literal");
- hival = getintlit(hi, "upper bound in slice is not constant literal");
- sz = tysize(tybase(exprtype(base))->sub[0]);
-
- lbl = htget(globls, base);
- b(seq, mkblobref(lbl, loval*sz, 1));
- b(seq, mkblobi(Bti64, (hival - loval)));
- return 16;
+ Node *base, *lo, *hi;
+ ssize_t loval, hival, sz;
+ char *lbl;
+
+ base = n->expr.args[0];
+ lo = n->expr.args[1];
+ hi = n->expr.args[2];
+
+ /* by this point, all slicing operations should have had their bases
+ * pulled out, and we should have vars with their pseudo-decls in their
+ * place */
+ if (exprop(base) != Ovar || !base->expr.isconst)
+ fatal(base, "slice base is not a constant value");
+ loval = getintlit(lo, "lower bound in slice is not constant literal");
+ hival = getintlit(hi, "upper bound in slice is not constant literal");
+ sz = tysize(tybase(exprtype(base))->sub[0]);
+
+ lbl = htget(globls, base);
+ b(seq, mkblobref(lbl, loval*sz, 1));
+ b(seq, mkblobi(Bti64, (hival - loval)));
+ return 16;
}
static Node *structmemb(Node *n, char *dcl)
{
- size_t i;
+ size_t i;
- for (i = 0; i < n->expr.nargs; i++)
- if (!strcmp(namestr(n->expr.args[i]->expr.idx), dcl))
- return n->expr.args[i];
- return NULL;
+ for (i = 0; i < n->expr.nargs; i++)
+ if (!strcmp(namestr(n->expr.args[i]->expr.idx), dcl))
+ return n->expr.args[i];
+ return NULL;
}
static size_t blobstruct(Blob *seq, Htab *globls, Htab *strtab, Node *n)
{
- size_t i, sz, pad, end, ndcl;
- Node **dcl, *m;
- Type *t;
-
- sz = 0;
- t = tybase(exprtype(n));
- assert(t->type == Tystruct);
- dcl = t->sdecls;
- ndcl = t->nmemb;
-
- for (i = 0; i < ndcl; i++) {
- pad = alignto(sz, decltype(dcl[i]));
- m = structmemb(n, declname(dcl[i]));
- sz += blobpad(seq, pad - sz);
- if (m)
- sz += blobrec(seq, globls, strtab, m);
- else
- sz += blobpad(seq, size(dcl[i]));
- }
- end = alignto(sz, t);
- sz += blobpad(seq, end - sz);
- return sz;
+ size_t i, sz, pad, end, ndcl;
+ Node **dcl, *m;
+ Type *t;
+
+ sz = 0;
+ t = tybase(exprtype(n));
+ assert(t->type == Tystruct);
+ dcl = t->sdecls;
+ ndcl = t->nmemb;
+
+ for (i = 0; i < ndcl; i++) {
+ pad = alignto(sz, decltype(dcl[i]));
+ m = structmemb(n, declname(dcl[i]));
+ sz += blobpad(seq, pad - sz);
+ if (m)
+ sz += blobrec(seq, globls, strtab, m);
+ else
+ sz += blobpad(seq, size(dcl[i]));
+ }
+ end = alignto(sz, t);
+ sz += blobpad(seq, end - sz);
+ return sz;
}
static size_t blobucon(Blob *seq, Htab *globls, Htab *strtab, Node *n)
{
- size_t sz;
- Ucon *uc;
-
- sz = 4;
- uc = finducon(exprtype(n), n->expr.args[0]);
- b(seq, mkblobi(Bti32, uc->id));
- if (n->expr.nargs > 1)
- sz += blobrec(seq, globls, strtab, n->expr.args[1]);
- sz += blobpad(seq, size(n) - sz);
- return sz;
+ size_t sz;
+ Ucon *uc;
+
+ sz = 4;
+ uc = finducon(exprtype(n), n->expr.args[0]);
+ b(seq, mkblobi(Bti32, uc->id));
+ if (n->expr.nargs > 1)
+ sz += blobrec(seq, globls, strtab, n->expr.args[1]);
+ sz += blobpad(seq, size(n) - sz);
+ return sz;
}
static size_t blobrec(Blob *b, Htab *globls, Htab *strtab, Node *n)
{
- size_t i, sz;
-
- switch(exprop(n)) {
- case Oucon: sz = blobucon(b, globls, strtab, n); break;
- case Oslice: sz = blobslice(b, globls, strtab, n); break;
- case Ostruct: sz = blobstruct(b, globls, strtab, n); break;
- case Olit: sz = bloblit(b, strtab, n->expr.args[0], exprtype(n)); break;
- case Otup:
- case Oarr:
- /* Assumption: We sorted this while folding */
- sz = 0;
- for (i = 0; i < n->expr.nargs; i++)
- sz += blobrec(b, globls, strtab, n->expr.args[i]);
- break;
- default:
- dump(n, stdout);
- die("Nonliteral initializer for global");
- break;
- }
- return sz;
+ size_t i, sz;
+
+ switch(exprop(n)) {
+ case Oucon: sz = blobucon(b, globls, strtab, n); break;
+ case Oslice: sz = blobslice(b, globls, strtab, n); break;
+ case Ostruct: sz = blobstruct(b, globls, strtab, n); break;
+ case Olit: sz = bloblit(b, strtab, n->expr.args[0], exprtype(n)); break;
+ case Otup:
+ case Oarr:
+ /* Assumption: We sorted this while folding */
+ sz = 0;
+ for (i = 0; i < n->expr.nargs; i++)
+ sz += blobrec(b, globls, strtab, n->expr.args[i]);
+ break;
+ default:
+ dump(n, stdout);
+ die("Nonliteral initializer for global");
+ break;
+ }
+ return sz;
}
Blob *litblob(Htab *globls, Htab *strtab, Node *n)
{
- Blob *b;
+ Blob *b;
- b = mkblobseq(NULL, 0);
- blobrec(b, globls, strtab, n);
- return b;
+ b = mkblobseq(NULL, 0);
+ blobrec(b, globls, strtab, n);
+ return b;
}
diff --git a/6/gen.c b/6/gen.c
index 5290e6d..608ca66 100644
--- a/6/gen.c
+++ b/6/gen.c
@@ -17,88 +17,88 @@
void fillglobls(Stab *st, Htab *globls)
{
- size_t i, j, nk, nns;
- void **k, **ns;
- Stab *stab;
- Node *s;
-
- k = htkeys(st->dcl, &nk);
- for (i = 0; i < nk; i++) {
- s = htget(st->dcl, k[i]);
- if (isconstfn(s))
- s->decl.type = codetype(s->decl.type);
- htput(globls, s, asmname(s));
- }
- free(k);
-
- ns = htkeys(file->file.ns, &nns);
- for (j = 0; j < nns; j++) {
- stab = htget(file->file.ns, ns[j]);
- k = htkeys(stab->dcl, &nk);
- for (i = 0; i < nk; i++) {
- s = htget(stab->dcl, k[i]);
- htput(globls, s, asmname(s));
- }
- free(k);
- }
- free(ns);
+ size_t i, j, nk, nns;
+ void **k, **ns;
+ Stab *stab;
+ Node *s;
+
+ k = htkeys(st->dcl, &nk);
+ for (i = 0; i < nk; i++) {
+ s = htget(st->dcl, k[i]);
+ if (isconstfn(s))
+ s->decl.type = codetype(s->decl.type);
+ htput(globls, s, asmname(s));
+ }
+ free(k);
+
+ ns = htkeys(file->file.ns, &nns);
+ for (j = 0; j < nns; j++) {
+ stab = htget(file->file.ns, ns[j]);
+ k = htkeys(stab->dcl, &nk);
+ for (i = 0; i < nk; i++) {
+ s = htget(stab->dcl, k[i]);
+ htput(globls, s, asmname(s));
+ }
+ free(k);
+ }
+ free(ns);
}
Type *codetype(Type *ft)
{
- ft = tybase(ft);
- if (ft->type == Tycode)
- return ft;
- assert(ft->type == Tyfunc);
- ft = tydup(ft);
- ft->type = Tycode;
- return ft;
+ ft = tybase(ft);
+ if (ft->type == Tycode)
+ return ft;
+ assert(ft->type == Tyfunc);
+ ft = tydup(ft);
+ ft->type = Tycode;
+ return ft;
}
Type *closuretype(Type *ft)
{
- ft = tybase(ft);
- if (ft->type == Tyfunc)
- return ft;
- assert(ft->type == Tycode);
- ft = tydup(ft);
- ft->type = Tyfunc;
- return ft;
+ ft = tybase(ft);
+ if (ft->type == Tyfunc)
+ return ft;
+ assert(ft->type == Tycode);
+ ft = tydup(ft);
+ ft->type = Tyfunc;
+ return ft;
}
static int islocal(Node *dcl)
{
- if (dcl->decl.vis != Visintern)
- return 0;
- if (dcl->decl.isimport || dcl->decl.isextern)
- return 0;
- return 1;
+ if (dcl->decl.vis != Visintern)
+ return 0;
+ if (dcl->decl.isimport || dcl->decl.isextern)
+ return 0;
+ return 1;
}
char *genlocallblstr(char *buf, size_t sz)
{
- if (asmsyntax == Plan9)
- return genlblstr(buf, 128, "<>");
- else
- return genlblstr(buf, 128, "");
+ if (asmsyntax == Plan9)
+ return genlblstr(buf, 128, "<>");
+ else
+ return genlblstr(buf, 128, "");
}
int isconstfn(Node *n)
{
- Node *d;
- Type *t;
-
- if (n->type == Nexpr) {
- if (exprop(n) != Ovar)
- return 0;
- d = decls[n->expr.did];
- } else {
- d = n;
- }
- t = tybase(decltype(d));
- if (d && d->decl.isconst && d->decl.isglobl)
- return t->type == Tyfunc || t->type == Tycode;
- return 0;
+ Node *d;
+ Type *t;
+
+ if (n->type == Nexpr) {
+ if (exprop(n) != Ovar)
+ return 0;
+ d = decls[n->expr.did];
+ } else {
+ d = n;
+ }
+ t = tybase(decltype(d));
+ if (d && d->decl.isconst && d->decl.isglobl)
+ return t->type == Tyfunc || t->type == Tycode;
+ return 0;
}
/*
@@ -110,60 +110,60 @@ int isconstfn(Node *n)
*/
char *asmname(Node *dcl)
{
- char buf[1024];
- char *vis, *pf, *ns, *name, *sep;
- Node *n;
-
- n = dcl->decl.name;
- pf = Symprefix;
- ns = n->name.ns;
- name = n->name.name;
- vis = "";
- sep = "";
- if (asmsyntax == Plan9)
- if (islocal(dcl))
- vis = "<>";
- if (!ns || !ns[0])
- ns = "";
- else
- sep = "$";
- if (name[0] == '.')
- pf = "";
-
- bprintf(buf, sizeof buf, "%s%s%s%s%s", pf, ns, sep, name, vis);
- return strdup(buf);
+ char buf[1024];
+ char *vis, *pf, *ns, *name, *sep;
+ Node *n;
+
+ n = dcl->decl.name;
+ pf = Symprefix;
+ ns = n->name.ns;
+ name = n->name.name;
+ vis = "";
+ sep = "";
+ if (asmsyntax == Plan9)
+ if (islocal(dcl))
+ vis = "<>";
+ if (!ns || !ns[0])
+ ns = "";
+ else
+ sep = "$";
+ if (name[0] == '.')
+ pf = "";
+
+ bprintf(buf, sizeof buf, "%s%s%s%s%s", pf, ns, sep, name, vis);
+ return strdup(buf);
}
char *tydescid(char *buf, size_t bufsz, Type *ty)
{
- char *sep, *ns;
-
- sep = "";
- ns = "";
- if (ty->type == Tyname) {
- if (ty->name->name.ns) {
- ns = ty->name->name.ns;
- sep = "$";
- }
- if (ty->vis == Visexport || ty->isimport)
- bprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
- else
- bprintf(buf, bufsz, "_tydesc$%s%s%s$%d", ns, sep, ty->name->name.name, ty->tid);
- } else {
- if (file->file.globls->name) {
- ns = file->file.globls->name;
- sep = "$";
- }
- bprintf(buf, bufsz, "_tydesc%s%s$%d",sep, ns, ty->tid);
- }
- return buf;
+ char *sep, *ns;
+
+ sep = "";
+ ns = "";
+ if (ty->type == Tyname) {
+ if (ty->name->name.ns) {
+ ns = ty->name->name.ns;
+ sep = "$";
+ }
+ if (ty->vis == Visexport || ty->isimport)
+ bprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
+ else
+ bprintf(buf, bufsz, "_tydesc$%s%s%s$%d", ns, sep, ty->name->name.name, ty->tid);
+ } else {
+ if (file->file.globls->name) {
+ ns = file->file.globls->name;
+ sep = "$";
+ }
+ bprintf(buf, bufsz, "_tydesc%s%s$%d",sep, ns, ty->tid);
+ }
+ return buf;
}
void gen(Node *file, char *out)
{
- switch (asmsyntax) {
- case Plan9: genp9(file, out); break;
- case Gnugas: gengas(file, out); break;
- default: die("unknown target"); break;
- }
+ switch (asmsyntax) {
+ case Plan9: genp9(file, out); break;
+ case Gnugas: gengas(file, out); break;
+ default: die("unknown target"); break;
+ }
}
diff --git a/6/gengas.c b/6/gengas.c
index 08a2b04..1578a09 100644
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -30,312 +30,312 @@ static char *regnames[] = {
};
static char* modenames[] = {
- [ModeB] = "b",
- [ModeW] = "w",
- [ModeL] = "l",
- [ModeQ] = "q",
- [ModeF] = "s",
- [ModeD] = "d"
+ [ModeB] = "b",
+ [ModeW] = "w",
+ [ModeL] = "l",
+ [ModeQ] = "q",
+ [ModeF] = "s",
+ [ModeD] = "d"
};
static void locprint(FILE *fd, Loc *l, char spec);
static void initconsts(Htab *globls)
{
- Type *ty;
- Node *name;
- Node *dcl;
-
- tyintptr = mktype(Zloc, Tyuint64);
- tyword = mktype(Zloc, Tyuint);
- tyvoid = mktype(Zloc, Tyvoid);
-
- ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
- ty->type = Tycode;
- name = mknsname(Zloc, "_rt", "abort_oob");
- dcl = mkdecl(Zloc, name, ty);
- dcl->decl.isconst = 1;
- dcl->decl.isextern = 1;
- dcl->decl.isglobl = 1;
- htput(globls, dcl, asmname(dcl));
-
- abortoob = mkexpr(Zloc, Ovar, name, NULL);
- abortoob->expr.type = ty;
- abortoob->expr.did = dcl->decl.did;
- abortoob->expr.isconst = 1;
+ Type *ty;
+ Node *name;
+ Node *dcl;
+
+ tyintptr = mktype(Zloc, Tyuint64);
+ tyword = mktype(Zloc, Tyuint);
+ tyvoid = mktype(Zloc, Tyvoid);
+
+ ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
+ ty->type = Tycode;
+ name = mknsname(Zloc, "_rt", "abort_oob");
+ dcl = mkdecl(Zloc, name, ty);
+ dcl->decl.isconst = 1;
+ dcl->decl.isextern = 1;
+ dcl->decl.isglobl = 1;
+ htput(globls, dcl, asmname(dcl));
+
+ abortoob = mkexpr(Zloc, Ovar, name, NULL);
+ abortoob->expr.type = ty;
+ abortoob->expr.did = dcl->decl.did;
+ abortoob->expr.isconst = 1;
}
void printmem(FILE *fd, Loc *l, char spec)
{
- if (l->type == Locmem) {
- if (l->mem.constdisp)
- fprintf(fd, "%ld", l->mem.constdisp);
- } else {
- if (l->mem.lbldisp)
- fprintf(fd, "%s", l->mem.lbldisp);
- }
- if (l->mem.base) {
- fprintf(fd, "(");
- locprint(fd, l->mem.base, 'r');
- if (l->mem.idx) {
- fprintf(fd, ",");
- locprint(fd, l->mem.idx, 'r');
- }
- if (l->mem.scale > 1)
- fprintf(fd, ",%d", l->mem.scale);
- if (l->mem.base)
- fprintf(fd, ")");
- } else if (l->type != Locmeml) {
- die("Only locmeml can have unspecified base reg");
- }
+ if (l->type == Locmem) {
+ if (l->mem.constdisp)
+ fprintf(fd, "%ld", l->mem.constdisp);
+ } else {
+ if (l->mem.lbldisp)
+ fprintf(fd, "%s", l->mem.lbldisp);
+ }
+ if (l->mem.base) {
+ fprintf(fd, "(");
+ locprint(fd, l->mem.base, 'r');
+ if (l->mem.idx) {
+ fprintf(fd, ",");
+ locprint(fd, l->mem.idx, 'r');
+ }
+ if (l->mem.scale > 1)
+ fprintf(fd, ",%d", l->mem.scale);
+ if (l->mem.base)
+ fprintf(fd, ")");
+ } else if (l->type != Locmeml) {
+ die("Only locmeml can have unspecified base reg");
+ }
}
static void locprint(FILE *fd, Loc *l, char spec)
{
- assert(l->mode);
- switch (l->type) {
- case Loclitl:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%s", l->lbl);
- break;
- case Loclbl:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- fprintf(fd, "%s", l->lbl);
- break;
- case Locreg:
- assert((spec == 'r' && isintmode(l->mode)) ||
- (spec == 'f' && isfloatmode(l->mode)) ||
- spec == 'v' ||
- spec == 'x' ||
- spec == 'u');
- if (l->reg.colour == Rnone)
- fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
- else
- fprintf(fd, "%s", regnames[l->reg.colour]);
- break;
- case Locmem:
- case Locmeml:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- printmem(fd, l, spec);
- break;
- case Loclit:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%ld", l->lit);
- break;
- case Locnone:
- die("Bad location in locprint()");
- break;
- }
+ assert(l->mode);
+ switch (l->type) {
+ case Loclitl:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%s", l->lbl);
+ break;
+ case Loclbl:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ fprintf(fd, "%s", l->lbl);
+ break;
+ case Locreg:
+ assert((spec == 'r' && isintmode(l->mode)) ||
+ (spec == 'f' && isfloatmode(l->mode)) ||
+ spec == 'v' ||
+ spec == 'x' ||
+ spec == 'u');
+ if (l->reg.colour == Rnone)
+ fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
+ else
+ fprintf(fd, "%s", regnames[l->reg.colour]);
+ break;
+ case Locmem:
+ case Locmeml:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ printmem(fd, l, spec);
+ break;
+ case Loclit:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%ld", l->lit);
+ break;
+ case Locnone:
+ die("Bad location in locprint()");
+ break;
+ }
}
static int issubreg(Loc *a, Loc *b)
{
- return rclass(a) == rclass(b) && a->mode != b->mode;
+ return rclass(a) == rclass(b) && a->mode != b->mode;
}
void iprintf(FILE *fd, Insn *insn)
{
- char *p;
- int i;
- int idx;
-
- /* x64 has a quirk; it has no movzlq because mov zero extends. This
- * means that we need to do a movl when we really want a movzlq. Since
- * we don't know the name of the reg to use, we need to sub it in when
- * writing... */
- switch (insn->op) {
- case Imovzx:
- if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
- if (insn->args[1]->reg.colour) {
- insn->op = Imov;
- insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
- }
- }
- break;
- case Imovs:
- if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
- break;
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- case Imov:
- assert(!isfloatmode(insn->args[0]->mode));
- if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
- break;
- if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
- break;
- /* if one reg is a subreg of another, we can just use the right
- * mode to move between them. */
- if (issubreg(insn->args[0], insn->args[1]))
- insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- default:
- break;
- }
- p = insnfmt[insn->op];
- i = 0;
- for (; *p; p++) {
- if (*p != '%') {
- fputc(*p, fd);
- continue;
- }
-
- /* %-formating */
- p++;
- idx = i;
+ char *p;
+ int i;
+ int idx;
+
+ /* x64 has a quirk; it has no movzlq because mov zero extends. This
+ * means that we need to do a movl when we really want a movzlq. Since
+ * we don't know the name of the reg to use, we need to sub it in when
+ * writing... */
+ switch (insn->op) {
+ case Imovzx:
+ if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
+ if (insn->args[1]->reg.colour) {
+ insn->op = Imov;
+ insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
+ }
+ }
+ break;
+ case Imovs:
+ if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+ break;
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ case Imov:
+ assert(!isfloatmode(insn->args[0]->mode));
+ if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
+ break;
+ if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+ break;
+ /* if one reg is a subreg of another, we can just use the right
+ * mode to move between them. */
+ if (issubreg(insn->args[0], insn->args[1]))
+ insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ default:
+ break;
+ }
+ p = insnfmt[insn->op];
+ i = 0;
+ for (; *p; p++) {
+ if (*p != '%') {
+ fputc(*p, fd);
+ continue;
+ }
+
+ /* %-formating */
+ p++;
+ idx = i;
again:
- switch (*p) {
- case '\0':
- goto done; /* skip the final p++ */
- case 'r': /* int register */
- case 'f': /* float register */
- case 'm': /* memory */
- case 'i': /* imm */
- case 'v': /* reg/mem */
- case 'u': /* reg/imm */
- case 'x': /* reg/mem/imm */
- locprint(fd, insn->args[idx], *p);
- i++;
- break;
- case 't':
- fputs(modenames[insn->args[idx]->mode], fd);
- break;
- default:
- /* the asm description uses 1-based indexing, so that 0
- * can be used as a sentinel. */
- if (!isdigit(*p))
- die("Invalid %%-specifier '%c'", *p);
- idx = strtol(p, &p, 10) - 1;
- goto again;
- break;
- }
- }
+ switch (*p) {
+ case '\0':
+ goto done; /* skip the final p++ */
+ case 'r': /* int register */
+ case 'f': /* float register */
+ case 'm': /* memory */
+ case 'i': /* imm */
+ case 'v': /* reg/mem */
+ case 'u': /* reg/imm */
+ case 'x': /* reg/mem/imm */
+ locprint(fd, insn->args[idx], *p);
+ i++;
+ break;
+ case 't':
+ fputs(modenames[insn->args[idx]->mode], fd);
+ break;
+ default:
+ /* the asm description uses 1-based indexing, so that 0
+ * can be used as a sentinel. */
+ if (!isdigit(*p))
+ die("Invalid %%-specifier '%c'", *p);
+ idx = strtol(p, &p, 10) - 1;
+ goto again;
+ break;
+ }
+ }
done:
- return;
+ return;
}
static void writebytes(FILE *fd, char *p, size_t sz)
{
- size_t i;
-
- for (i = 0; i < sz; i++) {
- if (i % 60 == 0)
- fprintf(fd, "\t.ascii \"");
- if (p[i] == '"' || p[i] == '\\')
- fprintf(fd, "\\");
- if (isprint(p[i]))
- fprintf(fd, "%c", p[i]);
- else
- fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
- /* line wrapping for readability */
- if (i % 60 == 59 || i == sz - 1)
- fprintf(fd, "\"\n");
- }
+ size_t i;
+
+ for (i = 0; i < sz; i++) {
+ if (i % 60 == 0)
+ fprintf(fd, "\t.ascii \"");
+ if (p[i] == '"' || p[i] == '\\')
+ fprintf(fd, "\\");
+ if (isprint(p[i]))
+ fprintf(fd, "%c", p[i]);
+ else
+ fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
+ /* line wrapping for readability */
+ if (i % 60 == 59 || i == sz - 1)
+ fprintf(fd, "\"\n");
+ }
}
void genstrings(FILE *fd, Htab *strtab)
{
- void **k;
- Str *s;
- size_t i, nk;
-
- k = htkeys(strtab, &nk);
- for (i = 0; i < nk; i++) {
- s = k[i];
- fprintf(fd, "%s:\n", (char*)htget(strtab, k[i]));
- writebytes(fd, s->buf, s->len);
- }
+ void **k;
+ Str *s;
+ size_t i, nk;
+
+ k = htkeys(strtab, &nk);
+ for (i = 0; i < nk; i++) {
+ s = k[i];
+ fprintf(fd, "%s:\n", (char*)htget(strtab, k[i]));
+ writebytes(fd, s->buf, s->len);
+ }
}
static void writeasm(FILE *fd, Isel *s, Func *fn)
{
- size_t i, j;
-
- if (fn->isexport)
- fprintf(fd, ".globl %s\n", fn->name);
- fprintf(fd, "%s:\n", fn->name);
- for (j = 0; j < s->cfg->nbb; j++) {
- if (!s->bb[j])
- continue;
- for (i = 0; i < s->bb[j]->nlbls; i++)
- fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
- for (i = 0; i < s->bb[j]->ni; i++)
- iprintf(fd, s->bb[j]->il[i]);
- }
+ size_t i, j;
+
+ if (fn->isexport)
+ fprintf(fd, ".globl %s\n", fn->name);
+ fprintf(fd, "%s:\n", fn->name);
+ for (j = 0; j < s->cfg->nbb; j++) {
+ if (!s->bb[j])
+ continue;
+ for (i = 0; i < s->bb[j]->nlbls; i++)
+ fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
+ for (i = 0; i < s->bb[j]->ni; i++)
+ iprintf(fd, s->bb[j]->il[i]);
+ }
}
static void encodemin(FILE *fd, uint64_t val)
{
- size_t i, shift;
- uint8_t b;
-
- if (val < 128) {
- fprintf(fd, "\t.byte %zd\n", val);
- return;
- }
-
- for (i = 1; i < 8; i++)
- if (val < 1ULL << (7*i))
- break;
- shift = 8 - i;
- b = ~0 << (shift + 1);
- b |= val & ((1 << (8 - shift)) - 1);
- fprintf(fd, "\t.byte %u\n", b);
- val >>= shift;
- while (val != 0) {
- fprintf(fd, "\t.byte %u\n", (uint)val & 0xff);
- val >>= 8;
- }
+ size_t i, shift;
+ uint8_t b;
+
+ if (val < 128) {
+ fprintf(fd, "\t.byte %zd\n", val);
+ return;
+ }
+
+ for (i = 1; i < 8; i++)
+ if (val < 1ULL << (7*i))
+ break;
+ shift = 8 - i;
+ b = ~0 << (shift + 1);
+ b |= val & ((1 << (8 - shift)) - 1);
+ fprintf(fd, "\t.byte %u\n", b);
+ val >>= shift;
+ while (val != 0) {
+ fprintf(fd, "\t.byte %u\n", (uint)val & 0xff);
+ val >>= 8;
+ }
}
static void writeblob(FILE *fd, Blob *b)
{
- size_t i;
-
- if (!b)
- return;
- if (b->lbl) {
- if (b->isglobl)
- fprintf(fd, ".globl %s%s\n", Symprefix, b->lbl);
- fprintf(fd, "%s%s:\n", Symprefix, b->lbl);
- }
- switch (b->type) {
- case Bti8:
- fprintf(fd, "\t.byte %zd\n", b->ival);
- break;
- case Bti16:
- fprintf(fd, "\t.short %zd\n", b->ival);
- break;
- case Bti32:
- fprintf(fd, "\t.long %zd\n", b->ival);
- break;
- case Bti64:
- fprintf(fd, "\t.quad %zd\n", b->ival);
- break;
- case Btimin:
- encodemin(fd, b->ival);
- break;
- case Btref:
- fprintf(fd, "\t.quad %s + %zd\n", b->ref.str, b->ref.off);
- break;
- case Btbytes:
- writebytes(fd, b->bytes.buf, b->bytes.len);
- break;
- case Btseq:
- for (i = 0; i < b->seq.nsub; i++)
- writeblob(fd, b->seq.sub[i]);
- break;
- case Btpad:
- for (i = 0; i < b->npad; i++)
- fprintf(fd, "\t.byte 0\n");
- break;
-
- }
+ size_t i;
+
+ if (!b)
+ return;
+ if (b->lbl) {
+ if (b->isglobl)
+ fprintf(fd, ".globl %s%s\n", Symprefix, b->lbl);
+ fprintf(fd, "%s%s:\n", Symprefix, b->lbl);
+ }
+ switch (b->type) {
+ case Bti8:
+ fprintf(fd, "\t.byte %zd\n", b->ival);
+ break;
+ case Bti16:
+ fprintf(fd, "\t.short %zd\n", b->ival);
+ break;
+ case Bti32:
+ fprintf(fd, "\t.long %zd\n", b->ival);
+ break;
+ case Bti64:
+ fprintf(fd, "\t.quad %zd\n", b->ival);
+ break;
+ case Btimin:
+ encodemin(fd, b->ival);
+ break;
+ case Btref:
+ fprintf(fd, "\t.quad %s + %zd\n", b->ref.str, b->ref.off);
+ break;
+ case Btbytes:
+ writebytes(fd, b->bytes.buf, b->bytes.len);
+ break;
+ case Btseq:
+ for (i = 0; i < b->seq.nsub; i++)
+ writeblob(fd, b->seq.sub[i]);
+ break;
+ case Btpad:
+ for (i = 0; i < b->npad; i++)
+ fprintf(fd, "\t.byte 0\n");
+ break;
+
+ }
}
/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
@@ -343,127 +343,127 @@ static void writeblob(FILE *fd, Blob *b)
* operations on x32, no structures, and so on. */
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;
- if (fn->hasenv)
- is.envp = locreg(ModeQ);
-
- selfunc(&is, fn, globls, strtab);
- if (debugopt['i'])
- writeasm(stdout, &is, fn);
- writeasm(fd, &is, fn);
+ 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;
+ if (fn->hasenv)
+ is.envp = locreg(ModeQ);
+
+ selfunc(&is, fn, globls, strtab);
+ if (debugopt['i'])
+ writeasm(stdout, &is, fn);
+ writeasm(fd, &is, fn);
}
void gentype(FILE *fd, Type *ty)
{
- Blob *b;
+ Blob *b;
- if (ty->type == Tyvar)
- return;
- b = tydescblob(ty);
- writeblob(fd, b);
- blobfree(b);
+ if (ty->type == Tyvar)
+ return;
+ b = tydescblob(ty);
+ writeblob(fd, b);
+ blobfree(b);
}
void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
{
- char *lbl;
- Blob *b;
-
- /* lits and such also get wrapped in decls */
- assert(blob->type == Ndecl);
-
- lbl = htget(globls, blob);
- if (blob->decl.vis != Visintern)
- fprintf(fd, ".globl %s\n", lbl);
- fprintf(fd, ".align %zd\n", tyalign(decltype(blob)));
- fprintf(fd, "%s:\n", lbl);
- if (blob->decl.init)
- b = litblob(globls, strtab, blob->decl.init);
- else
- b = mkblobpad(size(blob));
- writeblob(fd, b);
- blobfree(b);
+ char *lbl;
+ Blob *b;
+
+ /* lits and such also get wrapped in decls */
+ assert(blob->type == Ndecl);
+
+ lbl = htget(globls, blob);
+ if (blob->decl.vis != Visintern)
+ fprintf(fd, ".globl %s\n", lbl);
+ fprintf(fd, ".align %zd\n", tyalign(decltype(blob)));
+ fprintf(fd, "%s:\n", lbl);
+ if (blob->decl.init)
+ b = litblob(globls, strtab, blob->decl.init);
+ else
+ b = mkblobpad(size(blob));
+ writeblob(fd, b);
+ blobfree(b);
}
void gengas(Node *file, char *out)
{
- Htab *globls, *strtab;
- Node *n, **blob;
- Func **fn;
- size_t nfn, nblob;
- size_t i;
- FILE *fd;
-
- /* ensure that all physical registers have a loc created before any
- * other locs, so that locmap[Physreg] maps to the Loc for the physreg
- * in question */
- for (i = 0; i < Nreg; i++)
- locphysreg(i);
-
- fn = NULL;
- nfn = 0;
- blob = NULL;
- nblob = 0;
- globls = mkht(varhash, vareq);
- initconsts(globls);
-
- /* We need to define all global variables before use */
- fillglobls(file->file.globls, globls);
-
- pushstab(file->file.globls);
- for (i = 0; i < file->file.nstmts; i++) {
- n = file->file.stmts[i];
- switch (n->type) {
- case Nuse: /* nothing to do */
- case Nimpl:
- break;
- case Ndecl:
- simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
- break;
- default:
- die("Bad node %s in toplevel", nodestr[n->type]);
- break;
- }
- }
- popstab();
-
- fd = fopen(out, "w");
- if (!fd)
- die("Couldn't open fd %s", out);
-
- strtab = mkht(strlithash, strliteq);
- fprintf(fd, ".data\n");
- for (i = 0; i < nblob; i++)
- genblob(fd, blob[i], globls, strtab);
- fprintf(fd, "\n");
-
- fprintf(fd, ".text\n");
- for (i = 0; i < nfn; i++)
- genfunc(fd, fn[i], globls, strtab);
- fprintf(fd, "\n");
-
- for (i = 0; i < ntypes; i++)
- if (types[i]->isreflect && !types[i]->isimport)
- gentype(fd, types[i]);
- fprintf(fd, "\n");
-
- genstrings(fd, strtab);
- fclose(fd);
+ Htab *globls, *strtab;
+ Node *n, **blob;
+ Func **fn;
+ size_t nfn, nblob;
+ size_t i;
+ FILE *fd;
+
+ /* ensure that all physical registers have a loc created before any
+ * other locs, so that locmap[Physreg] maps to the Loc for the physreg
+ * in question */
+ for (i = 0; i < Nreg; i++)
+ locphysreg(i);
+
+ fn = NULL;
+ nfn = 0;
+ blob = NULL;
+ nblob = 0;
+ globls = mkht(varhash, vareq);
+ initconsts(globls);
+
+ /* We need to define all global variables before use */
+ fillglobls(file->file.globls, globls);
+
+ pushstab(file->file.globls);
+ for (i = 0; i < file->file.nstmts; i++) {
+ n = file->file.stmts[i];
+ switch (n->type) {
+ case Nuse: /* nothing to do */
+ case Nimpl:
+ break;
+ case Ndecl:
+ simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
+ break;
+ default:
+ die("Bad node %s in toplevel", nodestr[n->type]);
+ break;
+ }
+ }
+ popstab();
+
+ fd = fopen(out, "w");
+ if (!fd)
+ die("Couldn't open fd %s", out);
+
+ strtab = mkht(strlithash, strliteq);
+ fprintf(fd, ".data\n");
+ for (i = 0; i < nblob; i++)
+ genblob(fd, blob[i], globls, strtab);
+ fprintf(fd, "\n");
+
+ fprintf(fd, ".text\n");
+ for (i = 0; i < nfn; i++)
+ genfunc(fd, fn[i], globls, strtab);
+ fprintf(fd, "\n");
+
+ for (i = 0; i < ntypes; i++)
+ if (types[i]->isreflect && !types[i]->isimport)
+ gentype(fd, types[i]);
+ fprintf(fd, "\n");
+
+ genstrings(fd, strtab);
+ fclose(fd);
}
void dbglocprint(FILE *fd, Loc *l, char spec)
{
- locprint(fd, l, spec);
+ locprint(fd, l, spec);
}
void dbgiprintf(FILE *fd, Insn *i)
{
- iprintf(fd, i);
+ iprintf(fd, i);
}
diff --git a/6/genp9.c b/6/genp9.c
index 0a83335..68e9d1b 100644
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -29,334 +29,334 @@ static char *regnames[] = {
};
static char* modenames[] = {
- [ModeB] = "B",
- [ModeW] = "W",
- [ModeL] = "L",
- [ModeQ] = "Q",
- [ModeF] = "S",
- [ModeD] = "D"
+ [ModeB] = "B",
+ [ModeW] = "W",
+ [ModeL] = "L",
+ [ModeQ] = "Q",
+ [ModeF] = "S",
+ [ModeD] = "D"
};
static void locprint(FILE *fd, Loc *l, char spec);
static void initconsts(Htab *globls)
{
- Type *ty;
- Node *name;
- Node *dcl;
-
- tyintptr = mktype(Zloc, Tyuint64);
- tyword = mktype(Zloc, Tyuint);
- tyvoid = mktype(Zloc, Tyvoid);
-
- ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
- ty->type = Tycode;
- name = mknsname(Zloc, "_rt", "abort_oob");
- dcl = mkdecl(Zloc, name, ty);
- dcl->decl.isconst = 1;
- dcl->decl.isextern = 1;
- htput(globls, dcl, asmname(dcl));
-
- abortoob = mkexpr(Zloc, Ovar, name, NULL);
- abortoob->expr.type = ty;
- abortoob->expr.did = dcl->decl.did;
- abortoob->expr.isconst = 1;
+ Type *ty;
+ Node *name;
+ Node *dcl;
+
+ tyintptr = mktype(Zloc, Tyuint64);
+ tyword = mktype(Zloc, Tyuint);
+ tyvoid = mktype(Zloc, Tyvoid);
+
+ ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
+ ty->type = Tycode;
+ name = mknsname(Zloc, "_rt", "abort_oob");
+ dcl = mkdecl(Zloc, name, ty);
+ dcl->decl.isconst = 1;
+ dcl->decl.isextern = 1;
+ htput(globls, dcl, asmname(dcl));
+
+ abortoob = mkexpr(Zloc, Ovar, name, NULL);
+ abortoob->expr.type = ty;
+ abortoob->expr.did = dcl->decl.did;
+ abortoob->expr.isconst = 1;
}
static void printmem(FILE *fd, Loc *l, char spec)
{
- if (l->type == Locmem) {
- if (l->mem.constdisp)
- fprintf(fd, "%ld", l->mem.constdisp);
- } else if (l->mem.lbldisp) {
- fprintf(fd, "%s", l->mem.lbldisp);
- }
- if (!l->mem.base || l->mem.base->reg.colour == Rrip) {
- fprintf(fd, "+0(SB)");
- } else {
- fprintf(fd, "(");
- locprint(fd, l->mem.base, 'r');
- fprintf(fd, ")");
- }
- if (l->mem.idx) {
- fprintf(fd, "(");
- locprint(fd, l->mem.idx, 'r');
- fprintf(fd, "*%d", l->mem.scale);
- fprintf(fd, ")");
- }
+ if (l->type == Locmem) {
+ if (l->mem.constdisp)
+ fprintf(fd, "%ld", l->mem.constdisp);
+ } else if (l->mem.lbldisp) {
+ fprintf(fd, "%s", l->mem.lbldisp);
+ }
+ if (!l->mem.base || l->mem.base->reg.colour == Rrip) {
+ fprintf(fd, "+0(SB)");
+ } else {
+ fprintf(fd, "(");
+ locprint(fd, l->mem.base, 'r');
+ fprintf(fd, ")");
+ }
+ if (l->mem.idx) {
+ fprintf(fd, "(");
+ locprint(fd, l->mem.idx, 'r');
+ fprintf(fd, "*%d", l->mem.scale);
+ fprintf(fd, ")");
+ }
}
static void locprint(FILE *fd, Loc *l, char spec)
{
- spec = tolower(spec);
- assert(l->mode);
- switch (l->type) {
- case Loclitl:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%s", l->lbl);
- break;
- case Loclbl:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- fprintf(fd, "%s", l->lbl);
- break;
- case Locreg:
- assert((spec == 'r' && isintmode(l->mode)) ||
- (spec == 'f' && isfloatmode(l->mode)) ||
- spec == 'v' ||
- spec == 'x' ||
- spec == 'u');
- if (l->reg.colour == Rnone)
- fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
- else
- fprintf(fd, "%s", regnames[l->reg.colour]);
- break;
- case Locmem:
- case Locmeml:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- printmem(fd, l, spec);
- break;
- case Loclit:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%ld", l->lit);
- break;
- case Locnone:
- die("Bad location in locprint()");
- break;
- }
+ spec = tolower(spec);
+ assert(l->mode);
+ switch (l->type) {
+ case Loclitl:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%s", l->lbl);
+ break;
+ case Loclbl:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ fprintf(fd, "%s", l->lbl);
+ break;
+ case Locreg:
+ assert((spec == 'r' && isintmode(l->mode)) ||
+ (spec == 'f' && isfloatmode(l->mode)) ||
+ spec == 'v' ||
+ spec == 'x' ||
+ spec == 'u');
+ if (l->reg.colour == Rnone)
+ fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
+ else
+ fprintf(fd, "%s", regnames[l->reg.colour]);
+ break;
+ case Locmem:
+ case Locmeml:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ printmem(fd, l, spec);
+ break;
+ case Loclit:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%ld", l->lit);
+ break;
+ case Locnone:
+ die("Bad location in locprint()");
+ break;
+ }
}
static int issubreg(Loc *a, Loc *b)
{
- return rclass(a) == rclass(b) && a->mode != b->mode;
+ return rclass(a) == rclass(b) && a->mode != b->mode;
}
static void iprintf(FILE *fd, Insn *insn)
{
- char *p;
- int i;
- int idx;
-
- /* x64 has a quirk; it has no movzlq because mov zero extends. This
- * means that we need to do a movl when we really want a movzlq. Since
- * we don't know the name of the reg to use, we need to sub it in when
- * writing... */
- switch (insn->op) {
- case Imovzx:
- if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
- if (insn->args[1]->reg.colour) {
- insn->op = Imov;
- insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
- }
- }
- break;
- case Imovs:
- if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
- break;
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- case Imov:
- assert(!isfloatmode(insn->args[0]->mode));
- if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
- break;
- if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
- break;
- /* if one reg is a subreg of another, we can just use the right
- * mode to move between them. */
- if (issubreg(insn->args[0], insn->args[1]))
- insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- default:
- break;
- }
- p = insnfmt[insn->op];
- i = 0; /* NB: this is 1 based indexing */
- for (; *p; p++) {
- if (*p != '%') {
- fputc(*p, fd);
- continue;
- }
-
- /* %-formating */
- p++;
- idx = i;
+ char *p;
+ int i;
+ int idx;
+
+ /* x64 has a quirk; it has no movzlq because mov zero extends. This
+ * means that we need to do a movl when we really want a movzlq. Since
+ * we don't know the name of the reg to use, we need to sub it in when
+ * writing... */
+ switch (insn->op) {
+ case Imovzx:
+ if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
+ if (insn->args[1]->reg.colour) {
+ insn->op = Imov;
+ insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
+ }
+ }
+ break;
+ case Imovs:
+ if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+ break;
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ case Imov:
+ assert(!isfloatmode(insn->args[0]->mode));
+ if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
+ break;
+ if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+ break;
+ /* if one reg is a subreg of another, we can just use the right
+ * mode to move between them. */
+ if (issubreg(insn->args[0], insn->args[1]))
+ insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ default:
+ break;
+ }
+ p = insnfmt[insn->op];
+ i = 0; /* NB: this is 1 based indexing */
+ for (; *p; p++) {
+ if (*p != '%') {
+ fputc(*p, fd);
+ continue;
+ }
+
+ /* %-formating */
+ p++;
+ idx = i;
again:
- switch (*p) {
- case '\0':
- goto done; /* skip the final p++ */
- break;
- case 'R': /* int register */
- case 'F': /* float register */
- case 'M': /* memory */
- case 'I': /* imm */
- case 'V': /* reg/mem */
- case 'U': /* reg/imm */
- case 'X': /* reg/mem/imm */
- locprint(fd, insn->args[idx], *p);
- i++;
- break;
- case 'T':
- fputs(modenames[insn->args[idx]->mode], fd);
- break;
- default:
- /* the asm description uses 1-based indexing, so that 0
- * can be used as a sentinel. */
- if (!isdigit(*p))
- die("Invalid %%-specifier '%c'", *p);
- idx = strtol(p, &p, 10) - 1;
- goto again;
- break;
- }
- }
+ switch (*p) {
+ case '\0':
+ goto done; /* skip the final p++ */
+ break;
+ case 'R': /* int register */
+ case 'F': /* float register */
+ case 'M': /* memory */
+ case 'I': /* imm */
+ case 'V': /* reg/mem */
+ case 'U': /* reg/imm */
+ case 'X': /* reg/mem/imm */
+ locprint(fd, insn->args[idx], *p);
+ i++;
+ break;
+ case 'T':
+ fputs(modenames[insn->args[idx]->mode], fd);
+ break;
+ default:
+ /* the asm description uses 1-based indexing, so that 0
+ * can be used as a sentinel. */
+ if (!isdigit(*p))
+ die("Invalid %%-specifier '%c'", *p);
+ idx = strtol(p, &p, 10) - 1;
+ goto again;
+ break;
+ }
+ }
done:
- return;
+ return;
}
static size_t writebytes(FILE *fd, char *name, size_t off, char *p, size_t sz)
{
- size_t i, len;
-
- assert(sz != 0);
- for (i = 0; i < sz; i++) {
- len = min(sz - i, 8);
- if (i % 8 == 0)
- fprintf(fd, "DATA %s+%zd(SB)/%zd,$\"", name, off + i, len);
- if (p[i] == '"' || p[i] == '\\')
- fprintf(fd, "\\");
- if (isprint(p[i]))
- fprintf(fd, "%c", p[i]);
- else
- fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
- /* line wrapping for readability */
- if (i % 8 == 7 || i == sz - 1)
- fprintf(fd, "\"\n");
- }
-
- return sz;
+ size_t i, len;
+
+ assert(sz != 0);
+ for (i = 0; i < sz; i++) {
+ len = min(sz - i, 8);
+ if (i % 8 == 0)
+ fprintf(fd, "DATA %s+%zd(SB)/%zd,$\"", name, off + i, len);
+ if (p[i] == '"' || p[i] == '\\')
+ fprintf(fd, "\\");
+ if (isprint(p[i]))
+ fprintf(fd, "%c", p[i]);
+ else
+ fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
+ /* line wrapping for readability */
+ if (i % 8 == 7 || i == sz - 1)
+ fprintf(fd, "\"\n");
+ }
+
+ return sz;
}
static void genstrings(FILE *fd, Htab *strtab)
{
- void **k;
- char *lbl;
- Str *s;
- size_t i, nk;
-
- k = htkeys(strtab, &nk);
- for (i = 0; i < nk; i++) {
- s = k[i];
- lbl = htget(strtab, k[i]);
- if (s->len) {
- fprintf(fd, "GLOBL %s+0(SB),$%lld\n", lbl, (vlong)s->len);
- writebytes(fd, lbl, 0, s->buf, s->len);
- }
- }
+ void **k;
+ char *lbl;
+ Str *s;
+ size_t i, nk;
+
+ k = htkeys(strtab, &nk);
+ for (i = 0; i < nk; i++) {
+ s = k[i];
+ lbl = htget(strtab, k[i]);
+ if (s->len) {
+ fprintf(fd, "GLOBL %s+0(SB),$%lld\n", lbl, (vlong)s->len);
+ writebytes(fd, lbl, 0, s->buf, s->len);
+ }
+ }
}
static void writeasm(FILE *fd, Isel *s, Func *fn)
{
- size_t i, j;
- char *hidden;
-
- hidden = "";
- if (fn->isexport)
- hidden = "";
- /* we don't use the stack size directive: myrddin handles
- * the stack frobbing on its own */
- fprintf(fd, "TEXT %s%s+0(SB),$0\n", fn->name, hidden);
- for (j = 0; j < s->cfg->nbb; j++) {
- if (!s->bb[j])
- continue;
- for (i = 0; i < s->bb[j]->nlbls; i++)
- fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
- for (i = 0; i < s->bb[j]->ni; i++)
- iprintf(fd, s->bb[j]->il[i]);
- }
+ size_t i, j;
+ char *hidden;
+
+ hidden = "";
+ if (fn->isexport)
+ hidden = "";
+ /* we don't use the stack size directive: myrddin handles
+ * the stack frobbing on its own */
+ fprintf(fd, "TEXT %s%s+0(SB),$0\n", fn->name, hidden);
+ for (j = 0; j < s->cfg->nbb; j++) {
+ if (!s->bb[j])
+ continue;
+ for (i = 0; i < s->bb[j]->nlbls; i++)
+ fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
+ for (i = 0; i < s->bb[j]->ni; i++)
+ iprintf(fd, s->bb[j]->il[i]);
+ }
}
static size_t encodemin(FILE *fd, uint64_t val, size_t off, char *lbl)
{
- size_t i, shift, n;
- uint8_t b;
-
- if (val < 128) {
- fprintf(fd, "\tDATA %s+%zd(SB)/1,$%zd\n", lbl, off, val);
- return 1;
- }
-
- for (i = 1; i < 8; i++)
- if (val < 1ULL << (7*i))
- break;
-
- n = 0;
- shift = 8 - i;
- b = ~0 << (shift + 1);
- b |= val & ((1 << (8 - shift)) - 1);
- fprintf(fd, "\tDATA %s+%zd(SB)/1,$%u\n", lbl, off, b);
- val >>= shift;
- while (val != 0) {
- n++;
- fprintf(fd, "\tDATA %s+%zd(SB)/1,$%u\n", lbl, off+n, (uint)val & 0xff);
- val >>= 8;
- }
- return i;
+ size_t i, shift, n;
+ uint8_t b;
+
+ if (val < 128) {
+ fprintf(fd, "\tDATA %s+%zd(SB)/1,$%zd\n", lbl, off, val);
+ return 1;
+ }
+
+ for (i = 1; i < 8; i++)
+ if (val < 1ULL << (7*i))
+ break;
+
+ n = 0;
+ shift = 8 - i;
+ b = ~0 << (shift + 1);
+ b |= val & ((1 << (8 - shift)) - 1);
+ fprintf(fd, "\tDATA %s+%zd(SB)/1,$%u\n", lbl, off, b);
+ val >>= shift;
+ while (val != 0) {
+ n++;
+ fprintf(fd, "\tDATA %s+%zd(SB)/1,$%u\n", lbl, off+n, (uint)val & 0xff);
+ val >>= 8;
+ }
+ return i;
}
static size_t writeblob(FILE *fd, Blob *b, size_t off, char *lbl)
{
- size_t i, n;
-
- n = 0;
- if (!b)
- return 0;
- switch (b->type) {
- case Bti8:
- fprintf(fd, "DATA %s+%zd(SB)/1,$%zd\n", lbl, off+n, b->ival);
- n += 1;
- break;
- case Bti16:
- fprintf(fd, "DATA %s+%zd(SB)/2,$%zd\n", lbl, off+n, b->ival);
- n += 2;
- break;
- case Bti32:
- fprintf(fd, "DATA %s+%zd(SB)/4,$%zd\n", lbl, off+n, b->ival);
- n += 4;
- break;
- case Bti64:
- fprintf(fd, "DATA %s+%zd(SB)/8,$%lld\n", lbl, off+n, (vlong)b->ival);
- n += 8;
- break;
- case Btimin:
- n += encodemin(fd, b->ival, off+n, lbl);
- break;
- case Btref:
- if (b->ref.isextern || b->ref.str[0] == '.')
- fprintf(fd, "DATA %s+%zd(SB)/8,$%s+%zd(SB)\n",
- lbl, off+n, b->ref.str, b->ref.off);
- else
- fprintf(fd, "DATA %s+%zd(SB)/8,$%s<>+%zd(SB)\n",
- lbl, off+n, b->ref.str, b->ref.off);
- n += 8;
- break;
- case Btbytes:
- n += writebytes(fd, lbl, off+n, b->bytes.buf, b->bytes.len);
- break;
- case Btseq:
- for (i = 0; i < b->seq.nsub; i++)
- n += writeblob(fd, b->seq.sub[i], off+n, lbl);
- break;
- case Btpad:
- for (i = 0; i < b->npad; i++)
- fprintf(fd, "DATA %s+%zd(SB)/1,$0\n", lbl, off+n+i);
- n += b->npad;
- break;
- }
- return n;
+ size_t i, n;
+
+ n = 0;
+ if (!b)
+ return 0;
+ switch (b->type) {
+ case Bti8:
+ fprintf(fd, "DATA %s+%zd(SB)/1,$%zd\n", lbl, off+n, b->ival);
+ n += 1;
+ break;
+ case Bti16:
+ fprintf(fd, "DATA %s+%zd(SB)/2,$%zd\n", lbl, off+n, b->ival);
+ n += 2;
+ break;
+ case Bti32:
+ fprintf(fd, "DATA %s+%zd(SB)/4,$%zd\n", lbl, off+n, b->ival);
+ n += 4;
+ break;
+ case Bti64:
+ fprintf(fd, "DATA %s+%zd(SB)/8,$%lld\n", lbl, off+n, (vlong)b->ival);
+ n += 8;
+ break;
+ case Btimin:
+ n += encodemin(fd, b->ival, off+n, lbl);
+ break;
+ case Btref:
+ if (b->ref.isextern || b->ref.str[0] == '.')
+ fprintf(fd, "DATA %s+%zd(SB)/8,$%s+%zd(SB)\n",
+ lbl, off+n, b->ref.str, b->ref.off);
+ else
+ fprintf(fd, "DATA %s+%zd(SB)/8,$%s<>+%zd(SB)\n",
+ lbl, off+n, b->ref.str, b->ref.off);
+ n += 8;
+ break;
+ case Btbytes:
+ n += writebytes(fd, lbl, off+n, b->bytes.buf, b->bytes.len);
+ break;
+ case Btseq:
+ for (i = 0; i < b->seq.nsub; i++)
+ n += writeblob(fd, b->seq.sub[i], off+n, lbl);
+ break;
+ case Btpad:
+ for (i = 0; i < b->npad; i++)
+ fprintf(fd, "DATA %s+%zd(SB)/1,$0\n", lbl, off+n+i);
+ n += b->npad;
+ break;
+ }
+ return n;
}
/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
@@ -364,116 +364,116 @@ static size_t writeblob(FILE *fd, Blob *b, size_t off, char *lbl)
* operations on x32, no structures, and so on. */
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;
- if (fn->hasenv)
- is.envp = locreg(ModeQ);
-
- selfunc(&is, fn, globls, strtab);
- if (debugopt['i'])
- writeasm(stdout, &is, fn);
- writeasm(fd, &is, fn);
+ 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;
+ if (fn->hasenv)
+ is.envp = locreg(ModeQ);
+
+ selfunc(&is, fn, globls, strtab);
+ if (debugopt['i'])
+ writeasm(stdout, &is, fn);
+ writeasm(fd, &is, fn);
}
static void gentype(FILE *fd, Type *ty)
{
- Blob *b;
- char lbl[1024];
-
- if (ty->type == Tyvar)
- return;
- b = tydescblob(ty);
- if (!b)
- return;
- if (b->isglobl) {
- fprintf(fd, "GLOBL %s%s+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
- bprintf(lbl, sizeof lbl, "%s%s", Symprefix, b->lbl);
- } else {
- fprintf(fd, "GLOBL %s%s<>+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
- bprintf(lbl, sizeof lbl, "%s%s<>", Symprefix, b->lbl);
- }
- writeblob(fd, b, 0, lbl);
+ Blob *b;
+ char lbl[1024];
+
+ if (ty->type == Tyvar)
+ return;
+ b = tydescblob(ty);
+ if (!b)
+ return;
+ if (b->isglobl) {
+ fprintf(fd, "GLOBL %s%s+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
+ bprintf(lbl, sizeof lbl, "%s%s", Symprefix, b->lbl);
+ } else {
+ fprintf(fd, "GLOBL %s%s<>+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
+ bprintf(lbl, sizeof lbl, "%s%s<>", Symprefix, b->lbl);
+ }
+ writeblob(fd, b, 0, lbl);
}
static void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
{
- char *lbl;
- Blob *b;
-
- /* lits and such also get wrapped in decls */
- assert(blob->type == Ndecl);
-
- lbl = htget(globls, blob);
- fprintf(fd, "GLOBL %s+0(SB),$%zd\n", lbl, size(blob));
- if (blob->decl.init)
- b = litblob(globls, strtab, blob->decl.init);
- else
- b = mkblobpad(size(blob));
- writeblob(fd, b, 0, lbl);
+ char *lbl;
+ Blob *b;
+
+ /* lits and such also get wrapped in decls */
+ assert(blob->type == Ndecl);
+
+ lbl = htget(globls, blob);
+ fprintf(fd, "GLOBL %s+0(SB),$%zd\n", lbl, size(blob));
+ if (blob->decl.init)
+ b = litblob(globls, strtab, blob->decl.init);
+ else
+ b = mkblobpad(size(blob));
+ writeblob(fd, b, 0, lbl);
}
void genp9(Node *file, char *out)
{
- Htab *globls, *strtab;
- Node *n, **blob;
- Func **fn;
- size_t nfn, nblob;
- size_t i;
- FILE *fd;
-
- /* ensure that all physical registers have a loc created before any
- * other locs, so that locmap[Physreg] maps to the Loc for the physreg
- * in question */
- for (i = 0; i < Nreg; i++)
- locphysreg(i);
-
- fn = NULL;
- nfn = 0;
- blob = NULL;
- nblob = 0;
- globls = mkht(varhash, vareq);
- initconsts(globls);
-
- /* We need to define all global variables before use */
- fillglobls(file->file.globls, globls);
-
- pushstab(file->file.globls);
- for (i = 0; i < file->file.nstmts; i++) {
- n = file->file.stmts[i];
- switch (n->type) {
- case Nuse: /* nothing to do */
- case Nimpl:
- break;
- case Ndecl:
- simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
- break;
- default:
- die("Bad node %s in toplevel", nodestr[n->type]);
- break;
- }
- }
- popstab();
-
- fd = fopen(out, "w");
- if (!fd)
- die("Couldn't open fd %s", out);
-
- strtab = mkht(strlithash, strliteq);
- for (i = 0; i < nblob; i++)
- genblob(fd, blob[i], globls, strtab);
- for (i = 0; i < nfn; i++)
- genfunc(fd, fn[i], globls, strtab);
- for (i = 0; i < ntypes; i++)
- if (types[i]->isreflect && !types[i]->isimport)
- gentype(fd, types[i]);
- fprintf(fd, "\n");
- genstrings(fd, strtab);
-
- fclose(fd);
+ Htab *globls, *strtab;
+ Node *n, **blob;
+ Func **fn;
+ size_t nfn, nblob;
+ size_t i;
+ FILE *fd;
+
+ /* ensure that all physical registers have a loc created before any
+ * other locs, so that locmap[Physreg] maps to the Loc for the physreg
+ * in question */
+ for (i = 0; i < Nreg; i++)
+ locphysreg(i);
+
+ fn = NULL;
+ nfn = 0;
+ blob = NULL;
+ nblob = 0;
+ globls = mkht(varhash, vareq);
+ initconsts(globls);
+
+ /* We need to define all global variables before use */
+ fillglobls(file->file.globls, globls);
+
+ pushstab(file->file.globls);
+ for (i = 0; i < file->file.nstmts; i++) {
+ n = file->file.stmts[i];
+ switch (n->type) {
+ case Nuse: /* nothing to do */
+ case Nimpl:
+ break;
+ case Ndecl:
+ simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
+ break;
+ default:
+ die("Bad node %s in toplevel", nodestr[n->type]);
+ break;
+ }
+ }
+ popstab();
+
+ fd = fopen(out, "w");
+ if (!fd)
+ die("Couldn't open fd %s", out);
+
+ strtab = mkht(strlithash, strliteq);
+ for (i = 0; i < nblob; i++)
+ genblob(fd, blob[i], globls, strtab);
+ for (i = 0; i < nfn; i++)
+ genfunc(fd, fn[i], globls, strtab);
+ for (i = 0; i < ntypes; i++)
+ if (types[i]->isreflect && !types[i]->isimport)
+ gentype(fd, types[i]);
+ fprintf(fd, "\n");
+ genstrings(fd, strtab);
+
+ fclose(fd);
}
diff --git a/6/isel.c b/6/isel.c
index 18b0e78..356bdca 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -22,244 +22,244 @@ Loc *selexpr(Isel *s, Node *n);
#define Nfloatregargs 8
#define Nintregargs 6
regid floatargregs[] = {
- Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
- Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
+ Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
+ Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
};
regid intargregs[] = {Rrdi, Rrsi, Rrdx, Rrcx, Rr8, Rr9};
/* used to decide which operator is appropriate
* for implementing various conditional operators */
struct {
- AsmOp test;
- AsmOp jmp;
- AsmOp getflag;
+ AsmOp test;
+ AsmOp jmp;
+ AsmOp getflag;
} reloptab[Numops] = {
- [Olnot] = {Itest, Ijz, Isetz}, /* lnot invalid for floats */
- /* signed int */
- [Oeq] = {Icmp, Ijz, Isetz},
- [One] = {Icmp, Ijnz, Isetnz},
- [Ogt] = {Icmp, Ijg, Isetg},
- [Oge] = {Icmp, Ijge, Isetge},
- [Olt] = {Icmp, Ijl, Isetl},
- [Ole] = {Icmp, Ijle, Isetle},
- /* unsigned int */
- [Oueq] = {Icmp, Ijz, Isetz},
- [Oune] = {Icmp, Ijnz, Isetnz},
- [Ougt] = {Icmp, Ija, Iseta},
- [Ouge] = {Icmp, Ijae, Isetae},
- [Oult] = {Icmp, Ijb, Isetb},
- [Oule] = {Icmp, Ijbe, Isetbe},
- /* float */
- [Ofeq] = {Icomis, Ijz, Isetz},
- [Ofne] = {Icomis, Ijnz, Isetnz},
- [Ofgt] = {Icomis, Ija, Iseta},
- [Ofge] = {Icomis, Ijae, Isetae},
- [Oflt] = {Icomis, Ijb, Isetb},
- [Ofle] = {Icomis, Ijbe, Isetbe},
+ [Olnot] = {Itest, Ijz, Isetz}, /* lnot invalid for floats */
+ /* signed int */
+ [Oeq] = {Icmp, Ijz, Isetz},
+ [One] = {Icmp, Ijnz, Isetnz},
+ [Ogt] = {Icmp, Ijg, Isetg},
+ [Oge] = {Icmp, Ijge, Isetge},
+ [Olt] = {Icmp, Ijl, Isetl},
+ [Ole] = {Icmp, Ijle, Isetle},
+ /* unsigned int */
+ [Oueq] = {Icmp, Ijz, Isetz},
+ [Oune] = {Icmp, Ijnz, Isetnz},
+ [Ougt] = {Icmp, Ija, Iseta},
+ [Ouge] = {Icmp, Ijae, Isetae},
+ [Oult] = {Icmp, Ijb, Isetb},
+ [Oule] = {Icmp, Ijbe, Isetbe},
+ /* float */
+ [Ofeq] = {Icomis, Ijz, Isetz},
+ [Ofne] = {Icomis, Ijnz, Isetnz},
+ [Ofgt] = {Icomis, Ija, Iseta},
+ [Ofge] = {Icomis, Ijae, Isetae},
+ [Oflt] = {Icomis, Ijb, Isetb},
+ [Ofle] = {Icomis, Ijbe, Isetbe},
};
static Mode tymode(Type *t)
{
- /* FIXME: What should the mode for, say, structs be when we have no
- * intention of loading /through/ the pointer? For now, we'll just say it's
- * the pointer mode, since we expect to address through the pointer */
- t = tybase(t);
- switch (t->type) {
- case Tyflt32: return ModeF; break;
- case Tyflt64: return ModeD; break;
- default:
- if (isstacktype(t))
- return ModeQ;
- switch (tysize(t)) {
- case 1: return ModeB; break;
- case 2: return ModeW; break;
- case 4: return ModeL; break;
- case 8: return ModeQ; break;
- }
- break;
- }
- return ModeQ;
+ /* FIXME: What should the mode for, say, structs be when we have no
+ * intention of loading /through/ the pointer? For now, we'll just say it's
+ * the pointer mode, since we expect to address through the pointer */
+ t = tybase(t);
+ switch (t->type) {
+ case Tyflt32: return ModeF; break;
+ case Tyflt64: return ModeD; break;
+ default:
+ if (isstacktype(t))
+ return ModeQ;
+ switch (tysize(t)) {
+ case 1: return ModeB; break;
+ case 2: return ModeW; break;
+ case 4: return ModeL; break;
+ case 8: return ModeQ; break;
+ }
+ break;
+ }
+ return ModeQ;
}
static Mode mode(Node *n)
{
- if (n->type == Nexpr)
- return tymode(exprtype(n));
- else if (n->type == Ndecl)
- return tymode(n->decl.type);
- else
- die("invalid node type");
- return ModeNone;
+ if (n->type == Nexpr)
+ return tymode(exprtype(n));
+ else if (n->type == Ndecl)
+ return tymode(n->decl.type);
+ else
+ die("invalid node type");
+ return ModeNone;
}
static Loc *varloc(Isel *s, Node *n)
{
- ssize_t off;
- 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)) {
- off = ptoi(htget(s->envoff, n));
- l = locmem(off, s->envp, NULL, mode(n));
- } else if (hthas(s->stkoff, n)) {
- off = ptoi(htget(s->stkoff, n));
- l = locmem(-off, locphysreg(Rrbp), NULL, mode(n));
- } else {
- l = htget(s->reglocs, n);
- if (!l) {
- l = locreg(mode(n));
- htput(s->reglocs, n, l);
- }
- }
- return l;
+ ssize_t off;
+ 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)) {
+ off = ptoi(htget(s->envoff, n));
+ l = locmem(off, s->envp, NULL, mode(n));
+ } else if (hthas(s->stkoff, n)) {
+ off = ptoi(htget(s->stkoff, n));
+ l = locmem(-off, locphysreg(Rrbp), NULL, mode(n));
+ } else {
+ l = htget(s->reglocs, n);
+ if (!l) {
+ l = locreg(mode(n));
+ htput(s->reglocs, n, l);
+ }
+ }
+ return l;
}
static Loc *loc(Isel *s, Node *n)
{
- Node *v;
- Loc *l;
-
- if (n->type == Ndecl) {
- l = varloc(s, n);
- } else {
- switch (exprop(n)) {
- case Ovar:
- l = varloc(s, n);
- break;
- case Olit:
- v = n->expr.args[0];
- switch (v->lit.littype) {
- case Lchr: l = loclit(v->lit.chrval, mode(n)); break;
- case Lbool: l = loclit(v->lit.boolval, mode(n)); break;
- case Lint: l = loclit(v->lit.intval, mode(n)); break;
- default:
- die("Literal type %s should be blob", litstr[v->lit.littype]);
- }
- break;
- default:
- die("Node %s not leaf in loc()", opstr[exprop(n)]);
- break;
- }
- }
- return l;
+ Node *v;
+ Loc *l;
+
+ if (n->type == Ndecl) {
+ l = varloc(s, n);
+ } else {
+ switch (exprop(n)) {
+ case Ovar:
+ l = varloc(s, n);
+ break;
+ case Olit:
+ v = n->expr.args[0];
+ switch (v->lit.littype) {
+ case Lchr: l = loclit(v->lit.chrval, mode(n)); break;
+ case Lbool: l = loclit(v->lit.boolval, mode(n)); break;
+ case Lint: l = loclit(v->lit.intval, mode(n)); break;
+ default:
+ die("Literal type %s should be blob", litstr[v->lit.littype]);
+ }
+ break;
+ default:
+ die("Node %s not leaf in loc()", opstr[exprop(n)]);
+ break;
+ }
+ }
+ return l;
}
static Insn *mkinsnv(AsmOp op, va_list ap)
{
- Loc *l;
- Insn *i;
- int n;
- static size_t insnid;
-
- n = 0;
- i = malloc(sizeof(Insn));
- i->op = op;
- i->uid = insnid++;
- while ((l = va_arg(ap, Loc*)) != NULL)
- i->args[n++] = l;
- i->nargs = n;
- return i;
+ Loc *l;
+ Insn *i;
+ int n;
+ static size_t insnid;
+
+ n = 0;
+ i = malloc(sizeof(Insn));
+ i->op = op;
+ i->uid = insnid++;
+ while ((l = va_arg(ap, Loc*)) != NULL)
+ i->args[n++] = l;
+ i->nargs = n;
+ return i;
}
Insn *mkinsn(AsmOp op, ...)
{
- va_list ap;
- Insn *i;
+ va_list ap;
+ Insn *i;
- va_start(ap, op);
- i = mkinsnv(op, ap);
- va_end(ap);
- return i;
+ va_start(ap, op);
+ i = mkinsnv(op, ap);
+ va_end(ap);
+ return i;
}
static void g(Isel *s, AsmOp op, ...)
{
- va_list ap;
- Insn *i;
-
- va_start(ap, op);
- i = mkinsnv(op, ap);
- va_end(ap);
- if (debugopt['i']) {
- printf("GEN[uid=%zd] ", i->uid);
- dbgiprintf(stdout, i);
- }
- lappend(&s->curbb->il, &s->curbb->ni, i);
+ va_list ap;
+ Insn *i;
+
+ va_start(ap, op);
+ i = mkinsnv(op, ap);
+ va_end(ap);
+ if (debugopt['i']) {
+ printf("GEN[uid=%zd] ", i->uid);
+ dbgiprintf(stdout, i);
+ }
+ lappend(&s->curbb->il, &s->curbb->ni, i);
}
static void movz(Isel *s, Loc *src, Loc *dst)
{
- if (src->mode == dst->mode)
- g(s, Imov, src, dst, NULL);
- else
- g(s, Imovzx, src, dst, NULL);
+ if (src->mode == dst->mode)
+ g(s, Imov, src, dst, NULL);
+ else
+ g(s, Imovzx, src, dst, NULL);
}
static void load(Isel *s, Loc *a, Loc *b)
{
- Loc *l;
-
- assert(b->type == Locreg);
- if (a->type == Locreg)
- l = locmem(0, b, NULL, a->mode);
- else
- l = a;
- if (isfloatmode(b->mode))
- g(s, Imovs, l, b, NULL);
- else
- g(s, Imov, l, b, NULL);
+ Loc *l;
+
+ assert(b->type == Locreg);
+ if (a->type == Locreg)
+ l = locmem(0, b, NULL, a->mode);
+ else
+ l = a;
+ if (isfloatmode(b->mode))
+ g(s, Imovs, l, b, NULL);
+ else
+ g(s, Imov, l, b, NULL);
}
static void stor(Isel *s, Loc *a, Loc *b)
{
- Loc *l;
-
- assert(a->type == Locreg || a->type == Loclit);
- if (b->type == Locreg)
- l = locmem(0, b, NULL, b->mode);
- else
- l = b;
- if (isfloatmode(b->mode))
- g(s, Imovs, a, l, NULL);
- else
- g(s, Imov, a, l, NULL);
+ Loc *l;
+
+ assert(a->type == Locreg || a->type == Loclit);
+ if (b->type == Locreg)
+ l = locmem(0, b, NULL, b->mode);
+ else
+ l = b;
+ if (isfloatmode(b->mode))
+ g(s, Imovs, a, l, NULL);
+ else
+ g(s, Imov, a, l, NULL);
}
/* ensures that a location is within a reg */
static Loc *newr(Isel *s, Loc *a)
{
- Loc *r;
-
- r = locreg(a->mode);
- if (a->type == Locreg) {
- if (isfloatmode(a->mode))
- g(s, Imovs, a, r, NULL);
- else
- g(s, Imov, a, r, NULL);
- } else {
- load(s, a, r);
- }
- return r;
+ Loc *r;
+
+ r = locreg(a->mode);
+ if (a->type == Locreg) {
+ if (isfloatmode(a->mode))
+ g(s, Imovs, a, r, NULL);
+ else
+ g(s, Imov, a, r, NULL);
+ } else {
+ load(s, a, r);
+ }
+ return r;
}
static Loc *inr(Isel *s, Loc *a)
{
- if (a->type == Locreg)
- return a;
- return newr(s, a);
+ if (a->type == Locreg)
+ return a;
+ return newr(s, a);
}
/* ensures that a location is within a reg or an imm */
static Loc *inri(Isel *s, Loc *a)
{
- if (a->type == Locreg || a->type == Loclit)
- return a;
- else
- return newr(s, a);
+ if (a->type == Locreg || a->type == Loclit)
+ return a;
+ else
+ return newr(s, a);
}
/* If we're testing equality, etc, it's a bit silly
@@ -273,35 +273,35 @@ static Loc *inri(Isel *s, Loc *a)
* directly */
static void selcjmp(Isel *s, Node *n, Node **args)
{
- Loc *a, *b;
- Loc *l1, *l2;
- AsmOp cond, jmp;
-
- cond = reloptab[exprop(args[0])].test;
- jmp = reloptab[exprop(args[0])].jmp;
- /* if we have a cond, we're knocking off the redundant test,
- * and want to eval the children */
- if (cond) {
- a = selexpr(s, args[0]->expr.args[0]);
- if (args[0]->expr.nargs == 2)
- b = selexpr(s, args[0]->expr.args[1]);
- else
- b = a;
- a = newr(s, a);
- } else {
- cond = Itest;
- jmp = Ijnz;
- b = newr(s, selexpr(s, args[0])); /* cond */
- a = b;
- }
-
- /* the jump targets will always be evaluated the same way */
- l1 = loclbl(args[1]); /* if true */
- l2 = loclbl(args[2]); /* if false */
-
- g(s, cond, b, a, NULL);
- g(s, jmp, l1, NULL);
- g(s, Ijmp, l2, NULL);
+ Loc *a, *b;
+ Loc *l1, *l2;
+ AsmOp cond, jmp;
+
+ cond = reloptab[exprop(args[0])].test;
+ jmp = reloptab[exprop(args[0])].jmp;
+ /* if we have a cond, we're knocking off the redundant test,
+ * and want to eval the children */
+ if (cond) {
+ a = selexpr(s, args[0]->expr.args[0]);
+ if (args[0]->expr.nargs == 2)
+ b = selexpr(s, args[0]->expr.args[1]);
+ else
+ b = a;
+ a = newr(s, a);
+ } else {
+ cond = Itest;
+ jmp = Ijnz;
+ b = newr(s, selexpr(s, args[0])); /* cond */
+ a = b;
+ }
+
+ /* the jump targets will always be evaluated the same way */
+ l1 = loclbl(args[1]); /* if true */
+ l2 = loclbl(args[2]); /* if false */
+
+ g(s, cond, b, a, NULL);
+ g(s, jmp, l1, NULL);
+ g(s, Ijmp, l2, NULL);
}
/* Generate variable length jump. There are 3 cases
@@ -320,13 +320,13 @@ static void selvjmp(Isel *s, Node *n, Node **args)
static Loc *binop(Isel *s, AsmOp op, Node *x, Node *y)
{
- Loc *a, *b;
+ Loc *a, *b;
- a = selexpr(s, x);
- b = selexpr(s, y);
- a = newr(s, a);
- g(s, op, b, a, NULL);
- return a;
+ a = selexpr(s, x);
+ b = selexpr(s, y);
+ a = newr(s, a);
+ g(s, op, b, a, NULL);
+ return a;
}
/* We have a few common cases to optimize here:
@@ -344,723 +344,723 @@ static Loc *binop(Isel *s, AsmOp op, Node *x, Node *y)
*/
static int ismergablemul(Node *n, int *r)
{
- int v;
-
- if (exprop(n) != Omul)
- return 0;
- if (exprop(n->expr.args[1]) != Olit)
- return 0;
- if (n->expr.args[1]->expr.args[0]->type != Nlit)
- return 0;
- if (n->expr.args[1]->expr.args[0]->lit.littype != Lint)
- return 0;
- v = n->expr.args[1]->expr.args[0]->lit.intval;
- if (v != 2 && v != 4 && v != 8)
- return 0;
- *r = v;
- return 1;
+ int v;
+
+ if (exprop(n) != Omul)
+ return 0;
+ if (exprop(n->expr.args[1]) != Olit)
+ return 0;
+ if (n->expr.args[1]->expr.args[0]->type != Nlit)
+ return 0;
+ if (n->expr.args[1]->expr.args[0]->lit.littype != Lint)
+ return 0;
+ v = n->expr.args[1]->expr.args[0]->lit.intval;
+ if (v != 2 && v != 4 && v != 8)
+ return 0;
+ *r = v;
+ return 1;
}
static Loc *memloc(Isel *s, Node *e, Mode m)
{
- Node **args;
- Loc *l, *b, *o; /* location, base, offset */
- int scale;
-
- scale = 1;
- l = NULL;
- args = e->expr.args;
- if (exprop(e) == Oadd) {
- b = selexpr(s, args[0]);
- if (ismergablemul(args[1], &scale))
- o = selexpr(s, args[1]->expr.args[0]);
- else
- o = selexpr(s, args[1]);
-
- if (b->type != Locreg)
- b = inr(s, b);
- if (o->type == Loclit) {
- l = locmem(scale*o->lit, b, NULL, m);
- } else {
- b = inr(s, b);
- o = inr(s, o);
- l = locmems(0, b, o, scale, m);
- }
- } else {
- l = selexpr(s, e);
- l = inr(s, l);
- l = locmem(0, l, NULL, m);
- }
- assert(l != NULL);
- return l;
+ Node **args;
+ Loc *l, *b, *o; /* location, base, offset */
+ int scale;
+
+ scale = 1;
+ l = NULL;
+ args = e->expr.args;
+ if (exprop(e) == Oadd) {
+ b = selexpr(s, args[0]);
+ if (ismergablemul(args[1], &scale))
+ o = selexpr(s, args[1]->expr.args[0]);
+ else
+ o = selexpr(s, args[1]);
+
+ if (b->type != Locreg)
+ b = inr(s, b);
+ if (o->type == Loclit) {
+ l = locmem(scale*o->lit, b, NULL, m);
+ } else {
+ b = inr(s, b);
+ o = inr(s, o);
+ l = locmems(0, b, o, scale, m);
+ }
+ } else {
+ l = selexpr(s, e);
+ l = inr(s, l);
+ l = locmem(0, l, NULL, m);
+ }
+ assert(l != NULL);
+ return l;
}
static const Mode szmodes[] = {
- [8] = ModeQ,
- [4] = ModeL,
- [2] = ModeW,
- [1] = ModeB
+ [8] = ModeQ,
+ [4] = ModeL,
+ [2] = ModeW,
+ [1] = ModeB
};
static void blit(Isel *s, Loc *to, Loc *from, size_t dstoff, size_t srcoff, size_t sz, size_t align)
{
- size_t i, modesz;
- Loc *sp, *dp, *len; /* pointers to src, dst */
- Loc *tmp, *src, *dst; /* source memory, dst memory */
-
- assert(szmodes[align] != ModeNone); /* make sure we have a valid alignment */
- sp = inr(s, from);
- dp = inr(s, to);
-
- i = 0;
- if (align == 0)
- align = 8;
- if (sz <= 128) { /* arbitrary threshold; should be tuned */
- for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
- tmp = locreg(szmodes[modesz]);
- while (i + modesz <= sz) {
- src = locmem(i + srcoff, sp, NULL, szmodes[modesz]);
- dst = locmem(i + dstoff, dp, NULL, szmodes[modesz]);
- g(s, Imov, src, tmp, NULL);
- g(s, Imov, tmp, dst, NULL);
- i += modesz;
- }
- }
- } else {
- len = loclit(sz, ModeQ);
- sp = newr(s, from);
- dp = newr(s, to);
-
- /* length to blit */
- g(s, Imov, len, locphysreg(Rrcx), NULL);
- /* source address with offset */
- if (srcoff)
- g(s, Ilea, locmem(srcoff, sp, NULL, ModeQ), locphysreg(Rrsi), NULL);
- else
- g(s, Imov, sp, locphysreg(Rrsi), NULL);
- /* dest address with offset */
- if (dstoff)
- g(s, Ilea, locmem(dstoff, dp, NULL, ModeQ), locphysreg(Rrdi), NULL);
- else
- g(s, Imov, dp, locphysreg(Rrdi), NULL);
- g(s, Irepmovsb, NULL);
- }
-
+ size_t i, modesz;
+ Loc *sp, *dp, *len; /* pointers to src, dst */
+ Loc *tmp, *src, *dst; /* source memory, dst memory */
+
+ assert(szmodes[align] != ModeNone); /* make sure we have a valid alignment */
+ sp = inr(s, from);
+ dp = inr(s, to);
+
+ i = 0;
+ if (align == 0)
+ align = 8;
+ if (sz <= 128) { /* arbitrary threshold; should be tuned */
+ for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
+ tmp = locreg(szmodes[modesz]);
+ while (i + modesz <= sz) {
+ src = locmem(i + srcoff, sp, NULL, szmodes[modesz]);
+ dst = locmem(i + dstoff, dp, NULL, szmodes[modesz]);
+ g(s, Imov, src, tmp, NULL);
+ g(s, Imov, tmp, dst, NULL);
+ i += modesz;
+ }
+ }
+ } else {
+ len = loclit(sz, ModeQ);
+ sp = newr(s, from);
+ dp = newr(s, to);
+
+ /* length to blit */
+ g(s, Imov, len, locphysreg(Rrcx), NULL);
+ /* source address with offset */
+ if (srcoff)
+ g(s, Ilea, locmem(srcoff, sp, NULL, ModeQ), locphysreg(Rrsi), NULL);
+ else
+ g(s, Imov, sp, locphysreg(Rrsi), NULL);
+ /* dest address with offset */
+ if (dstoff)
+ g(s, Ilea, locmem(dstoff, dp, NULL, ModeQ), locphysreg(Rrdi), NULL);
+ else
+ g(s, Imov, dp, locphysreg(Rrdi), NULL);
+ g(s, Irepmovsb, NULL);
+ }
+
}
static void clear(Isel *s, Loc *val, size_t sz, size_t align)
{
- Loc *dp, *len, *rax; /* pointers to src, dst */
- Loc *zero, *dst; /* source memory, dst memory */
- size_t modesz, i;
-
- i = 0;
- dp = inr(s, val);
- rax = locphysreg(Rrax);
- g(s, Ixor, rax, rax, NULL);
- if (align == 0)
- align = 8;
- if (sz <= 128) { /* arbitrary threshold; should be tuned */
- for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
- zero = loclit(0, szmodes[modesz]);
- while (i + modesz <= sz) {
- zero = coreg(Rrax, szmodes[modesz]);
- dst = locmem(i, dp, NULL, szmodes[modesz]);
- g(s, Imov, zero, dst, NULL);
- i += modesz;
- }
- }
- } else {
- len = loclit(sz, ModeQ);
- /* length to blit */
- g(s, Imov, len, locphysreg(Rrcx), NULL);
- g(s, Imov, dp, locphysreg(Rrdi), NULL);
- g(s, Irepstosb, NULL);
- }
+ Loc *dp, *len, *rax; /* pointers to src, dst */
+ Loc *zero, *dst; /* source memory, dst memory */
+ size_t modesz, i;
+
+ i = 0;
+ dp = inr(s, val);
+ rax = locphysreg(Rrax);
+ g(s, Ixor, rax, rax, NULL);
+ if (align == 0)
+ align = 8;
+ if (sz <= 128) { /* arbitrary threshold; should be tuned */
+ for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
+ zero = loclit(0, szmodes[modesz]);
+ while (i + modesz <= sz) {
+ zero = coreg(Rrax, szmodes[modesz]);
+ dst = locmem(i, dp, NULL, szmodes[modesz]);
+ g(s, Imov, zero, dst, NULL);
+ i += modesz;
+ }
+ }
+ } else {
+ len = loclit(sz, ModeQ);
+ /* length to blit */
+ g(s, Imov, len, locphysreg(Rrcx), NULL);
+ g(s, Imov, dp, locphysreg(Rrdi), NULL);
+ g(s, Irepstosb, NULL);
+ }
}
static void call(Isel *s, Node *n)
{
- AsmOp op;
- Node *fn;
- Loc *f, *e;
-
- if (exprop(n) == Ocall) {
- op = Icall;
- fn = n->expr.args[0];
- assert(tybase(exprtype(fn))->type == Tycode);
- f = locmeml(htget(s->globls, fn), NULL, NULL, mode(fn));
- } else {
- op = Icallind;
- f = selexpr(s, n->expr.args[0]);
- e = selexpr(s, n->expr.args[1]);
- g(s, Imov, e, locphysreg(Rrax), NULL);
- }
- g(s, op, f, NULL);
+ AsmOp op;
+ Node *fn;
+ Loc *f, *e;
+
+ if (exprop(n) == Ocall) {
+ op = Icall;
+ fn = n->expr.args[0];
+ assert(tybase(exprtype(fn))->type == Tycode);
+ f = locmeml(htget(s->globls, fn), NULL, NULL, mode(fn));
+ } else {
+ op = Icallind;
+ f = selexpr(s, n->expr.args[0]);
+ e = selexpr(s, n->expr.args[1]);
+ g(s, Imov, e, locphysreg(Rrax), NULL);
+ }
+ g(s, op, f, NULL);
}
static size_t countargs(Type *t)
{
- size_t nargs;
-
- t = tybase(t);
- nargs = t->nsub - 1;
- if (isstacktype(t->sub[0]))
- nargs++;
- /* valists are replaced with hidden type parameter,
- * which we want on the stack for ease of ABI */
- if (tybase(t->sub[t->nsub - 1])->type == Tyvalist)
- nargs--;
- return nargs;
+ size_t nargs;
+
+ t = tybase(t);
+ nargs = t->nsub - 1;
+ if (isstacktype(t->sub[0]))
+ nargs++;
+ /* valists are replaced with hidden type parameter,
+ * which we want on the stack for ease of ABI */
+ if (tybase(t->sub[t->nsub - 1])->type == Tyvalist)
+ nargs--;
+ return nargs;
}
static Loc *gencall(Isel *s, Node *n)
{
- Loc *src, *dst, *arg; /* values we reduced */
- size_t argsz, argoff, nargs, vasplit;
- size_t nfloats, nints;
- Loc *retloc, *rsp, *ret; /* hard-coded registers */
- Loc *stkbump; /* calculated stack offset */
- Type *t, *fn;
- Node **args;
- size_t i, a;
- int vararg;
-
- rsp = locphysreg(Rrsp);
- t = exprtype(n);
- if (tybase(t)->type == Tyvoid || isstacktype(t)) {
- retloc = NULL;
- ret = NULL;
- } else if (istyfloat(t)) {
- retloc = coreg(Rxmm0d, mode(n));
- ret = locreg(mode(n));
- } else {
- retloc = coreg(Rrax, mode(n));
- ret = locreg(mode(n));
- }
- fn = tybase(exprtype(n->expr.args[0]));
- /* calculate the number of args we expect to see, adjust
- * for a hidden return argument. */
- vasplit = countargs(fn);
- argsz = 0;
- if (exprop(n) == Ocall) {
- args = &n->expr.args[1];
- nargs = n->expr.nargs - 1;
- } else {
- args = &n->expr.args[2];
- nargs = n->expr.nargs - 2;
- }
- /* Have to calculate the amount to bump the stack
- * pointer by in one pass first, otherwise if we push
- * one at a time, we evaluate the args in reverse order.
- * Not good.
- *
- * Skip the first operand, since it's the function itself */
- for (i = 0; i < nargs; i++) {
- argsz = align(argsz, min(size(args[i]), Ptrsz));
- argsz += size(args[i]);
- }
- argsz = align(argsz, 16);
- stkbump = loclit(argsz, ModeQ);
- if (argsz)
- g(s, Isub, stkbump, rsp, NULL);
-
- /* Now, we can evaluate the arguments */
- argoff = 0;
- nfloats = 0;
- nints = 0;
- vararg = 0;
- for (i = 0; i < nargs; i++) {
- arg = selexpr(s, args[i]);
- argoff = alignto(argoff, exprtype(args[i]));
- if (i >= vasplit)
- vararg = 1;
- if (stacknode(args[i])) {
- src = locreg(ModeQ);
- g(s, Ilea, arg, src, NULL);
- a = tyalign(exprtype(args[i]));
- blit(s, rsp, src, argoff, 0, size(args[i]), a);
- argoff += size(args[i]);
- } else if (!vararg && isfloatmode(arg->mode) && nfloats < Nfloatregargs) {
- dst = coreg(floatargregs[nfloats], arg->mode);
- arg = inri(s, arg);
- g(s, Imovs, arg, dst, NULL);
- nfloats++;
- } else if (!vararg && isintmode(arg->mode) && nints < Nintregargs) {
- dst = coreg(intargregs[nints], arg->mode);
- arg = inri(s, arg);
- g(s, Imov, arg, dst, NULL);
- nints++;
- } else {
- dst = locmem(argoff, rsp, NULL, arg->mode);
- arg = inri(s, arg);
- stor(s, arg, dst);
- argoff += size(args[i]);
- }
- }
- call(s, n);
- if (argsz)
- g(s, Iadd, stkbump, rsp, NULL);
- if (retloc) {
- if (isfloatmode(retloc->mode))
- g(s, Imovs, retloc, ret, NULL);
- else
- g(s, Imov, retloc, ret, NULL);
- }
- return ret;
+ Loc *src, *dst, *arg; /* values we reduced */
+ size_t argsz, argoff, nargs, vasplit;
+ size_t nfloats, nints;
+ Loc *retloc, *rsp, *ret; /* hard-coded registers */
+ Loc *stkbump; /* calculated stack offset */
+ Type *t, *fn;
+ Node **args;
+ size_t i, a;
+ int vararg;
+
+ rsp = locphysreg(Rrsp);
+ t = exprtype(n);
+ if (tybase(t)->type == Tyvoid || isstacktype(t)) {
+ retloc = NULL;
+ ret = NULL;
+ } else if (istyfloat(t)) {
+ retloc = coreg(Rxmm0d, mode(n));
+ ret = locreg(mode(n));
+ } else {
+ retloc = coreg(Rrax, mode(n));
+ ret = locreg(mode(n));
+ }
+ fn = tybase(exprtype(n->expr.args[0]));
+ /* calculate the number of args we expect to see, adjust
+ * for a hidden return argument. */
+ vasplit = countargs(fn);
+ argsz = 0;
+ if (exprop(n) == Ocall) {
+ args = &n->expr.args[1];
+ nargs = n->expr.nargs - 1;
+ } else {
+ args = &n->expr.args[2];
+ nargs = n->expr.nargs - 2;
+ }
+ /* Have to calculate the amount to bump the stack
+ * pointer by in one pass first, otherwise if we push
+ * one at a time, we evaluate the args in reverse order.
+ * Not good.
+ *
+ * Skip the first operand, since it's the function itself */
+ for (i = 0; i < nargs; i++) {
+ argsz = align(argsz, min(size(args[i]), Ptrsz));
+ argsz += size(args[i]);
+ }
+ argsz = align(argsz, 16);
+ stkbump = loclit(argsz, ModeQ);
+ if (argsz)
+ g(s, Isub, stkbump, rsp, NULL);
+
+ /* Now, we can evaluate the arguments */
+ argoff = 0;
+ nfloats = 0;
+ nints = 0;
+ vararg = 0;
+ for (i = 0; i < nargs; i++) {
+ arg = selexpr(s, args[i]);
+ argoff = alignto(argoff, exprtype(args[i]));
+ if (i >= vasplit)
+ vararg = 1;
+ if (stacknode(args[i])) {
+ src = locreg(ModeQ);
+ g(s, Ilea, arg, src, NULL);
+ a = tyalign(exprtype(args[i]));
+ blit(s, rsp, src, argoff, 0, size(args[i]), a);
+ argoff += size(args[i]);
+ } else if (!vararg && isfloatmode(arg->mode) && nfloats < Nfloatregargs) {
+ dst = coreg(floatargregs[nfloats], arg->mode);
+ arg = inri(s, arg);
+ g(s, Imovs, arg, dst, NULL);
+ nfloats++;
+ } else if (!vararg && isintmode(arg->mode) && nints < Nintregargs) {
+ dst = coreg(intargregs[nints], arg->mode);
+ arg = inri(s, arg);
+ g(s, Imov, arg, dst, NULL);
+ nints++;
+ } else {
+ dst = locmem(argoff, rsp, NULL, arg->mode);
+ arg = inri(s, arg);
+ stor(s, arg, dst);
+ argoff += size(args[i]);
+ }
+ }
+ call(s, n);
+ if (argsz)
+ g(s, Iadd, stkbump, rsp, NULL);
+ if (retloc) {
+ if (isfloatmode(retloc->mode))
+ g(s, Imovs, retloc, ret, NULL);
+ else
+ g(s, Imov, retloc, ret, NULL);
+ }
+ return ret;
}
Loc *selexpr(Isel *s, Node *n)
{
- Loc *a, *b, *c, *d, *r;
- Loc *edx, *cl; /* x86 wants some hard-coded regs */
- Node **args;
- size_t al;
- Op op;
-
- args = n->expr.args;
- edx = locphysreg(Redx);
- cl = locphysreg(Rcl);
- r = NULL;
- switch (exprop(n)) {
- case Oadd: r = binop(s, Iadd, args[0], args[1]); break;
- case Osub: r = binop(s, Isub, args[0], args[1]); break;
- case Obor: r = binop(s, Ior, args[0], args[1]); break;
- case Oband: r = binop(s, Iand, args[0], args[1]); break;
- case Obxor: r = binop(s, Ixor, args[0], args[1]); break;
- case Omul:
- if (size(args[0]) == 1) {
- a = selexpr(s, args[0]);
- b = inr(s, selexpr(s, args[1]));
-
- c = locphysreg(Ral);
- r = locreg(a->mode);
- g(s, Imov, a, c, NULL);
- g(s, Iimul_r, b, NULL);
- g(s, Imov, c, r, NULL);
- } else {
- r = binop(s, Iimul, args[0], args[1]);
- }
- break;
- case Odiv:
- case Omod:
- /* these get clobbered by the div insn */
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- b = newr(s, b);
- c = coreg(Reax, mode(n));
- r = locreg(a->mode);
- g(s, Imov, a, c, NULL);
- if (istysigned(exprtype(args[0]))) {
- switch (r->mode) {
- case ModeB: g(s, Imovsx, c, coreg(Rrax, ModeW), NULL); break;
- case ModeW: g(s, Icwd, NULL); break;
- case ModeL: g(s, Icdq, NULL); break;
- case ModeQ: g(s, Icqo, NULL); break;
- default: die("invalid mode in division"); break;
- }
- g(s, Iidiv, b, NULL);
- } else {
- if (r->mode == ModeB)
- g(s, Ixor, locphysreg(Rah), locphysreg(Rah), NULL);
- else
- g(s, Ixor, edx, edx, NULL);
- g(s, Idiv, b, NULL);
- }
- if (exprop(n) == Odiv)
- d = coreg(Reax, mode(n));
- else if (r->mode != ModeB)
- d = coreg(Redx, mode(n));
- else
- d = locphysreg(Rah);
- g(s, Imov, d, r, NULL);
- break;
- case Oneg:
- r = selexpr(s, args[0]);
- r = newr(s, r);
- g(s, Ineg, r, NULL);
- break;
-
- /* fp expressions */
- case Ofadd: r = binop(s, Iadds, args[0], args[1]); break;
- case Ofsub: r = binop(s, Isubs, args[0], args[1]); break;
- case Ofmul: r = binop(s, Imuls, args[0], args[1]); break;
- case Ofdiv: r = binop(s, Idivs, args[0], args[1]); break;
- case Ofneg:
- r = selexpr(s, args[0]);
- r = newr(s, r);
- a = NULL;
- b = NULL;
- if (mode(args[0]) == ModeF) {
- a = locreg(ModeF);
- b = loclit(1LL << (31), ModeF);
- g(s, Imovs, r, a);
- } else if (mode(args[0]) == ModeD) {
- a = locreg(ModeQ);
- b = loclit(1LL << 63, ModeQ);
- g(s, Imov, r, a, NULL);
- }
- g(s, Ixor, b, a, NULL);
- g(s, Imov, a, r, NULL);
- break;
- case Obsl:
- case Obsr:
- a = newr(s, selexpr(s, args[0]));
- b = selexpr(s, args[1]);
- if (b->type == Loclit) {
- d = b;
- } else {
- c = coreg(Rcl, b->mode);
- g(s, Imov, b, c, NULL);
- d = cl;
- }
- if (exprop(n) == Obsr) {
- if (istysigned(n->expr.type))
- g(s, Isar, d, a, NULL);
- else
- g(s, Ishr, d, a, NULL);
- } else {
- g(s, Ishl, d, a, NULL);
- }
- r = a;
- break;
- case Obnot:
- r = selexpr(s, args[0]);
- r = newr(s, r);
- g(s, Inot, r, NULL);
- break;
-
- case Oderef:
- r = memloc(s, args[0], mode(n));
- break;
-
- case Oaddr:
- a = selexpr(s, args[0]);
- if (a->type == Loclbl || (a->type == Locmeml && !a->mem.base)) {
- r = loclitl(a->lbl);
- } else {
- r = locreg(ModeQ);
- g(s, Ilea, a, r, NULL);
- }
- break;
-
- case Olnot:
- a = newr(s, selexpr(s, args[0]));
- b = locreg(ModeB);
- r = locreg(mode(n));
- /* lnot only valid for integer-like values */
- g(s, reloptab[exprop(n)].test, a, a, NULL);
- g(s, reloptab[exprop(n)].getflag, b, NULL);
- movz(s, b, r);
- break;
-
- case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
- case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
- case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- a = newr(s, a);
- c = locreg(ModeB);
- r = locreg(mode(n));
- g(s, reloptab[exprop(n)].test, b, a, NULL);
- g(s, reloptab[exprop(n)].getflag, c, NULL);
- movz(s, c, r);
- return r;
-
- case Oasn: /* relabel */
- die("Unimplemented op %s", opstr[exprop(n)]);
- break;
- case Oset:
- op = exprop(args[0]);
- assert(op == Ovar || op == Oderef || op == Ogap);
- assert(!stacknode(args[0]));
-
- if (op == Ogap)
- break;
-
- b = selexpr(s, args[1]);
- if (exprop(args[0]) == Oderef)
- a = memloc(s, args[0]->expr.args[0], mode(n));
- else
- a = selexpr(s, args[0]);
- b = inri(s, b);
- if (isfloatmode(b->mode))
- g(s, Imovs, b, a, NULL);
- else
- g(s, Imov, b, a, NULL);
- r = b;
- break;
- case Ocall:
- case Ocallind:
- r = gencall(s, n);
- break;
- case Oret:
- a = locstrlbl(s->cfg->end->lbls[0]);
- g(s, Ijmp, a, NULL);
- break;
- case Ojmp:
- g(s, Ijmp, loclbl(args[0]), NULL);
- break;
- case Ocjmp:
- selcjmp(s, n, args);
- break;
- case Ovjmp:
- selvjmp(s, n, args);
- break;
- case Olit: /* fall through */
- r = loc(s, n);
- break;
- case Ovar:
- if (isconstfn(n)) {
- r = locreg(ModeQ);
- a = loc(s, n);
- g(s, Ilea, a, r, NULL);
- } else {
- r = loc(s, n);
- }
- break;
- case Ogap:
- break;
- case Oblit:
- a = selexpr(s, args[0]);
- r = selexpr(s, args[1]);
- al = alignto(1, args[0]->expr.type->sub[0]);
- blit(s, a, r, 0, 0, args[2]->expr.args[0]->lit.intval, al);
- break;
-
- case Oclear:
- a = selexpr(s, args[0]);
- clear(s, a, args[1]->expr.args[0]->lit.intval, 0);
- break;
-
- /* cast operators that actually modify the values */
- case Otrunc:
- a = selexpr(s, args[0]);
- a = inr(s, a);
- r = locreg(mode(n));
- g(s, Imov, a, r, NULL);
- break;
- case Ozwiden:
- a = selexpr(s, args[0]);
- a = inr(s, a);
- r = locreg(mode(n));
- movz(s, a, r);
- break;
- case Oswiden:
- a = selexpr(s, args[0]);
- a = inr(s, a);
- r = locreg(mode(n));
- g(s, Imovsx, a, r, NULL);
- break;
- case Oint2flt:
- a = selexpr(s, args[0]);
- r = locreg(mode(n));
- g(s, Icvttsi2sd, a, r, NULL);
- break;
- case Oflt2int:
- a = selexpr(s, args[0]);
- r = locreg(mode(n));
- g(s, Icvttsd2si, a, r, NULL);
- break;
-
- case Oflt2flt:
- a = selexpr(s, args[0]);
- r = locreg(mode(n));
- if (a->mode == ModeD)
- g(s, Icvttsd2ss, a, r, NULL);
- else
- g(s, Icvttss2sd, a, r, NULL);
- break;
- case Odead:
- case Oundef:
- case Odef:
- /* nothing */
- break;
-
- /* These operators should never show up in the reduced trees,
- * since they should have been replaced with more primitive
- * expressions by now */
- case Obad: case Opreinc: case Opostinc: case Opredec:
- case Opostdec: case Olor: case Oland: case Oaddeq:
- case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
- case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
- case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
- case Oucon: case Otup: case Oarr: case Ostruct:
- case Oslice: case Oidx: case Osize: case Otupget: case Oidxlen:
- case Obreak: case Ocontinue:
- case Numops:
- dump(n, stdout);
- die("Should not see %s in isel", opstr[exprop(n)]);
- break;
- }
- return r;
+ Loc *a, *b, *c, *d, *r;
+ Loc *edx, *cl; /* x86 wants some hard-coded regs */
+ Node **args;
+ size_t al;
+ Op op;
+
+ args = n->expr.args;
+ edx = locphysreg(Redx);
+ cl = locphysreg(Rcl);
+ r = NULL;
+ switch (exprop(n)) {
+ case Oadd: r = binop(s, Iadd, args[0], args[1]); break;
+ case Osub: r = binop(s, Isub, args[0], args[1]); break;
+ case Obor: r = binop(s, Ior, args[0], args[1]); break;
+ case Oband: r = binop(s, Iand, args[0], args[1]); break;
+ case Obxor: r = binop(s, Ixor, args[0], args[1]); break;
+ case Omul:
+ if (size(args[0]) == 1) {
+ a = selexpr(s, args[0]);
+ b = inr(s, selexpr(s, args[1]));
+
+ c = locphysreg(Ral);
+ r = locreg(a->mode);
+ g(s, Imov, a, c, NULL);
+ g(s, Iimul_r, b, NULL);
+ g(s, Imov, c, r, NULL);
+ } else {
+ r = binop(s, Iimul, args[0], args[1]);
+ }
+ break;
+ case Odiv:
+ case Omod:
+ /* these get clobbered by the div insn */
+ a = selexpr(s, args[0]);
+ b = selexpr(s, args[1]);
+ b = newr(s, b);
+ c = coreg(Reax, mode(n));
+ r = locreg(a->mode);
+ g(s, Imov, a, c, NULL);
+ if (istysigned(exprtype(args[0]))) {
+ switch (r->mode) {
+ case ModeB: g(s, Imovsx, c, coreg(Rrax, ModeW), NULL); break;
+ case ModeW: g(s, Icwd, NULL); break;
+ case ModeL: g(s, Icdq, NULL); break;
+ case ModeQ: g(s, Icqo, NULL); break;
+ default: die("invalid mode in division"); break;
+ }
+ g(s, Iidiv, b, NULL);
+ } else {
+ if (r->mode == ModeB)
+ g(s, Ixor, locphysreg(Rah), locphysreg(Rah), NULL);
+ else
+ g(s, Ixor, edx, edx, NULL);
+ g(s, Idiv, b, NULL);
+ }
+ if (exprop(n) == Odiv)
+ d = coreg(Reax, mode(n));
+ else if (r->mode != ModeB)
+ d = coreg(Redx, mode(n));
+ else
+ d = locphysreg(Rah);
+ g(s, Imov, d, r, NULL);
+ break;
+ case Oneg:
+ r = selexpr(s, args[0]);
+ r = newr(s, r);
+ g(s, Ineg, r, NULL);
+ break;
+
+ /* fp expressions */
+ case Ofadd: r = binop(s, Iadds, args[0], args[1]); break;
+ case Ofsub: r = binop(s, Isubs, args[0], args[1]); break;
+ case Ofmul: r = binop(s, Imuls, args[0], args[1]); break;
+ case Ofdiv: r = binop(s, Idivs, args[0], args[1]); break;
+ case Ofneg:
+ r = selexpr(s, args[0]);
+ r = newr(s, r);
+ a = NULL;
+ b = NULL;
+ if (mode(args[0]) == ModeF) {
+ a = locreg(ModeF);
+ b = loclit(1LL << (31), ModeF);
+ g(s, Imovs, r, a);
+ } else if (mode(args[0]) == ModeD) {
+ a = locreg(ModeQ);
+ b = loclit(1LL << 63, ModeQ);
+ g(s, Imov, r, a, NULL);
+ }
+ g(s, Ixor, b, a, NULL);
+ g(s, Imov, a, r, NULL);
+ break;
+ case Obsl:
+ case Obsr:
+ a = newr(s, selexpr(s, args[0]));
+ b = selexpr(s, args[1]);
+ if (b->type == Loclit) {
+ d = b;
+ } else {
+ c = coreg(Rcl, b->mode);
+ g(s, Imov, b, c, NULL);
+ d = cl;
+ }
+ if (exprop(n) == Obsr) {
+ if (istysigned(n->expr.type))
+ g(s, Isar, d, a, NULL);
+ else
+ g(s, Ishr, d, a, NULL);
+ } else {
+ g(s, Ishl, d, a, NULL);
+ }
+ r = a;
+ break;
+ case Obnot:
+ r = selexpr(s, args[0]);
+ r = newr(s, r);
+ g(s, Inot, r, NULL);
+ break;
+
+ case Oderef:
+ r = memloc(s, args[0], mode(n));
+ break;
+
+ case Oaddr:
+ a = selexpr(s, args[0]);
+ if (a->type == Loclbl || (a->type == Locmeml && !a->mem.base)) {
+ r = loclitl(a->lbl);
+ } else {
+ r = locreg(ModeQ);
+ g(s, Ilea, a, r, NULL);
+ }
+ break;
+
+ case Olnot:
+ a = newr(s, selexpr(s, args[0]));
+ b = locreg(ModeB);
+ r = locreg(mode(n));
+ /* lnot only valid for integer-like values */
+ g(s, reloptab[exprop(n)].test, a, a, NULL);
+ g(s, reloptab[exprop(n)].getflag, b, NULL);
+ movz(s, b, r);
+ break;
+
+ case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
+ case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
+ case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
+ a = selexpr(s, args[0]);
+ b = selexpr(s, args[1]);
+ a = newr(s, a);
+ c = locreg(ModeB);
+ r = locreg(mode(n));
+ g(s, reloptab[exprop(n)].test, b, a, NULL);
+ g(s, reloptab[exprop(n)].getflag, c, NULL);
+ movz(s, c, r);
+ return r;
+
+ case Oasn: /* relabel */
+ die("Unimplemented op %s", opstr[exprop(n)]);
+ break;
+ case Oset:
+ op = exprop(args[0]);
+ assert(op == Ovar || op == Oderef || op == Ogap);
+ assert(!stacknode(args[0]));
+
+ if (op == Ogap)
+ break;
+
+ b = selexpr(s, args[1]);
+ if (exprop(args[0]) == Oderef)
+ a = memloc(s, args[0]->expr.args[0], mode(n));
+ else
+ a = selexpr(s, args[0]);
+ b = inri(s, b);
+ if (isfloatmode(b->mode))
+ g(s, Imovs, b, a, NULL);
+ else
+ g(s, Imov, b, a, NULL);
+ r = b;
+ break;
+ case Ocall:
+ case Ocallind:
+ r = gencall(s, n);
+ break;
+ case Oret:
+ a = locstrlbl(s->cfg->end->lbls[0]);
+ g(s, Ijmp, a, NULL);
+ break;
+ case Ojmp:
+ g(s, Ijmp, loclbl(args[0]), NULL);
+ break;
+ case Ocjmp:
+ selcjmp(s, n, args);
+ break;
+ case Ovjmp:
+ selvjmp(s, n, args);
+ break;
+ case Olit: /* fall through */
+ r = loc(s, n);
+ break;
+ case Ovar:
+ if (isconstfn(n)) {
+ r = locreg(ModeQ);
+ a = loc(s, n);
+ g(s, Ilea, a, r, NULL);
+ } else {
+ r = loc(s, n);
+ }
+ break;
+ case Ogap:
+ break;
+ case Oblit:
+ a = selexpr(s, args[0]);
+ r = selexpr(s, args[1]);
+ al = alignto(1, args[0]->expr.type->sub[0]);
+ blit(s, a, r, 0, 0, args[2]->expr.args[0]->lit.intval, al);
+ break;
+
+ case Oclear:
+ a = selexpr(s, args[0]);
+ clear(s, a, args[1]->expr.args[0]->lit.intval, 0);
+ break;
+
+ /* cast operators that actually modify the values */
+ case Otrunc:
+ a = selexpr(s, args[0]);
+ a = inr(s, a);
+ r = locreg(mode(n));
+ g(s, Imov, a, r, NULL);
+ break;
+ case Ozwiden:
+ a = selexpr(s, args[0]);
+ a = inr(s, a);
+ r = locreg(mode(n));
+ movz(s, a, r);
+ break;
+ case Oswiden:
+ a = selexpr(s, args[0]);
+ a = inr(s, a);
+ r = locreg(mode(n));
+ g(s, Imovsx, a, r, NULL);
+ break;
+ case Oint2flt:
+ a = selexpr(s, args[0]);
+ r = locreg(mode(n));
+ g(s, Icvttsi2sd, a, r, NULL);
+ break;
+ case Oflt2int:
+ a = selexpr(s, args[0]);
+ r = locreg(mode(n));
+ g(s, Icvttsd2si, a, r, NULL);
+ break;
+
+ case Oflt2flt:
+ a = selexpr(s, args[0]);
+ r = locreg(mode(n));
+ if (a->mode == ModeD)
+ g(s, Icvttsd2ss, a, r, NULL);
+ else
+ g(s, Icvttss2sd, a, r, NULL);
+ break;
+ case Odead:
+ case Oundef:
+ case Odef:
+ /* nothing */
+ break;
+
+ /* These operators should never show up in the reduced trees,
+ * since they should have been replaced with more primitive
+ * expressions by now */
+ case Obad: case Opreinc: case Opostinc: case Opredec:
+ case Opostdec: case Olor: case Oland: case Oaddeq:
+ case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
+ case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
+ case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
+ case Oucon: case Otup: case Oarr: case Ostruct:
+ case Oslice: case Oidx: case Osize: case Otupget: case Oidxlen:
+ case Obreak: case Ocontinue:
+ case Numops:
+ dump(n, stdout);
+ die("Should not see %s in isel", opstr[exprop(n)]);
+ break;
+ }
+ return r;
}
static void isel(Isel *s, Node *n)
{
- switch (n->type) {
- case Nexpr:
- selexpr(s, n);
- break;
- case Ndecl:
- break;
- default:
- die("Bad node type in isel()");
- break;
- }
+ switch (n->type) {
+ case Nexpr:
+ selexpr(s, n);
+ break;
+ case Ndecl:
+ break;
+ default:
+ die("Bad node type in isel()");
+ break;
+ }
}
/* %rax is for int returns, %xmm0d is for floating returns */
Reg savedregs[] = {
- Rr12, Rr13, Rr14, Rr15,
- Rnone
+ Rr12, Rr13, Rr14, Rr15,
+ Rnone
};
void addarglocs(Isel *s, Func *fn)
{
- size_t i, nints, nfloats, nargs;
- size_t argoff;
- int vararg;
- Node *arg;
- Loc *a, *l;
-
- argoff = 0;
- nfloats = 0;
- nints = 0;
- vararg = 0;
- nargs = countargs(fn->type);
- for (i = 0; i < fn->nargs; i++) {
- arg = fn->args[i];
- argoff = align(argoff, min(size(arg), Ptrsz));
- if (i >= nargs)
- vararg = 1;
- if (stacknode(arg)) {
- htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
- argoff += size(arg);
- } else if (!vararg && isfloatmode(mode(arg)) && nfloats < Nfloatregargs) {
- a = coreg(floatargregs[nfloats], mode(arg));
- l = loc(s, arg);
- g(s, Imovs, a, l, NULL);
- htput(s->reglocs, arg, l);
- nfloats++;
- } else if (!vararg && isintmode(mode(arg)) && nints < Nintregargs) {
- a = coreg(intargregs[nints], mode(arg));
- l = loc(s, arg);
- g(s, Imov, a, l, NULL);
- htput(s->reglocs, arg, l);
- nints++;
- } else {
- htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
- argoff += size(arg);
- }
- }
+ size_t i, nints, nfloats, nargs;
+ size_t argoff;
+ int vararg;
+ Node *arg;
+ Loc *a, *l;
+
+ argoff = 0;
+ nfloats = 0;
+ nints = 0;
+ vararg = 0;
+ nargs = countargs(fn->type);
+ for (i = 0; i < fn->nargs; i++) {
+ arg = fn->args[i];
+ argoff = align(argoff, min(size(arg), Ptrsz));
+ if (i >= nargs)
+ vararg = 1;
+ if (stacknode(arg)) {
+ htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
+ argoff += size(arg);
+ } else if (!vararg && isfloatmode(mode(arg)) && nfloats < Nfloatregargs) {
+ a = coreg(floatargregs[nfloats], mode(arg));
+ l = loc(s, arg);
+ g(s, Imovs, a, l, NULL);
+ htput(s->reglocs, arg, l);
+ nfloats++;
+ } else if (!vararg && isintmode(mode(arg)) && nints < Nintregargs) {
+ a = coreg(intargregs[nints], mode(arg));
+ l = loc(s, arg);
+ g(s, Imov, a, l, NULL);
+ htput(s->reglocs, arg, l);
+ nints++;
+ } else {
+ htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
+ argoff += size(arg);
+ }
+ }
}
static void prologue(Isel *s, Func *fn, size_t sz)
{
- Loc *rsp;
- Loc *rbp;
- Loc *stksz;
- Loc *phys;
- size_t i;
-
- rsp = locphysreg(Rrsp);
- rbp = locphysreg(Rrbp);
- stksz = loclit(sz, ModeQ);
- /* enter function */
- g(s, Ipush, rbp, NULL);
- g(s, Imov, rsp, rbp, NULL);
- g(s, Isub, stksz, rsp, NULL);
- /* save registers */
- for (i = 0; savedregs[i] != Rnone; i++) {
- phys = locphysreg(savedregs[i]);
- s->calleesave[i] = locreg(phys->mode);
- if (isfloatmode(phys->mode)) {
- g(s, Imovs, phys, s->calleesave[i], NULL);
- } else {
- g(s, Imov, phys, s->calleesave[i], NULL);
- }
- }
- if (s->envp)
- g(s, Imov, locphysreg(Rrax), s->envp, NULL);
- addarglocs(s, fn);
- s->nsaved = i;
- s->stksz = stksz; /* need to update if we spill */
+ Loc *rsp;
+ Loc *rbp;
+ Loc *stksz;
+ Loc *phys;
+ size_t i;
+
+ rsp = locphysreg(Rrsp);
+ rbp = locphysreg(Rrbp);
+ stksz = loclit(sz, ModeQ);
+ /* enter function */
+ g(s, Ipush, rbp, NULL);
+ g(s, Imov, rsp, rbp, NULL);
+ g(s, Isub, stksz, rsp, NULL);
+ /* save registers */
+ for (i = 0; savedregs[i] != Rnone; i++) {
+ phys = locphysreg(savedregs[i]);
+ s->calleesave[i] = locreg(phys->mode);
+ if (isfloatmode(phys->mode)) {
+ g(s, Imovs, phys, s->calleesave[i], NULL);
+ } else {
+ g(s, Imov, phys, s->calleesave[i], NULL);
+ }
+ }
+ if (s->envp)
+ g(s, Imov, locphysreg(Rrax), s->envp, NULL);
+ addarglocs(s, fn);
+ s->nsaved = i;
+ s->stksz = stksz; /* need to update if we spill */
}
static void epilogue(Isel *s)
{
- Loc *rsp, *rbp;
- Loc *ret;
- size_t i;
-
- rsp = locphysreg(Rrsp);
- rbp = locphysreg(Rrbp);
- if (s->ret) {
- ret = loc(s, s->ret);
- if (istyfloat(exprtype(s->ret)))
- g(s, Imovs, ret, coreg(Rxmm0d, ret->mode), NULL);
- else
- g(s, Imov, ret, coreg(Rax, ret->mode), NULL);
- }
- /* restore registers */
- for (i = 0; savedregs[i] != Rnone; i++) {
- if (isfloatmode(s->calleesave[i]->mode)) {
- g(s, Imovs, s->calleesave[i], locphysreg(savedregs[i]), NULL);
- } else {
- g(s, Imov, s->calleesave[i], locphysreg(savedregs[i]), NULL);
- }
- }
- /* leave function */
- g(s, Imov, rbp, rsp, NULL);
- g(s, Ipop, rbp, NULL);
- g(s, Iret, NULL);
+ Loc *rsp, *rbp;
+ Loc *ret;
+ size_t i;
+
+ rsp = locphysreg(Rrsp);
+ rbp = locphysreg(Rrbp);
+ if (s->ret) {
+ ret = loc(s, s->ret);
+ if (istyfloat(exprtype(s->ret)))
+ g(s, Imovs, ret, coreg(Rxmm0d, ret->mode), NULL);
+ else
+ g(s, Imov, ret, coreg(Rax, ret->mode), NULL);
+ }
+ /* restore registers */
+ for (i = 0; savedregs[i] != Rnone; i++) {
+ if (isfloatmode(s->calleesave[i]->mode)) {
+ g(s, Imovs, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+ } else {
+ g(s, Imov, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+ }
+ }
+ /* leave function */
+ g(s, Imov, rbp, rsp, NULL);
+ g(s, Ipop, rbp, NULL);
+ g(s, Iret, NULL);
}
static Asmbb *mkasmbb(Bb *bb)
{
- Asmbb *as;
-
- if (!bb)
- return NULL;
- as = zalloc(sizeof(Asmbb));
- as->id = bb->id;
- as->pred = bsdup(bb->pred);
- as->succ = bsdup(bb->succ);
- as->lbls = memdup(bb->lbls, bb->nlbls*sizeof(char*));
- as->nlbls = bb->nlbls;
- return as;
+ Asmbb *as;
+
+ if (!bb)
+ return NULL;
+ as = zalloc(sizeof(Asmbb));
+ as->id = bb->id;
+ as->pred = bsdup(bb->pred);
+ as->succ = bsdup(bb->succ);
+ as->lbls = memdup(bb->lbls, bb->nlbls*sizeof(char*));
+ as->nlbls = bb->nlbls;
+ return as;
}
void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab)
{
- Node *n;
- Bb *bb;
- size_t i, j;
- char buf[128];
-
-
- for (i = 0; i < fn->cfg->nbb; i++)
- lappend(&is->bb, &is->nbb, mkasmbb(fn->cfg->bb[i]));
-
- is->curbb = is->bb[0];
- prologue(is, fn, fn->stksz);
- for (j = 0; j < fn->cfg->nbb - 1; j++) {
- is->curbb = is->bb[j];
- if (!is->bb[j])
- continue;
- bb = fn->cfg->bb[j];
- for (i = 0; i < bb->nnl; i++) {
- /* put in a comment that says where this line comes from */
- n = bb->nl[i];
- bprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
- j, i, file->file.files[n->loc.file], n->loc.line);
- g(is, Icomment, locstrlbl(buf), NULL);
- isel(is, fn->cfg->bb[j]->nl[i]);
- }
- }
- is->curbb = is->bb[is->nbb - 1];
- epilogue(is);
- peep(is);
- regalloc(is);
- is->stksz->lit = align(is->stksz->lit, 16);
+ Node *n;
+ Bb *bb;
+ size_t i, j;
+ char buf[128];
+
+
+ for (i = 0; i < fn->cfg->nbb; i++)
+ lappend(&is->bb, &is->nbb, mkasmbb(fn->cfg->bb[i]));
+
+ is->curbb = is->bb[0];
+ prologue(is, fn, fn->stksz);
+ for (j = 0; j < fn->cfg->nbb - 1; j++) {
+ is->curbb = is->bb[j];
+ if (!is->bb[j])
+ continue;
+ bb = fn->cfg->bb[j];
+ for (i = 0; i < bb->nnl; i++) {
+ /* put in a comment that says where this line comes from */
+ n = bb->nl[i];
+ bprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
+ j, i, file->file.files[n->loc.file], n->loc.line);
+ g(is, Icomment, locstrlbl(buf), NULL);
+ isel(is, fn->cfg->bb[j]->nl[i]);
+ }
+ }
+ is->curbb = is->bb[is->nbb - 1];
+ epilogue(is);
+ peep(is);
+ regalloc(is);
+ is->stksz->lit = align(is->stksz->lit, 16);
}
diff --git a/6/locs.c b/6/locs.c
index ba5dbd0..f81c84e 100644
--- a/6/locs.c
+++ b/6/locs.c
@@ -23,44 +23,44 @@ Mode regmodes[] = {
int isintmode(Mode m)
{
- return m == ModeB || m == ModeW || m == ModeL || m == ModeQ;
+ return m == ModeB || m == ModeW || m == ModeL || m == ModeQ;
}
int isfloatmode(Mode m)
{
- return m == ModeF || m == ModeD;
+ return m == ModeF || m == ModeD;
}
Loc *locstrlbl(char *lbl)
{
- Loc *l;
+ Loc *l;
- l = zalloc(sizeof(Loc));
- l->type = Loclbl;
- l->mode = ModeQ;
- l->lbl = strdup(lbl);
- return l;
+ l = zalloc(sizeof(Loc));
+ l->type = Loclbl;
+ l->mode = ModeQ;
+ l->lbl = strdup(lbl);
+ return l;
}
Loc *loclitl(char *lbl)
{
- Loc *l;
+ Loc *l;
- l = zalloc(sizeof(Loc));
- l->type = Loclitl;
- l->mode = ModeQ;
- l->lbl = strdup(lbl);
- return l;
+ l = zalloc(sizeof(Loc));
+ l->type = Loclitl;
+ l->mode = ModeQ;
+ l->lbl = strdup(lbl);
+ return l;
}
Loc *loclbl(Node *e)
{
- Node *lbl;
- assert(e->type == Nexpr);
- lbl = e->expr.args[0];
- assert(lbl->type == Nlit);
- assert(lbl->lit.littype == Llbl);
- return locstrlbl(lbl->lit.lblval);
+ Node *lbl;
+ assert(e->type == Nexpr);
+ lbl = e->expr.args[0];
+ assert(lbl->type == Nlit);
+ assert(lbl->lit.littype == Llbl);
+ return locstrlbl(lbl->lit.lblval);
}
Loc **locmap = NULL;
@@ -68,189 +68,189 @@ size_t maxregid = 0;
static Loc *locregid(regid id, Mode m)
{
- Loc *l;
-
- l = zalloc(sizeof(Loc));
- l->type = Locreg;
- l->mode = m;
- l->reg.id = id;
- locmap = xrealloc(locmap, maxregid * sizeof(Loc*));
- locmap[l->reg.id] = l;
- return l;
+ Loc *l;
+
+ l = zalloc(sizeof(Loc));
+ l->type = Locreg;
+ l->mode = m;
+ l->reg.id = id;
+ locmap = xrealloc(locmap, maxregid * sizeof(Loc*));
+ locmap[l->reg.id] = l;
+ return l;
}
Loc *locreg(Mode m)
{
- return locregid(maxregid++, m);
+ return locregid(maxregid++, m);
}
Loc *locphysreg(Reg r)
{
- static Loc *physregs[Nreg] = {0,};
+ static Loc *physregs[Nreg] = {0,};
- if (physregs[r])
- return physregs[r];
- physregs[r] = locreg(regmodes[r]);
- physregs[r]->reg.colour = r;
- return physregs[r];
+ if (physregs[r])
+ return physregs[r];
+ physregs[r] = locreg(regmodes[r]);
+ physregs[r]->reg.colour = r;
+ return physregs[r];
}
Loc *locmem(long disp, Loc *base, Loc *idx, Mode mode)
{
- Loc *l;
-
- l = zalloc(sizeof(Loc));
- l->type = Locmem;
- l->mode = mode;
- l->mem.constdisp = disp;
- l->mem.base = base;
- l->mem.idx = idx;
- l->mem.scale = 1;
- return l;
+ Loc *l;
+
+ l = zalloc(sizeof(Loc));
+ l->type = Locmem;
+ l->mode = mode;
+ l->mem.constdisp = disp;
+ l->mem.base = base;
+ l->mem.idx = idx;
+ l->mem.scale = 1;
+ return l;
}
Loc *locmems(long disp, Loc *base, Loc *idx, int scale, Mode mode)
{
- Loc *l;
+ Loc *l;
- l = locmem(disp, base, idx, mode);
- l->mem.scale = scale;
- return l;
+ l = locmem(disp, base, idx, mode);
+ l->mem.scale = scale;
+ return l;
}
Loc *locmeml(char *disp, Loc *base, Loc *idx, Mode mode)
{
- Loc *l;
-
- l = zalloc(sizeof(Loc));
- l->type = Locmeml;
- l->mode = mode;
- l->mem.lbldisp = strdup(disp);
- l->mem.base = base;
- l->mem.idx = idx;
- l->mem.scale = 1;
- return l;
+ Loc *l;
+
+ l = zalloc(sizeof(Loc));
+ l->type = Locmeml;
+ l->mode = mode;
+ l->mem.lbldisp = strdup(disp);
+ l->mem.base = base;
+ l->mem.idx = idx;
+ l->mem.scale = 1;
+ return l;
}
Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode)
{
- Loc *l;
+ Loc *l;
- l = locmeml(disp, base, idx, mode);
- l->mem.scale = scale;
- return l;
+ l = locmeml(disp, base, idx, mode);
+ l->mem.scale = scale;
+ return l;
}
Loc *loclit(long val, Mode m)
{
- Loc *l;
+ Loc *l;
- l = zalloc(sizeof(Loc));
- l->type = Loclit;
- l->mode = m;
- l->lit = val;
- return l;
+ l = zalloc(sizeof(Loc));
+ l->type = Loclit;
+ l->mode = m;
+ l->lit = val;
+ return l;
}
Loc *coreg(Reg r, Mode m)
{
- Reg crtab[][Nmode + 1] = {
- [Ral] = {Rnone, Ral, Rax, Reax, Rrax},
- [Rcl] = {Rnone, Rcl, Rcx, Recx, Rrcx},
- [Rdl] = {Rnone, Rdl, Rdx, Redx, Rrdx},
- [Rbl] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
- [Rsil] = {Rnone, Rsil, Rsi, Resi, Rrsi},
- [Rdil] = {Rnone, Rdil, Rdi, Redi, Rrdi},
- [Rr8b] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
- [Rr9b] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
- [Rr10b] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
- [Rr11b] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
- [Rr12b] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
- [Rr13b] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
- [Rr14b] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
- [Rr15b] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
-
- [Rax] = {Rnone, Ral, Rax, Reax, Rrax},
- [Rcx] = {Rnone, Rcl, Rcx, Recx, Rrcx},
- [Rdx] = {Rnone, Rdl, Rdx, Redx, Rrdx},
- [Rbx] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
- [Rsi] = {Rnone, Rsil, Rsi, Resi, Rrsi},
- [Rdi] = {Rnone, Rsil, Rdi, Redi, Rrdi},
- [Rr8w] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
- [Rr9w] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
- [Rr10w] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
- [Rr11w] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
- [Rr12w] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
- [Rr13w] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
- [Rr14w] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
- [Rr15w] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
-
- [Reax] = {Rnone, Ral, Rax, Reax, Rrax},
- [Recx] = {Rnone, Rcl, Rcx, Recx, Rrcx},
- [Redx] = {Rnone, Rdl, Rdx, Redx, Rrdx},
- [Rebx] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
- [Resi] = {Rnone, Rsil, Rsi, Resi, Rrsi},
- [Redi] = {Rnone, Rsil, Rdi, Redi, Rrdi},
- [Rr8d] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
- [Rr9d] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
- [Rr10d] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
- [Rr11d] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
- [Rr12d] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
- [Rr13d] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
- [Rr14d] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
- [Rr15d] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
-
- [Rrax] = {Rnone, Ral, Rax, Reax, Rrax},
- [Rrcx] = {Rnone, Rcl, Rcx, Recx, Rrcx},
- [Rrdx] = {Rnone, Rdl, Rdx, Redx, Rrdx},
- [Rrbx] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
- [Rrsi] = {Rnone, Rsil, Rsi, Resi, Rrsi},
- [Rrdi] = {Rnone, Rsil, Rdi, Redi, Rrdi},
- [Rr8] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
- [Rr9] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
- [Rr10] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
- [Rr11] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
- [Rr12] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
- [Rr13] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
- [Rr14] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
- [Rr15] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
-
- [Rxmm0f] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
- [Rxmm1f] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
- [Rxmm2f] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
- [Rxmm3f] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
- [Rxmm4f] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
- [Rxmm5f] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
- [Rxmm6f] = {[ModeF] = Rxmm6f, [ModeD] = Rxmm6d},
- [Rxmm7f] = {[ModeF] = Rxmm7f, [ModeD] = Rxmm7d},
- [Rxmm8f] = {[ModeF] = Rxmm8f, [ModeD] = Rxmm8d},
- [Rxmm9f] = {[ModeF] = Rxmm9f, [ModeD] = Rxmm9d},
- [Rxmm10f] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
- [Rxmm11f] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
- [Rxmm12f] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
- [Rxmm13f] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
- [Rxmm14f] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
- [Rxmm15f] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
-
- [Rxmm0d] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
- [Rxmm1d] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
- [Rxmm2d] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
- [Rxmm3d] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
- [Rxmm4d] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
- [Rxmm5d] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
- [Rxmm6d] = {[ModeF] = Rxmm6f, [ModeD] = Rxmm6d},
- [Rxmm7d] = {[ModeF] = Rxmm7f, [ModeD] = Rxmm7d},
- [Rxmm8d] = {[ModeF] = Rxmm8f, [ModeD] = Rxmm8d},
- [Rxmm9d] = {[ModeF] = Rxmm9f, [ModeD] = Rxmm9d},
- [Rxmm10d] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
- [Rxmm11d] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
- [Rxmm12d] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
- [Rxmm13d] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
- [Rxmm14d] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
- [Rxmm15d] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
- };
-
- assert(crtab[r][m] != Rnone);
- return locphysreg(crtab[r][m]);
+ Reg crtab[][Nmode + 1] = {
+ [Ral] = {Rnone, Ral, Rax, Reax, Rrax},
+ [Rcl] = {Rnone, Rcl, Rcx, Recx, Rrcx},
+ [Rdl] = {Rnone, Rdl, Rdx, Redx, Rrdx},
+ [Rbl] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
+ [Rsil] = {Rnone, Rsil, Rsi, Resi, Rrsi},
+ [Rdil] = {Rnone, Rdil, Rdi, Redi, Rrdi},
+ [Rr8b] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
+ [Rr9b] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
+ [Rr10b] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
+ [Rr11b] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
+ [Rr12b] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
+ [Rr13b] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
+ [Rr14b] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
+ [Rr15b] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
+
+ [Rax] = {Rnone, Ral, Rax, Reax, Rrax},
+ [Rcx] = {Rnone, Rcl, Rcx, Recx, Rrcx},
+ [Rdx] = {Rnone, Rdl, Rdx, Redx, Rrdx},
+ [Rbx] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
+ [Rsi] = {Rnone, Rsil, Rsi, Resi, Rrsi},
+ [Rdi] = {Rnone, Rsil, Rdi, Redi, Rrdi},
+ [Rr8w] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
+ [Rr9w] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
+ [Rr10w] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
+ [Rr11w] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
+ [Rr12w] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
+ [Rr13w] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
+ [Rr14w] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
+ [Rr15w] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
+
+ [Reax] = {Rnone, Ral, Rax, Reax, Rrax},
+ [Recx] = {Rnone, Rcl, Rcx, Recx, Rrcx},
+ [Redx] = {Rnone, Rdl, Rdx, Redx, Rrdx},
+ [Rebx] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
+ [Resi] = {Rnone, Rsil, Rsi, Resi, Rrsi},
+ [Redi] = {Rnone, Rsil, Rdi, Redi, Rrdi},
+ [Rr8d] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
+ [Rr9d] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
+ [Rr10d] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
+ [Rr11d] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
+ [Rr12d] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
+ [Rr13d] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
+ [Rr14d] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
+ [Rr15d] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
+
+ [Rrax] = {Rnone, Ral, Rax, Reax, Rrax},
+ [Rrcx] = {Rnone, Rcl, Rcx, Recx, Rrcx},
+ [Rrdx] = {Rnone, Rdl, Rdx, Redx, Rrdx},
+ [Rrbx] = {Rnone, Rbl, Rbx, Rebx, Rrbx},
+ [Rrsi] = {Rnone, Rsil, Rsi, Resi, Rrsi},
+ [Rrdi] = {Rnone, Rsil, Rdi, Redi, Rrdi},
+ [Rr8] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8},
+ [Rr9] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9},
+ [Rr10] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10},
+ [Rr11] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11},
+ [Rr12] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12},
+ [Rr13] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13},
+ [Rr14] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14},
+ [Rr15] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15},
+
+ [Rxmm0f] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
+ [Rxmm1f] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
+ [Rxmm2f] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
+ [Rxmm3f] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
+ [Rxmm4f] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
+ [Rxmm5f] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
+ [Rxmm6f] = {[ModeF] = Rxmm6f, [ModeD] = Rxmm6d},
+ [Rxmm7f] = {[ModeF] = Rxmm7f, [ModeD] = Rxmm7d},
+ [Rxmm8f] = {[ModeF] = Rxmm8f, [ModeD] = Rxmm8d},
+ [Rxmm9f] = {[ModeF] = Rxmm9f, [ModeD] = Rxmm9d},
+ [Rxmm10f] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
+ [Rxmm11f] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
+ [Rxmm12f] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
+ [Rxmm13f] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
+ [Rxmm14f] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
+ [Rxmm15f] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
+
+ [Rxmm0d] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
+ [Rxmm1d] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
+ [Rxmm2d] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
+ [Rxmm3d] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
+ [Rxmm4d] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
+ [Rxmm5d] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
+ [Rxmm6d] = {[ModeF] = Rxmm6f, [ModeD] = Rxmm6d},
+ [Rxmm7d] = {[ModeF] = Rxmm7f, [ModeD] = Rxmm7d},
+ [Rxmm8d] = {[ModeF] = Rxmm8f, [ModeD] = Rxmm8d},
+ [Rxmm9d] = {[ModeF] = Rxmm9f, [ModeD] = Rxmm9d},
+ [Rxmm10d] = {[ModeF] = Rxmm0f, [ModeD] = Rxmm0d},
+ [Rxmm11d] = {[ModeF] = Rxmm1f, [ModeD] = Rxmm1d},
+ [Rxmm12d] = {[ModeF] = Rxmm2f, [ModeD] = Rxmm2d},
+ [Rxmm13d] = {[ModeF] = Rxmm3f, [ModeD] = Rxmm3d},
+ [Rxmm14d] = {[ModeF] = Rxmm4f, [ModeD] = Rxmm4d},
+ [Rxmm15d] = {[ModeF] = Rxmm5f, [ModeD] = Rxmm5d},
+ };
+
+ assert(crtab[r][m] != Rnone);
+ return locphysreg(crtab[r][m]);
}
diff --git a/6/main.c b/6/main.c
index 4d884e6..5d66e38 100644
--- a/6/main.c
+++ b/6/main.c
@@ -32,215 +32,215 @@ Asmsyntax asmsyntax;
static void usage(char *prog)
{
- printf("%s [-?] [-o outfile] [-d[dbgopts]] inputs\n", prog);
- printf("\t-?\tPrint this help\n");
- printf("\t-o\tOutput to outfile\n");
- printf("\t-S\tGenerate assembly source alongside object code\n");
- printf("\t-c\tEnable additional (possibly flaky) checking\n");
- printf("\t-I path\tAdd 'path' to use search path\n");
- printf("\t-d\tPrint debug dumps. Recognized options: f r p i\n");
- printf("\t-G\tGenerate asm in gas syntax\n");
- printf("\t-8\tGenerate asm in plan 9 syntax\n");
- printf("\t-d opts: additional debug logging. Options are listed below:\n");
- printf("\t\tf: log folded trees\n");
- printf("\t\tl: log lowered pre-cfg trees\n");
- printf("\t\tT: log tree immediately\n");
- printf("\t\tr: log register allocation activity\n");
- printf("\t\ti: log instruction selection activity\n");
- printf("\t\tu: log type unifications\n");
+ printf("%s [-?] [-o outfile] [-d[dbgopts]] inputs\n", prog);
+ printf("\t-?\tPrint this help\n");
+ printf("\t-o\tOutput to outfile\n");
+ printf("\t-S\tGenerate assembly source alongside object code\n");
+ printf("\t-c\tEnable additional (possibly flaky) checking\n");
+ printf("\t-I path\tAdd 'path' to use search path\n");
+ printf("\t-d\tPrint debug dumps. Recognized options: f r p i\n");
+ printf("\t-G\tGenerate asm in gas syntax\n");
+ printf("\t-8\tGenerate asm in plan 9 syntax\n");
+ printf("\t-d opts: additional debug logging. Options are listed below:\n");
+ printf("\t\tf: log folded trees\n");
+ printf("\t\tl: log lowered pre-cfg trees\n");
+ printf("\t\tT: log tree immediately\n");
+ printf("\t\tr: log register allocation activity\n");
+ printf("\t\ti: log instruction selection activity\n");
+ printf("\t\tu: log type unifications\n");
}
static void swapout(char* buf, size_t sz, char* suf) {
- char* psuffix;
- psuffix = strrchr(outfile, '.');
- if (psuffix != NULL)
- swapsuffix(buf, sz, outfile, psuffix, suf);
- else
- bprintf(buf, sz, "%s%s", outfile, suf);
+ char* psuffix;
+ psuffix = strrchr(outfile, '.');
+ if (psuffix != NULL)
+ swapsuffix(buf, sz, outfile, psuffix, suf);
+ else
+ bprintf(buf, sz, "%s%s", outfile, suf);
}
static void assemble(char *asmsrc, char *path)
{
- char *asmcmd[] = Asmcmd;
- char objfile[1024];
- char *psuffix;
- char **p, **cmd;
- size_t ncmd;
- int pid, status;
-
- if (outfile != NULL)
- strncpy(objfile, outfile, 1024);
- else {
- psuffix = strrchr(path, '+');
- if (psuffix != NULL)
- swapsuffix(objfile, 1024, path, psuffix, Objsuffix);
- else
- swapsuffix(objfile, 1024, path, ".myr", Objsuffix);
- }
- cmd = NULL;
- ncmd = 0;
- for (p = asmcmd; *p != NULL; p++)
- lappend(&cmd, &ncmd, *p);
- lappend(&cmd, &ncmd, objfile);
- lappend(&cmd, &ncmd, asmsrc);
- lappend(&cmd, &ncmd, NULL);
-
- pid = fork();
- if (pid == -1) {
- die("couldn't fork");
- } else if (pid == 0) {
- if (execvp(cmd[0], cmd) == -1)
- die("Couldn't exec assembler\n");
- } else {
- waitpid(pid, &status, 0);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- die("Couldn't run assembler");
- }
+ char *asmcmd[] = Asmcmd;
+ char objfile[1024];
+ char *psuffix;
+ char **p, **cmd;
+ size_t ncmd;
+ int pid, status;
+
+ if (outfile != NULL)
+ strncpy(objfile, outfile, 1024);
+ else {
+ psuffix = strrchr(path, '+');
+ if (psuffix != NULL)
+ swapsuffix(objfile, 1024, path, psuffix, Objsuffix);
+ else
+ swapsuffix(objfile, 1024, path, ".myr", Objsuffix);
+ }
+ cmd = NULL;
+ ncmd = 0;
+ for (p = asmcmd; *p != NULL; p++)
+ lappend(&cmd, &ncmd, *p);
+ lappend(&cmd, &ncmd, objfile);
+ lappend(&cmd, &ncmd, asmsrc);
+ lappend(&cmd, &ncmd, NULL);
+
+ pid = fork();
+ if (pid == -1) {
+ die("couldn't fork");
+ } else if (pid == 0) {
+ if (execvp(cmd[0], cmd) == -1)
+ die("Couldn't exec assembler\n");
+ } else {
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ die("Couldn't run assembler");
+ }
}
static char *gentempfile(char *buf, size_t bufsz, char *path, char *suffix)
{
- char *tmpdir;
- char *base;
- struct timeval tv;
-
- tmpdir = getenv("TMPDIR");
- if (!tmpdir)
- tmpdir = "/tmp";
- base = strrchr(path, '/');
- if (base)
- base++;
- else
- base = path;
- gettimeofday(&tv, NULL);
- bprintf(buf, bufsz, "%s/tmp%lx%lx-%s%s", tmpdir, (long)tv.tv_sec, (long)tv.tv_usec, base, suffix);
- return buf;
+ char *tmpdir;
+ char *base;
+ struct timeval tv;
+
+ tmpdir = getenv("TMPDIR");
+ if (!tmpdir)
+ tmpdir = "/tmp";
+ base = strrchr(path, '/');
+ if (base)
+ base++;
+ else
+ base = path;
+ gettimeofday(&tv, NULL);
+ bprintf(buf, bufsz, "%s/tmp%lx%lx-%s%s", tmpdir, (long)tv.tv_sec, (long)tv.tv_usec, base, suffix);
+ return buf;
}
static int hasmain(Node *file)
{
- Node *n, *name;
-
- name = mknsname(Zloc, "", "main");
- n = getdcl(file->file.globls, name);
- if (!n)
- return 0;
- n = n->decl.name;
- if (n->name.ns)
- return 0;
- return 1;
+ Node *n, *name;
+
+ name = mknsname(Zloc, "", "main");
+ n = getdcl(file->file.globls, name);
+ if (!n)
+ return 0;
+ n = n->decl.name;
+ if (n->name.ns)
+ return 0;
+ return 1;
}
static void genuse(char *path)
{
- FILE *f;
- char buf[1024];
- char *psuffix;
-
- if (outfile != NULL)
- swapout(buf, 1024, ".use");
- else {
- psuffix = strrchr(path, '+');
- if (psuffix != NULL)
- swapsuffix(buf, 1024, path, psuffix, ".use");
- else
- swapsuffix(buf, 1024, path, ".myr", ".use");
- }
- f = fopen(buf, "w");
- if (!f) {
- fprintf(stderr, "Could not open path %s\n", buf);
- exit(1);
- }
- writeuse(f, file);
- fclose(f);
+ FILE *f;
+ char buf[1024];
+ char *psuffix;
+
+ if (outfile != NULL)
+ swapout(buf, 1024, ".use");
+ else {
+ psuffix = strrchr(path, '+');
+ if (psuffix != NULL)
+ swapsuffix(buf, 1024, path, psuffix, ".use");
+ else
+ swapsuffix(buf, 1024, path, ".myr", ".use");
+ }
+ f = fopen(buf, "w");
+ if (!f) {
+ fprintf(stderr, "Could not open path %s\n", buf);
+ exit(1);
+ }
+ writeuse(f, file);
+ fclose(f);
}
int main(int argc, char **argv)
{
- char buf[1024];
- Stab *globls;
- Optctx ctx;
- size_t i;
-
- outfile = NULL;
-
- optinit(&ctx, "d:hSo:I:9G", argv, argc);
- asmsyntax = Defaultasm;
- while (!optdone(&ctx)) {
- switch (optnext(&ctx)) {
- case 'o':
- outfile = ctx.optarg;
- break;
- case 'S':
- writeasm = 1;
- break;
- case '?':
- case 'h':
- usage(argv[0]);
- exit(0);
- break;
- case 'c':
- extracheck = 1;
- case 'd':
- while (ctx.optarg && *ctx.optarg)
- debugopt[*ctx.optarg++ & 0x7f]++;
- break;
- case '9':
- asmsyntax = Plan9;
- break;
- case 'G':
- asmsyntax = Gnugas;
- break;
- case 'I':
- lappend(&incpaths, &nincpaths, ctx.optarg);
- break;
- default:
- usage(argv[0]);
- exit(0);
- break;
- }
- }
-
- lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
-
- if (ctx.nargs == 0) {
- fprintf(stderr, "No input files given\n");
- exit(1);
- }
- else if (ctx.nargs > 1)
- outfile = NULL;
-
- for (i = 0; i < ctx.nargs; i++) {
- globls = mkstab(0);
- tyinit(globls);
- tokinit(ctx.args[i]);
- file = mkfile(ctx.args[i]);
- file->file.globls = globls;
- yyparse();
-
- /* before we do anything to the parse */
- if (debugopt['T'])
- dump(file, stdout);
- infer(file);
- if (hasmain(file))
- geninit(file);
- tagexports(file, 0);
- /* after all type inference */
- if (debugopt['t'])
- dump(file, stdout);
-
- if (writeasm) {
- if (outfile != NULL)
- swapout(buf, sizeof buf, ".s");
- else
- swapsuffix(buf, sizeof buf, ctx.args[i], ".myr", ".s");
- } else {
- gentempfile(buf, sizeof buf, ctx.args[i], ".s");
- }
- genuse(ctx.args[i]);
- gen(file, buf);
- assemble(buf, ctx.args[i]);
- }
-
- return 0;
+ char buf[1024];
+ Stab *globls;
+ Optctx ctx;
+ size_t i;
+
+ outfile = NULL;
+
+ optinit(&ctx, "d:hSo:I:9G", argv, argc);
+ asmsyntax = Defaultasm;
+ while (!optdone(&ctx)) {
+ switch (optnext(&ctx)) {
+ case 'o':
+ outfile = ctx.optarg;
+ break;
+ case 'S':
+ writeasm = 1;
+ break;
+ case '?':
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ case 'c':
+ extracheck = 1;
+ case 'd':
+ while (ctx.optarg && *ctx.optarg)
+ debugopt[*ctx.optarg++ & 0x7f]++;
+ break;
+ case '9':
+ asmsyntax = Plan9;
+ break;
+ case 'G':
+ asmsyntax = Gnugas;
+ break;
+ case 'I':
+ lappend(&incpaths, &nincpaths, ctx.optarg);
+ break;
+ default:
+ usage(argv[0]);
+ exit(0);
+ break;
+ }
+ }
+
+ lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
+
+ if (ctx.nargs == 0) {
+ fprintf(stderr, "No input files given\n");
+ exit(1);
+ }
+ else if (ctx.nargs > 1)
+ outfile = NULL;
+
+ for (i = 0; i < ctx.nargs; i++) {
+ globls = mkstab(0);
+ tyinit(globls);
+ tokinit(ctx.args[i]);
+ file = mkfile(ctx.args[i]);
+ file->file.globls = globls;
+ yyparse();
+
+ /* before we do anything to the parse */
+ if (debugopt['T'])
+ dump(file, stdout);
+ infer(file);
+ if (hasmain(file))
+ geninit(file);
+ tagexports(file, 0);
+ /* after all type inference */
+ if (debugopt['t'])
+ dump(file, stdout);
+
+ if (writeasm) {
+ if (outfile != NULL)
+ swapout(buf, sizeof buf, ".s");
+ else
+ swapsuffix(buf, sizeof buf, ctx.args[i], ".myr", ".s");
+ } else {
+ gentempfile(buf, sizeof buf, ctx.args[i], ".s");
+ }
+ genuse(ctx.args[i]);
+ gen(file, buf);
+ assemble(buf, ctx.args[i]);
+ }
+
+ return 0;
}
diff --git a/6/peep.c b/6/peep.c
index f36cdff..cb31911 100644
--- a/6/peep.c
+++ b/6/peep.c
@@ -21,17 +21,17 @@
* at that point */
static void deadcode(Isel *s, Asmbb *bb)
{
- size_t i;
+ size_t i;
- if (!bb)
- return;
- for (i = 0; i < bb->ni; i++) {
- if (bb->il[i]->op == Ijmp) {
- i++;
- break;
- }
- }
- bb->ni = i;
+ if (!bb)
+ return;
+ for (i = 0; i < bb->ni; i++) {
+ if (bb->il[i]->op == Ijmp) {
+ i++;
+ break;
+ }
+ }
+ bb->ni = i;
}
/* checks for of dumb jump code.
@@ -42,48 +42,48 @@ static void deadcode(Isel *s, Asmbb *bb)
*/
static void nopjmp(Isel *s, Asmbb *bb, size_t idx)
{
- Insn *jmp;
- Loc *targ;
- Asmbb *nextbb;
- size_t i;
+ Insn *jmp;
+ Loc *targ;
+ Asmbb *nextbb;
+ size_t i;
- /* skip empty bbs */
- if (!bb || !bb->ni)
- return;
- /* find the target of the last unconditional
- * jump in the bb */
- targ = NULL;
- if (bb->il[bb->ni - 1]->op == Ijmp) {
- jmp = bb->il[bb->ni - 1];
- if (jmp->args[0]->type == Loclbl)
- targ = jmp->args[0];
- }
- if (!targ)
- return;
-
- /* figure out if it's somewhere in the head of the next bb */
- nextbb = NULL;
- for (i = idx + 1; i < s->nbb; i++) {
- nextbb = s->bb[i];
- if (nextbb)
- break;
- }
- if (!nextbb)
- return;
- for (i = 0; i < nextbb->nlbls; i++) {
- if (!strcmp(nextbb->lbls[i], targ->lbl)) {
- bb->ni--;
- break;
- }
- }
+ /* skip empty bbs */
+ if (!bb || !bb->ni)
+ return;
+ /* find the target of the last unconditional
+ * jump in the bb */
+ targ = NULL;
+ if (bb->il[bb->ni - 1]->op == Ijmp) {
+ jmp = bb->il[bb->ni - 1];
+ if (jmp->args[0]->type == Loclbl)
+ targ = jmp->args[0];
+ }
+ if (!targ)
+ return;
+
+ /* figure out if it's somewhere in the head of the next bb */
+ nextbb = NULL;
+ for (i = idx + 1; i < s->nbb; i++) {
+ nextbb = s->bb[i];
+ if (nextbb)
+ break;
+ }
+ if (!nextbb)
+ return;
+ for (i = 0; i < nextbb->nlbls; i++) {
+ if (!strcmp(nextbb->lbls[i], targ->lbl)) {
+ bb->ni--;
+ break;
+ }
+ }
}
void peep(Isel *s)
{
- size_t i;
+ size_t i;
- for (i = 0; i < s->nbb; i++) {
- deadcode(s, s->bb[i]);
- nopjmp(s, s->bb[i], i);
- }
+ for (i = 0; i < s->nbb; i++) {
+ deadcode(s, s->bb[i]);
+ nopjmp(s, s->bb[i], i);
+ }
}
diff --git a/6/ra.c b/6/ra.c
index 7e8fe83..5c7452b 100644
--- a/6/ra.c
+++ b/6/ra.c
@@ -15,8 +15,8 @@
typedef struct Usemap Usemap;
struct Usemap {
- int l[Nreg + 1]; /* location of arg used in instruction's arg list */
- int r[Nreg + 1]; /* list of registers used implicitly by instruction */
+ int l[Nreg + 1]; /* location of arg used in instruction's arg list */
+ int r[Nreg + 1]; /* list of registers used implicitly by instruction */
};
void wlprint(FILE *fd, char *name, Loc **wl, size_t nwl);
@@ -47,297 +47,296 @@ Usemap deftab[] = {
/* A map of which registers interfere */
#define Northogonal 32
Reg regmap[Northogonal][Nmode] = {
- /* None, ModeB, ModeW, ModeL, ModeQ, ModeF, ModeD */
- [0] = {Rnone, Ral, Rax, Reax, Rrax, Rnone, Rnone},
- [1] = {Rnone, Rcl, Rcx, Recx, Rrcx, Rnone, Rnone},
- [2] = {Rnone, Rdl, Rdx, Redx, Rrdx, Rnone, Rnone},
- [3] = {Rnone, Rbl, Rbx, Rebx, Rrbx, Rnone, Rnone},
- [4] = {Rnone, Rsil, Rsi, Resi, Rrsi, Rnone, Rnone},
- [5] = {Rnone, Rdil, Rdi, Redi, Rrdi, Rnone, Rnone},
- [6] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8, Rnone, Rnone},
- [7] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9, Rnone, Rnone},
- [8] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10, Rnone, Rnone},
- [9] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11, Rnone, Rnone},
- [10] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12, Rnone, Rnone},
- [11] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13, Rnone, Rnone},
- [12] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14, Rnone, Rnone},
- [13] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15, Rnone, Rnone},
- [14] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rnone, Rnone},
- [15] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rnone, Rnone},
- [16] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm0f, Rxmm0d},
- [17] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm1f, Rxmm1d},
- [18] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm2f, Rxmm2d},
- [19] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm3f, Rxmm3d},
- [20] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm4f, Rxmm4d},
- [21] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm5f, Rxmm5d},
- [22] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm6f, Rxmm6d},
- [23] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm7f, Rxmm7d},
- [24] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm8f, Rxmm8d},
- [25] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm9f, Rxmm9d},
- [26] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm10f, Rxmm10d},
- [27] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm11f, Rxmm11d},
- [28] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm12f, Rxmm12d},
- [29] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm13f, Rxmm13d},
- [30] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm14f, Rxmm14d},
- [31] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm15f, Rxmm15d},
+ /* None, ModeB, ModeW, ModeL, ModeQ, ModeF, ModeD */
+ [0] = {Rnone, Ral, Rax, Reax, Rrax, Rnone, Rnone},
+ [1] = {Rnone, Rcl, Rcx, Recx, Rrcx, Rnone, Rnone},
+ [2] = {Rnone, Rdl, Rdx, Redx, Rrdx, Rnone, Rnone},
+ [3] = {Rnone, Rbl, Rbx, Rebx, Rrbx, Rnone, Rnone},
+ [4] = {Rnone, Rsil, Rsi, Resi, Rrsi, Rnone, Rnone},
+ [5] = {Rnone, Rdil, Rdi, Redi, Rrdi, Rnone, Rnone},
+ [6] = {Rnone, Rr8b, Rr8w, Rr8d, Rr8, Rnone, Rnone},
+ [7] = {Rnone, Rr9b, Rr9w, Rr9d, Rr9, Rnone, Rnone},
+ [8] = {Rnone, Rr10b, Rr10w, Rr10d, Rr10, Rnone, Rnone},
+ [9] = {Rnone, Rr11b, Rr11w, Rr11d, Rr11, Rnone, Rnone},
+ [10] = {Rnone, Rr12b, Rr12w, Rr12d, Rr12, Rnone, Rnone},
+ [11] = {Rnone, Rr13b, Rr13w, Rr13d, Rr13, Rnone, Rnone},
+ [12] = {Rnone, Rr14b, Rr14w, Rr14d, Rr14, Rnone, Rnone},
+ [13] = {Rnone, Rr15b, Rr15w, Rr15d, Rr15, Rnone, Rnone},
+ [14] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rnone, Rnone},
+ [15] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rnone, Rnone},
+ [16] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm0f, Rxmm0d},
+ [17] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm1f, Rxmm1d},
+ [18] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm2f, Rxmm2d},
+ [19] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm3f, Rxmm3d},
+ [20] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm4f, Rxmm4d},
+ [21] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm5f, Rxmm5d},
+ [22] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm6f, Rxmm6d},
+ [23] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm7f, Rxmm7d},
+ [24] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm8f, Rxmm8d},
+ [25] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm9f, Rxmm9d},
+ [26] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm10f, Rxmm10d},
+ [27] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm11f, Rxmm11d},
+ [28] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm12f, Rxmm12d},
+ [29] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm13f, Rxmm13d},
+ [30] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm14f, Rxmm14d},
+ [31] = {Rnone, Rnone, Rnone, Rnone, Rnone, Rxmm15f, Rxmm15d},
};
/* Which regmap entry a register maps to */
int colourmap[Nreg] = {
- /* byte */
- [Ral] = 0, [Rax] = 0, [Reax] = 0, [Rrax] = 0,
- [Rcl] = 1, [Rcx] = 1, [Recx] = 1, [Rrcx] = 1,
- [Rdl] = 2, [Rdx] = 2, [Redx] = 2, [Rrdx] = 2,
- [Rbl] = 3, [Rbx] = 3, [Rebx] = 3, [Rrbx] = 3,
- [Rsil] = 4, [Rsi] = 4, [Resi] = 4, [Rrsi] = 4,
- [Rdil] = 5, [Rdi] = 5, [Redi] = 5, [Rrdi] = 5,
- [Rr8b] = 6, [Rr8w] = 6, [Rr8d] = 6, [Rr8] = 6,
- [Rr9b] = 7, [Rr9w] = 7, [Rr9d] = 7, [Rr9] = 7,
- [Rr10b] = 8, [Rr10w] = 8, [Rr10d] = 8, [Rr10] = 8,
- [Rr11b] = 9, [Rr11w] = 9, [Rr11d] = 9, [Rr11] = 9,
- [Rr12b] = 10, [Rr12w] = 10, [Rr12d] = 10, [Rr12] = 10,
- [Rr13b] = 11, [Rr13w] = 11, [Rr13d] = 11, [Rr13] = 11,
- [Rr14b] = 12, [Rr14w] = 12, [Rr14d] = 12, [Rr14] = 12,
- [Rr15b] = 13, [Rr15w] = 13, [Rr15d] = 13, [Rr15] = 13,
-
- /* float */
- [Rxmm0f] = 16, [Rxmm0d] = 16,
- [Rxmm1f] = 17, [Rxmm1d] = 17,
- [Rxmm2f] = 18, [Rxmm2d] = 18,
- [Rxmm3f] = 19, [Rxmm3d] = 19,
- [Rxmm4f] = 20, [Rxmm4d] = 20,
- [Rxmm5f] = 21, [Rxmm5d] = 21,
- [Rxmm6f] = 22, [Rxmm6d] = 22,
- [Rxmm7f] = 23, [Rxmm7d] = 23,
- [Rxmm8f] = 24, [Rxmm8d] = 24,
- [Rxmm9f] = 25, [Rxmm9d] = 25,
- [Rxmm10f] = 26, [Rxmm10d] = 26,
- [Rxmm11f] = 27, [Rxmm11d] = 27,
- [Rxmm12f] = 28, [Rxmm12d] = 28,
- [Rxmm13f] = 29, [Rxmm13d] = 29,
- [Rxmm14f] = 30, [Rxmm14d] = 30,
- [Rxmm15f] = 31, [Rxmm15d] = 31,
+ /* byte */
+ [Ral] = 0, [Rax] = 0, [Reax] = 0, [Rrax] = 0,
+ [Rcl] = 1, [Rcx] = 1, [Recx] = 1, [Rrcx] = 1,
+ [Rdl] = 2, [Rdx] = 2, [Redx] = 2, [Rrdx] = 2,
+ [Rbl] = 3, [Rbx] = 3, [Rebx] = 3, [Rrbx] = 3,
+ [Rsil] = 4, [Rsi] = 4, [Resi] = 4, [Rrsi] = 4,
+ [Rdil] = 5, [Rdi] = 5, [Redi] = 5, [Rrdi] = 5,
+ [Rr8b] = 6, [Rr8w] = 6, [Rr8d] = 6, [Rr8] = 6,
+ [Rr9b] = 7, [Rr9w] = 7, [Rr9d] = 7, [Rr9] = 7,
+ [Rr10b] = 8, [Rr10w] = 8, [Rr10d] = 8, [Rr10] = 8,
+ [Rr11b] = 9, [Rr11w] = 9, [Rr11d] = 9, [Rr11] = 9,
+ [Rr12b] = 10, [Rr12w] = 10, [Rr12d] = 10, [Rr12] = 10,
+ [Rr13b] = 11, [Rr13w] = 11, [Rr13d] = 11, [Rr13] = 11,
+ [Rr14b] = 12, [Rr14w] = 12, [Rr14d] = 12, [Rr14] = 12,
+ [Rr15b] = 13, [Rr15w] = 13, [Rr15d] = 13, [Rr15] = 13,
+
+ /* float */
+ [Rxmm0f] = 16, [Rxmm0d] = 16,
+ [Rxmm1f] = 17, [Rxmm1d] = 17,
+ [Rxmm2f] = 18, [Rxmm2d] = 18,
+ [Rxmm3f] = 19, [Rxmm3d] = 19,
+ [Rxmm4f] = 20, [Rxmm4d] = 20,
+ [Rxmm5f] = 21, [Rxmm5d] = 21,
+ [Rxmm6f] = 22, [Rxmm6d] = 22,
+ [Rxmm7f] = 23, [Rxmm7d] = 23,
+ [Rxmm8f] = 24, [Rxmm8d] = 24,
+ [Rxmm9f] = 25, [Rxmm9d] = 25,
+ [Rxmm10f] = 26, [Rxmm10d] = 26,
+ [Rxmm11f] = 27, [Rxmm11d] = 27,
+ [Rxmm12f] = 28, [Rxmm12d] = 28,
+ [Rxmm13f] = 29, [Rxmm13d] = 29,
+ [Rxmm14f] = 30, [Rxmm14d] = 30,
+ [Rxmm15f] = 31, [Rxmm15d] = 31,
};
size_t modesize[Nmode] = {
- [ModeNone] = 0,
- [ModeB] = 1,
- [ModeW] = 2,
- [ModeL] = 4,
- [ModeQ] = 8,
- [ModeF] = 4,
- [ModeD] = 8,
+ [ModeNone] = 0,
+ [ModeB] = 1,
+ [ModeW] = 2,
+ [ModeL] = 4,
+ [ModeQ] = 8,
+ [ModeF] = 4,
+ [ModeD] = 8,
};
-
static int _K[Nclass] = {
- [Classbad] = 0,
- [Classint] = 14,
- [Classflt] = 16,
+ [Classbad] = 0,
+ [Classint] = 14,
+ [Classflt] = 16,
};
Rclass rclass(Loc *l)
{
- switch (l->mode) {
- case ModeNone: return Classbad;
- case Nmode: return Classbad;
- case ModeB: return Classint;
- case ModeW: return Classint;
- case ModeL: return Classint;
- case ModeQ: return Classint;
-
- case ModeF: return Classflt;
- case ModeD: return Classflt;
- }
- return Classbad;
+ switch (l->mode) {
+ case ModeNone: return Classbad;
+ case Nmode: return Classbad;
+ case ModeB: return Classint;
+ case ModeW: return Classint;
+ case ModeL: return Classint;
+ case ModeQ: return Classint;
+
+ case ModeF: return Classflt;
+ case ModeD: return Classflt;
+ }
+ return Classbad;
}
/* %esp, %ebp are not in the allocatable pool */
static int isfixreg(Loc *l)
{
- if (l->reg.colour == Resp)
- return 1;
- if (l->reg.colour == Rebp)
- return 1;
- return 0;
+ if (l->reg.colour == Resp)
+ return 1;
+ if (l->reg.colour == Rebp)
+ return 1;
+ return 0;
}
static size_t uses(Insn *insn, regid *u)
{
- size_t i, j;
- int k;
- Loc *m;
-
- j = 0;
- /* Add all the registers used and defined. Duplicates
- * in this list are fine, since they're being added to
- * a set anyways */
- for (i = 0; i < Maxarg; i++) {
- if (!usetab[insn->op].l[i])
- break;
- k = usetab[insn->op].l[i] - 1;
- /* non-registers are handled later */
- if (insn->args[k]->type == Locreg)
- if (!isfixreg(insn->args[k]))
- u[j++] = insn->args[k]->reg.id;
- }
- /* some insns don't reflect their defs in the args.
- * These are explictly listed in the insn description */
- for (i = 0; i < Nreg; i++) {
- if (!usetab[insn->op].r[i])
- break;
- /* not a leak; physical registers get memoized */
- u[j++] = locphysreg(usetab[insn->op].r[i])->reg.id;
- }
- /* If the registers are in an address calculation,
- * they're used no matter what. */
- for (i = 0; i < insn->nargs; i++) {
- m = insn->args[i];
- if (m->type != Locmem && m->type != Locmeml)
- continue;
- if (m->mem.base)
- if (!isfixreg(m->mem.base))
- u[j++] = m->mem.base->reg.id;
- if (m->mem.idx)
- if (!isfixreg(m->mem.base))
- u[j++] = m->mem.idx->reg.id;
- }
- return j;
+ size_t i, j;
+ int k;
+ Loc *m;
+
+ j = 0;
+ /* Add all the registers used and defined. Duplicates
+ * in this list are fine, since they're being added to
+ * a set anyways */
+ for (i = 0; i < Maxarg; i++) {
+ if (!usetab[insn->op].l[i])
+ break;
+ k = usetab[insn->op].l[i] - 1;
+ /* non-registers are handled later */
+ if (insn->args[k]->type == Locreg)
+ if (!isfixreg(insn->args[k]))
+ u[j++] = insn->args[k]->reg.id;
+ }
+ /* some insns don't reflect their defs in the args.
+ * These are explictly listed in the insn description */
+ for (i = 0; i < Nreg; i++) {
+ if (!usetab[insn->op].r[i])
+ break;
+ /* not a leak; physical registers get memoized */
+ u[j++] = locphysreg(usetab[insn->op].r[i])->reg.id;
+ }
+ /* If the registers are in an address calculation,
+ * they're used no matter what. */
+ for (i = 0; i < insn->nargs; i++) {
+ m = insn->args[i];
+ if (m->type != Locmem && m->type != Locmeml)
+ continue;
+ if (m->mem.base)
+ if (!isfixreg(m->mem.base))
+ u[j++] = m->mem.base->reg.id;
+ if (m->mem.idx)
+ if (!isfixreg(m->mem.base))
+ u[j++] = m->mem.idx->reg.id;
+ }
+ return j;
}
static size_t defs(Insn *insn, regid *d)
{
- size_t i, j;
- int k;
-
- j = 0;
- /* Add all the registers dsed and defined. Duplicates
- * in this list are fine, since they're being added to
- * a set anyways */
- for (i = 0; i < Maxarg; i++) {
- if (!deftab[insn->op].l[i])
- break;
- k = deftab[insn->op].l[i] - 1;
- if (insn->args[k]->type == Locreg)
- if (!isfixreg(insn->args[k]))
- d[j++] = insn->args[k]->reg.id;
- }
- /* some insns don't reflect their defs in the args.
- * These are explictly listed in the insn description */
- for (i = 0; i < Nreg; i++) {
- if (!deftab[insn->op].r[i])
- break;
- /* not a leak; physical registers get memoized */
- d[j++] = locphysreg(deftab[insn->op].r[i])->reg.id;
- }
- return j;
+ size_t i, j;
+ int k;
+
+ j = 0;
+ /* Add all the registers dsed and defined. Duplicates
+ * in this list are fine, since they're being added to
+ * a set anyways */
+ for (i = 0; i < Maxarg; i++) {
+ if (!deftab[insn->op].l[i])
+ break;
+ k = deftab[insn->op].l[i] - 1;
+ if (insn->args[k]->type == Locreg)
+ if (!isfixreg(insn->args[k]))
+ d[j++] = insn->args[k]->reg.id;
+ }
+ /* some insns don't reflect their defs in the args.
+ * These are explictly listed in the insn description */
+ for (i = 0; i < Nreg; i++) {
+ if (!deftab[insn->op].r[i])
+ break;
+ /* not a leak; physical registers get memoized */
+ d[j++] = locphysreg(deftab[insn->op].r[i])->reg.id;
+ }
+ return j;
}
/* The uses and defs for an entire BB. */
static void udcalc(Asmbb *bb)
{
- regid u[Nreg], d[Nreg];
- size_t nu, nd;
- size_t i, j;
-
- bb->use = bsclear(bb->use);
- bb->def = bsclear(bb->def);
- for (i = 0; i < bb->ni; i++) {
- nu = uses(bb->il[i], u);
- nd = defs(bb->il[i], d);
- for (j = 0; j < nu; j++)
- if (!bshas(bb->def, u[j]))
- bsput(bb->use, u[j]);
- for (j = 0; j < nd; j++)
- bsput(bb->def, d[j]);
- }
+ regid u[Nreg], d[Nreg];
+ size_t nu, nd;
+ size_t i, j;
+
+ bb->use = bsclear(bb->use);
+ bb->def = bsclear(bb->def);
+ for (i = 0; i < bb->ni; i++) {
+ nu = uses(bb->il[i], u);
+ nd = defs(bb->il[i], d);
+ for (j = 0; j < nu; j++)
+ if (!bshas(bb->def, u[j]))
+ bsput(bb->use, u[j]);
+ for (j = 0; j < nd; j++)
+ bsput(bb->def, d[j]);
+ }
}
static int istrivial(Isel *s, regid r)
{
- return s->degree[r] < _K[rclass(locmap[r])];
+ return s->degree[r] < _K[rclass(locmap[r])];
}
static void liveness(Isel *s)
{
- Bitset *old;
- Asmbb **bb;
- ssize_t nbb;
- ssize_t i;
- size_t j;
- int changed;
-
- bb = s->bb;
- nbb = s->nbb;
- for (i = 0; i < nbb; i++) {
- if (!bb[i])
- continue;
- udcalc(s->bb[i]);
- bb[i]->livein = bsclear(bb[i]->livein);
- bb[i]->liveout = bsclear(bb[i]->liveout);
- }
-
- changed = 1;
- while (changed) {
- changed = 0;
- old = NULL;
- for (i = nbb - 1; i >= 0; i--) {
- if (!bb[i])
- continue;
- old = bsdup(bb[i]->liveout);
- /* liveout[b] = U(s in succ) livein[s] */
- for (j = 0; bsiter(bb[i]->succ, &j); j++)
- bsunion(bb[i]->liveout, bb[j]->livein);
- /* livein[b] = use[b] U (out[b] \ def[b]) */
- bb[i]->livein = bsclear(bb[i]->livein);
- bsunion(bb[i]->livein, bb[i]->liveout);
- bsdiff(bb[i]->livein, bb[i]->def);
- bsunion(bb[i]->livein, bb[i]->use);
- if (!changed)
- changed = !bseq(old, bb[i]->liveout);
- bsfree(old);
- }
- }
+ Bitset *old;
+ Asmbb **bb;
+ ssize_t nbb;
+ ssize_t i;
+ size_t j;
+ int changed;
+
+ bb = s->bb;
+ nbb = s->nbb;
+ for (i = 0; i < nbb; i++) {
+ if (!bb[i])
+ continue;
+ udcalc(s->bb[i]);
+ bb[i]->livein = bsclear(bb[i]->livein);
+ bb[i]->liveout = bsclear(bb[i]->liveout);
+ }
+
+ changed = 1;
+ while (changed) {
+ changed = 0;
+ old = NULL;
+ for (i = nbb - 1; i >= 0; i--) {
+ if (!bb[i])
+ continue;
+ old = bsdup(bb[i]->liveout);
+ /* liveout[b] = U(s in succ) livein[s] */
+ for (j = 0; bsiter(bb[i]->succ, &j); j++)
+ bsunion(bb[i]->liveout, bb[j]->livein);
+ /* livein[b] = use[b] U (out[b] \ def[b]) */
+ bb[i]->livein = bsclear(bb[i]->livein);
+ bsunion(bb[i]->livein, bb[i]->liveout);
+ bsdiff(bb[i]->livein, bb[i]->def);
+ bsunion(bb[i]->livein, bb[i]->use);
+ if (!changed)
+ changed = !bseq(old, bb[i]->liveout);
+ bsfree(old);
+ }
+ }
}
/* we're only interested in register->register moves */
static int ismove(Insn *i)
{
- if (i->op != Imov && i->op != Imovs)
- return 0;
- return i->args[0]->type == Locreg && i->args[1]->type == Locreg;
+ if (i->op != Imov && i->op != Imovs)
+ return 0;
+ return i->args[0]->type == Locreg && i->args[1]->type == Locreg;
}
static int gbhasedge(Isel *s, size_t u, size_t v)
{
- size_t i;
- i = (s->nreg * v) + u;
- return (s->gbits[i/Sizetbits] & (1ULL <<(i % Sizetbits))) != 0;
+ size_t i;
+ i = (s->nreg * v) + u;
+ return (s->gbits[i/Sizetbits] & (1ULL <<(i % Sizetbits))) != 0;
}
static void gbputedge(Isel *s, size_t u, size_t v)
{
- size_t i, j;
+ size_t i, j;
- i = (s->nreg * u) + v;
- j = (s->nreg * v) + u;
- s->gbits[i/Sizetbits] |= 1ULL << (i % Sizetbits);
- s->gbits[j/Sizetbits] |= 1ULL << (j % Sizetbits);
- assert(gbhasedge(s, u, v) && gbhasedge(s, v, u));
+ i = (s->nreg * u) + v;
+ j = (s->nreg * v) + u;
+ s->gbits[i/Sizetbits] |= 1ULL << (i % Sizetbits);
+ s->gbits[j/Sizetbits] |= 1ULL << (j % Sizetbits);
+ assert(gbhasedge(s, u, v) && gbhasedge(s, v, u));
}
static int wlfind(Loc **wl, size_t nwl, regid v, size_t *idx)
{
- size_t i;
-
- for (i = 0; i < nwl; i++) {
- if (wl[i]->reg.id == v) {
- *idx = i;
- return 1;
- }
- }
- *idx = -1;
- return 0;
+ size_t i;
+
+ for (i = 0; i < nwl; i++) {
+ if (wl[i]->reg.id == v) {
+ *idx = i;
+ return 1;
+ }
+ }
+ *idx = -1;
+ return 0;
}
/*
@@ -347,609 +346,609 @@ static int wlfind(Loc **wl, size_t nwl, regid v, size_t *idx)
*/
static int degreechange(Isel *s, regid u, regid v)
{
- regid phys, virt, r;
- size_t i;
-
- if (bshas(s->prepainted, u)) {
- phys = u;
- virt = v;
- } else if (bshas(s->prepainted, v)) {
- phys = v;
- virt = u;
- } else {
- return 1;
- }
-
- for (i = 0; i < Nmode; i++) {
- r = regmap[colourmap[phys]][i];
- if (r != phys && gbhasedge(s, virt, regmap[colourmap[phys]][i])) {
- return 0;
- }
- }
- return 1;
+ regid phys, virt, r;
+ size_t i;
+
+ if (bshas(s->prepainted, u)) {
+ phys = u;
+ virt = v;
+ } else if (bshas(s->prepainted, v)) {
+ phys = v;
+ virt = u;
+ } else {
+ return 1;
+ }
+
+ for (i = 0; i < Nmode; i++) {
+ r = regmap[colourmap[phys]][i];
+ if (r != phys && gbhasedge(s, virt, regmap[colourmap[phys]][i])) {
+ return 0;
+ }
+ }
+ return 1;
}
static void alputedge(Isel *s, regid u, regid v)
{
- s->ngadj[u]++;
- s->gadj[u] = xrealloc(s->gadj[u], s->ngadj[u]*sizeof(regid));
- s->gadj[u][s->ngadj[u] - 1] = v;
+ s->ngadj[u]++;
+ s->gadj[u] = xrealloc(s->gadj[u], s->ngadj[u]*sizeof(regid));
+ s->gadj[u][s->ngadj[u] - 1] = v;
}
static void wlput(Loc ***wl, size_t *nwl, Loc *l)
{
- lappend(wl, nwl, l);
- l->list = wl;
+ lappend(wl, nwl, l);
+ l->list = wl;
}
static void wldel(Isel *s, Loc ***wl, size_t *nwl, size_t idx)
{
- (*wl)[idx]->list = NULL;
- ldel(wl, nwl, idx);
+ (*wl)[idx]->list = NULL;
+ ldel(wl, nwl, idx);
}
static void wlputset(Bitset *bs, regid r)
{
- bsput(bs, r);
- locmap[r]->list = bs;
+ bsput(bs, r);
+ locmap[r]->list = bs;
}
static void addedge(Isel *s, regid u, regid v)
{
- if (u == v || gbhasedge(s, u, v))
- return;
- if (u == Rrbp || u == Rrsp || u == Rrip)
- return;
- if (v == Rrbp || v == Rrsp || v == Rrip)
- return;
- if (rclass(locmap[u]) != rclass(locmap[v]))
- return;
- if (bshas(s->prepainted, u) && bshas(s->prepainted, v))
- return;
-
- gbputedge(s, u, v);
- gbputedge(s, v, u);
- if (!bshas(s->prepainted, u)) {
- alputedge(s, u, v);
- s->degree[u] += degreechange(s, v, u);
- }
- if (!bshas(s->prepainted, v)) {
- alputedge(s, v, u);
- s->degree[v] += degreechange(s, u, v);
- }
+ if (u == v || gbhasedge(s, u, v))
+ return;
+ if (u == Rrbp || u == Rrsp || u == Rrip)
+ return;
+ if (v == Rrbp || v == Rrsp || v == Rrip)
+ return;
+ if (rclass(locmap[u]) != rclass(locmap[v]))
+ return;
+ if (bshas(s->prepainted, u) && bshas(s->prepainted, v))
+ return;
+
+ gbputedge(s, u, v);
+ gbputedge(s, v, u);
+ if (!bshas(s->prepainted, u)) {
+ alputedge(s, u, v);
+ s->degree[u] += degreechange(s, v, u);
+ }
+ if (!bshas(s->prepainted, v)) {
+ alputedge(s, v, u);
+ s->degree[v] += degreechange(s, u, v);
+ }
}
static void gfree(Isel *s)
{
- size_t i;
+ size_t i;
- for (i = 0; i < s->nreg; i++)
- free(s->gadj[i]);
- free(s->gbits);
- free(s->gadj);
- free(s->ngadj);
+ for (i = 0; i < s->nreg; i++)
+ free(s->gadj[i]);
+ free(s->gbits);
+ free(s->gadj);
+ free(s->ngadj);
}
static void setup(Isel *s)
{
- size_t gchunks;
- size_t i;
-
- gfree(s);
- s->nreg = maxregid;
- gchunks = (s->nreg*s->nreg)/Sizetbits + 1;
- s->gbits = zalloc(gchunks*sizeof(size_t));
- /* fresh adj list repr. */
- s->gadj = zalloc(s->nreg * sizeof(regid*));
- s->ngadj = zalloc(s->nreg * sizeof(size_t));
-
- s->mactiveset = bsclear(s->mactiveset);
- s->wlmoveset = bsclear(s->wlmoveset);
- s->spilled = bsclear(s->spilled);
- s->coalesced = bsclear(s->coalesced);
- lfree(&s->wlspill, &s->nwlspill);
- lfree(&s->wlfreeze, &s->nwlfreeze);
- lfree(&s->wlsimp, &s->nwlsimp);
-
- free(s->aliasmap);
- free(s->degree);
- free(s->rmoves);
- free(s->nrmoves);
-
- s->aliasmap = zalloc(s->nreg * sizeof(Loc*));
- s->degree = zalloc(s->nreg * sizeof(int));
- s->nuses = zalloc(s->nreg * sizeof(int));
- s->rmoves = zalloc(s->nreg * sizeof(Insn**));
- s->nrmoves = zalloc(s->nreg * sizeof(size_t));
-
- for (i = 0; bsiter(s->prepainted, &i); i++)
- s->degree[i] = 1<<16;
+ size_t gchunks;
+ size_t i;
+
+ gfree(s);
+ s->nreg = maxregid;
+ gchunks = (s->nreg*s->nreg)/Sizetbits + 1;
+ s->gbits = zalloc(gchunks*sizeof(size_t));
+ /* fresh adj list repr. */
+ s->gadj = zalloc(s->nreg * sizeof(regid*));
+ s->ngadj = zalloc(s->nreg * sizeof(size_t));
+
+ s->mactiveset = bsclear(s->mactiveset);
+ s->wlmoveset = bsclear(s->wlmoveset);
+ s->spilled = bsclear(s->spilled);
+ s->coalesced = bsclear(s->coalesced);
+ lfree(&s->wlspill, &s->nwlspill);
+ lfree(&s->wlfreeze, &s->nwlfreeze);
+ lfree(&s->wlsimp, &s->nwlsimp);
+
+ free(s->aliasmap);
+ free(s->degree);
+ free(s->rmoves);
+ free(s->nrmoves);
+
+ s->aliasmap = zalloc(s->nreg * sizeof(Loc*));
+ s->degree = zalloc(s->nreg * sizeof(int));
+ s->nuses = zalloc(s->nreg * sizeof(int));
+ s->rmoves = zalloc(s->nreg * sizeof(Insn**));
+ s->nrmoves = zalloc(s->nreg * sizeof(size_t));
+
+ for (i = 0; bsiter(s->prepainted, &i); i++)
+ s->degree[i] = 1<<16;
}
static void build(Isel *s)
{
- regid u[Nreg], d[Nreg];
- size_t nu, nd;
- size_t i, k, a;
- ssize_t j;
- Bitset *live;
- Asmbb **bb;
- size_t nbb;
- Insn *insn;
- size_t l;
-
- /* set up convenience vars */
- bb = s->bb;
- nbb = s->nbb;
-
- for (i = 0; i < nbb; i++) {
- if (!bb[i])
- continue;
- live = bsdup(bb[i]->liveout);
- for (j = bb[i]->ni - 1; j >= 0; j--) {
- insn = bb[i]->il[j];
- nu = uses(insn, u);
- nd = defs(insn, d);
-
- /* add these to the initial set */
- for (k = 0; k < nu; k++) {
- if (!bshas(s->prepainted, u[k])) {
- wlputset(s->initial, u[k]);
- s->nuses[u[k]]++;
- }
- }
- for (k = 0; k < nd; k++) {
- if (!bshas(s->prepainted, d[k]))
- wlputset(s->initial, d[k]);
- }
-
- /* moves get special treatment, since we don't want spurious
- * edges between the src and dest */
- //iprintf(stdout, insn);
- if (ismove(insn)) {
- /* live \= uses(i) */
- for (k = 0; k < nu; k++) {
- /* remove all physical register aliases */
- if (bshas(s->prepainted, u[k])) {
- for (a = 0; a < Nmode; a++)
- bsdel(live, regmap[colourmap[u[k]]][a]);
- } else {
- bsdel(live, u[k]);
- }
- }
-
- for (k = 0; k < nu; k++)
- lappend(&s->rmoves[u[k]], &s->nrmoves[u[k]], insn);
- for (k = 0; k < nd; k++)
- lappend(&s->rmoves[d[k]], &s->nrmoves[d[k]], insn);
- lappend(&s->wlmove, &s->nwlmove, insn);
- bsput(s->wlmoveset, insn->uid);
- }
- /* live = live U def(i) */
- for (k = 0; k < nd; k++)
- bsput(live, d[k]);
-
- for (k = 0; k < nd; k++)
- for (l = 0; bsiter(live, &l); l++)
- addedge(s, d[k], l);
- /* live = use(i) U (live \ def(i)) */
- for (k = 0; k < nd; k++)
- bsdel(live, d[k]);
- for (k = 0; k < nu; k++)
- bsput(live, u[k]);
- }
- bsfree(live);
- }
+ regid u[Nreg], d[Nreg];
+ size_t nu, nd;
+ size_t i, k, a;
+ ssize_t j;
+ Bitset *live;
+ Asmbb **bb;
+ size_t nbb;
+ Insn *insn;
+ size_t l;
+
+ /* set up convenience vars */
+ bb = s->bb;
+ nbb = s->nbb;
+
+ for (i = 0; i < nbb; i++) {
+ if (!bb[i])
+ continue;
+ live = bsdup(bb[i]->liveout);
+ for (j = bb[i]->ni - 1; j >= 0; j--) {
+ insn = bb[i]->il[j];
+ nu = uses(insn, u);
+ nd = defs(insn, d);
+
+ /* add these to the initial set */
+ for (k = 0; k < nu; k++) {
+ if (!bshas(s->prepainted, u[k])) {
+ wlputset(s->initial, u[k]);
+ s->nuses[u[k]]++;
+ }
+ }
+ for (k = 0; k < nd; k++) {
+ if (!bshas(s->prepainted, d[k]))
+ wlputset(s->initial, d[k]);
+ }
+
+ /* moves get special treatment, since we don't want spurious
+ * edges between the src and dest */
+ //iprintf(stdout, insn);
+ if (ismove(insn)) {
+ /* live \= uses(i) */
+ for (k = 0; k < nu; k++) {
+ /* remove all physical register aliases */
+ if (bshas(s->prepainted, u[k])) {
+ for (a = 0; a < Nmode; a++)
+ bsdel(live, regmap[colourmap[u[k]]][a]);
+ } else {
+ bsdel(live, u[k]);
+ }
+ }
+
+ for (k = 0; k < nu; k++)
+ lappend(&s->rmoves[u[k]], &s->nrmoves[u[k]], insn);
+ for (k = 0; k < nd; k++)
+ lappend(&s->rmoves[d[k]], &s->nrmoves[d[k]], insn);
+ lappend(&s->wlmove, &s->nwlmove, insn);
+ bsput(s->wlmoveset, insn->uid);
+ }
+ /* live = live U def(i) */
+ for (k = 0; k < nd; k++)
+ bsput(live, d[k]);
+
+ for (k = 0; k < nd; k++)
+ for (l = 0; bsiter(live, &l); l++)
+ addedge(s, d[k], l);
+ /* live = use(i) U (live \ def(i)) */
+ for (k = 0; k < nd; k++)
+ bsdel(live, d[k]);
+ for (k = 0; k < nu; k++)
+ bsput(live, u[k]);
+ }
+ bsfree(live);
+ }
}
static int adjavail(Isel *s, regid r)
{
- if (bshas(s->coalesced, r))
- return 0;
- if (locmap[r]->list == &s->selstk)
- return 0;
- return 1;
+ if (bshas(s->coalesced, r))
+ return 0;
+ if (locmap[r]->list == &s->selstk)
+ return 0;
+ return 1;
}
static size_t nodemoves(Isel *s, regid n, Insn ***pil)
{
- size_t i;
- size_t count;
-
- /* FIXME: inefficient. Do I care? */
- count = 0;
- if (pil)
- *pil = NULL;
- for (i = 0; i < s->nrmoves[n]; i++) {
- if (bshas(s->mactiveset, s->rmoves[n][i]->uid))
- lappend(pil, &count, s->rmoves[n][i]);
- if (bshas(s->wlmoveset, s->rmoves[n][i]->uid))
- lappend(pil, &count, s->rmoves[n][i]);
- }
- return count;
+ size_t i;
+ size_t count;
+
+ /* FIXME: inefficient. Do I care? */
+ count = 0;
+ if (pil)
+ *pil = NULL;
+ for (i = 0; i < s->nrmoves[n]; i++) {
+ if (bshas(s->mactiveset, s->rmoves[n][i]->uid))
+ lappend(pil, &count, s->rmoves[n][i]);
+ if (bshas(s->wlmoveset, s->rmoves[n][i]->uid))
+ lappend(pil, &count, s->rmoves[n][i]);
+ }
+ return count;
}
static int moverelated(Isel *s, regid n)
{
- size_t i;
-
- for (i = 0; i < s->nrmoves[n]; i++) {
- if (bshas(s->mactiveset, s->rmoves[n][i]->uid))
- return 1;
- if (bshas(s->wlmoveset, s->rmoves[n][i]->uid))
- return 1;
- }
- return 0;
+ size_t i;
+
+ for (i = 0; i < s->nrmoves[n]; i++) {
+ if (bshas(s->mactiveset, s->rmoves[n][i]->uid))
+ return 1;
+ if (bshas(s->wlmoveset, s->rmoves[n][i]->uid))
+ return 1;
+ }
+ return 0;
}
static void mkworklist(Isel *s)
{
- size_t i;
-
- for (i = 0; bsiter(s->initial, &i); i++) {
- if (bshas(s->prepainted, i))
- continue;
- else if (!istrivial(s, i))
- wlput(&s->wlspill, &s->nwlspill, locmap[i]);
- else if (moverelated(s, i)) {
- wlput(&s->wlfreeze, &s->nwlfreeze, locmap[i]);
- }
- else
- wlput(&s->wlsimp, &s->nwlsimp, locmap[i]);
- locmap[i]->reg.colour = 0;
- }
+ size_t i;
+
+ for (i = 0; bsiter(s->initial, &i); i++) {
+ if (bshas(s->prepainted, i))
+ continue;
+ else if (!istrivial(s, i))
+ wlput(&s->wlspill, &s->nwlspill, locmap[i]);
+ else if (moverelated(s, i)) {
+ wlput(&s->wlfreeze, &s->nwlfreeze, locmap[i]);
+ }
+ else
+ wlput(&s->wlsimp, &s->nwlsimp, locmap[i]);
+ locmap[i]->reg.colour = 0;
+ }
}
static void enablemove(Isel *s, regid n)
{
- size_t i, j;
- Insn **il;
- size_t ni;
-
- ni = nodemoves(s, n, &il);
- for (i = 0; i < ni; i++) {
- if (!bshas(s->mactiveset, il[i]->uid))
- continue;
- for (j = 0; j < s->nmactive; j++) {
- if (il[i] == s->mactive[j]) {
- ldel(&s->mactive, &s->nmactive, j);
- lappend(&s->wlmove, &s->nwlmove, il[i]);
- bsdel(s->mactiveset, il[i]->uid);
- bsput(s->wlmoveset, il[i]->uid);
- }
- }
- }
+ size_t i, j;
+ Insn **il;
+ size_t ni;
+
+ ni = nodemoves(s, n, &il);
+ for (i = 0; i < ni; i++) {
+ if (!bshas(s->mactiveset, il[i]->uid))
+ continue;
+ for (j = 0; j < s->nmactive; j++) {
+ if (il[i] == s->mactive[j]) {
+ ldel(&s->mactive, &s->nmactive, j);
+ lappend(&s->wlmove, &s->nwlmove, il[i]);
+ bsdel(s->mactiveset, il[i]->uid);
+ bsput(s->wlmoveset, il[i]->uid);
+ }
+ }
+ }
}
static void decdegree(Isel *s, regid m)
{
- int before, after;
- int found;
- size_t idx, i;
- regid n;
-
- assert(m < s->nreg);
- before = istrivial(s, m);
- s->degree[m]--;
- after = istrivial(s, m);
-
- if (before != after) {
- enablemove(s, m);
- for (i = 0; i < s->ngadj[m]; i++) {
- n = s->gadj[m][i];
- if (adjavail(s, n))
- enablemove(s, n);
- }
-
- /* Subtle:
- *
- * If this code is being called from coalesce(),
- * then the degree could have been bumped up only
- * temporarily. This means that the node can already
- * be on wlfreeze or wlsimp.
- *
- * Therefore, if we don't find it on wlspill, we assert
- * that the node is already on the list that we'd be
- * moving it to.
- */
- found = wlfind(s->wlspill, s->nwlspill, m, &idx);
- if (found)
- wldel(s, &s->wlspill, &s->nwlspill, idx);
- if (moverelated(s, m)) {
- if (!found) {
- assert(wlfind(s->wlfreeze, s->nwlfreeze, m, &idx) != 0);
- } else {
- wlput(&s->wlfreeze, &s->nwlfreeze, locmap[m]);
- }
- } else {
- if (!found) {
- assert(wlfind(s->wlsimp, s->nwlsimp, m, &idx));
- } else {
- wlput(&s->wlsimp, &s->nwlsimp, locmap[m]);
- }
- }
- }
+ int before, after;
+ int found;
+ size_t idx, i;
+ regid n;
+
+ assert(m < s->nreg);
+ before = istrivial(s, m);
+ s->degree[m]--;
+ after = istrivial(s, m);
+
+ if (before != after) {
+ enablemove(s, m);
+ for (i = 0; i < s->ngadj[m]; i++) {
+ n = s->gadj[m][i];
+ if (adjavail(s, n))
+ enablemove(s, n);
+ }
+
+ /* Subtle:
+ *
+ * If this code is being called from coalesce(),
+ * then the degree could have been bumped up only
+ * temporarily. This means that the node can already
+ * be on wlfreeze or wlsimp.
+ *
+ * Therefore, if we don't find it on wlspill, we assert
+ * that the node is already on the list that we'd be
+ * moving it to.
+ */
+ found = wlfind(s->wlspill, s->nwlspill, m, &idx);
+ if (found)
+ wldel(s, &s->wlspill, &s->nwlspill, idx);
+ if (moverelated(s, m)) {
+ if (!found) {
+ assert(wlfind(s->wlfreeze, s->nwlfreeze, m, &idx) != 0);
+ } else {
+ wlput(&s->wlfreeze, &s->nwlfreeze, locmap[m]);
+ }
+ } else {
+ if (!found) {
+ assert(wlfind(s->wlsimp, s->nwlsimp, m, &idx));
+ } else {
+ wlput(&s->wlsimp, &s->nwlsimp, locmap[m]);
+ }
+ }
+ }
}
static void simp(Isel *s)
{
- Loc *l;
- regid m;
- size_t i;
-
- l = lpop(&s->wlsimp, &s->nwlsimp);
- wlput(&s->selstk, &s->nselstk, l);
- for (i = 0; i < s->ngadj[l->reg.id]; i++) {
- m = s->gadj[l->reg.id][i];
- if (adjavail(s, m))
- decdegree(s, m);
- }
+ Loc *l;
+ regid m;
+ size_t i;
+
+ l = lpop(&s->wlsimp, &s->nwlsimp);
+ wlput(&s->selstk, &s->nselstk, l);
+ for (i = 0; i < s->ngadj[l->reg.id]; i++) {
+ m = s->gadj[l->reg.id][i];
+ if (adjavail(s, m))
+ decdegree(s, m);
+ }
}
static regid getmappedalias(Loc **aliasmap, size_t nreg, regid id)
{
- /*
- * if we get called from rewrite(), we can get a register that
- * we just created, with an id bigger than the number of entries
- * in the alias map. We should just return its id in that case.
- */
- while (id < nreg) {
- if (!aliasmap[id])
- break;
- id = aliasmap[id]->reg.id;
- };
- return id;
+ /*
+ * if we get called from rewrite(), we can get a register that
+ * we just created, with an id bigger than the number of entries
+ * in the alias map. We should just return its id in that case.
+ */
+ while (id < nreg) {
+ if (!aliasmap[id])
+ break;
+ id = aliasmap[id]->reg.id;
+ };
+ return id;
}
static regid getalias(Isel *s, regid id)
{
- return getmappedalias(s->aliasmap, s->nreg, id);
+ return getmappedalias(s->aliasmap, s->nreg, id);
}
static void wladd(Isel *s, regid u)
{
- size_t i;
-
- if (bshas(s->prepainted, u))
- return;
- if (moverelated(s, u))
- return;
- if (!istrivial(s, u))
- return;
-
- assert(locmap[u]->list == &s->wlfreeze || locmap[u]->list == &s->wlsimp);
- if (wlfind(s->wlfreeze, s->nwlfreeze, u, &i))
- wldel(s, &s->wlfreeze, &s->nwlfreeze, i);
- wlput(&s->wlsimp, &s->nwlsimp, locmap[u]);
+ size_t i;
+
+ if (bshas(s->prepainted, u))
+ return;
+ if (moverelated(s, u))
+ return;
+ if (!istrivial(s, u))
+ return;
+
+ assert(locmap[u]->list == &s->wlfreeze || locmap[u]->list == &s->wlsimp);
+ if (wlfind(s->wlfreeze, s->nwlfreeze, u, &i))
+ wldel(s, &s->wlfreeze, &s->nwlfreeze, i);
+ wlput(&s->wlsimp, &s->nwlsimp, locmap[u]);
}
static int conservative(Isel *s, regid u, regid v)
{
- int k;
- size_t i;
- regid n;
-
- k = 0;
- for (i = 0; i < s->ngadj[u]; i++) {
- n = s->gadj[u][i];
- if (adjavail(s, n) && !istrivial(s, n))
- k++;
- }
- for (i = 0; i < s->ngadj[v]; i++) {
- n = s->gadj[v][i];
- if (adjavail(s, n) && !istrivial(s, n))
- k++;
- }
- return k < _K[rclass(locmap[u])];
+ int k;
+ size_t i;
+ regid n;
+
+ k = 0;
+ for (i = 0; i < s->ngadj[u]; i++) {
+ n = s->gadj[u][i];
+ if (adjavail(s, n) && !istrivial(s, n))
+ k++;
+ }
+ for (i = 0; i < s->ngadj[v]; i++) {
+ n = s->gadj[v][i];
+ if (adjavail(s, n) && !istrivial(s, n))
+ k++;
+ }
+ return k < _K[rclass(locmap[u])];
}
/* FIXME: is this actually correct? */
static int ok(Isel *s, regid t, regid r)
{
- return istrivial(s, t) || bshas(s->prepainted, t) || gbhasedge(s, t, r);
+ return istrivial(s, t) || bshas(s->prepainted, t) || gbhasedge(s, t, r);
}
static int combinable(Isel *s, regid u, regid v)
{
- regid t;
- size_t i;
-
- /* Regs of different modes can't be combined as things stand.
- * In principle they should be combinable, but it confused the
- * whole mode dance. */
- if (locmap[u]->mode != locmap[v]->mode)
- return 0;
- /* if u isn't prepainted, can we conservatively coalesce? */
- if (!bshas(s->prepainted, u) && conservative(s, u, v))
- return 1;
-
- /* if it is, are the adjacent nodes ok to combine with this? */
- for (i = 0; i < s->ngadj[v]; i++) {
- t = s->gadj[v][i];
- if (adjavail(s, t) && !ok(s, t, u))
- return 0;
- }
- return 1;
+ regid t;
+ size_t i;
+
+ /* Regs of different modes can't be combined as things stand.
+ * In principle they should be combinable, but it confused the
+ * whole mode dance. */
+ if (locmap[u]->mode != locmap[v]->mode)
+ return 0;
+ /* if u isn't prepainted, can we conservatively coalesce? */
+ if (!bshas(s->prepainted, u) && conservative(s, u, v))
+ return 1;
+
+ /* if it is, are the adjacent nodes ok to combine with this? */
+ for (i = 0; i < s->ngadj[v]; i++) {
+ t = s->gadj[v][i];
+ if (adjavail(s, t) && !ok(s, t, u))
+ return 0;
+ }
+ return 1;
}
static void combine(Isel *s, regid u, regid v)
{
- regid t;
- size_t idx;
- size_t i, j;
- int has;
-
- if (debugopt['r'] > 2)
- printedge(stdout, "combining:", u, v);
- if (wlfind(s->wlfreeze, s->nwlfreeze, v, &idx))
- wldel(s, &s->wlfreeze, &s->nwlfreeze, idx);
- else if (wlfind(s->wlspill, s->nwlspill, v, &idx)) {
- wldel(s, &s->wlspill, &s->nwlspill, idx);
- }
- wlputset(s->coalesced, v);
- s->aliasmap[v] = locmap[u];
- s->nuses[u] += s->nuses[v];
-
- /* nodemoves[u] = nodemoves[u] U nodemoves[v] */
- for (i = 0; i < s->nrmoves[v]; i++) {
- has = 0;
- for (j = 0; j < s->nrmoves[u]; j++) {
- if (s->rmoves[v][i] == s->rmoves[u][j]) {
- has = 1;
- break;
- }
- }
- if (!has)
- lappend(&s->rmoves[u], &s->nrmoves[u], s->rmoves[v][i]);
- }
-
- for (i = 0; i < s->ngadj[v]; i++) {
- t = s->gadj[v][i];
- if (!adjavail(s, t))
- continue;
- if (debugopt['r'] > 2)
- printedge(stdout, "combine-putedge:", t, u);
- addedge(s, t, u);
- decdegree(s, t);
- }
- if (!istrivial(s, u) && wlfind(s->wlfreeze, s->nwlfreeze, u, &idx)) {
- wldel(s, &s->wlfreeze, &s->nwlfreeze, idx);
- wlput(&s->wlspill, &s->nwlspill, locmap[u]);
- }
+ regid t;
+ size_t idx;
+ size_t i, j;
+ int has;
+
+ if (debugopt['r'] > 2)
+ printedge(stdout, "combining:", u, v);
+ if (wlfind(s->wlfreeze, s->nwlfreeze, v, &idx))
+ wldel(s, &s->wlfreeze, &s->nwlfreeze, idx);
+ else if (wlfind(s->wlspill, s->nwlspill, v, &idx)) {
+ wldel(s, &s->wlspill, &s->nwlspill, idx);
+ }
+ wlputset(s->coalesced, v);
+ s->aliasmap[v] = locmap[u];
+ s->nuses[u] += s->nuses[v];
+
+ /* nodemoves[u] = nodemoves[u] U nodemoves[v] */
+ for (i = 0; i < s->nrmoves[v]; i++) {
+ has = 0;
+ for (j = 0; j < s->nrmoves[u]; j++) {
+ if (s->rmoves[v][i] == s->rmoves[u][j]) {
+ has = 1;
+ break;
+ }
+ }
+ if (!has)
+ lappend(&s->rmoves[u], &s->nrmoves[u], s->rmoves[v][i]);
+ }
+
+ for (i = 0; i < s->ngadj[v]; i++) {
+ t = s->gadj[v][i];
+ if (!adjavail(s, t))
+ continue;
+ if (debugopt['r'] > 2)
+ printedge(stdout, "combine-putedge:", t, u);
+ addedge(s, t, u);
+ decdegree(s, t);
+ }
+ if (!istrivial(s, u) && wlfind(s->wlfreeze, s->nwlfreeze, u, &idx)) {
+ wldel(s, &s->wlfreeze, &s->nwlfreeze, idx);
+ wlput(&s->wlspill, &s->nwlspill, locmap[u]);
+ }
}
static int constrained(Isel *s, regid u, regid v)
{
- size_t i;
-
- if (bshas(s->prepainted, v))
- return 1;
- if (bshas(s->prepainted, u))
- for (i = 0; i < Nmode; i++)
- if (regmap[colourmap[u]][i] && gbhasedge(s, regmap[colourmap[u]][i], v))
- return 1;
- return gbhasedge(s, u, v);
+ size_t i;
+
+ if (bshas(s->prepainted, v))
+ return 1;
+ if (bshas(s->prepainted, u))
+ for (i = 0; i < Nmode; i++)
+ if (regmap[colourmap[u]][i] && gbhasedge(s, regmap[colourmap[u]][i], v))
+ return 1;
+ return gbhasedge(s, u, v);
}
static void coalesce(Isel *s)
{
- Insn *m;
- regid u, v, tmp;
-
- m = lpop(&s->wlmove, &s->nwlmove);
- bsdel(s->wlmoveset, m->uid);
- u = getalias(s, m->args[0]->reg.id);
- v = getalias(s, m->args[1]->reg.id);
-
- if (bshas(s->prepainted, v)) {
- tmp = u;
- u = v;
- v = tmp;
- }
-
- if (u == v) {
- lappend(&s->mcoalesced, &s->nmcoalesced, m);
- wladd(s, u);
- wladd(s, v);
- } else if (constrained(s, u, v)) {
- lappend(&s->mconstrained, &s->nmconstrained, m);
- wladd(s, u);
- wladd(s, v);
- } else if (combinable(s, u, v)) {
- lappend(&s->mcoalesced, &s->nmcoalesced, m);
- combine(s, u, v);
- wladd(s, u);
- } else {
- lappend(&s->mactive, &s->nmactive, m);
- bsput(s->mactiveset, m->uid);
- }
+ Insn *m;
+ regid u, v, tmp;
+
+ m = lpop(&s->wlmove, &s->nwlmove);
+ bsdel(s->wlmoveset, m->uid);
+ u = getalias(s, m->args[0]->reg.id);
+ v = getalias(s, m->args[1]->reg.id);
+
+ if (bshas(s->prepainted, v)) {
+ tmp = u;
+ u = v;
+ v = tmp;
+ }
+
+ if (u == v) {
+ lappend(&s->mcoalesced, &s->nmcoalesced, m);
+ wladd(s, u);
+ wladd(s, v);
+ } else if (constrained(s, u, v)) {
+ lappend(&s->mconstrained, &s->nmconstrained, m);
+ wladd(s, u);
+ wladd(s, v);
+ } else if (combinable(s, u, v)) {
+ lappend(&s->mcoalesced, &s->nmcoalesced, m);
+ combine(s, u, v);
+ wladd(s, u);
+ } else {
+ lappend(&s->mactive, &s->nmactive, m);
+ bsput(s->mactiveset, m->uid);
+ }
}
static int mldel(Insn ***ml, size_t *nml, Bitset *bs, Insn *m)
{
- size_t i;
- if (bshas(bs, m->uid)) {
- bsdel(bs, m->uid);
- for (i = 0; i < *nml; i++) {
- if (m == (*ml)[i]) {
- ldel(ml, nml, i);
- return 1;
- }
- }
- }
- return 0;
+ size_t i;
+ if (bshas(bs, m->uid)) {
+ bsdel(bs, m->uid);
+ for (i = 0; i < *nml; i++) {
+ if (m == (*ml)[i]) {
+ ldel(ml, nml, i);
+ return 1;
+ }
+ }
+ }
+ return 0;
}
static void freezemoves(Isel *s, Loc *u)
{
- size_t i;
- Insn **ml;
- Insn *m;
- size_t nml;
- size_t idx;
- Loc *v;
-
- nml = nodemoves(s, u->reg.id, &ml);
- for (i = 0; i < nml; i++) {
- m = ml[i];
- if (getalias(s, m->args[0]->reg.id) == getalias(s, u->reg.id))
- v = locmap[getalias(s, m->args[1]->reg.id)];
- else
- v = locmap[getalias(s, m->args[0]->reg.id)];
-
- if (!mldel(&s->mactive, &s->nmactive, s->mactiveset, m))
- mldel(&s->wlmove, &s->nwlmove, s->wlmoveset, m);
-
- lappend(&s->mfrozen, &s->nmfrozen, m);
- if (!moverelated(s, v->reg.id) && istrivial(s, v->reg.id)) {
- if (!wlfind(s->wlfreeze, s->nwlfreeze, v->reg.id, &idx))
- die("Reg %zd not in freeze wl\n", v->reg.id);
- wldel(s, &s->wlfreeze, &s->nwlfreeze, idx);
- wlput(&s->wlsimp, &s->nwlsimp, v);
- }
-
- }
- lfree(&ml, &nml);
+ size_t i;
+ Insn **ml;
+ Insn *m;
+ size_t nml;
+ size_t idx;
+ Loc *v;
+
+ nml = nodemoves(s, u->reg.id, &ml);
+ for (i = 0; i < nml; i++) {
+ m = ml[i];
+ if (getalias(s, m->args[0]->reg.id) == getalias(s, u->reg.id))
+ v = locmap[getalias(s, m->args[1]->reg.id)];
+ else
+ v = locmap[getalias(s, m->args[0]->reg.id)];
+
+ if (!mldel(&s->mactive, &s->nmactive, s->mactiveset, m))
+ mldel(&s->wlmove, &s->nwlmove, s->wlmoveset, m);
+
+ lappend(&s->mfrozen, &s->nmfrozen, m);
+ if (!moverelated(s, v->reg.id) && istrivial(s, v->reg.id)) {
+ if (!wlfind(s->wlfreeze, s->nwlfreeze, v->reg.id, &idx))
+ die("Reg %zd not in freeze wl\n", v->reg.id);
+ wldel(s, &s->wlfreeze, &s->nwlfreeze, idx);
+ wlput(&s->wlsimp, &s->nwlsimp, v);
+ }
+
+ }
+ lfree(&ml, &nml);
}
static void freeze(Isel *s)
{
- Loc *l;
+ Loc *l;
- l = lpop(&s->wlfreeze, &s->nwlfreeze);
- wlput(&s->wlsimp, &s->nwlsimp, l);
- freezemoves(s, l);
+ l = lpop(&s->wlfreeze, &s->nwlfreeze);
+ wlput(&s->wlsimp, &s->nwlsimp, l);
+ freezemoves(s, l);
}
/* Select the spill candidates */
static void selspill(Isel *s)
{
- size_t i;
- Loc *m;
-
- /* FIXME: pick a better heuristic for spilling */
- m = NULL;
- for (i = 0; i < s->nwlspill; i++) {
- if (!bshas(s->shouldspill, s->wlspill[i]->reg.id))
- continue;
- m = s->wlspill[i];
- wldel(s, &s->wlspill, &s->nwlspill, i);
- break;
- }
- if (!m) {
- for (i = 0; i < s->nwlspill; i++) {
- if (bshas(s->neverspill, s->wlspill[i]->reg.id)) {
- continue;
- }
- m = s->wlspill[i];
- wldel(s, &s->wlspill, &s->nwlspill, i);
- break;
- }
- }
- assert(m != NULL);
- wlput(&s->wlsimp, &s->nwlsimp, m);
- freezemoves(s, m);
+ size_t i;
+ Loc *m;
+
+ /* FIXME: pick a better heuristic for spilling */
+ m = NULL;
+ for (i = 0; i < s->nwlspill; i++) {
+ if (!bshas(s->shouldspill, s->wlspill[i]->reg.id))
+ continue;
+ m = s->wlspill[i];
+ wldel(s, &s->wlspill, &s->nwlspill, i);
+ break;
+ }
+ if (!m) {
+ for (i = 0; i < s->nwlspill; i++) {
+ if (bshas(s->neverspill, s->wlspill[i]->reg.id)) {
+ continue;
+ }
+ m = s->wlspill[i];
+ wldel(s, &s->wlspill, &s->nwlspill, i);
+ break;
+ }
+ }
+ assert(m != NULL);
+ wlput(&s->wlsimp, &s->nwlsimp, m);
+ freezemoves(s, m);
}
/*
@@ -958,98 +957,98 @@ static void selspill(Isel *s)
*/
static int paint(Isel *s)
{
- int taken[Nreg];
- Loc *n, *w;
- regid l;
- size_t i, j;
- int spilled;
- int found;
-
- spilled = 0;
- while (s->nselstk) {
- memset(taken, 0, Nreg*sizeof(int));
- n = lpop(&s->selstk, &s->nselstk);
-
- for (j = 0; j < s->ngadj[n->reg.id];j++) {
- l = s->gadj[n->reg.id][j];
- if (debugopt['r'] > 1)
- printedge(stdout, "paint-edge:", n->reg.id, l);
- w = locmap[getalias(s, l)];
- if (w->reg.colour)
- taken[colourmap[w->reg.colour]] = 1;
- }
-
- found = 0;
- for (i = 0; i < Northogonal; i++) {
- if (regmap[i][n->mode] && !taken[i]) {
- n->reg.colour = regmap[i][n->mode];
- found = 1;
- break;
- }
- }
- if (!found) {
- spilled = 1;
- wlputset(s->spilled, n->reg.id);
- }
- }
- for (l = 0; bsiter(s->coalesced, &l); l++) {
- n = locmap[getalias(s, l)];
- locmap[l]->reg.colour = n->reg.colour;
- }
- return spilled;
+ int taken[Nreg];
+ Loc *n, *w;
+ regid l;
+ size_t i, j;
+ int spilled;
+ int found;
+
+ spilled = 0;
+ while (s->nselstk) {
+ memset(taken, 0, Nreg*sizeof(int));
+ n = lpop(&s->selstk, &s->nselstk);
+
+ for (j = 0; j < s->ngadj[n->reg.id];j++) {
+ l = s->gadj[n->reg.id][j];
+ if (debugopt['r'] > 1)
+ printedge(stdout, "paint-edge:", n->reg.id, l);
+ w = locmap[getalias(s, l)];
+ if (w->reg.colour)
+ taken[colourmap[w->reg.colour]] = 1;
+ }
+
+ found = 0;
+ for (i = 0; i < Northogonal; i++) {
+ if (regmap[i][n->mode] && !taken[i]) {
+ n->reg.colour = regmap[i][n->mode];
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ spilled = 1;
+ wlputset(s->spilled, n->reg.id);
+ }
+ }
+ for (l = 0; bsiter(s->coalesced, &l); l++) {
+ n = locmap[getalias(s, l)];
+ locmap[l]->reg.colour = n->reg.colour;
+ }
+ return spilled;
}
static Loc *mapfind(Isel *s, Htab *map, Loc *old)
{
- Loc *new;
- Loc *base;
- Loc *idx;
- regid id;
-
- if (!old)
- return NULL;
-
- new = NULL;
- if (old->type == Locreg) {
- id = getalias(s, old->reg.id);
- new = htget(map, locmap[id]);
- } else if (old->type == Locmem || old->type == Locmeml) {
- base = old->mem.base;
- idx = old->mem.idx;
- if (base)
- base = locmap[getalias(s, base->reg.id)];
- if (idx)
- idx = locmap[getalias(s, idx->reg.id)];
- base = mapfind(s, map, base);
- idx = mapfind(s, map, idx);
- if (base != old->mem.base || idx != old->mem.idx) {
- if (old->type == Locmem)
- new = locmems(old->mem.constdisp, base, idx, old->mem.scale, old->mode);
- else
- new = locmemls(old->mem.lbldisp, base, idx, old->mem.scale, old->mode);
- }
- }
- if (new)
- return new;
- return old;
+ Loc *new;
+ Loc *base;
+ Loc *idx;
+ regid id;
+
+ if (!old)
+ return NULL;
+
+ new = NULL;
+ if (old->type == Locreg) {
+ id = getalias(s, old->reg.id);
+ new = htget(map, locmap[id]);
+ } else if (old->type == Locmem || old->type == Locmeml) {
+ base = old->mem.base;
+ idx = old->mem.idx;
+ if (base)
+ base = locmap[getalias(s, base->reg.id)];
+ if (idx)
+ idx = locmap[getalias(s, idx->reg.id)];
+ base = mapfind(s, map, base);
+ idx = mapfind(s, map, idx);
+ if (base != old->mem.base || idx != old->mem.idx) {
+ if (old->type == Locmem)
+ new = locmems(old->mem.constdisp, base, idx, old->mem.scale, old->mode);
+ else
+ new = locmemls(old->mem.lbldisp, base, idx, old->mem.scale, old->mode);
+ }
+ }
+ if (new)
+ return new;
+ return old;
}
static Loc *spillslot(Isel *s, regid reg)
{
- size_t stkoff;
+ size_t stkoff;
- stkoff = ptoi(htget(s->spillslots, itop(reg)));
- return locmem(-stkoff, locphysreg(Rrbp), NULL, locmap[reg]->mode);
+ stkoff = ptoi(htget(s->spillslots, itop(reg)));
+ return locmem(-stkoff, locphysreg(Rrbp), NULL, locmap[reg]->mode);
}
static void updatelocs(Isel *s, Htab *map, Insn *insn)
{
- size_t i;
+ size_t i;
- for (i = 0; i < insn->nargs; i++) {
- insn->args[i] = mapfind(s, map, insn->args[i]);
- insn->args[i] = mapfind(s, map, insn->args[i]);
- }
+ for (i = 0; i < insn->nargs; i++) {
+ insn->args[i] = mapfind(s, map, insn->args[i]);
+ insn->args[i] = mapfind(s, map, insn->args[i]);
+ }
}
/*
@@ -1059,82 +1058,82 @@ static void updatelocs(Isel *s, Htab *map, Insn *insn)
*/
static int remap(Isel *s, Htab *map, Insn *insn, regid *use, size_t nuse, regid *def, size_t ndef)
{
- regid ruse, rdef;
- int remapped;
- Loc *tmp;
- size_t i;
-
- remapped = 0;
- for (i = 0; i < nuse; i++) {
- ruse = getalias(s, use[i]);
- if (!bshas(s->spilled, ruse))
- continue;
- tmp = locreg(locmap[ruse]->mode);
- htput(map, locmap[ruse], tmp);
- bsput(s->neverspill, tmp->reg.id);
- remapped = 1;
- }
-
- for (i = 0; i < ndef; i++) {
- rdef = getalias(s, def[i]);
- if (!bshas(s->spilled, rdef))
- continue;
- if (hthas(map, locmap[rdef]))
- continue;
- tmp = locreg(locmap[rdef]->mode);
- htput(map, locmap[rdef], tmp);
- bsput(s->neverspill, tmp->reg.id);
- remapped = 1;
- }
-
- return remapped;
+ regid ruse, rdef;
+ int remapped;
+ Loc *tmp;
+ size_t i;
+
+ remapped = 0;
+ for (i = 0; i < nuse; i++) {
+ ruse = getalias(s, use[i]);
+ if (!bshas(s->spilled, ruse))
+ continue;
+ tmp = locreg(locmap[ruse]->mode);
+ htput(map, locmap[ruse], tmp);
+ bsput(s->neverspill, tmp->reg.id);
+ remapped = 1;
+ }
+
+ for (i = 0; i < ndef; i++) {
+ rdef = getalias(s, def[i]);
+ if (!bshas(s->spilled, rdef))
+ continue;
+ if (hthas(map, locmap[rdef]))
+ continue;
+ tmp = locreg(locmap[rdef]->mode);
+ htput(map, locmap[rdef], tmp);
+ bsput(s->neverspill, tmp->reg.id);
+ remapped = 1;
+ }
+
+ return remapped;
}
static int nopmov(Insn *insn)
{
- if (insn->op != Imov && insn->op != Imovs)
- return 0;
- if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
- return 0;
- return insn->args[0]->reg.id == insn->args[1]->reg.id;
+ if (insn->op != Imov && insn->op != Imovs)
+ return 0;
+ if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
+ return 0;
+ return insn->args[0]->reg.id == insn->args[1]->reg.id;
}
void replacealias(Isel *s, Loc **map, size_t nreg, Insn *insn)
{
- size_t i;
- Loc *l;
-
- if (!map)
- return;
- for (i = 0; i < insn->nargs; i++) {
- l = insn->args[i];
- if (l->type == Locreg) {
- insn->args[i] = locmap[getalias(s, l->reg.id)];
- } else if (l->type == Locmem || l->type == Locmeml) {
- if (l->mem.base)
- l->mem.base = locmap[getalias(s, l->mem.base->reg.id)];
- if (l->mem.idx)
- l->mem.idx = locmap[getalias(s, l->mem.idx->reg.id)];
- }
- }
+ size_t i;
+ Loc *l;
+
+ if (!map)
+ return;
+ for (i = 0; i < insn->nargs; i++) {
+ l = insn->args[i];
+ if (l->type == Locreg) {
+ insn->args[i] = locmap[getalias(s, l->reg.id)];
+ } else if (l->type == Locmem || l->type == Locmeml) {
+ if (l->mem.base)
+ l->mem.base = locmap[getalias(s, l->mem.base->reg.id)];
+ if (l->mem.idx)
+ l->mem.idx = locmap[getalias(s, l->mem.idx->reg.id)];
+ }
+ }
}
static ulong reglochash(void *p)
{
- Loc *l;
-
- l = p;
- return inthash(l->reg.id);
+ Loc *l;
+
+ l = p;
+ return inthash(l->reg.id);
}
static int regloceq(void *pa, void *pb)
{
- Loc *a, *b;
-
- a = pa;
- b = pb;
- return a->reg.id == b->reg.id;
+ Loc *a, *b;
+
+ a = pa;
+ b = pb;
+ return a->reg.id == b->reg.id;
}
/*
* Rewrite instructions using spilled registers, inserting
@@ -1142,74 +1141,74 @@ static int regloceq(void *pa, void *pb)
*/
static void rewritebb(Isel *s, Asmbb *bb, Loc **aliasmap)
{
- regid use[Nreg], def[Nreg];
- size_t nuse, ndef;
- Insn *insn, *mov;
- size_t i, j;
- Insn **new;
- size_t nnew;
- Htab *map;
- Loc *tmp;
-
- new = NULL;
- nnew = 0;
- if (!bb)
- return;
- map = mkht(reglochash, regloceq);
- for (j = 0; j < bb->ni; j++) {
- insn = bb->il[j];
- replacealias(s, aliasmap, s->nreg, insn);
- if (nopmov(insn))
- continue;
- nuse = uses(insn, use);
- ndef = defs(insn, def);
- /* if there is a remapping, insert the loads and stores as needed */
- if (remap(s, map, insn, use, nuse, def, ndef)) {
- for (i = 0; i < nuse; i++) {
- tmp = htget(map, locmap[use[i]]);
- if (!tmp)
- continue;
- if (isfloatmode(tmp->mode))
- mov = mkinsn(Imovs, spillslot(s, use[i]), tmp, NULL);
- else
- mov = mkinsn(Imov, spillslot(s, use[i]), tmp, NULL);
- lappend(&new, &nnew, mov);
- }
- updatelocs(s, map, insn);
- lappend(&new, &nnew, insn);
- for (i = 0; i < ndef; i++) {
- tmp = htget(map, locmap[def[i]]);
- if (!tmp)
- continue;
- if (isfloatmode(tmp->mode))
- mov = mkinsn(Imovs, tmp, spillslot(s, def[i]), NULL);
- else
- mov = mkinsn(Imov, tmp, spillslot(s, def[i]), NULL);
- lappend(&new, &nnew, mov);
- }
- for (i = 0; i < nuse; i++)
- htdel(map, locmap[use[i]]);
- for (i = 0; i < ndef; i++)
- htdel(map, locmap[def[i]]);
- } else {
- lappend(&new, &nnew, insn);
- }
- }
- lfree(&bb->il, &bb->ni);
- bb->il = new;
- bb->ni = nnew;
+ regid use[Nreg], def[Nreg];
+ size_t nuse, ndef;
+ Insn *insn, *mov;
+ size_t i, j;
+ Insn **new;
+ size_t nnew;
+ Htab *map;
+ Loc *tmp;
+
+ new = NULL;
+ nnew = 0;
+ if (!bb)
+ return;
+ map = mkht(reglochash, regloceq);
+ for (j = 0; j < bb->ni; j++) {
+ insn = bb->il[j];
+ replacealias(s, aliasmap, s->nreg, insn);
+ if (nopmov(insn))
+ continue;
+ nuse = uses(insn, use);
+ ndef = defs(insn, def);
+ /* if there is a remapping, insert the loads and stores as needed */
+ if (remap(s, map, insn, use, nuse, def, ndef)) {
+ for (i = 0; i < nuse; i++) {
+ tmp = htget(map, locmap[use[i]]);
+ if (!tmp)
+ continue;
+ if (isfloatmode(tmp->mode))
+ mov = mkinsn(Imovs, spillslot(s, use[i]), tmp, NULL);
+ else
+ mov = mkinsn(Imov, spillslot(s, use[i]), tmp, NULL);
+ lappend(&new, &nnew, mov);
+ }
+ updatelocs(s, map, insn);
+ lappend(&new, &nnew, insn);
+ for (i = 0; i < ndef; i++) {
+ tmp = htget(map, locmap[def[i]]);
+ if (!tmp)
+ continue;
+ if (isfloatmode(tmp->mode))
+ mov = mkinsn(Imovs, tmp, spillslot(s, def[i]), NULL);
+ else
+ mov = mkinsn(Imov, tmp, spillslot(s, def[i]), NULL);
+ lappend(&new, &nnew, mov);
+ }
+ for (i = 0; i < nuse; i++)
+ htdel(map, locmap[use[i]]);
+ for (i = 0; i < ndef; i++)
+ htdel(map, locmap[def[i]]);
+ } else {
+ lappend(&new, &nnew, insn);
+ }
+ }
+ lfree(&bb->il, &bb->ni);
+ bb->il = new;
+ bb->ni = nnew;
}
static void addspill(Isel *s, Loc *l)
{
- s->stksz->lit += modesize[l->mode];
- s->stksz->lit = align(s->stksz->lit, modesize[l->mode]);
- if (debugopt['r']) {
- printf("spill ");
- dbglocprint(stdout, l, 'x');
- printf(" to %zd(%%rbp)\n", s->stksz->lit);
- }
- htput(s->spillslots, itop(l->reg.id), itop(s->stksz->lit));
+ s->stksz->lit += modesize[l->mode];
+ s->stksz->lit = align(s->stksz->lit, modesize[l->mode]);
+ if (debugopt['r']) {
+ printf("spill ");
+ dbglocprint(stdout, l, 'x');
+ printf(" to %zd(%%rbp)\n", s->stksz->lit);
+ }
+ htput(s->spillslots, itop(l->reg.id), itop(s->stksz->lit));
}
/*
@@ -1226,18 +1225,18 @@ static void addspill(Isel *s, Loc *l)
*/
static void rewrite(Isel *s, Loc **aliasmap)
{
- size_t i;
-
- s->spillslots = mkht(ptrhash, ptreq);
- /* set up stack locations for all spilled registers. */
- for (i = 0; bsiter(s->spilled, &i); i++)
- addspill(s, locmap[i]);
-
- /* rewrite instructions using them */
- for (i = 0; i < s->nbb; i++)
- rewritebb(s, s->bb[i], aliasmap);
- htfree(s->spillslots);
- bsclear(s->spilled);
+ size_t i;
+
+ s->spillslots = mkht(ptrhash, ptreq);
+ /* set up stack locations for all spilled registers. */
+ for (i = 0; bsiter(s->spilled, &i); i++)
+ addspill(s, locmap[i]);
+
+ /* rewrite instructions using them */
+ for (i = 0; i < s->nbb; i++)
+ rewritebb(s, s->bb[i], aliasmap);
+ htfree(s->spillslots);
+ bsclear(s->spilled);
}
/*
@@ -1250,187 +1249,187 @@ static void rewrite(Isel *s, Loc **aliasmap)
*/
static void delnops(Isel *s)
{
- Insn *insn;
- Asmbb *bb;
- Insn **new;
- size_t nnew;
- size_t i, j;
-
- for (i = 0; i < s->nbb; i++) {
- if (!s->bb[i])
- continue;
- new = NULL;
- nnew = 0;
- bb = s->bb[i];
- for (j = 0; j < bb->ni; j++) {
- insn = bb->il[j];
- if (ismove(insn) && insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- continue;
- lappend(&new, &nnew, insn);
- }
- lfree(&bb->il, &bb->ni);
- bb->il = new;
- bb->ni = nnew;
- }
- if (debugopt['r'])
- dumpasm(s, stdout);
+ Insn *insn;
+ Asmbb *bb;
+ Insn **new;
+ size_t nnew;
+ size_t i, j;
+
+ for (i = 0; i < s->nbb; i++) {
+ if (!s->bb[i])
+ continue;
+ new = NULL;
+ nnew = 0;
+ bb = s->bb[i];
+ for (j = 0; j < bb->ni; j++) {
+ insn = bb->il[j];
+ if (ismove(insn) && insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ continue;
+ lappend(&new, &nnew, insn);
+ }
+ lfree(&bb->il, &bb->ni);
+ bb->il = new;
+ bb->ni = nnew;
+ }
+ if (debugopt['r'])
+ dumpasm(s, stdout);
}
void regalloc(Isel *s)
{
- int spilled;
- size_t i;
- Loc **aliasmap;
-
- /* Initialize the list of prepainted registers */
- s->prepainted = mkbs();
- bsput(s->prepainted, 0);
- for (i = 0; i < Nreg; i++)
- bsput(s->prepainted, i);
-
- s->shouldspill = mkbs();
- s->neverspill = mkbs();
- s->initial = mkbs();
- for (i = 0; i < s->nsaved; i++)
- bsput(s->shouldspill, s->calleesave[i]->reg.id);
- do {
- aliasmap = NULL;
- setup(s);
- liveness(s);
- build(s);
- mkworklist(s);
- if (debugopt['r'])
- dumpasm(s, stdout);
- do {
- if (s->nwlsimp)
- simp(s);
- else if (s->nwlmove)
- coalesce(s);
- else if (s->nwlfreeze)
- freeze(s);
- else if (s->nwlspill) {
- if (!aliasmap)
- aliasmap = memdup(s->aliasmap, s->nreg * sizeof(Loc*));
- selspill(s);
- }
- } while (s->nwlsimp || s->nwlmove || s->nwlfreeze || s->nwlspill);
- spilled = paint(s);
- if (spilled)
- rewrite(s, aliasmap);
- } while (spilled);
- delnops(s);
- bsfree(s->prepainted);
- bsfree(s->shouldspill);
- bsfree(s->neverspill);
- gfree(s);
+ int spilled;
+ size_t i;
+ Loc **aliasmap;
+
+ /* Initialize the list of prepainted registers */
+ s->prepainted = mkbs();
+ bsput(s->prepainted, 0);
+ for (i = 0; i < Nreg; i++)
+ bsput(s->prepainted, i);
+
+ s->shouldspill = mkbs();
+ s->neverspill = mkbs();
+ s->initial = mkbs();
+ for (i = 0; i < s->nsaved; i++)
+ bsput(s->shouldspill, s->calleesave[i]->reg.id);
+ do {
+ aliasmap = NULL;
+ setup(s);
+ liveness(s);
+ build(s);
+ mkworklist(s);
+ if (debugopt['r'])
+ dumpasm(s, stdout);
+ do {
+ if (s->nwlsimp)
+ simp(s);
+ else if (s->nwlmove)
+ coalesce(s);
+ else if (s->nwlfreeze)
+ freeze(s);
+ else if (s->nwlspill) {
+ if (!aliasmap)
+ aliasmap = memdup(s->aliasmap, s->nreg * sizeof(Loc*));
+ selspill(s);
+ }
+ } while (s->nwlsimp || s->nwlmove || s->nwlfreeze || s->nwlspill);
+ spilled = paint(s);
+ if (spilled)
+ rewrite(s, aliasmap);
+ } while (spilled);
+ delnops(s);
+ bsfree(s->prepainted);
+ bsfree(s->shouldspill);
+ bsfree(s->neverspill);
+ gfree(s);
}
void wlprint(FILE *fd, char *name, Loc **wl, size_t nwl)
{
- size_t i;
- char *sep;
-
- sep = "";
- fprintf(fd, "%s = [", name);
- for (i = 0; i < nwl; i++) {
- fprintf(fd, "%s", sep);
- dbglocprint(fd, wl[i], 'x');
- fprintf(fd, "(%zd)", wl[i]->reg.id);
- sep = ",";
- }
- fprintf(fd, "]\n");
+ size_t i;
+ char *sep;
+
+ sep = "";
+ fprintf(fd, "%s = [", name);
+ for (i = 0; i < nwl; i++) {
+ fprintf(fd, "%s", sep);
+ dbglocprint(fd, wl[i], 'x');
+ fprintf(fd, "(%zd)", wl[i]->reg.id);
+ sep = ",";
+ }
+ fprintf(fd, "]\n");
}
static void setprint(FILE *fd, Bitset *s)
{
- char *sep;
- size_t i;
-
- sep = "";
- for (i = 0; i < bsmax(s); i++) {
- if (bshas(s, i)) {
- fprintf(fd, "%s%zd", sep, i);
- sep = ",";
- }
- }
- fprintf(fd, "\n");
+ char *sep;
+ size_t i;
+
+ sep = "";
+ for (i = 0; i < bsmax(s); i++) {
+ if (bshas(s, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
}
static void locsetprint(FILE *fd, Bitset *s)
{
- char *sep;
- size_t i;
-
- sep = "";
- for (i = 0; i < bsmax(s); i++) {
- if (bshas(s, i)) {
- fprintf(fd, "%s", sep);
- dbglocprint(fd, locmap[i], 'x');
- sep = ",";
- }
- }
- fprintf(fd, "\n");
+ char *sep;
+ size_t i;
+
+ sep = "";
+ for (i = 0; i < bsmax(s); i++) {
+ if (bshas(s, i)) {
+ fprintf(fd, "%s", sep);
+ dbglocprint(fd, locmap[i], 'x');
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
}
static void printedge(FILE *fd, char *msg, size_t a, size_t b)
{
- fprintf(fd, "\t%s ", msg);
- dbglocprint(fd, locmap[a], 'x');
- fprintf(fd, " -- ");
- dbglocprint(fd, locmap[b], 'x');
- fprintf(fd, "\n");
+ fprintf(fd, "\t%s ", msg);
+ dbglocprint(fd, locmap[a], 'x');
+ fprintf(fd, " -- ");
+ dbglocprint(fd, locmap[b], 'x');
+ fprintf(fd, "\n");
}
void dumpasm(Isel *s, FILE *fd)
{
- size_t i, j;
- char *sep;
- Asmbb *bb;
-
- fprintf(fd, "WORKLISTS -- \n");
- wlprint(stdout, "spill", s->wlspill, s->nwlspill);
- wlprint(stdout, "simp", s->wlsimp, s->nwlsimp);
- wlprint(stdout, "freeze", s->wlfreeze, s->nwlfreeze);
- /* noisy to dump this all the time; only dump for higher debug levels */
- if (debugopt['r'] > 2) {
- fprintf(fd, "IGRAPH ----- \n");
- for (i = 0; i < s->nreg; i++) {
- for (j = i; j < s->nreg; j++) {
- if (gbhasedge(s, i, j))
- printedge(stdout, "", i, j);
- }
- }
- }
- fprintf(fd, "ASM -------- \n");
- for (j = 0; j < s->nbb; j++) {
- bb = s->bb[j];
- if (!bb)
- continue;
- fprintf(fd, "\n");
- fprintf(fd, "Bb: %d labels=(", bb->id);
- sep = "";
- for (i = 0; i < bb->nlbls; i++) {;
- fprintf(fd, "%s%s", bb->lbls[i], sep);
- sep = ",";
- }
- fprintf(fd, ")\n");
-
- fprintf(fd, "Pred: ");
- setprint(fd, bb->pred);
- fprintf(fd, "Succ: ");
- setprint(fd, bb->succ);
-
- fprintf(fd, "Use: ");
- locsetprint(fd, bb->use);
- fprintf(fd, "Def: ");
- locsetprint(fd, bb->def);
- fprintf(fd, "Livein: ");
- locsetprint(fd, bb->livein);
- fprintf(fd, "Liveout: ");
- locsetprint(fd, bb->liveout);
- for (i = 0; i < bb->ni; i++)
- dbgiprintf(fd, bb->il[i]);
- }
- fprintf(fd, "ENDASM -------- \n");
+ size_t i, j;
+ char *sep;
+ Asmbb *bb;
+
+ fprintf(fd, "WORKLISTS -- \n");
+ wlprint(stdout, "spill", s->wlspill, s->nwlspill);
+ wlprint(stdout, "simp", s->wlsimp, s->nwlsimp);
+ wlprint(stdout, "freeze", s->wlfreeze, s->nwlfreeze);
+ /* noisy to dump this all the time; only dump for higher debug levels */
+ if (debugopt['r'] > 2) {
+ fprintf(fd, "IGRAPH ----- \n");
+ for (i = 0; i < s->nreg; i++) {
+ for (j = i; j < s->nreg; j++) {
+ if (gbhasedge(s, i, j))
+ printedge(stdout, "", i, j);
+ }
+ }
+ }
+ fprintf(fd, "ASM -------- \n");
+ for (j = 0; j < s->nbb; j++) {
+ bb = s->bb[j];
+ if (!bb)
+ continue;
+ fprintf(fd, "\n");
+ fprintf(fd, "Bb: %d labels=(", bb->id);
+ sep = "";
+ for (i = 0; i < bb->nlbls; i++) {;
+ fprintf(fd, "%s%s", bb->lbls[i], sep);
+ sep = ",";
+ }
+ fprintf(fd, ")\n");
+
+ fprintf(fd, "Pred: ");
+ setprint(fd, bb->pred);
+ fprintf(fd, "Succ: ");
+ setprint(fd, bb->succ);
+
+ fprintf(fd, "Use: ");
+ locsetprint(fd, bb->use);
+ fprintf(fd, "Def: ");
+ locsetprint(fd, bb->def);
+ fprintf(fd, "Livein: ");
+ locsetprint(fd, bb->livein);
+ fprintf(fd, "Liveout: ");
+ locsetprint(fd, bb->liveout);
+ for (i = 0; i < bb->ni; i++)
+ dbgiprintf(fd, bb->il[i]);
+ }
+ fprintf(fd, "ENDASM -------- \n");
}
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);
}
diff --git a/6/typeinfo.c b/6/typeinfo.c
index 0f420cf..5a0cef2 100644
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -21,353 +21,354 @@ Blob *tydescsub(Type *ty);
size_t blobsz(Blob *b)
{
- size_t n;
- size_t i;
-
- switch (b->type) {
- case Bti8: return 1; break;
- case Bti16: return 2; break;
- case Bti32: return 4; break;
- case Bti64: return 8; break;
- case Btref: return 8; break;
- case Btbytes: return b->bytes.len; break;
- case Btimin:
- if (b->ival >= 1ULL << 56)
- die("packed int too big");
-
- for (i = 1; i < 8; i++)
- if (b->ival < 1ULL << (7*i))
- return i;
- die("impossible blob size");
- break;
- case Btseq:
- n = 0;
- for (i = 0; i < b->seq.nsub; i++)
- n += blobsz(b->seq.sub[i]);
- return n;
- break;
- default:
- die("unknown blob type");
- }
- return 0;
+ size_t n;
+ size_t i;
+
+ switch (b->type) {
+ case Bti8: return 1; break;
+ case Bti16: return 2; break;
+ case Bti32: return 4; break;
+ case Bti64: return 8; break;
+ case Btref: return 8; break;
+ case Btbytes: return b->bytes.len; break;
+ case Btimin:
+ if (b->ival >= 1ULL << 56)
+ die("packed int too big");
+
+ for (i = 1; i < 8; i++)
+ if (b->ival < 1ULL << (7*i))
+ return i;
+ die("impossible blob size");
+ break;
+ case Btseq:
+ n = 0;
+ for (i = 0; i < b->seq.nsub; i++)
+ n += blobsz(b->seq.sub[i]);
+ return n;
+ break;
+ default:
+ die("unknown blob type");
+ }
+ return 0;
}
void namevec(Blob ***sub, size_t *nsub, Node *n)
{
- char *buf;
- size_t len;
-
- if (n->name.ns) {
- len = strlen(n->name.name) + strlen(n->name.ns) + 1;
- buf = xalloc(len + 1);
- bprintf(buf, len + 1, "%s.%s", n->name.ns, n->name.name);
- } else {
- len = strlen(n->name.name);
- buf = xalloc(len + 1);
- bprintf(buf, len + 1, "%s", n->name.name);
- }
- lappend(sub, nsub, mkblobi(Btimin, len));
- lappend(sub, nsub, mkblobbytes(buf, len));
+ char *buf;
+ size_t len;
+
+ if (n->name.ns) {
+ len = strlen(n->name.name) + strlen(n->name.ns) + 1;
+ buf = xalloc(len + 1);
+ bprintf(buf, len + 1, "%s.%s", n->name.ns, n->name.name);
+ } else {
+ len = strlen(n->name.name);
+ buf = xalloc(len + 1);
+ bprintf(buf, len + 1, "%s", n->name.name);
+ }
+ lappend(sub, nsub, mkblobi(Btimin, len));
+ lappend(sub, nsub, mkblobbytes(buf, len));
}
static void structmemb(Blob ***sub, size_t *nsub, Node *sdecl)
{
- Blob *b;
+ Blob *b;
- namevec(sub, nsub, sdecl->decl.name);
- b = tydescsub(sdecl->decl.type);
- lappend(sub, nsub, b);
+ namevec(sub, nsub, sdecl->decl.name);
+ b = tydescsub(sdecl->decl.type);
+ lappend(sub, nsub, b);
}
static void unionmemb(Blob ***sub, size_t *nsub, Ucon *ucon)
{
- namevec(sub, nsub, ucon->name);
- if (ucon->etype) {
- lappend(sub, nsub, tydescsub(ucon->etype));
- } else {
- lappend(sub, nsub, mkblobi(Btimin, 1));
- lappend(sub, nsub, mkblobi(Bti8, Tybad));
- }
+ namevec(sub, nsub, ucon->name);
+ if (ucon->etype) {
+ lappend(sub, nsub, tydescsub(ucon->etype));
+ } else {
+ lappend(sub, nsub, mkblobi(Btimin, 1));
+ lappend(sub, nsub, mkblobi(Bti8, Tybad));
+ }
}
static void encodetypeinfo(Blob ***sub, size_t *nsub, Type *t)
{
- lappend(sub, nsub, mkblobi(Btimin, tysize(t)));
- lappend(sub, nsub, mkblobi(Btimin, tyalign(t)));
+ lappend(sub, nsub, mkblobi(Btimin, tysize(t)));
+ lappend(sub, nsub, mkblobi(Btimin, tyalign(t)));
}
Blob *tydescsub(Type *ty)
{
- Blob **sub, *sz, *bt, *b;
- size_t i, nsub;
- char buf[512];
- uint8_t tt;
- Node *len;
-
- sub = NULL;
- nsub = 0;
- /* names are pulled out of line */
- tt = ty->type;
- /* tyvars can get tagged, but aren't desired */
- if (ty->type == Tyvar)
- return NULL;
-
- if (ty->type == Tyname)
- tt |= Tdindirect;
- sz = mkblobi(Btimin, 0);
- bt = mkblobi(Bti8, tt);
- lappend(&sub, &nsub, bt);
- switch (ty->type) {
- case Ntypes: case Tyvar: case Tybad: case Typaram:
- case Tygeneric: case Tycode: case Tyunres:
- die("invalid type in tydesc"); break;
-
- /* atomic types -- nothing else to do */
- case Tyvoid: case Tychar: case Tybool: case Tyint8:
- case Tyint16: case Tyint: case Tyint32: case Tyint64:
- case Tybyte: case Tyuint8: case Tyuint16:
- case Tyuint: case Tyuint32: case Tyuint64:
- case Tyflt32: case Tyflt64: case Tyvalist:
- break;
-
- case Typtr:
- lappend(&sub, &nsub, tydescsub(ty->sub[0]));
- break;
- case Tyslice:
- lappend(&sub, &nsub, tydescsub(ty->sub[0]));
- break;
- case Tyarray:
- encodetypeinfo(&sub, &nsub, ty);
- ty->asize = fold(ty->asize, 1);
- len = ty->asize;
- if (len) {
- assert(len->type == Nexpr);
- len = len->expr.args[0];
- assert(len->type == Nlit && len->lit.littype == Lint);
- lappend(&sub, &nsub, mkblobi(Btimin, len->lit.intval));
- } else {
- lappend(&sub, &nsub, mkblobi(Btimin, 0));
- }
-
- lappend(&sub, &nsub, tydescsub(ty->sub[0]));
- break;
- case Tyfunc:
- lappend(&sub, &nsub, mkblobi(Btimin, ty->nsub));
- for (i = 0; i < ty->nsub; i++)
- lappend(&sub, &nsub, tydescsub(ty->sub[i]));
- break;
- case Tytuple:
- encodetypeinfo(&sub, &nsub, ty);
- lappend(&sub, &nsub, mkblobi(Btimin, ty->nsub));
- for (i = 0; i < ty->nsub; i++)
- lappend(&sub, &nsub, tydescsub(ty->sub[i]));
- break;
- case Tystruct:
- encodetypeinfo(&sub, &nsub, ty);
- lappend(&sub, &nsub, mkblobi(Btimin, ty->nmemb));
- for (i = 0; i < ty->nmemb; i++)
- structmemb(&sub, &nsub, ty->sdecls[i]);
- break;
- case Tyunion:
- encodetypeinfo(&sub, &nsub, ty);
- lappend(&sub, &nsub, mkblobi(Btimin, ty->nmemb));
- for (i = 0; i < ty->nmemb; i++)
- unionmemb(&sub, &nsub, ty->udecls[i]);
- break;
- case Tyname:
- i = bprintf(buf, sizeof buf, "%s", Symprefix);
- tydescid(buf + i, sizeof buf - i, ty);
- lappend(&sub, &nsub, mkblobref(buf, 0, ty->isimport || ty->vis == Visexport));
- break;
- }
- b = mkblobseq(sub, nsub);
- sz->ival = blobsz(b);
- linsert(&b->seq.sub, &b->seq.nsub, 0, sz);
- return b;
+ Blob **sub, *sz, *bt, *b;
+ size_t i, nsub;
+ char buf[512];
+ uint8_t tt;
+ Node *len;
+
+ sub = NULL;
+ nsub = 0;
+ /* names are pulled out of line */
+ tt = ty->type;
+ /* tyvars can get tagged, but aren't desired */
+ if (ty->type == Tyvar)
+ return NULL;
+
+ if (ty->type == Tyname)
+ tt |= Tdindirect;
+ sz = mkblobi(Btimin, 0);
+ bt = mkblobi(Bti8, tt);
+ lappend(&sub, &nsub, bt);
+ switch (ty->type) {
+ case Ntypes: case Tyvar: case Tybad: case Typaram:
+ case Tygeneric: case Tycode: case Tyunres:
+ die("invalid type in tydesc");
+ break;
+
+ /* atomic types -- nothing else to do */
+ case Tyvoid: case Tychar: case Tybool: case Tyint8:
+ case Tyint16: case Tyint: case Tyint32: case Tyint64:
+ case Tybyte: case Tyuint8: case Tyuint16:
+ case Tyuint: case Tyuint32: case Tyuint64:
+ case Tyflt32: case Tyflt64: case Tyvalist:
+ break;
+
+ case Typtr:
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ break;
+ case Tyslice:
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ break;
+ case Tyarray:
+ encodetypeinfo(&sub, &nsub, ty);
+ ty->asize = fold(ty->asize, 1);
+ len = ty->asize;
+ if (len) {
+ assert(len->type == Nexpr);
+ len = len->expr.args[0];
+ assert(len->type == Nlit && len->lit.littype == Lint);
+ lappend(&sub, &nsub, mkblobi(Btimin, len->lit.intval));
+ } else {
+ lappend(&sub, &nsub, mkblobi(Btimin, 0));
+ }
+
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ break;
+ case Tyfunc:
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nsub));
+ for (i = 0; i < ty->nsub; i++)
+ lappend(&sub, &nsub, tydescsub(ty->sub[i]));
+ break;
+ case Tytuple:
+ encodetypeinfo(&sub, &nsub, ty);
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nsub));
+ for (i = 0; i < ty->nsub; i++)
+ lappend(&sub, &nsub, tydescsub(ty->sub[i]));
+ break;
+ case Tystruct:
+ encodetypeinfo(&sub, &nsub, ty);
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nmemb));
+ for (i = 0; i < ty->nmemb; i++)
+ structmemb(&sub, &nsub, ty->sdecls[i]);
+ break;
+ case Tyunion:
+ encodetypeinfo(&sub, &nsub, ty);
+ lappend(&sub, &nsub, mkblobi(Btimin, ty->nmemb));
+ for (i = 0; i < ty->nmemb; i++)
+ unionmemb(&sub, &nsub, ty->udecls[i]);
+ break;
+ case Tyname:
+ i = bprintf(buf, sizeof buf, "%s", Symprefix);
+ tydescid(buf + i, sizeof buf - i, ty);
+ lappend(&sub, &nsub, mkblobref(buf, 0, ty->isimport || ty->vis == Visexport));
+ break;
+ }
+ b = mkblobseq(sub, nsub);
+ sz->ival = blobsz(b);
+ linsert(&b->seq.sub, &b->seq.nsub, 0, sz);
+ return b;
}
Blob *namedesc(Type *ty)
{
- Blob **sub;
- size_t nsub;
-
- sub = NULL;
- nsub = 0;
- lappend(&sub, &nsub, mkblobi(Bti8, Tyname));
- namevec(&sub, &nsub, ty->name);
- lappend(&sub, &nsub, tydescsub(ty->sub[0]));
- return mkblobseq(sub, nsub);
+ Blob **sub;
+ size_t nsub;
+
+ sub = NULL;
+ nsub = 0;
+ lappend(&sub, &nsub, mkblobi(Bti8, Tyname));
+ namevec(&sub, &nsub, ty->name);
+ lappend(&sub, &nsub, tydescsub(ty->sub[0]));
+ return mkblobseq(sub, nsub);
}
Blob *tydescblob(Type *ty)
{
- char buf[512];
- Blob *b, *sz, *sub;
-
- if (ty->type == Tyname && hasparams(ty))
- return NULL;
-
- if (ty->type == Tyname) {
- b = mkblobseq(NULL, 0);
- sz = mkblobi(Btimin, 0);
- sub = namedesc(ty);
- sz->ival = blobsz(sub);
- lappend(&b->seq.sub, &b->seq.nsub, sz);
- lappend(&b->seq.sub, &b->seq.nsub, sub);
- if (ty->vis == Visexport)
- b->isglobl = 1;
- } else {
- b = tydescsub(ty);
- }
- tydescid(buf, sizeof buf, ty);
- b->lbl = strdup(buf);
- return b;
+ char buf[512];
+ Blob *b, *sz, *sub;
+
+ if (ty->type == Tyname && hasparams(ty))
+ return NULL;
+
+ if (ty->type == Tyname) {
+ b = mkblobseq(NULL, 0);
+ sz = mkblobi(Btimin, 0);
+ sub = namedesc(ty);
+ sz->ival = blobsz(sub);
+ lappend(&b->seq.sub, &b->seq.nsub, sz);
+ lappend(&b->seq.sub, &b->seq.nsub, sub);
+ if (ty->vis == Visexport)
+ b->isglobl = 1;
+ } else {
+ b = tydescsub(ty);
+ }
+ tydescid(buf, sizeof buf, ty);
+ b->lbl = strdup(buf);
+ return b;
}
size_t tysize(Type *t)
{
- size_t sz;
- size_t i;
-
- sz = 0;
- if (!t)
- die("size of empty type => bailing.");
- switch (t->type) {
- case Tyvoid:
- return 0;
- case Tybool: case Tyint8:
- case Tybyte: case Tyuint8:
- return 1;
- case Tyint16: case Tyuint16:
- return 2;
- case Tyint: case Tyint32:
- case Tyuint: case Tyuint32:
- case Tychar: /* utf32 */
- return 4;
-
- case Typtr:
- case Tyvalist: /* ptr to first element of valist */
- return Ptrsz;
-
- case Tyint64:
- case Tyuint64:
- return 8;
-
- /*end integer types*/
- case Tyflt32:
- return 4;
- case Tyflt64:
- return 8;
-
- case Tycode:
- return Ptrsz;
- case Tyfunc:
- return 2*Ptrsz;
- case Tyslice:
- return 2*Ptrsz; /* len; ptr */
- case Tyname:
- return tysize(t->sub[0]);
- case Tyarray:
- if (!t->asize)
- return 0;
- t->asize = fold(t->asize, 1);
- assert(exprop(t->asize) == Olit);
- return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
- case Tytuple:
- for (i = 0; i < t->nsub; i++) {
- sz = alignto(sz, t->sub[i]);
- sz += tysize(t->sub[i]);
- }
- sz = alignto(sz, t);
- return sz;
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++) {
- sz = alignto(sz, decltype(t->sdecls[i]));
- sz += size(t->sdecls[i]);
- }
- sz = alignto(sz, t);
- return sz;
- break;
- case Tyunion:
- sz = Wordsz;
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- sz = max(sz, tysize(t->udecls[i]->etype) + Wordsz);
- return align(sz, Ptrsz);
- break;
- case Tygeneric: case Tybad: case Tyvar:
- case Typaram: case Tyunres: case Ntypes:
- die("Type %s does not have size; why did it get down to here?", tystr(t));
- break;
- }
- return -1;
+ size_t sz;
+ size_t i;
+
+ sz = 0;
+ if (!t)
+ die("size of empty type => bailing.");
+ switch (t->type) {
+ case Tyvoid:
+ return 0;
+ case Tybool: case Tyint8:
+ case Tybyte: case Tyuint8:
+ return 1;
+ case Tyint16: case Tyuint16:
+ return 2;
+ case Tyint: case Tyint32:
+ case Tyuint: case Tyuint32:
+ case Tychar: /* utf32 */
+ return 4;
+
+ case Typtr:
+ case Tyvalist: /* ptr to first element of valist */
+ return Ptrsz;
+
+ case Tyint64:
+ case Tyuint64:
+ return 8;
+
+ /*end integer types*/
+ case Tyflt32:
+ return 4;
+ case Tyflt64:
+ return 8;
+
+ case Tycode:
+ return Ptrsz;
+ case Tyfunc:
+ return 2*Ptrsz;
+ case Tyslice:
+ return 2*Ptrsz; /* len; ptr */
+ case Tyname:
+ return tysize(t->sub[0]);
+ case Tyarray:
+ if (!t->asize)
+ return 0;
+ t->asize = fold(t->asize, 1);
+ assert(exprop(t->asize) == Olit);
+ return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
+ case Tytuple:
+ for (i = 0; i < t->nsub; i++) {
+ sz = alignto(sz, t->sub[i]);
+ sz += tysize(t->sub[i]);
+ }
+ sz = alignto(sz, t);
+ return sz;
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++) {
+ sz = alignto(sz, decltype(t->sdecls[i]));
+ sz += size(t->sdecls[i]);
+ }
+ sz = alignto(sz, t);
+ return sz;
+ break;
+ case Tyunion:
+ sz = Wordsz;
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ sz = max(sz, tysize(t->udecls[i]->etype) + Wordsz);
+ return align(sz, Ptrsz);
+ break;
+ case Tygeneric: case Tybad: case Tyvar:
+ case Typaram: case Tyunres: case Ntypes:
+ die("Type %s does not have size; why did it get down to here?", tystr(t));
+ break;
+ }
+ return -1;
}
size_t tyalign(Type *ty)
{
- size_t align, i;
-
- align = 1;
- switch (ty->type) {
- case Tyarray:
- align = tyalign(ty->sub[0]);
- break;
- case Tytuple:
- for (i = 0; i < ty->nsub; i++)
- align = max(align, tyalign(ty->sub[0]));
- break;
- case Tyunion:
- align = 4;
- for (i = 0; i < ty->nmemb; i++)
- if (ty->udecls[i]->etype)
- align = max(align, tyalign(ty->udecls[i]->etype));
- break;
- case Tystruct:
- for (i = 0; i < ty->nmemb; i++)
- align = max(align, tyalign(decltype(ty->sdecls[i])));
- break;
- default:
- align = tysize(ty);
- }
- return min(align, Ptrsz);
+ size_t align, i;
+
+ align = 1;
+ switch (ty->type) {
+ case Tyarray:
+ align = tyalign(ty->sub[0]);
+ break;
+ case Tytuple:
+ for (i = 0; i < ty->nsub; i++)
+ align = max(align, tyalign(ty->sub[0]));
+ break;
+ case Tyunion:
+ align = 4;
+ for (i = 0; i < ty->nmemb; i++)
+ if (ty->udecls[i]->etype)
+ align = max(align, tyalign(ty->udecls[i]->etype));
+ break;
+ case Tystruct:
+ for (i = 0; i < ty->nmemb; i++)
+ align = max(align, tyalign(decltype(ty->sdecls[i])));
+ break;
+ default:
+ align = tysize(ty);
+ }
+ return min(align, Ptrsz);
}
/* gets the byte offset of 'memb' within the aggregate type 'aggr' */
ssize_t tyoffset(Type *ty, Node *memb)
{
- size_t i;
- size_t off;
-
- ty = tybase(ty);
- if (ty->type == Typtr)
- ty = tybase(ty->sub[0]);
-
- assert(ty->type == Tystruct);
- off = 0;
- for (i = 0; i < ty->nmemb; i++) {
- off = alignto(off, decltype(ty->sdecls[i]));
- if (!strcmp(namestr(memb), declname(ty->sdecls[i])))
- return off;
- off += size(ty->sdecls[i]);
- }
- die("bad offset");
- return 0;
+ size_t i;
+ size_t off;
+
+ ty = tybase(ty);
+ if (ty->type == Typtr)
+ ty = tybase(ty->sub[0]);
+
+ assert(ty->type == Tystruct);
+ off = 0;
+ for (i = 0; i < ty->nmemb; i++) {
+ off = alignto(off, decltype(ty->sdecls[i]));
+ if (!strcmp(namestr(memb), declname(ty->sdecls[i])))
+ return off;
+ off += size(ty->sdecls[i]);
+ }
+ die("bad offset");
+ return 0;
}
size_t size(Node *n)
{
- Type *t;
+ Type *t;
- if (n->type == Nexpr)
- t = n->expr.type;
- else
- t = n->decl.type;
- return tysize(t);
+ if (n->type == Nexpr)
+ t = n->expr.type;
+ else
+ t = n->decl.type;
+ return tysize(t);
}
ssize_t offset(Node *aggr, Node *memb)
{
- return tyoffset(exprtype(aggr), memb);
+ return tyoffset(exprtype(aggr), memb);
}
diff --git a/bench/runner.c b/bench/runner.c
deleted file mode 100644
index a43d65b..0000000
--- a/bench/runner.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* written in C instead of Myrddin because I don't have FP in Myrddin yet... */
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <err.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-
-#define Nsamp 10
-
-double run(char *prog)
-{
- struct rusage ru;
- double sec, usec;
- int in, out;
- char *cmd[2];
- int pid;
- int status;
-
- sec = 0;
- usec = 0;
- pid = fork();
- if (pid < 0) {
- err(1, "Could not fork\n");
- } else if (pid == 0) {
- if ((in = open("/dev/zero", O_RDONLY)) < 0)
- err(1, "could not open /dev/zero");
- if ((out = open("/dev/null", O_WRONLY)) < 0)
- err(1, "could not open /dev/null");
- if (dup2(in, 0) < 0)
- err(1, "could not reopen stdin");
- if (dup2(out, 1) < 0)
- err(1, "could not reopen stdout");
-
- cmd[0] = prog;
- cmd[1] = NULL;
- execv(prog, cmd);
- err(1, "Failed to exec\n");
- } else {
- wait4(pid, &status, 0, &ru);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- err(1, "Subprogram failed to execute\n");
- sec = ru.ru_utime.tv_sec;
- usec = ru.ru_utime.tv_usec / (1000.0 * 1000.0);
- }
- return sec + usec;
-}
-
-double timed_run(char *prog)
-{
- double avg, m, d, x;
- int i, n;
-
- avg = 0;
- m = 0;
- n = 0;
- for (i = 0; i < Nsamp; i++) {
- n++;
- x = run(prog);
- d = (x - avg);
- avg += d/n;
- m = m + d*(x - avg);
- }
- printf("%s:\t%fs (σ^2: %f)\n", prog, avg, m/(n-1));
- return avg;
-}
-
-int main(int argc, char **argv)
-{
- double tot;
- int i;
-
- printf("Running benchmarks: %d samples per binary\n", Nsamp);
- tot = 0;
- for (i = 1; i < argc; i++)
- tot += timed_run(argv[i]);
- printf("total:\t%fs\n", tot);
- return 0;
-}
-
diff --git a/mi/cfg.c b/mi/cfg.c
index 39b59fe..f5c6961 100644
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -16,298 +16,298 @@
static Bb *mkbb(Cfg *cfg)
{
- Bb *bb;
+ Bb *bb;
- bb = zalloc(sizeof(Bb));
- bb->id = cfg->nextbbid++;
- bb->pred = mkbs();
- bb->succ = mkbs();
- lappend(&cfg->bb, &cfg->nbb, bb);
- return bb;
+ bb = zalloc(sizeof(Bb));
+ bb->id = cfg->nextbbid++;
+ bb->pred = mkbs();
+ bb->succ = mkbs();
+ lappend(&cfg->bb, &cfg->nbb, bb);
+ return bb;
}
static void strlabel(Cfg *cfg, char *lbl, Bb *bb)
{
- htput(cfg->lblmap, lbl, bb);
- lappend(&bb->lbls, &bb->nlbls, lbl);
+ htput(cfg->lblmap, lbl, bb);
+ lappend(&bb->lbls, &bb->nlbls, lbl);
}
static void label(Cfg *cfg, Node *lbl, Bb *bb)
{
- strlabel(cfg, lblstr(lbl), bb);
+ strlabel(cfg, lblstr(lbl), bb);
}
static int isnonretcall(Node *fn)
{
- Node *dcl;
+ Node *dcl;
- if (exprop(fn) != Ovar)
- return 0;
- dcl = decls[fn->expr.did];
- return dcl->decl.isnoret;
+ if (exprop(fn) != Ovar)
+ return 0;
+ dcl = decls[fn->expr.did];
+ return dcl->decl.isnoret;
}
static int addnode(Cfg *cfg, Bb *bb, Node *n)
{
- switch (exprop(n)) {
- case Ojmp:
- case Ocjmp:
- case Oret:
- lappend(&bb->nl, &bb->nnl, n);
- lappend(&cfg->fixjmp, &cfg->nfixjmp, n);
- lappend(&cfg->fixblk, &cfg->nfixblk, bb);
- return 1;
- case Ocall:
- lappend(&bb->nl, &bb->nnl, n);
- return isnonretcall(n->expr.args[0]);
- case Odead:
- lappend(&bb->nl, &bb->nnl, n);
- return 1;
- default:
- lappend(&bb->nl, &bb->nnl, n);
- break;
- }
- return 0;
+ switch (exprop(n)) {
+ case Ojmp:
+ case Ocjmp:
+ case Oret:
+ lappend(&bb->nl, &bb->nnl, n);
+ lappend(&cfg->fixjmp, &cfg->nfixjmp, n);
+ lappend(&cfg->fixblk, &cfg->nfixblk, bb);
+ return 1;
+ case Ocall:
+ lappend(&bb->nl, &bb->nnl, n);
+ return isnonretcall(n->expr.args[0]);
+ case Odead:
+ lappend(&bb->nl, &bb->nnl, n);
+ return 1;
+ default:
+ lappend(&bb->nl, &bb->nnl, n);
+ break;
+ }
+ return 0;
}
static int islabel(Node *n)
{
- Node *l;
- if (n->type != Nexpr)
- return 0;
- if (exprop(n) != Olit)
- return 0;
- l = n->expr.args[0];
- if (l->type != Nlit)
- return 0;
- if (l->lit.littype != Llbl)
- return 0;
- return 1;
+ Node *l;
+ if (n->type != Nexpr)
+ return 0;
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->type != Nlit)
+ return 0;
+ if (l->lit.littype != Llbl)
+ return 0;
+ return 1;
}
static Bb *addlabel(Cfg *cfg, Bb *bb, Node **nl, size_t i, Srcloc loc)
{
- /* if the current block assumes fall-through, insert an explicit jump */
- if (i > 0 && nl[i - 1]->type == Nexpr) {
- if (exprop(nl[i - 1]) != Ocjmp && exprop(nl[i - 1]) != Ojmp)
- addnode(cfg, bb, mkexpr(loc, Ojmp, mklbl(loc, lblstr(nl[i])), NULL));
- }
- if (bb->nnl)
- bb = mkbb(cfg);
- label(cfg, nl[i], bb);
- return bb;
+ /* if the current block assumes fall-through, insert an explicit jump */
+ if (i > 0 && nl[i - 1]->type == Nexpr) {
+ if (exprop(nl[i - 1]) != Ocjmp && exprop(nl[i - 1]) != Ojmp)
+ addnode(cfg, bb, mkexpr(loc, Ojmp, mklbl(loc, lblstr(nl[i])), NULL));
+ }
+ if (bb->nnl)
+ bb = mkbb(cfg);
+ label(cfg, nl[i], bb);
+ return bb;
}
void delete(Cfg *cfg, Bb *bb)
{
- size_t i, j;
+ size_t i, j;
- if (bb == cfg->start || bb == cfg->end)
- return;
- for (i = 0; bsiter(bb->pred, &i); i++) {
- bsunion(cfg->bb[i]->succ, bb->succ);
- bsdel(cfg->bb[i]->succ, bb->id);
- }
- for (i = 0; bsiter(bb->succ, &i); i++) {
- bsunion(cfg->bb[i]->pred, bb->pred);
- bsdel(cfg->bb[i]->pred, bb->id);
- for (j = 0; j < bb->nlbls; j++)
- strlabel(cfg, bb->lbls[j], cfg->bb[i]);
- }
- cfg->bb[bb->id] = NULL;
+ if (bb == cfg->start || bb == cfg->end)
+ return;
+ for (i = 0; bsiter(bb->pred, &i); i++) {
+ bsunion(cfg->bb[i]->succ, bb->succ);
+ bsdel(cfg->bb[i]->succ, bb->id);
+ }
+ for (i = 0; bsiter(bb->succ, &i); i++) {
+ bsunion(cfg->bb[i]->pred, bb->pred);
+ bsdel(cfg->bb[i]->pred, bb->id);
+ for (j = 0; j < bb->nlbls; j++)
+ strlabel(cfg, bb->lbls[j], cfg->bb[i]);
+ }
+ cfg->bb[bb->id] = NULL;
}
void noexit(Cfg *cfg, Bb *bb)
{
- size_t i;
- for (i = 0; bsiter(bb->succ, &i); i++)
- bsdel(cfg->bb[i]->pred, bb->id);
- bsclear(bb->succ);
+ size_t i;
+ for (i = 0; bsiter(bb->succ, &i); i++)
+ bsdel(cfg->bb[i]->pred, bb->id);
+ bsclear(bb->succ);
}
void trimdead(Cfg *cfg, Bb *bb)
{
- size_t i;
+ size_t i;
- if (!bb)
- return;
- for (i = 0; i < bb->nnl; i++) {
- switch (exprop(bb->nl[i])) {
- /* if we're jumping, we can't keep going
- * within this BB */
- case Ojmp:
- case Ocjmp:
- case Oret:
- bb->nnl = i + 1;
- return;
- case Odead:
- noexit(cfg, bb);
- bb->nnl = i + 1;
- return;
- case Ocall:
- if (isnonretcall(bb->nl[i]->expr.args[0])) {
- noexit(cfg, bb);
- bb->nnl = i + 1;
- return;
- }
- break;
- default:
- /* nothing */
- break;
- }
- }
+ if (!bb)
+ return;
+ for (i = 0; i < bb->nnl; i++) {
+ switch (exprop(bb->nl[i])) {
+ /* if we're jumping, we can't keep going
+ * within this BB */
+ case Ojmp:
+ case Ocjmp:
+ case Oret:
+ bb->nnl = i + 1;
+ return;
+ case Odead:
+ noexit(cfg, bb);
+ bb->nnl = i + 1;
+ return;
+ case Ocall:
+ if (isnonretcall(bb->nl[i]->expr.args[0])) {
+ noexit(cfg, bb);
+ bb->nnl = i + 1;
+ return;
+ }
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ }
}
void trim(Cfg *cfg)
{
- Bb *bb;
- size_t i;
- int deleted;
+ Bb *bb;
+ size_t i;
+ int deleted;
- deleted = 1;
- while (deleted) {
- deleted = 0;
- for (i = 0; i < cfg->nbb; i++) {
- bb = cfg->bb[i];
- if (bb == cfg->start || bb == cfg->end)
- continue;
- trimdead(cfg, bb);
- if (bb && bsisempty(bb->pred)) {
- delete(cfg, bb);
- deleted = 1;
- }
- }
- }
+ deleted = 1;
+ while (deleted) {
+ deleted = 0;
+ for (i = 0; i < cfg->nbb; i++) {
+ bb = cfg->bb[i];
+ if (bb == cfg->start || bb == cfg->end)
+ continue;
+ trimdead(cfg, bb);
+ if (bb && bsisempty(bb->pred)) {
+ delete(cfg, bb);
+ deleted = 1;
+ }
+ }
+ }
}
Cfg *mkcfg(Node *fn, Node **nl, size_t nn)
{
- Cfg *cfg;
- Bb *pre, *post;
- Bb *bb, *targ;
- Node *a, *b;
- static int nextret;
- char buf[32];
- size_t i;
+ Cfg *cfg;
+ Bb *pre, *post;
+ Bb *bb, *targ;
+ Node *a, *b;
+ static int nextret;
+ char buf[32];
+ size_t i;
- cfg = zalloc(sizeof(Cfg));
- cfg->fn = fn;
- cfg->lblmap = mkht(strhash, streq);
- pre = mkbb(cfg);
- bb = mkbb(cfg);
- for (i = 0; i < nn; i++) {
- switch (nl[i]->type) {
- case Nexpr:
- if (islabel(nl[i]))
- bb = addlabel(cfg, bb, nl, i, nl[i]->loc);
- else if (addnode(cfg, bb, nl[i]))
- bb = mkbb(cfg);
- break;
- break;
- case Ndecl:
- break;
- default:
- die("Invalid node type %s in mkcfg", nodestr[nl[i]->type]);
- }
- }
- post = mkbb(cfg);
- bprintf(buf, sizeof buf, ".R%d", nextret++);
- label(cfg, mklbl(fn->loc, buf), post);
+ cfg = zalloc(sizeof(Cfg));
+ cfg->fn = fn;
+ cfg->lblmap = mkht(strhash, streq);
+ pre = mkbb(cfg);
+ bb = mkbb(cfg);
+ for (i = 0; i < nn; i++) {
+ switch (nl[i]->type) {
+ case Nexpr:
+ if (islabel(nl[i]))
+ bb = addlabel(cfg, bb, nl, i, nl[i]->loc);
+ else if (addnode(cfg, bb, nl[i]))
+ bb = mkbb(cfg);
+ break;
+ break;
+ case Ndecl:
+ break;
+ default:
+ die("Invalid node type %s in mkcfg", nodestr[nl[i]->type]);
+ }
+ }
+ post = mkbb(cfg);
+ bprintf(buf, sizeof buf, ".R%d", nextret++);
+ label(cfg, mklbl(fn->loc, buf), post);
- cfg->start = pre;
- cfg->end = post;
- bsput(pre->succ, cfg->bb[1]->id);
- bsput(cfg->bb[1]->pred, pre->id);
- bsput(cfg->bb[cfg->nbb - 2]->succ, post->id);
- bsput(post->pred, cfg->bb[cfg->nbb - 2]->id);
+ cfg->start = pre;
+ cfg->end = post;
+ bsput(pre->succ, cfg->bb[1]->id);
+ bsput(cfg->bb[1]->pred, pre->id);
+ bsput(cfg->bb[cfg->nbb - 2]->succ, post->id);
+ bsput(post->pred, cfg->bb[cfg->nbb - 2]->id);
- for (i = 0; i < cfg->nfixjmp; i++) {
- bb = cfg->fixblk[i];
- switch (exprop(cfg->fixjmp[i])) {
- case Ojmp:
- a = cfg->fixjmp[i]->expr.args[0];
- b = NULL;
- break;
- case Ocjmp:
- a = cfg->fixjmp[i]->expr.args[1];
- b = cfg->fixjmp[i]->expr.args[2];
- break;
- case Oret:
- a = mklbl(cfg->fixjmp[i]->loc, cfg->end->lbls[0]);
- b = NULL;
- break;
- default:
- die("Bad jump fix thingy");
- break;
- }
- if (a) {
- targ = htget(cfg->lblmap, lblstr(a));
- if (!targ)
- die("No bb with label \"%s\"", lblstr(a));
- bsput(bb->succ, targ->id);
- bsput(targ->pred, bb->id);
- }
- if (b) {
- targ = htget(cfg->lblmap, lblstr(b));
- if (!targ)
- die("No bb with label \"%s\"", lblstr(b));
- bsput(bb->succ, targ->id);
- bsput(targ->pred, bb->id);
- }
- }
- trim(cfg);
- return cfg;
+ for (i = 0; i < cfg->nfixjmp; i++) {
+ bb = cfg->fixblk[i];
+ switch (exprop(cfg->fixjmp[i])) {
+ case Ojmp:
+ a = cfg->fixjmp[i]->expr.args[0];
+ b = NULL;
+ break;
+ case Ocjmp:
+ a = cfg->fixjmp[i]->expr.args[1];
+ b = cfg->fixjmp[i]->expr.args[2];
+ break;
+ case Oret:
+ a = mklbl(cfg->fixjmp[i]->loc, cfg->end->lbls[0]);
+ b = NULL;
+ break;
+ default:
+ die("Bad jump fix thingy");
+ break;
+ }
+ if (a) {
+ targ = htget(cfg->lblmap, lblstr(a));
+ if (!targ)
+ die("No bb with label \"%s\"", lblstr(a));
+ bsput(bb->succ, targ->id);
+ bsput(targ->pred, bb->id);
+ }
+ if (b) {
+ targ = htget(cfg->lblmap, lblstr(b));
+ if (!targ)
+ die("No bb with label \"%s\"", lblstr(b));
+ bsput(bb->succ, targ->id);
+ bsput(targ->pred, bb->id);
+ }
+ }
+ trim(cfg);
+ return cfg;
}
void dumpbb(Bb *bb, FILE *fd)
{
- size_t i;
- char *sep;
+ size_t i;
+ char *sep;
- fprintf(fd, "Bb: %d labels=(", bb->id);
- sep = "";
- for (i = 0; i < bb->nlbls; i++) {;
- fprintf(fd, "%s%s", bb->lbls[i], sep);
- sep = ",";
- }
- fprintf(fd, ")\n");
+ fprintf(fd, "Bb: %d labels=(", bb->id);
+ sep = "";
+ for (i = 0; i < bb->nlbls; i++) {;
+ fprintf(fd, "%s%s", bb->lbls[i], sep);
+ sep = ",";
+ }
+ fprintf(fd, ")\n");
- /* in edges */
- fprintf(fd, "Pred: ");
- sep = "";
- for (i = 0; i < bsmax(bb->pred); i++) {
- if (bshas(bb->pred, i)) {
- fprintf(fd, "%s%zd", sep, i);
- sep = ",";
- }
- }
- fprintf(fd, "\n");
+ /* in edges */
+ fprintf(fd, "Pred: ");
+ sep = "";
+ for (i = 0; i < bsmax(bb->pred); i++) {
+ if (bshas(bb->pred, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
- /* out edges */
- fprintf(fd, "Succ: ");
- sep = "";
- for (i = 0; i < bsmax(bb->succ); i++) {
- if (bshas(bb->succ, i)) {
- fprintf(fd, "%s%zd", sep, i);
- sep = ",";
- }
- }
- fprintf(fd, "\n");
+ /* out edges */
+ fprintf(fd, "Succ: ");
+ sep = "";
+ for (i = 0; i < bsmax(bb->succ); i++) {
+ if (bshas(bb->succ, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
- for (i = 0; i < bb->nnl; i++)
- dump(bb->nl[i], fd);
- fprintf(fd, "\n");
+ for (i = 0; i < bb->nnl; i++)
+ dump(bb->nl[i], fd);
+ fprintf(fd, "\n");
}
void dumpcfg(Cfg *cfg, FILE *fd)
{
- size_t i;
+ size_t i;
- for (i = 0; i < cfg->nbb; i++) {
- if (!cfg->bb[i])
- continue;
- fprintf(fd, "\n");
- dumpbb(cfg->bb[i], fd);
- }
+ for (i = 0; i < cfg->nbb; i++) {
+ if (!cfg->bb[i])
+ continue;
+ fprintf(fd, "\n");
+ dumpbb(cfg->bb[i], fd);
+ }
}
diff --git a/mi/dfcheck.c b/mi/dfcheck.c
index 316bf65..a83f1db 100644
--- a/mi/dfcheck.c
+++ b/mi/dfcheck.c
@@ -15,117 +15,117 @@
static void checkundef(Node *n, Reaching *r, Bitset *reach, Bitset *kill)
{
- size_t i, j, did;
- Node *def;
- Type *t;
+ size_t i, j, did;
+ Node *def;
+ Type *t;
- if (n->type != Nexpr)
- return;
- if (exprop(n) == Ovar) {
- did = n->expr.did;
- for (j = 0; j < r->ndefs[did]; j++) {
- t = tybase(exprtype(n));
- if (t->type == Tystruct || t->type == Tyunion || t->type == Tyarray || t->type == Tytuple)
- continue;
- if (bshas(kill, r->defs[did][j]))
- continue;
- if (!bshas(reach, r->defs[did][j]))
- continue;
- def = nodes[r->defs[did][j]];
- if (exprop(def) == Oundef)
- fatal(n, "%s used before definition", namestr(n->expr.args[0]));
- }
- } else {
- switch (exprop(n)) {
- case Oset:
- case Oasn:
- case Oblit:
- checkundef(n->expr.args[1], r, reach, kill);
- break;
- case Oaddr:
- case Oslice:
- /* these don't actually look at the of args[0], so they're ok. */
- for (i = 1; i < n->expr.nargs; i++)
- checkundef(n->expr.args[i], r, reach, kill);
- break;
- case Ocall:
- for (i = 1; i < n->expr.nargs; i++)
- if (exprop(n->expr.args[i]) != Oaddr)
- checkundef(n->expr.args[i], r, reach, kill);
- break;
- default:
- for (i = 0; i < n->expr.nargs; i++)
- checkundef(n->expr.args[i], r, reach, kill);
- break;
- }
- }
+ if (n->type != Nexpr)
+ return;
+ if (exprop(n) == Ovar) {
+ did = n->expr.did;
+ for (j = 0; j < r->ndefs[did]; j++) {
+ t = tybase(exprtype(n));
+ if (t->type == Tystruct || t->type == Tyunion || t->type == Tyarray || t->type == Tytuple)
+ continue;
+ if (bshas(kill, r->defs[did][j]))
+ continue;
+ if (!bshas(reach, r->defs[did][j]))
+ continue;
+ def = nodes[r->defs[did][j]];
+ if (exprop(def) == Oundef)
+ fatal(n, "%s used before definition", namestr(n->expr.args[0]));
+ }
+ } else {
+ switch (exprop(n)) {
+ case Oset:
+ case Oasn:
+ case Oblit:
+ checkundef(n->expr.args[1], r, reach, kill);
+ break;
+ case Oaddr:
+ case Oslice:
+ /* these don't actually look at the of args[0], so they're ok. */
+ for (i = 1; i < n->expr.nargs; i++)
+ checkundef(n->expr.args[i], r, reach, kill);
+ break;
+ case Ocall:
+ for (i = 1; i < n->expr.nargs; i++)
+ if (exprop(n->expr.args[i]) != Oaddr)
+ checkundef(n->expr.args[i], r, reach, kill);
+ break;
+ default:
+ for (i = 0; i < n->expr.nargs; i++)
+ checkundef(n->expr.args[i], r, reach, kill);
+ break;
+ }
+ }
}
static void checkreach(Cfg *cfg)
{
- Bitset *reach, *kill;
- size_t i, j, k;
- Reaching *r;
- Node *n, *m;
- Bb *bb;
+ Bitset *reach, *kill;
+ size_t i, j, k;
+ Reaching *r;
+ Node *n, *m;
+ Bb *bb;
- r = reaching(cfg);
- for (i = 0; i < cfg->nbb; i++) {
- bb = cfg->bb[i];
- if (!bb)
- continue;
- reach = bsdup(r->in[i]);
- kill = mkbs();
- for (j = 0; j < bb->nnl; j++) {
- n = bb->nl[j];
- if (exprop(n) == Oundef) {
- bsput(reach, n->nid);
- } else {
- m = assignee(n);
- if (m)
- for (k = 0; k < r->ndefs[m->expr.did]; k++)
- bsput(kill, r->defs[m->expr.did][k]);
- checkundef(n, r, reach, kill);
- }
- }
- bsfree(reach);
- bsfree(kill);
- }
+ r = reaching(cfg);
+ for (i = 0; i < cfg->nbb; i++) {
+ bb = cfg->bb[i];
+ if (!bb)
+ continue;
+ reach = bsdup(r->in[i]);
+ kill = mkbs();
+ for (j = 0; j < bb->nnl; j++) {
+ n = bb->nl[j];
+ if (exprop(n) == Oundef) {
+ bsput(reach, n->nid);
+ } else {
+ m = assignee(n);
+ if (m)
+ for (k = 0; k < r->ndefs[m->expr.did]; k++)
+ bsput(kill, r->defs[m->expr.did][k]);
+ checkundef(n, r, reach, kill);
+ }
+ }
+ bsfree(reach);
+ bsfree(kill);
+ }
}
static void checkpredret(Cfg *cfg, Bb *bb)
{
- Bb *pred;
- Op op;
- size_t i;
+ Bb *pred;
+ Op op;
+ size_t i;
- for (i = 0; bsiter(bb->pred, &i); i++) {
- pred = cfg->bb[i];
- if (pred->nnl == 0) {
- checkpredret(cfg, pred);
- } else {
- op = exprop(pred->nl[pred->nnl - 1]);
- if (op != Oret && op != Odead) {
- fatal(pred->nl[pred->nnl-1], "Reaches end of function without return\n");
- }
- }
- }
+ for (i = 0; bsiter(bb->pred, &i); i++) {
+ pred = cfg->bb[i];
+ if (pred->nnl == 0) {
+ checkpredret(cfg, pred);
+ } else {
+ op = exprop(pred->nl[pred->nnl - 1]);
+ if (op != Oret && op != Odead) {
+ fatal(pred->nl[pred->nnl-1], "Reaches end of function without return\n");
+ }
+ }
+ }
}
static void checkret(Cfg *cfg)
{
- Type *ft;
+ Type *ft;
- ft = tybase(decltype(cfg->fn));
- assert(ft->type == Tyfunc || ft->type == Tycode);
- if (ft->sub[0]->type == Tyvoid)
- return;
+ ft = tybase(decltype(cfg->fn));
+ assert(ft->type == Tyfunc || ft->type == Tycode);
+ if (ft->sub[0]->type == Tyvoid)
+ return;
- checkpredret(cfg, cfg->end);
+ checkpredret(cfg, cfg->end);
}
void check(Cfg *cfg)
{
- checkret(cfg);
- if(0) checkreach(cfg);
+ checkret(cfg);
+ if(0) checkreach(cfg);
}
diff --git a/mi/fold.c b/mi/fold.c
index 2658431..f62e440 100644
--- a/mi/fold.c
+++ b/mi/fold.c
@@ -15,226 +15,226 @@
static int getintlit(Node *n, vlong *v)
{
- Node *l;
-
- if (exprop(n) != Olit)
- return 0;
- l = n->expr.args[0];
- if (l->lit.littype != Lint)
- return 0;
- *v = l->lit.intval;
- return 1;
+ Node *l;
+
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->lit.littype != Lint)
+ return 0;
+ *v = l->lit.intval;
+ return 1;
}
static int isintval(Node *n, vlong val)
{
- vlong v;
+ vlong v;
- if (!getintlit(n, &v))
- return 0;
- return v == val;
+ if (!getintlit(n, &v))
+ return 0;
+ return v == val;
}
static Node *val(Srcloc loc, vlong val, Type *t)
{
- Node *l, *n;
+ Node *l, *n;
- l = mkint(loc, val);
- n = mkexpr(loc, Olit, l, NULL);
- l->lit.type = t;
- n->expr.type = t;
- return n;
+ l = mkint(loc, val);
+ n = mkexpr(loc, Olit, l, NULL);
+ l->lit.type = t;
+ n->expr.type = t;
+ return n;
}
static int issmallconst(Node *dcl)
{
- Type *t;
-
- if (!dcl->decl.isconst)
- return 0;
- if (!dcl->decl.init)
- return 0;
- t = tybase(exprtype(dcl->decl.init));
- if (t->type <= Tyflt64)
- return 1;
- return 0;
+ Type *t;
+
+ if (!dcl->decl.isconst)
+ return 0;
+ if (!dcl->decl.init)
+ return 0;
+ t = tybase(exprtype(dcl->decl.init));
+ if (t->type <= Tyflt64)
+ return 1;
+ return 0;
}
static Node *foldcast(Node *n)
{
- Type *to, *from;
- Node *sub;
-
- sub = n->expr.args[0];
- to = exprtype(n);
- from = exprtype(sub);
-
- 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:
- switch (tybase(from)->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:
- if (exprop(sub) == Olit || tybase(from)->type == tybase(to)->type) {
- sub->expr.type = to;
- return sub;
- } else {
- return n;
- }
- default:
- return n;
- }
- default:
- return n;
- }
- return n;
+ Type *to, *from;
+ Node *sub;
+
+ sub = n->expr.args[0];
+ to = exprtype(n);
+ from = exprtype(sub);
+
+ 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:
+ switch (tybase(from)->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:
+ if (exprop(sub) == Olit || tybase(from)->type == tybase(to)->type) {
+ sub->expr.type = to;
+ return sub;
+ } else {
+ return n;
+ }
+ default:
+ return n;
+ }
+ default:
+ return n;
+ }
+ return n;
}
int idxcmp(const void *pa, const void *pb)
{
- Node *a, *b;
- vlong av, bv;
-
- a = *(Node **)pa;
- b = *(Node **)pb;
-
- assert(getintlit(a->expr.idx, &av));
- assert(getintlit(b->expr.idx, &bv));
-
- /* don't trust overflow with int64 */
- if (av < bv)
- return -1;
- else if (av == bv)
- return 0;
- else
- return 1;
+ Node *a, *b;
+ vlong av, bv;
+
+ a = *(Node **)pa;
+ b = *(Node **)pb;
+
+ assert(getintlit(a->expr.idx, &av));
+ assert(getintlit(b->expr.idx, &bv));
+
+ /* don't trust overflow with int64 */
+ if (av < bv)
+ return -1;
+ else if (av == bv)
+ return 0;
+ else
+ return 1;
}
Node *fold(Node *n, int foldvar)
{
- Node **args, *r;
- Type *t;
- vlong a, b;
- size_t i;
-
- if (!n)
- return NULL;
- if (n->type != Nexpr)
- return n;
-
- r = NULL;
- args = n->expr.args;
- if (n->expr.idx)
- n->expr.idx = fold(n->expr.idx, foldvar);
- for (i = 0; i < n->expr.nargs; i++)
- args[i] = fold(args[i], foldvar);
- switch (exprop(n)) {
- case Ovar:
- if (foldvar && issmallconst(decls[n->expr.did]))
- r = fold(decls[n->expr.did]->decl.init, foldvar);
- break;
- case Oadd:
- /* x + 0 = 0 */
- if (isintval(args[0], 0))
- r = args[1];
- if (isintval(args[1], 0))
- r = args[0];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a + b, exprtype(n));
- break;
- case Osub:
- /* x - 0 = 0 */
- if (isintval(args[1], 0))
- r = args[0];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a - b, exprtype(n));
- break;
- case Omul:
- /* 1 * x = x */
- if (isintval(args[0], 1))
- r = args[1];
- if (isintval(args[1], 1))
- r = args[0];
- /* 0 * x = 0 */
- if (isintval(args[0], 0))
- r = args[0];
- if (isintval(args[1], 0))
- r = args[1];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a * b, exprtype(n));
- break;
- case Odiv:
- /* x/0 = error */
- if (isintval(args[1], 0))
- fatal(args[1], "division by zero");
- /* x/1 = x */
- if (isintval(args[1], 1))
- r = args[0];
- /* 0/x = 0 */
- if (isintval(args[1], 0))
- r = args[1];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a / b, exprtype(n));
- break;
- case Omod:
- /* x%1 = x */
- if (isintval(args[1], 0))
- r = args[0];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a % b, exprtype(n));
- break;
- case Oneg:
- if (getintlit(args[0], &a))
- r = val(n->loc, -a, exprtype(n));
- break;
- case Obsl:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a << b, exprtype(n));
- break;
- case Obsr:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a >> b, exprtype(n));
- break;
- case Obor:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a | b, exprtype(n));
- break;
- case Oband:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a & b, exprtype(n));
- break;
- case Obxor:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a ^ b, exprtype(n));
- break;
- case Omemb:
- t = tybase(exprtype(args[0]));
- /* we only fold lengths right now */
- if (t->type == Tyarray && !strcmp(namestr(args[1]), "len"))
- r = t->asize;
- break;
- case Oarr:
- qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
- break;
- case Ocast:
- r = foldcast(n);
- break;
- default:
- break;
- }
-
- if (r && n->expr.idx)
- r->expr.idx = n->expr.idx;
-
- if (r)
- return r;
- else
- return n;
+ Node **args, *r;
+ Type *t;
+ vlong a, b;
+ size_t i;
+
+ if (!n)
+ return NULL;
+ if (n->type != Nexpr)
+ return n;
+
+ r = NULL;
+ args = n->expr.args;
+ if (n->expr.idx)
+ n->expr.idx = fold(n->expr.idx, foldvar);
+ for (i = 0; i < n->expr.nargs; i++)
+ args[i] = fold(args[i], foldvar);
+ switch (exprop(n)) {
+ case Ovar:
+ if (foldvar && issmallconst(decls[n->expr.did]))
+ r = fold(decls[n->expr.did]->decl.init, foldvar);
+ break;
+ case Oadd:
+ /* x + 0 = 0 */
+ if (isintval(args[0], 0))
+ r = args[1];
+ if (isintval(args[1], 0))
+ r = args[0];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a + b, exprtype(n));
+ break;
+ case Osub:
+ /* x - 0 = 0 */
+ if (isintval(args[1], 0))
+ r = args[0];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a - b, exprtype(n));
+ break;
+ case Omul:
+ /* 1 * x = x */
+ if (isintval(args[0], 1))
+ r = args[1];
+ if (isintval(args[1], 1))
+ r = args[0];
+ /* 0 * x = 0 */
+ if (isintval(args[0], 0))
+ r = args[0];
+ if (isintval(args[1], 0))
+ r = args[1];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a * b, exprtype(n));
+ break;
+ case Odiv:
+ /* x/0 = error */
+ if (isintval(args[1], 0))
+ fatal(args[1], "division by zero");
+ /* x/1 = x */
+ if (isintval(args[1], 1))
+ r = args[0];
+ /* 0/x = 0 */
+ if (isintval(args[1], 0))
+ r = args[1];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a / b, exprtype(n));
+ break;
+ case Omod:
+ /* x%1 = x */
+ if (isintval(args[1], 0))
+ r = args[0];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a % b, exprtype(n));
+ break;
+ case Oneg:
+ if (getintlit(args[0], &a))
+ r = val(n->loc, -a, exprtype(n));
+ break;
+ case Obsl:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a << b, exprtype(n));
+ break;
+ case Obsr:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a >> b, exprtype(n));
+ break;
+ case Obor:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a | b, exprtype(n));
+ break;
+ case Oband:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a & b, exprtype(n));
+ break;
+ case Obxor:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a ^ b, exprtype(n));
+ break;
+ case Omemb:
+ t = tybase(exprtype(args[0]));
+ /* we only fold lengths right now */
+ if (t->type == Tyarray && !strcmp(namestr(args[1]), "len"))
+ r = t->asize;
+ break;
+ case Oarr:
+ qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
+ break;
+ case Ocast:
+ r = foldcast(n);
+ break;
+ default:
+ break;
+ }
+
+ if (r && n->expr.idx)
+ r->expr.idx = n->expr.idx;
+
+ if (r)
+ return r;
+ else
+ return n;
}
diff --git a/mi/match.c b/mi/match.c
index 2588f59..df335f8 100644
--- a/mi/match.c
+++ b/mi/match.c
@@ -14,26 +14,26 @@
typedef struct Dtree Dtree;
struct Dtree {
- int id;
- Srcloc loc;
-
- /* values for matching */
- Node *lbl;
- Node *load;
- size_t nconstructors;
- int accept;
- int emitted;
-
- /* the decision tree step */
- Node **pat;
- size_t npat;
- Dtree **next;
- size_t nnext;
- Dtree *any;
-
- /* captured variables and action */
- Node **cap;
- size_t ncap;
+ int id;
+ Srcloc loc;
+
+ /* values for matching */
+ Node *lbl;
+ Node *load;
+ size_t nconstructors;
+ int accept;
+ int emitted;
+
+ /* the decision tree step */
+ Node **pat;
+ size_t npat;
+ Dtree **next;
+ size_t nnext;
+ Dtree *any;
+
+ /* captured variables and action */
+ Node **cap;
+ size_t ncap;
};
@@ -44,752 +44,752 @@ void dtreedump(FILE *fd, Dtree *dt);
static Node *utag(Node *n)
{
- Node *tag;
+ Node *tag;
- tag = mkexpr(n->loc, Outag, n, NULL);
- tag->expr.type = mktype(n->loc, Tyint32);
- return tag;
+ tag = mkexpr(n->loc, Outag, n, NULL);
+ tag->expr.type = mktype(n->loc, Tyint32);
+ return tag;
}
static Node *uvalue(Node *n, Type *ty)
{
- Node *elt;
+ Node *elt;
- elt = mkexpr(n->loc, Oudata, n, NULL);
- elt->expr.type = ty;
- return elt;
+ elt = mkexpr(n->loc, Oudata, n, NULL);
+ elt->expr.type = ty;
+ return elt;
}
static Node *tupelt(Node *n, size_t i)
{
- Node *idx, *elt;
+ Node *idx, *elt;
- idx = mkintlit(n->loc, i);
- idx->expr.type = mktype(n->loc, Tyuint64);
- elt = mkexpr(n->loc, Otupget, n, idx, NULL);
- elt->expr.type = tybase(exprtype(n))->sub[i];
- return elt;
+ idx = mkintlit(n->loc, i);
+ idx->expr.type = mktype(n->loc, Tyuint64);
+ elt = mkexpr(n->loc, Otupget, n, idx, NULL);
+ elt->expr.type = tybase(exprtype(n))->sub[i];
+ return elt;
}
static Node *arrayelt(Node *n, size_t i)
{
- Node *idx, *elt;
+ Node *idx, *elt;
- idx = mkintlit(n->loc, i);
- idx->expr.type = mktype(n->loc, Tyuint64);
- elt = mkexpr(n->loc, Oidx, n, idx, NULL);
- elt->expr.type = tybase(exprtype(n))->sub[0];
- return elt;
+ idx = mkintlit(n->loc, i);
+ idx->expr.type = mktype(n->loc, Tyuint64);
+ elt = mkexpr(n->loc, Oidx, n, idx, NULL);
+ elt->expr.type = tybase(exprtype(n))->sub[0];
+ return elt;
}
static Node *findmemb(Node *pat, Node *name)
{
- Node *n;
- size_t i;
-
- for (i = 0; i < pat->expr.nargs; i++) {
- n = pat->expr.args[i];
- if (nameeq(n->expr.idx, name))
- return n;
- }
- return NULL;
+ Node *n;
+ size_t i;
+
+ for (i = 0; i < pat->expr.nargs; i++) {
+ n = pat->expr.args[i];
+ if (nameeq(n->expr.idx, name))
+ return n;
+ }
+ return NULL;
}
static Dtree *dtbytag(Dtree *t, Ucon *uc)
{
- uint32_t tagval;
- Node *taglit;
- size_t i;
-
- for (i = 0; i < t->npat; i++) {
- taglit = t->pat[i]->expr.args[0];
- tagval = taglit->lit.intval;
- if (tagval == uc->id) {
- return t->next[i];
- }
- }
- return NULL;
+ uint32_t tagval;
+ Node *taglit;
+ size_t i;
+
+ for (i = 0; i < t->npat; i++) {
+ taglit = t->pat[i]->expr.args[0];
+ tagval = taglit->lit.intval;
+ if (tagval == uc->id) {
+ return t->next[i];
+ }
+ }
+ return NULL;
}
static Node *structmemb(Node *n, Node *name, Type *ty)
{
- Node *elt;
+ Node *elt;
- elt = mkexpr(n->loc, Omemb, n, name, NULL);
- elt->expr.type = ty;
- return elt;
+ elt = mkexpr(n->loc, Omemb, n, name, NULL);
+ elt->expr.type = ty;
+ return elt;
}
static Node *addcapture(Node *n, Node **cap, size_t ncap)
{
- Node **blk;
- size_t nblk, i;
-
- nblk = 0;
- blk = NULL;
-
- for (i = 0; i < ncap; i++)
- lappend(&blk, &nblk, cap[i]);
- for (i = 0; i < n->block.nstmts; i++)
- lappend(&blk, &nblk, n->block.stmts[i]);
- lfree(&n->block.stmts, &n->block.nstmts);
- n->block.stmts = blk;
- n->block.nstmts = nblk;
- return n;
+ Node **blk;
+ size_t nblk, i;
+
+ nblk = 0;
+ blk = NULL;
+
+ for (i = 0; i < ncap; i++)
+ lappend(&blk, &nblk, cap[i]);
+ for (i = 0; i < n->block.nstmts; i++)
+ lappend(&blk, &nblk, n->block.stmts[i]);
+ lfree(&n->block.stmts, &n->block.nstmts);
+ n->block.stmts = blk;
+ n->block.nstmts = nblk;
+ return n;
}
static Dtree *mkdtree(Srcloc loc, Node *lbl)
{
- static int ndtree;
- Dtree *t;
-
- t = zalloc(sizeof(Dtree));
- t->lbl = lbl;
- t->loc = loc;
- t->id = ndtree++;
- return t;
+ static int ndtree;
+ Dtree *t;
+
+ t = zalloc(sizeof(Dtree));
+ t->lbl = lbl;
+ t->loc = loc;
+ t->id = ndtree++;
+ return t;
}
static Dtree *nextnode(Srcloc loc, size_t idx, size_t count, Dtree *accept)
{
- if (idx == count - 1)
- return accept;
- else
- return mkdtree(loc, genlbl(loc));
+ if (idx == count - 1)
+ return accept;
+ else
+ return mkdtree(loc, genlbl(loc));
}
static size_t nconstructors(Type *t)
{
- if (!t)
- return 0;
-
- t = tybase(t);
- switch (t->type) {
- case Tyvoid: return 0; break;
- case Tybool: return 2; break;
- case Tychar: return 0x10ffff; break;
-
- /* signed ints */
- case Tyint8: return 0x100; break;
- case Tyint16: return 0x10000; break;
- case Tyint32: return 0x100000000; break;
- case Tyint: return 0x100000000; break;
- case Tyint64: return ~0ull; break;
-
- /* unsigned ints */
- case Tybyte: return 0x100; break;
- case Tyuint8: return 0x100; break;
- case Tyuint16: return 0x10000; break;
- case Tyuint32: return 0x100000000; break;
- case Tyuint: return 0x100000000; break;
- case Tyuint64: return ~0ull; break;
-
- /* floats */
- case Tyflt32: return ~0ull; break;
- case Tyflt64: return ~0ull; break;
-
- /* complex types */
- case Typtr: return 1; break;
- case Tyarray: return 1; break;
- case Tytuple: return 1; break;
- case Tystruct: return 1;
- case Tyunion: return t->nmemb; break;
- case Tyslice: return ~0ULL; break;
-
- case Tyvar: case Typaram: case Tyunres: case Tyname:
- case Tybad: case Tyvalist: case Tygeneric: case Ntypes:
- case Tyfunc: case Tycode:
- die("Invalid constructor type %s in match", tystr(t));
- break;
- }
- return 0;
+ if (!t)
+ return 0;
+
+ t = tybase(t);
+ switch (t->type) {
+ case Tyvoid: return 0; break;
+ case Tybool: return 2; break;
+ case Tychar: return 0x10ffff; break;
+
+ /* signed ints */
+ case Tyint8: return 0x100; break;
+ case Tyint16: return 0x10000; break;
+ case Tyint32: return 0x100000000; break;
+ case Tyint: return 0x100000000; break;
+ case Tyint64: return ~0ull; break;
+
+ /* unsigned ints */
+ case Tybyte: return 0x100; break;
+ case Tyuint8: return 0x100; break;
+ case Tyuint16: return 0x10000; break;
+ case Tyuint32: return 0x100000000; break;
+ case Tyuint: return 0x100000000; break;
+ case Tyuint64: return ~0ull; break;
+
+ /* floats */
+ case Tyflt32: return ~0ull; break;
+ case Tyflt64: return ~0ull; break;
+
+ /* complex types */
+ case Typtr: return 1; break;
+ case Tyarray: return 1; break;
+ case Tytuple: return 1; break;
+ case Tystruct: return 1;
+ case Tyunion: return t->nmemb; break;
+ case Tyslice: return ~0ULL; break;
+
+ case Tyvar: case Typaram: case Tyunres: case Tyname:
+ case Tybad: case Tyvalist: case Tygeneric: case Ntypes:
+ case Tyfunc: case Tycode:
+ die("Invalid constructor type %s in match", tystr(t));
+ break;
+ }
+ return 0;
}
static int verifymatch(Dtree *t)
{
- size_t i;
- int ret;
-
- if (t->accept)
- return 1;
-
- ret = 0;
- if (t->nnext == t->nconstructors || t->any)
- ret = 1;
- for (i = 0; i < t->nnext; i++)
- if (!verifymatch(t->next[i]))
- ret = 0;
- return ret;
+ size_t i;
+ int ret;
+
+ if (t->accept)
+ return 1;
+
+ ret = 0;
+ if (t->nnext == t->nconstructors || t->any)
+ ret = 1;
+ for (i = 0; i < t->nnext; i++)
+ if (!verifymatch(t->next[i]))
+ ret = 0;
+ return ret;
}
static int acceptall(Dtree *t, Dtree *accept)
{
- size_t i;
- int ret;
-
- if (t->any == accept)
- return 0;
-
- ret = 0;
- if (t->any) {
- if (acceptall(t->any, accept))
- ret = 1;
- } else {
- t->any = accept;
- ret = 1;
- }
-
- for (i = 0; i < t->nnext; i++)
- if (acceptall(t->next[i], accept))
- ret = 1;
- return ret;
+ size_t i;
+ int ret;
+
+ if (t->any == accept)
+ return 0;
+
+ ret = 0;
+ if (t->any) {
+ if (acceptall(t->any, accept))
+ ret = 1;
+ } else {
+ t->any = accept;
+ ret = 1;
+ }
+
+ for (i = 0; i < t->nnext; i++)
+ if (acceptall(t->next[i], accept))
+ ret = 1;
+ return ret;
}
static int addwildrec(Srcloc loc, Type *ty, Dtree *start, Dtree *accept, Dtree ***end, size_t *nend)
{
- Dtree *next, **last, **tail;
- size_t i, j, nelt, nlast, ntail;
- Node *asize;
- Ucon *uc;
- int ret;
-
- tail = NULL;
- ntail = 0;
- ty = tybase(ty);
- if (istyprimitive(ty)) {
- for (i = 0; i < start->nnext; i++)
- lappend(end, nend, start->next[i]);
- if (start->any) {
- lappend(end, nend, start->any);
- return 0;
- } else {
- start->any = accept;
- lappend(end, nend, accept);
- return 1;
- }
- }
-
- ret = 0;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- switch (ty->type) {
- case Tytuple:
- for (i = 0; i < ty->nsub; i++) {
- next = nextnode(loc, i, ty->nsub, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addwildrec(loc, ty->sub[i], last[j], next, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- break;
- case Tyarray:
- asize = fold(ty->asize, 1);
- nelt = asize->expr.args[0]->lit.intval;
- for (i = 0; i < nelt; i++) {
- next = nextnode(loc, i, nelt, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addwildrec(loc, ty->sub[0], last[j], next, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- break;
- case Tystruct:
- for (i = 0; i < ty->nmemb; i++) {
- next = nextnode(loc, i, ty->nmemb, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addwildrec(loc, decltype(ty->sdecls[i]), last[j], next, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- break;
- case Tyunion:
- for (i = 0; i < ty->nmemb; i++) {
- uc = ty->udecls[i];
- next = dtbytag(start, uc);
- if (next) {
- if (uc->etype) {
- if (addwildrec(loc, uc->etype, next, accept, end, nend))
- ret = 1;
- } else {
- lappend(end, nend, next);
- }
- }
- }
- if (!start->any) {
- start->any = accept;
- ret = 1;
- }
- lappend(end, nend, start->any);
- break;
- case Tyslice:
- ret = acceptall(start, accept);
- lappend(&last, &nlast, accept);
- break;
- default:
- lappend(&last, &nlast, accept);
- break;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ Dtree *next, **last, **tail;
+ size_t i, j, nelt, nlast, ntail;
+ Node *asize;
+ Ucon *uc;
+ int ret;
+
+ tail = NULL;
+ ntail = 0;
+ ty = tybase(ty);
+ if (istyprimitive(ty)) {
+ for (i = 0; i < start->nnext; i++)
+ lappend(end, nend, start->next[i]);
+ if (start->any) {
+ lappend(end, nend, start->any);
+ return 0;
+ } else {
+ start->any = accept;
+ lappend(end, nend, accept);
+ return 1;
+ }
+ }
+
+ ret = 0;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ switch (ty->type) {
+ case Tytuple:
+ for (i = 0; i < ty->nsub; i++) {
+ next = nextnode(loc, i, ty->nsub, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addwildrec(loc, ty->sub[i], last[j], next, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ break;
+ case Tyarray:
+ asize = fold(ty->asize, 1);
+ nelt = asize->expr.args[0]->lit.intval;
+ for (i = 0; i < nelt; i++) {
+ next = nextnode(loc, i, nelt, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addwildrec(loc, ty->sub[0], last[j], next, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ break;
+ case Tystruct:
+ for (i = 0; i < ty->nmemb; i++) {
+ next = nextnode(loc, i, ty->nmemb, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addwildrec(loc, decltype(ty->sdecls[i]), last[j], next, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ break;
+ case Tyunion:
+ for (i = 0; i < ty->nmemb; i++) {
+ uc = ty->udecls[i];
+ next = dtbytag(start, uc);
+ if (next) {
+ if (uc->etype) {
+ if (addwildrec(loc, uc->etype, next, accept, end, nend))
+ ret = 1;
+ } else {
+ lappend(end, nend, next);
+ }
+ }
+ }
+ if (!start->any) {
+ start->any = accept;
+ ret = 1;
+ }
+ lappend(end, nend, start->any);
+ break;
+ case Tyslice:
+ ret = acceptall(start, accept);
+ lappend(&last, &nlast, accept);
+ break;
+ default:
+ lappend(&last, &nlast, accept);
+ break;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addwild(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Node *asn;
-
- asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
- asn->expr.type = exprtype(pat);
- if (cap && ncap) {
- asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
- asn->expr.type = exprtype(pat);
- lappend(cap, ncap, asn);
- }
- return addwildrec(pat->loc, exprtype(pat), start, accept, end, nend);
+ Node *asn;
+
+ asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
+ asn->expr.type = exprtype(pat);
+ if (cap && ncap) {
+ asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
+ asn->expr.type = exprtype(pat);
+ lappend(cap, ncap, asn);
+ }
+ return addwildrec(pat->loc, exprtype(pat), start, accept, end, nend);
}
static int addunion(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Node *tagid;
- Dtree *next;
- Ucon *uc;
-
- if (start->any) {
- lappend(end, nend, start->any);
- return 0;
- }
-
- uc = finducon(tybase(exprtype(pat)), pat->expr.args[0]);
- next = dtbytag(start, uc);
- if (next) {
- if (!uc->etype) {
- lappend(end, nend, next);
- return 0;
- } else {
- return addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
- }
- }
-
- if (!start->load) {
- start->load = utag(val);
- start->nconstructors = nconstructors(tybase(exprtype(pat)));
- }
-
- tagid = mkintlit(pat->loc, uc->id);
- tagid->expr.type = mktype(pat->loc, Tyint32);
- lappend(&start->pat, &start->npat, tagid);
- if (uc->etype) {
- next = mkdtree(pat->loc, genlbl(pat->loc));
- lappend(&start->next, &start->nnext, next);
- addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
- } else {
- lappend(&start->next, &start->nnext, accept);
- lappend(end, nend, accept);
- }
- return 1;
+ Node *tagid;
+ Dtree *next;
+ Ucon *uc;
+
+ if (start->any) {
+ lappend(end, nend, start->any);
+ return 0;
+ }
+
+ uc = finducon(tybase(exprtype(pat)), pat->expr.args[0]);
+ next = dtbytag(start, uc);
+ if (next) {
+ if (!uc->etype) {
+ lappend(end, nend, next);
+ return 0;
+ } else {
+ return addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
+ }
+ }
+
+ if (!start->load) {
+ start->load = utag(val);
+ start->nconstructors = nconstructors(tybase(exprtype(pat)));
+ }
+
+ tagid = mkintlit(pat->loc, uc->id);
+ tagid->expr.type = mktype(pat->loc, Tyint32);
+ lappend(&start->pat, &start->npat, tagid);
+ if (uc->etype) {
+ next = mkdtree(pat->loc, genlbl(pat->loc));
+ lappend(&start->next, &start->nnext, next);
+ addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
+ } else {
+ lappend(&start->next, &start->nnext, accept);
+ lappend(end, nend, accept);
+ }
+ return 1;
}
static int addstr(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Dtree **tail, **last, *next;
- size_t i, j, n, ntail, nlast;
- Node *p, *v, *lit;
- Type *ty;
- char *s;
- int ret;
-
- lit = pat->expr.args[0];
- n = lit->lit.strval.len;
- s = lit->lit.strval.buf;
-
- ty = mktype(pat->loc, Tyuint64);
- p = mkintlit(lit->loc, n);
- v = structmemb(val, mkname(pat->loc, "len"), ty);
- p->expr.type = ty;
-
- if (n == 0)
- next = accept;
- else
- next = mkdtree(pat->loc, genlbl(pat->loc));
-
- last = NULL;
- nlast = 0;
- if (addpat(p, v, start, next, cap, ncap, &last, &nlast))
- ret = 1;
-
- ty = mktype(pat->loc, Tybyte);
- for (i = 0; i < n; i++) {
- p = mkintlit(lit->loc, s[i]);
- p->expr.type = ty;
- v = arrayelt(val, i);
-
- tail = NULL;
- ntail = 0;
- next = nextnode(pat->loc, i, n, accept);
- for (j = 0; j < nlast; j++)
- if (addpat(p, v, last[j], next, NULL, NULL, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ Dtree **tail, **last, *next;
+ size_t i, j, n, ntail, nlast;
+ Node *p, *v, *lit;
+ Type *ty;
+ char *s;
+ int ret;
+
+ lit = pat->expr.args[0];
+ n = lit->lit.strval.len;
+ s = lit->lit.strval.buf;
+
+ ty = mktype(pat->loc, Tyuint64);
+ p = mkintlit(lit->loc, n);
+ v = structmemb(val, mkname(pat->loc, "len"), ty);
+ p->expr.type = ty;
+
+ if (n == 0)
+ next = accept;
+ else
+ next = mkdtree(pat->loc, genlbl(pat->loc));
+
+ last = NULL;
+ nlast = 0;
+ if (addpat(p, v, start, next, cap, ncap, &last, &nlast))
+ ret = 1;
+
+ ty = mktype(pat->loc, Tybyte);
+ for (i = 0; i < n; i++) {
+ p = mkintlit(lit->loc, s[i]);
+ p->expr.type = ty;
+ v = arrayelt(val, i);
+
+ tail = NULL;
+ ntail = 0;
+ next = nextnode(pat->loc, i, n, accept);
+ for (j = 0; j < nlast; j++)
+ if (addpat(p, v, last[j], next, NULL, NULL, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addlit(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- size_t i;
-
- if (pat->expr.args[0]->lit.littype == Lstr) {
- return addstr(pat, val, start, accept, cap, ncap, end, nend);
- } else {
- /* if we already have a match, we're not adding a new node */
- if (start->any) {
- lappend(end, nend, start->any);
- return 0;
- }
-
- for (i = 0; i < start->npat; i++) {
- if (liteq(start->pat[i]->expr.args[0], pat->expr.args[0])) {
- lappend(end, nend, start->next[i]);
- return 0;
- }
- }
-
- /* wire up an edge from start to 'accept' */
- if (!start->load) {
- start->load = val;
- start->nconstructors = nconstructors(exprtype(pat));
- }
- lappend(&start->pat, &start->npat, pat);
- lappend(&start->next, &start->nnext, accept);
- lappend(end, nend, accept);
- return 1;
- }
+ size_t i;
+
+ if (pat->expr.args[0]->lit.littype == Lstr) {
+ return addstr(pat, val, start, accept, cap, ncap, end, nend);
+ } else {
+ /* if we already have a match, we're not adding a new node */
+ if (start->any) {
+ lappend(end, nend, start->any);
+ return 0;
+ }
+
+ for (i = 0; i < start->npat; i++) {
+ if (liteq(start->pat[i]->expr.args[0], pat->expr.args[0])) {
+ lappend(end, nend, start->next[i]);
+ return 0;
+ }
+ }
+
+ /* wire up an edge from start to 'accept' */
+ if (!start->load) {
+ start->load = val;
+ start->nconstructors = nconstructors(exprtype(pat));
+ }
+ lappend(&start->pat, &start->npat, pat);
+ lappend(&start->next, &start->nnext, accept);
+ lappend(end, nend, accept);
+ return 1;
+ }
}
static int addtup(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- size_t nargs, nlast, ntail, i, j;
- Dtree *next, **last, **tail;
- Node **args;
- int ret;
-
- args = pat->expr.args;
- nargs = pat->expr.nargs;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- ret = 0;
-
- for (i = 0; i < nargs; i++) {
- next = nextnode(args[i]->loc, i, nargs, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addpat(pat->expr.args[i], tupelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ size_t nargs, nlast, ntail, i, j;
+ Dtree *next, **last, **tail;
+ Node **args;
+ int ret;
+
+ args = pat->expr.args;
+ nargs = pat->expr.nargs;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ ret = 0;
+
+ for (i = 0; i < nargs; i++) {
+ next = nextnode(args[i]->loc, i, nargs, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addpat(pat->expr.args[i], tupelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addarr(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- size_t nargs, nlast, ntail, i, j;
- Dtree *next, **last, **tail;
- Node **args;
- int ret;
-
- args = pat->expr.args;
- nargs = pat->expr.nargs;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- ret = 0;
-
- for (i = 0; i < nargs; i++) {
- next = nextnode(args[i]->loc, i, nargs, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addpat(pat->expr.args[i], arrayelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ size_t nargs, nlast, ntail, i, j;
+ Dtree *next, **last, **tail;
+ Node **args;
+ int ret;
+
+ args = pat->expr.args;
+ nargs = pat->expr.nargs;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ ret = 0;
+
+ for (i = 0; i < nargs; i++) {
+ next = nextnode(args[i]->loc, i, nargs, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addpat(pat->expr.args[i], arrayelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addstruct(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Dtree *next, **last, **tail;
- Node *memb, *name;
- Type *ty, *mty;
- size_t i, j, ntail, nlast;
- int ret;
-
- ret = 0;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- ty = tybase(exprtype(pat));
-
- for (i = 0; i < ty->nmemb; i++) {
- mty = decltype(ty->sdecls[i]);
- name = ty->sdecls[i]->decl.name;
- memb = findmemb(pat, name);
- next = nextnode(pat->loc, i, ty->nmemb, accept);
- tail = NULL;
- ntail = 0;
-
- for (j = 0; j < nlast; j++) {
- /* add a _ capture if we don't specify the value */
- if (!memb) {
- if (addwild(memb, NULL, last[j], next, NULL, NULL, &tail, &ntail))
- ret = 1;
- } else {
- if (addpat(memb, structmemb(val, name, mty), last[j], next, cap, ncap, &tail, &ntail))
- ret = 1;
- }
- }
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ Dtree *next, **last, **tail;
+ Node *memb, *name;
+ Type *ty, *mty;
+ size_t i, j, ntail, nlast;
+ int ret;
+
+ ret = 0;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ ty = tybase(exprtype(pat));
+
+ for (i = 0; i < ty->nmemb; i++) {
+ mty = decltype(ty->sdecls[i]);
+ name = ty->sdecls[i]->decl.name;
+ memb = findmemb(pat, name);
+ next = nextnode(pat->loc, i, ty->nmemb, accept);
+ tail = NULL;
+ ntail = 0;
+
+ for (j = 0; j < nlast; j++) {
+ /* add a _ capture if we don't specify the value */
+ if (!memb) {
+ if (addwild(memb, NULL, last[j], next, NULL, NULL, &tail, &ntail))
+ ret = 1;
+ } else {
+ if (addpat(memb, structmemb(val, name, mty), last[j], next, cap, ncap, &tail, &ntail))
+ ret = 1;
+ }
+ }
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addpat(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- int ret;
- Node *dcl;
-
- pat = fold(pat, 1);
- ret = 0;
- switch (exprop(pat)) {
- case Ovar:
- dcl = decls[pat->expr.did];
- if (dcl->decl.isconst)
- ret = addpat(dcl->decl.init, val, start, accept, cap, ncap, end, nend);
- else
- ret = addwild(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Oucon:
- ret = addunion(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Olit:
- ret = addlit(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Otup:
- ret = addtup(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Oarr:
- ret = addarr(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Ostruct:
- ret = addstruct(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Ogap:
- ret = addwild(pat, NULL, start, accept, NULL, NULL, end, nend);
- break;
- default:
- fatal(pat, "unsupported pattern %s of type %s", opstr[exprop(pat)], tystr(exprtype(pat)));
- break;
- }
- return ret;
+ int ret;
+ Node *dcl;
+
+ pat = fold(pat, 1);
+ ret = 0;
+ switch (exprop(pat)) {
+ case Ovar:
+ dcl = decls[pat->expr.did];
+ if (dcl->decl.isconst)
+ ret = addpat(dcl->decl.init, val, start, accept, cap, ncap, end, nend);
+ else
+ ret = addwild(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Oucon:
+ ret = addunion(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Olit:
+ ret = addlit(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Otup:
+ ret = addtup(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Oarr:
+ ret = addarr(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Ostruct:
+ ret = addstruct(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Ogap:
+ ret = addwild(pat, NULL, start, accept, NULL, NULL, end, nend);
+ break;
+ default:
+ fatal(pat, "unsupported pattern %s of type %s", opstr[exprop(pat)], tystr(exprtype(pat)));
+ break;
+ }
+ return ret;
}
/* val must be a pure, fully evaluated value */
Dtree *gendtree(Node *m, Node *val, Node **lbl, size_t nlbl)
{
- Dtree *start, *accept, **end;
- Node **pat, **cap;
- size_t npat, ncap, nend;
- size_t i;
-
- pat = m->matchstmt.matches;
- npat = m->matchstmt.nmatches;
-
- end = NULL;
- nend = 0;
- start = mkdtree(m->loc, genlbl(m->loc));
- for (i = 0; i < npat; i++) {
- cap = NULL;
- ncap = 0;
- accept = mkdtree(lbl[i]->loc, lbl[i]);
- accept->accept = 1;
-
- if (!addpat(pat[i]->match.pat, val, start, accept, &cap, &ncap, &end, &nend))
- fatal(pat[i], "pattern matched by earlier case");
- addcapture(pat[i]->match.block, cap, ncap);
- }
- if (!verifymatch(start))
- fatal(m, "nonexhaustive pattern set in match statement");
- return start;
+ Dtree *start, *accept, **end;
+ Node **pat, **cap;
+ size_t npat, ncap, nend;
+ size_t i;
+
+ pat = m->matchstmt.matches;
+ npat = m->matchstmt.nmatches;
+
+ end = NULL;
+ nend = 0;
+ start = mkdtree(m->loc, genlbl(m->loc));
+ for (i = 0; i < npat; i++) {
+ cap = NULL;
+ ncap = 0;
+ accept = mkdtree(lbl[i]->loc, lbl[i]);
+ accept->accept = 1;
+
+ if (!addpat(pat[i]->match.pat, val, start, accept, &cap, &ncap, &end, &nend))
+ fatal(pat[i], "pattern matched by earlier case");
+ addcapture(pat[i]->match.block, cap, ncap);
+ }
+ if (!verifymatch(start))
+ fatal(m, "nonexhaustive pattern set in match statement");
+ return start;
}
void genmatchcode(Dtree *dt, Node ***out, size_t *nout)
{
- Node *jmp, *eq, *fail;
- int emit;
- size_t i;
-
- if (dt->emitted)
- return;
- dt->emitted = 1;
-
- /* the we jump to the accept label when generating the parent */
- if (dt->accept) {
- jmp = mkexpr(dt->loc, Ojmp, dt->lbl, NULL);
- jmp->expr.type = mktype(dt->loc, Tyvoid);
- lappend(out, nout, jmp);
- return;
- }
-
- lappend(out, nout, dt->lbl);
- for (i = 0; i < dt->nnext; i++) {
- if (i == dt->nnext - 1 && dt->any) {
- fail = dt->any->lbl;
- emit = 0;
- } else {
- fail = genlbl(dt->loc);
- emit = 1;
- }
-
- eq = mkexpr(dt->loc, Oeq, dt->load, dt->pat[i], NULL);
- eq->expr.type = mktype(dt->loc, Tybool);
- jmp = mkexpr(dt->loc, Ocjmp, eq, dt->next[i]->lbl, fail, NULL);
- jmp->expr.type = mktype(dt->loc, Tyvoid);
- lappend(out, nout, jmp);
-
- genmatchcode(dt->next[i], out, nout);
- if (emit)
- lappend(out, nout, fail);
- }
- if (dt->any) {
- jmp = mkexpr(dt->loc, Ojmp, dt->any->lbl, NULL);
- jmp->expr.type = mktype(dt->loc, Tyvoid);
- lappend(out, nout, jmp);
- genmatchcode(dt->any, out, nout);
- }
+ Node *jmp, *eq, *fail;
+ int emit;
+ size_t i;
+
+ if (dt->emitted)
+ return;
+ dt->emitted = 1;
+
+ /* the we jump to the accept label when generating the parent */
+ if (dt->accept) {
+ jmp = mkexpr(dt->loc, Ojmp, dt->lbl, NULL);
+ jmp->expr.type = mktype(dt->loc, Tyvoid);
+ lappend(out, nout, jmp);
+ return;
+ }
+
+ lappend(out, nout, dt->lbl);
+ for (i = 0; i < dt->nnext; i++) {
+ if (i == dt->nnext - 1 && dt->any) {
+ fail = dt->any->lbl;
+ emit = 0;
+ } else {
+ fail = genlbl(dt->loc);
+ emit = 1;
+ }
+
+ eq = mkexpr(dt->loc, Oeq, dt->load, dt->pat[i], NULL);
+ eq->expr.type = mktype(dt->loc, Tybool);
+ jmp = mkexpr(dt->loc, Ocjmp, eq, dt->next[i]->lbl, fail, NULL);
+ jmp->expr.type = mktype(dt->loc, Tyvoid);
+ lappend(out, nout, jmp);
+
+ genmatchcode(dt->next[i], out, nout);
+ if (emit)
+ lappend(out, nout, fail);
+ }
+ if (dt->any) {
+ jmp = mkexpr(dt->loc, Ojmp, dt->any->lbl, NULL);
+ jmp->expr.type = mktype(dt->loc, Tyvoid);
+ lappend(out, nout, jmp);
+ genmatchcode(dt->any, out, nout);
+ }
}
void genonematch(Node *pat, Node *val, Node *iftrue, Node *iffalse, Node ***out, size_t *nout, Node ***cap, size_t *ncap)
{
- Dtree *start, *accept, *reject, **end;
- size_t nend;
+ Dtree *start, *accept, *reject, **end;
+ size_t nend;
- end = NULL;
- nend = 0;
+ end = NULL;
+ nend = 0;
- start = mkdtree(pat->loc, genlbl(pat->loc));
- accept = mkdtree(iftrue->loc, iftrue);
- accept->accept = 1;
- reject = mkdtree(iffalse->loc, iffalse);
- reject->accept = 1;
+ start = mkdtree(pat->loc, genlbl(pat->loc));
+ accept = mkdtree(iftrue->loc, iftrue);
+ accept->accept = 1;
+ reject = mkdtree(iffalse->loc, iffalse);
+ reject->accept = 1;
- assert(addpat(pat, val, start, accept, cap, ncap, &end, &nend));
- acceptall(start, reject);
- genmatchcode(start, out, nout);
+ assert(addpat(pat, val, start, accept, cap, ncap, &end, &nend));
+ acceptall(start, reject);
+ genmatchcode(start, out, nout);
}
void genmatch(Node *m, Node *val, Node ***out, size_t *nout)
{
- Node **pat, **lbl, *end, *endlbl;
- size_t npat, nlbl, i;
- Dtree *dt;
-
- lbl = NULL;
- nlbl = 0;
-
- pat = m->matchstmt.matches;
- npat = m->matchstmt.nmatches;
- for (i = 0; i < npat; i++)
- lappend(&lbl, &nlbl, genlbl(pat[i]->match.block->loc));
-
-
- endlbl = genlbl(m->loc);
- dt = gendtree(m, val, lbl, nlbl);
- genmatchcode(dt, out, nout);
-
- for (i = 0; i < npat; i++) {
- end = mkexpr(pat[i]->loc, Ojmp, endlbl, NULL);
- end->expr.type = mktype(end->loc, Tyvoid);
- lappend(out, nout, lbl[i]);
- lappend(out, nout, pat[i]->match.block);
- lappend(out, nout, end);
- }
- lappend(out, nout, endlbl);
-
- if (debugopt['m']) {
- dtreedump(stdout, dt);
- for (i = 0; i < *nout; i++)
- dump((*out)[i], stdout);
- }
+ Node **pat, **lbl, *end, *endlbl;
+ size_t npat, nlbl, i;
+ Dtree *dt;
+
+ lbl = NULL;
+ nlbl = 0;
+
+ pat = m->matchstmt.matches;
+ npat = m->matchstmt.nmatches;
+ for (i = 0; i < npat; i++)
+ lappend(&lbl, &nlbl, genlbl(pat[i]->match.block->loc));
+
+
+ endlbl = genlbl(m->loc);
+ dt = gendtree(m, val, lbl, nlbl);
+ genmatchcode(dt, out, nout);
+
+ for (i = 0; i < npat; i++) {
+ end = mkexpr(pat[i]->loc, Ojmp, endlbl, NULL);
+ end->expr.type = mktype(end->loc, Tyvoid);
+ lappend(out, nout, lbl[i]);
+ lappend(out, nout, pat[i]->match.block);
+ lappend(out, nout, end);
+ }
+ lappend(out, nout, endlbl);
+
+ if (debugopt['m']) {
+ dtreedump(stdout, dt);
+ for (i = 0; i < *nout; i++)
+ dump((*out)[i], stdout);
+ }
}
void dtreedumplit(FILE *fd, Dtree *dt, Node *n, size_t depth)
{
- char *s;
-
- s = lblstr(dt->lbl);
- switch (n->lit.littype) {
- case Lchr: findentf(fd, depth, "%s: Lchr %c\n", s, n->lit.chrval); break;
- case Lbool: findentf(fd, depth, "%s: Lbool %s\n", s, n->lit.boolval ? "true" : "false"); break;
- case Lint: findentf(fd, depth, "%s: Lint %llu\n", s, n->lit.intval); break;
- case Lflt: findentf(fd, depth, "%s: Lflt %lf\n", s, n->lit.fltval); break;
- case Lstr: findentf(fd, depth, "%s: Lstr %.*s\n", s, (int)n->lit.strval.len, n->lit.strval.buf); break;
- case Llbl: findentf(fd, depth, "%s: Llbl %s\n", s, n->lit.lblval); break;
- case Lfunc: findentf(fd, depth, "%s: Lfunc\n"); break;
- }
+ char *s;
+
+ s = lblstr(dt->lbl);
+ switch (n->lit.littype) {
+ case Lchr: findentf(fd, depth, "%s: Lchr %c\n", s, n->lit.chrval); break;
+ case Lbool: findentf(fd, depth, "%s: Lbool %s\n", s, n->lit.boolval ? "true" : "false"); break;
+ case Lint: findentf(fd, depth, "%s: Lint %llu\n", s, n->lit.intval); break;
+ case Lflt: findentf(fd, depth, "%s: Lflt %lf\n", s, n->lit.fltval); break;
+ case Lstr: findentf(fd, depth, "%s: Lstr %.*s\n", s, (int)n->lit.strval.len, n->lit.strval.buf); break;
+ case Llbl: findentf(fd, depth, "%s: Llbl %s\n", s, n->lit.lblval); break;
+ case Lfunc: findentf(fd, depth, "%s: Lfunc\n"); break;
+ }
}
void dtreedumpnode(FILE *fd, Dtree *dt, size_t depth)
{
- size_t i;
-
- if (dt->accept)
- findentf(fd, depth, "%s: accept\n", lblstr(dt->lbl));
-
- for (i = 0; i < dt->nnext; i++) {
- dtreedumplit(fd, dt, dt->pat[i]->expr.args[0], depth);
- dtreedumpnode(fd, dt->next[i], depth + 1);
- }
- if (dt->any) {
- findentf(fd, depth, "%s: wildcard\n", lblstr(dt->lbl));
- dtreedumpnode(fd, dt->any, depth + 1);
- }
+ size_t i;
+
+ if (dt->accept)
+ findentf(fd, depth, "%s: accept\n", lblstr(dt->lbl));
+
+ for (i = 0; i < dt->nnext; i++) {
+ dtreedumplit(fd, dt, dt->pat[i]->expr.args[0], depth);
+ dtreedumpnode(fd, dt->next[i], depth + 1);
+ }
+ if (dt->any) {
+ findentf(fd, depth, "%s: wildcard\n", lblstr(dt->lbl));
+ dtreedumpnode(fd, dt->any, depth + 1);
+ }
}
void dtreedump(FILE *fd, Dtree *dt)
{
- dtreedumpnode(fd, dt, 0);
+ dtreedumpnode(fd, dt, 0);
}
diff --git a/mi/mi.h b/mi/mi.h
index 0b9c8a8..021a3f7 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -3,36 +3,36 @@ typedef struct Bb Bb;
typedef struct Reaching Reaching;
struct Cfg {
- Node *fn;
- Bb **bb;
- Bb *start;
- Bb *end;
- size_t nbb;
-
- /* for building bb */
- int nextbbid;
- Htab *lblmap; /* label => Bb mapping */
- Node **fixjmp;
- size_t nfixjmp;
- Bb **fixblk;
- size_t nfixblk;
+ Node *fn;
+ Bb **bb;
+ Bb *start;
+ Bb *end;
+ size_t nbb;
+
+ /* for building bb */
+ int nextbbid;
+ Htab *lblmap; /* label => Bb mapping */
+ Node **fixjmp;
+ size_t nfixjmp;
+ Bb **fixblk;
+ size_t nfixblk;
};
struct Bb {
- int id;
- char **lbls;
- size_t nlbls;
- Node **nl;
- size_t nnl;
- Bitset *pred;
- Bitset *succ;
+ int id;
+ char **lbls;
+ size_t nlbls;
+ Node **nl;
+ size_t nnl;
+ Bitset *pred;
+ Bitset *succ;
};
struct Reaching {
- Bitset **in;
- Bitset **out;
- size_t **defs;
- size_t *ndefs;
+ Bitset **in;
+ Bitset **out;
+ size_t **defs;
+ size_t *ndefs;
};
/* expression folding */
diff --git a/mi/reaching.c b/mi/reaching.c
index 01bd798..aaaaedc 100644
--- a/mi/reaching.c
+++ b/mi/reaching.c
@@ -15,153 +15,138 @@
Node *assignee(Node *n)
{
- Node *a;
+ Node *a;
- switch (exprop(n)) {
- case Oundef: case Odef:
- case Oset:
- case Oasn: case Oaddeq:
- case Osubeq: case Omuleq:
- case Odiveq: case Omodeq:
- case Oboreq: case Obandeq:
- case Obxoreq: case Obsleq:
- case Obsreq:
- return n->expr.args[0];
- break;
- case Oblit:
- case Oclear:
- a = n->expr.args[0];
- if (exprop(a) != Oaddr)
- break;
- a = a->expr.args[0];
- if (exprop(a) != Ovar)
- break;
- return a;
- default:
- break;
- }
- return NULL;
+ switch (exprop(n)) {
+ case Oundef: case Odef:
+ case Oset:
+ case Oasn: case Oaddeq:
+ case Osubeq: case Omuleq:
+ case Odiveq: case Omodeq:
+ case Oboreq: case Obandeq:
+ case Obxoreq: case Obsleq:
+ case Obsreq:
+ return n->expr.args[0];
+ break;
+ case Oblit:
+ case Oclear:
+ a = n->expr.args[0];
+ if (exprop(a) != Oaddr)
+ break;
+ a = a->expr.args[0];
+ if (exprop(a) != Ovar)
+ break;
+ return a;
+ default:
+ break;
+ }
+ return NULL;
}
static void collectdefs(Cfg *cfg, size_t **defs, size_t *ndefs)
{
- size_t i, j, did;
- Node *n;
- Bb *bb;
+ size_t i, j, did;
+ Node *n;
+ Bb *bb;
- for (i = 0; i < cfg->nbb; i++) {
- bb = cfg->bb[i];
- if (!bb)
- continue;
- for (j = 0; j < bb->nnl; j++) {
- n = assignee(bb->nl[j]);
- if (n && exprop(n) == Ovar) {
- did = n->expr.did;
- ndefs[did]++;
- defs[did] = xrealloc(defs[did], ndefs[did] * sizeof(size_t));
- defs[did][ndefs[did] - 1] = bb->nl[j]->nid;
- }
- }
- }
+ for (i = 0; i < cfg->nbb; i++) {
+ bb = cfg->bb[i];
+ if (!bb)
+ continue;
+ for (j = 0; j < bb->nnl; j++) {
+ n = assignee(bb->nl[j]);
+ if (n && exprop(n) == Ovar) {
+ did = n->expr.did;
+ ndefs[did]++;
+ defs[did] = xrealloc(defs[did], ndefs[did] * sizeof(size_t));
+ defs[did][ndefs[did] - 1] = bb->nl[j]->nid;
+ }
+ }
+ }
}
static void genkill(Bb *bb, size_t **defs, size_t *ndefs, Bitset *gen, Bitset *kill)
{
- size_t i, j, did;
- Node *n;
+ size_t i, j, did;
+ Node *n;
- for (i = 0; i < bb->nnl; i++) {
- n = assignee(bb->nl[i]);
- if (!n)
- continue;
- did = n->expr.did;
- for (j = 0; j < ndefs[did]; j++) {
- bsput(kill, defs[did][j]);
- bsdel(gen, defs[did][j]);
- }
- bsput(gen, bb->nl[i]->nid);
- bsdel(kill, bb->nl[i]->nid);
- }
+ for (i = 0; i < bb->nnl; i++) {
+ n = assignee(bb->nl[i]);
+ if (!n)
+ continue;
+ did = n->expr.did;
+ for (j = 0; j < ndefs[did]; j++) {
+ bsput(kill, defs[did][j]);
+ bsdel(gen, defs[did][j]);
+ }
+ bsput(gen, bb->nl[i]->nid);
+ bsdel(kill, bb->nl[i]->nid);
+ }
}
void bsdump(Bitset *bs)
{
- size_t i;
- for (i = 0; bsiter(bs, &i); i++)
- printf("%zd ", i);
- printf("\n");
+ size_t i;
+ for (i = 0; bsiter(bs, &i); i++)
+ printf("%zd ", i);
+ printf("\n");
}
Reaching *reaching(Cfg *cfg)
{
- Bitset **in, **out;
- Bitset **gen, **kill;
- Bitset *bbin, *bbout;
- Reaching *reaching;
- size_t **defs; /* mapping from did => [def,list] */
- size_t *ndefs;
- size_t i, j;
- int changed;
+ Bitset **in, **out;
+ Bitset **gen, **kill;
+ Bitset *bbin, *bbout;
+ Reaching *reaching;
+ size_t **defs; /* mapping from did => [def,list] */
+ size_t *ndefs;
+ size_t i, j;
+ int changed;
- in = zalloc(cfg->nbb * sizeof(Bb*));
- out = zalloc(cfg->nbb * sizeof(Bb*));
- gen = zalloc(cfg->nbb * sizeof(Bb*));
- kill = zalloc(cfg->nbb * sizeof(Bb*));
- defs = zalloc(ndecls * sizeof(size_t*));
- ndefs = zalloc(ndecls * sizeof(size_t));
+ in = zalloc(cfg->nbb * sizeof(Bb*));
+ out = zalloc(cfg->nbb * sizeof(Bb*));
+ gen = zalloc(cfg->nbb * sizeof(Bb*));
+ kill = zalloc(cfg->nbb * sizeof(Bb*));
+ defs = zalloc(ndecls * sizeof(size_t*));
+ ndefs = zalloc(ndecls * sizeof(size_t));
- collectdefs(cfg, defs, ndefs);
- for (i = 0; i < cfg->nbb; i++) {
- in[i] = mkbs();
- out[i] = mkbs();
- gen[i] = mkbs();
- kill[i] = mkbs();
- if (cfg->bb[i])
- genkill(cfg->bb[i], defs, ndefs, gen[i], kill[i]);
- }
+ collectdefs(cfg, defs, ndefs);
+ for (i = 0; i < cfg->nbb; i++) {
+ in[i] = mkbs();
+ out[i] = mkbs();
+ gen[i] = mkbs();
+ kill[i] = mkbs();
+ if (cfg->bb[i])
+ genkill(cfg->bb[i], defs, ndefs, gen[i], kill[i]);
+ }
- do {
- changed = 0;
- for (i = 0; i < cfg->nbb; i++) {
- if (!cfg->bb[i])
- continue;
- bbin = mkbs();
- for (j = 0; bsiter(cfg->bb[i]->pred, &j); j++)
- bsunion(bbin, out[j]);
- bbout = bsdup(bbin);
- bsdiff(bbout, kill[i]);
- bsunion(bbout, gen[i]);
+ do {
+ changed = 0;
+ for (i = 0; i < cfg->nbb; i++) {
+ if (!cfg->bb[i])
+ continue;
+ bbin = mkbs();
+ for (j = 0; bsiter(cfg->bb[i]->pred, &j); j++)
+ bsunion(bbin, out[j]);
+ bbout = bsdup(bbin);
+ bsdiff(bbout, kill[i]);
+ bsunion(bbout, gen[i]);
- if (!bseq(out[i], bbout) || !bseq(in[i], bbin)) {
- changed = 1;
- bsfree(in[i]);
- bsfree(out[i]);
- in[i] = bbin;
- out[i] = bbout;
- }
- }
- } while (changed);
+ if (!bseq(out[i], bbout) || !bseq(in[i], bbin)) {
+ changed = 1;
+ bsfree(in[i]);
+ bsfree(out[i]);
+ in[i] = bbin;
+ out[i] = bbout;
+ }
+ }
+ } while (changed);
-// for (i = 0; i < ndecls; i++) {
-// if (defs[i])
-// printf("\t%zd: ", i);
-// for (j = 0; j < ndefs[i]; j++)
-// printf("%zd ", defs[i][j]);
-// if (defs[i])
-// printf("\n");
-// }
-// for (i = 0; i < cfg->nbb; i++) {
-// printf("bb %zd\n", i);
-// printf("\tin: ");
-// bsdump(in[i]);
-// printf("\tout: ");
-// bsdump(out[i]);
-// }
- reaching = xalloc(sizeof(Reaching));
- reaching->in = in;
- reaching->out = out;
- reaching->defs = defs;
- reaching->ndefs = ndefs;
- return reaching;
+ reaching = xalloc(sizeof(Reaching));
+ reaching->in = in;
+ reaching->out = out;
+ reaching->defs = defs;
+ reaching->ndefs = ndefs;
+ return reaching;
}
diff --git a/mk/lexyacc.mk b/mk/lexyacc.mk
index 5306d97..4851366 100644
--- a/mk/lexyacc.mk
+++ b/mk/lexyacc.mk
@@ -3,7 +3,7 @@
%.h %.c: %.y
rm -f $*.h y.tab.h
yacc -d -o$*.c $<
- [ -f y.tab.h ] && mv y.tab.h $*.h
+ [ -f y.tab.h ] && mv y.tab.h $*.h || [ -f $*.h ]
%.c: %.l
flex -o$*.c $<
diff --git a/muse/muse.c b/muse/muse.c
index c00ade6..cec2b20 100644
--- a/muse/muse.c
+++ b/muse/muse.c
@@ -26,87 +26,87 @@ size_t nextralibs;
static void usage(char *prog)
{
- printf("%s [-hIdos] [-o outfile] [-m] inputs\n", prog);
- printf("\t-h\tprint this help\n");
- printf("\t\tThe outfile must be the same name as each package merged.\n");
- printf("\t-I path\tAdd 'path' to use search path\n");
- printf("\t-d\tPrint debug dumps\n");
- printf("\t-o out\tOutput to outfile\n");
- printf("\t-s\tShow the contents of usefiles `inputs`\n");
+ printf("%s [-hIdos] [-o outfile] [-m] inputs\n", prog);
+ printf("\t-h\tprint this help\n");
+ printf("\t\tThe outfile must be the same name as each package merged.\n");
+ printf("\t-I path\tAdd 'path' to use search path\n");
+ printf("\t-d\tPrint debug dumps\n");
+ printf("\t-o out\tOutput to outfile\n");
+ printf("\t-s\tShow the contents of usefiles `inputs`\n");
}
static void mergeuse(char *path)
{
- FILE *f;
- Stab *st;
+ FILE *f;
+ Stab *st;
- st = file->file.globls;
- f = fopen(path, "r");
- if (!f)
- die("Couldn't open %s\n", path);
- loaduse(path, f, st, Visexport);
- fclose(f);
+ st = file->file.globls;
+ f = fopen(path, "r");
+ if (!f)
+ die("Couldn't open %s\n", path);
+ loaduse(path, f, st, Visexport);
+ fclose(f);
}
int main(int argc, char **argv)
{
- Optctx ctx;
- size_t i;
- FILE *f;
+ Optctx ctx;
+ size_t i;
+ FILE *f;
- optinit(&ctx, "d:hmo:I:l:", argv, argc);
- while (!optdone(&ctx)) {
- switch (optnext(&ctx)) {
- case 'h':
- usage(argv[0]);
- exit(0);
- break;
- case 'o':
- outfile = ctx.optarg;
- break;
- case 'd':
- while (ctx.optarg && *ctx.optarg)
- debugopt[*ctx.optarg++ & 0x7f] = 1;
- break;
- case 'I':
- lappend(&incpaths, &nincpaths, ctx.optarg);
- break;
- case 'l':
- lappend(&extralibs, &nextralibs, ctx.optarg);
- break;
- case 's':
- show = 1;
- break;
- default:
- usage(argv[0]);
- exit(0);
- break;
- }
- }
+ optinit(&ctx, "d:hmo:I:l:", argv, argc);
+ while (!optdone(&ctx)) {
+ switch (optnext(&ctx)) {
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ case 'o':
+ outfile = ctx.optarg;
+ break;
+ case 'd':
+ while (ctx.optarg && *ctx.optarg)
+ debugopt[*ctx.optarg++ & 0x7f] = 1;
+ break;
+ case 'I':
+ lappend(&incpaths, &nincpaths, ctx.optarg);
+ break;
+ case 'l':
+ lappend(&extralibs, &nextralibs, ctx.optarg);
+ break;
+ case 's':
+ show = 1;
+ break;
+ default:
+ usage(argv[0]);
+ exit(0);
+ break;
+ }
+ }
- lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
- if (!outfile) {
- fprintf(stderr, "output file needed when merging usefiles.\n");
- exit(1);
- }
+ lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
+ if (!outfile) {
+ fprintf(stderr, "output file needed when merging usefiles.\n");
+ exit(1);
+ }
- /* read and parse the file */
- file = mkfile("internal");
- file->file.globls = mkstab(0);
- updatens(file->file.globls, outfile);
- tyinit(file->file.globls);
- for (i = 0; i < ctx.nargs; i++)
- mergeuse(ctx.args[i]);
- infer(file);
- tagexports(file, 1);
- addextlibs(file, extralibs, nextralibs);
+ /* read and parse the file */
+ file = mkfile("internal");
+ file->file.globls = mkstab(0);
+ updatens(file->file.globls, outfile);
+ tyinit(file->file.globls);
+ for (i = 0; i < ctx.nargs; i++)
+ mergeuse(ctx.args[i]);
+ infer(file);
+ tagexports(file, 1);
+ addextlibs(file, extralibs, nextralibs);
- /* generate the usefile */
- f = fopen(outfile, "w");
- if (debugopt['s'] || show)
- dumpstab(file->file.globls, stdout);
- else
- writeuse(f, file);
- fclose(f);
- return 0;
+ /* generate the usefile */
+ f = fopen(outfile, "w");
+ if (debugopt['s'] || show)
+ dumpstab(file->file.globls, stdout);
+ else
+ writeuse(f, file);
+ fclose(f);
+ return 0;
}
diff --git a/parse/bitset.c b/parse/bitset.c
index 7450515..ac72f6e 100644
--- a/parse/bitset.c
+++ b/parse/bitset.c
@@ -8,7 +8,7 @@
#include "parse.h"
-#define Sizetbits (CHAR_BIT*sizeof(size_t)) /* used in graph reprs */
+#define Sizetbits (CHAR_BIT * sizeof(size_t)) /* used in graph reprs */
/* Equalizes the size of a and b by
* growing the smaller to the size of the
@@ -19,91 +19,91 @@
*/
static void eqsz(Bitset *a, Bitset *b)
{
- size_t sz;
- size_t i;
- size_t *p;
-
- if (a->nchunks > b->nchunks)
- sz = a->nchunks;
- else
- sz = b->nchunks;
-
- if (a->nchunks != sz) {
- p = zalloc(sz * sizeof(size_t));
- for (i = 0; i < a->nchunks; i++)
- p[i] = a->chunks[i];
- free(a->chunks);
- a->chunks = p;
- a->nchunks = sz;
- }
-
- if (b->nchunks != sz) {
- p = zalloc(sz * sizeof(size_t));
- for (i = 0; i < b->nchunks; i++)
- p[i] = b->chunks[i];
- free(b->chunks);
- b->chunks = p;
- b->nchunks = sz;
- }
+ size_t sz;
+ size_t i;
+ size_t *p;
+
+ if (a->nchunks > b->nchunks)
+ sz = a->nchunks;
+ else
+ sz = b->nchunks;
+
+ if (a->nchunks != sz) {
+ p = zalloc(sz * sizeof(size_t));
+ for (i = 0; i < a->nchunks; i++)
+ p[i] = a->chunks[i];
+ free(a->chunks);
+ a->chunks = p;
+ a->nchunks = sz;
+ }
+
+ if (b->nchunks != sz) {
+ p = zalloc(sz * sizeof(size_t));
+ for (i = 0; i < b->nchunks; i++)
+ p[i] = b->chunks[i];
+ free(b->chunks);
+ b->chunks = p;
+ b->nchunks = sz;
+ }
}
/* Creates a new all-zero bit set */
Bitset *mkbs()
{
- Bitset *bs;
+ Bitset *bs;
- bs = xalloc(sizeof(Bitset));
- bs->nchunks = 1;
- bs->chunks = zalloc(1*sizeof(size_t));
- return bs;
+ bs = xalloc(sizeof(Bitset));
+ bs->nchunks = 1;
+ bs->chunks = zalloc(1 * sizeof(size_t));
+ return bs;
}
/* Frees a bitset. Safe to call on NULL. */
void bsfree(Bitset *bs)
{
- if (!bs)
- return;
- free(bs->chunks);
- free(bs);
+ if (!bs)
+ return;
+ free(bs->chunks);
+ free(bs);
}
/* Duplicates a bitset. NULL is duplicated to NULL. */
Bitset *bsdup(Bitset *a)
{
- Bitset *bs;
-
- if (!a)
- return NULL;
- bs = xalloc(sizeof(Bitset));
- bs->nchunks = a->nchunks;
- bs->chunks = xalloc(a->nchunks*sizeof(size_t));
- memcpy(bs->chunks, a->chunks, a->nchunks*sizeof(size_t));
- return bs;
+ Bitset *bs;
+
+ if (!a)
+ return NULL;
+ bs = xalloc(sizeof(Bitset));
+ bs->nchunks = a->nchunks;
+ bs->chunks = xalloc(a->nchunks * sizeof(size_t));
+ memcpy(bs->chunks, a->chunks, a->nchunks * sizeof(size_t));
+ return bs;
}
/* Zeroes all values in a bit set */
Bitset *bsclear(Bitset *bs)
{
- size_t i;
+ size_t i;
- if (!bs)
- return mkbs();
- for (i = 0; i < bs->nchunks; i++)
- bs->chunks[i] = 0;
- return bs;
+ if (!bs)
+ return mkbs();
+ for (i = 0; i < bs->nchunks; i++)
+ bs->chunks[i] = 0;
+ return bs;
}
/* Counts the number of values held in a bit set */
size_t bscount(Bitset *bs)
{
- size_t i, j, n;
-
- n = 0;
- for (i = 0; i < bs->nchunks; i++)
- for (j = 0; j < sizeof(size_t)*CHAR_BIT; j++)
- if (bs->chunks[i] & 1ULL << j)
- n++;
- return n;
+ size_t i, j, n;
+
+ n = 0;
+ for (i = 0; i < bs->nchunks; i++)
+ for (j = 0; j < sizeof(size_t) * CHAR_BIT; j++)
+ if (bs->chunks[i] & 1ULL << j)
+ n++;
+ return n;
}
/* A slightly tricky function to iterate over the contents
@@ -116,8 +116,8 @@ size_t bscount(Bitset *bs)
*
* Typical usage of this function:
*
- * for (i = 0; bsiter(set, &i); i++)
- * use(i);
+ * for (i = 0; bsiter(set, &i); i++)
+ * use(i);
*
* The increment of 'i' in the for loop is needed in order
* to prevent the function from returning the same value
@@ -125,105 +125,101 @@ size_t bscount(Bitset *bs)
*/
int bsiter(Bitset *bs, size_t *elt)
{
- size_t i;
-
- for (i = *elt; i < bsmax(bs); i++) {
- while (i < bsmax(bs) && !bs->chunks[i/Sizetbits])
- i = (i + Sizetbits) & ~(Sizetbits - 1);
- if (bshas(bs, i)) {
- *elt = i;
- return 1;
- }
- }
- return 0;
+ size_t i;
+
+ for (i = *elt; i < bsmax(bs); i++) {
+ while (i < bsmax(bs) && !bs->chunks[i / Sizetbits])
+ i = (i + Sizetbits) & ~(Sizetbits - 1);
+ if (bshas(bs, i)) {
+ *elt = i;
+ return 1;
+ }
+ }
+ return 0;
}
/* Returns the largest value that the bitset can possibly
* hold. It's conservative, but scanning the entire bitset
* is a bit slow. This is mostly an aid to iterate over it. */
-size_t bsmax(Bitset *bs)
-{
- return bs->nchunks*Sizetbits;
-}
+size_t bsmax(Bitset *bs) { return bs->nchunks * Sizetbits; }
void bsput(Bitset *bs, size_t elt)
{
- size_t sz;
- if (elt >= bs->nchunks*Sizetbits) {
- sz = (elt/Sizetbits)+1;
- bs->chunks = zrealloc(bs->chunks, bs->nchunks*sizeof(size_t), sz*sizeof(size_t));
- bs->nchunks = sz;
- }
- bs->chunks[elt/Sizetbits] |= 1ULL << (elt % Sizetbits);
+ size_t sz;
+ if (elt >= bs->nchunks * Sizetbits) {
+ sz = (elt / Sizetbits) + 1;
+ bs->chunks = zrealloc(bs->chunks, bs->nchunks * sizeof(size_t), sz * sizeof(size_t));
+ bs->nchunks = sz;
+ }
+ bs->chunks[elt / Sizetbits] |= 1ULL << (elt % Sizetbits);
}
void bsdel(Bitset *bs, size_t elt)
{
- if (elt < bs->nchunks*Sizetbits)
- bs->chunks[elt/Sizetbits] &= ~(1ULL << (elt % Sizetbits));
+ if (elt < bs->nchunks * Sizetbits)
+ bs->chunks[elt / Sizetbits] &= ~(1ULL << (elt % Sizetbits));
}
-
void bsunion(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] |= b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] |= b->chunks[i];
}
void bsintersect(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] &= b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] &= b->chunks[i];
}
void bsdiff(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] &= ~b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] &= ~b->chunks[i];
}
int bseq(Bitset *a, Bitset *b)
{
- size_t i;
-
- if (!a || !b)
- return bsisempty(a) && bsisempty(b);
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++) {
- if (a->chunks[i] != b->chunks[i])
- return 0;
- }
- return 1;
+ size_t i;
+
+ if (!a || !b)
+ return bsisempty(a) && bsisempty(b);
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++) {
+ if (a->chunks[i] != b->chunks[i])
+ return 0;
+ }
+ return 1;
}
int bsissubset(Bitset *set, Bitset *sub)
{
- size_t i;
+ size_t i;
- eqsz(set, sub);
- for (i = 0; i < set->nchunks; i++)
- if ((sub->chunks[i] & set->chunks[i]) != set->chunks[i])
- return 0;
- return 1;
+ eqsz(set, sub);
+ for (i = 0; i < set->nchunks; i++)
+ if ((sub->chunks[i] & set->chunks[i]) != set->chunks[i])
+ return 0;
+ return 1;
}
int bsisempty(Bitset *set)
{
- size_t i;
-
- if (!set)
- return 1;
- for (i = 0; i < set->nchunks; i++)
- if (set->chunks[i])
- return 0;
- return 1;
+ size_t i;
+
+ if (!set)
+ return 1;
+ for (i = 0; i < set->nchunks; i++)
+ if (set->chunks[i])
+ return 0;
+ return 1;
}
diff --git a/parse/dump.c b/parse/dump.c
index 92dc99b..9651b60 100644
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -15,9 +15,9 @@
/* outputs a fully qualified name */
static void outname(Node *n, FILE *fd)
{
- if (n->name.ns)
- fprintf(fd, "%s.", n->name.ns);
- fprintf(fd, "%s", n->name.name);
+ if (n->name.ns)
+ fprintf(fd, "%s.", n->name.ns);
+ fprintf(fd, "%s", n->name.name);
}
/* outputs a sym in a one-line short form (ie,
@@ -25,20 +25,17 @@ static void outname(Node *n, FILE *fd)
* expressed in indented tree. */
static void outsym(Node *s, FILE *fd, int depth)
{
- char buf[1024];
+ char buf[1024];
- if (s->decl.isconst)
- findentf(fd, depth, "const ");
- else
- findentf(fd, depth, "var ");
- outname(s->decl.name, fd);
- fprintf(fd, " : %s\n", tyfmt(buf, 1024, s->decl.type));
+ if (s->decl.isconst)
+ findentf(fd, depth, "const ");
+ else
+ findentf(fd, depth, "var ");
+ outname(s->decl.name, fd);
+ fprintf(fd, " : %s\n", tyfmt(buf, 1024, s->decl.type));
}
-void dumpsym(Node *s, FILE *fd)
-{
- outsym(s, fd, 0);
-}
+void dumpsym(Node *s, FILE *fd) { outsym(s, fd, 0); }
/* Outputs a symbol table, and it's sub-tables
* recursively, with a sigil describing the symbol
@@ -51,71 +48,68 @@ void dumpsym(Node *s, FILE *fd)
*/
static void outstab(Stab *st, FILE *fd, int depth)
{
- size_t i, n;
- char *name;
- void **k;
- char *ty;
- Type *t;
+ size_t i, n;
+ char *name;
+ void **k;
+ char *ty;
+ Type *t;
- name = "";
- if (st->name)
- name = st->name;
- findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, name);
- if (!st)
- return;
+ name = "";
+ if (st->name)
+ name = st->name;
+ findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, name);
+ if (!st)
+ return;
- /* print types */
- k = htkeys(st->ty, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "T ");
- /* already indented */
- outname(k[i], fd);
- t = gettype(st, k[i]);
- if (t->nsub)
- ty = tystr(t->sub[0]);
- else
- ty = strdup("none");
- fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
- free(ty);
- }
- free(k);
+ /* print types */
+ k = htkeys(st->ty, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "T ");
+ /* already indented */
+ outname(k[i], fd);
+ t = gettype(st, k[i]);
+ if (t->nsub)
+ ty = tystr(t->sub[0]);
+ else
+ ty = strdup("none");
+ fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
+ free(ty);
+ }
+ free(k);
- /* dump declarations */
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "S ");
- /* already indented */
- outsym(getdcl(st, k[i]), fd, 0);
- }
- free(k);
+ /* dump declarations */
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "S ");
+ /* already indented */
+ outsym(getdcl(st, k[i]), fd, 0);
+ }
+ free(k);
- /* dump closure */
- if (st->env) {
- k = htkeys(st->env, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "U ");
- /* already indented */
- outsym(getclosed(st, k[i]), fd, 0);
- }
- free(k);
- }
+ /* dump closure */
+ if (st->env) {
+ k = htkeys(st->env, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "U ");
+ /* already indented */
+ outsym(getclosed(st, k[i]), fd, 0);
+ }
+ free(k);
+ }
}
-void dumpstab(Stab *st, FILE *fd)
-{
- outstab(st, fd, 0);
-}
+void dumpstab(Stab *st, FILE *fd) { outstab(st, fd, 0); }
void dumpfilestabs(Node *file, int depth, FILE *fd)
{
- size_t nk, i;
- void **k;
+ size_t nk, i;
+ void **k;
- k = htkeys(file->file.ns, &nk);
- for (i = 0; i < nk; i++) {
- outstab(htget(file->file.ns, k[i]), fd, depth);
- }
- free(k);
+ k = htkeys(file->file.ns, &nk);
+ for (i = 0; i < nk; i++) {
+ outstab(htget(file->file.ns, k[i]), fd, depth);
+ }
+ free(k);
}
/* Outputs a node in indented tree form. This is
@@ -123,148 +117,142 @@ void dumpfilestabs(Node *file, int depth, FILE *fd)
* understanding and debugging. */
static void outnode(Node *n, FILE *fd, int depth)
{
- size_t i;
- char *ty;
- char *tr;
- int tid;
- char buf[1024];
+ size_t i;
+ char *ty;
+ char *tr;
+ int tid;
+ char buf[1024];
- if (!n) {
- findentf(fd, depth, "Nil\n");
- return;
- }
- findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
- switch(n->type) {
- case Nfile:
- fprintf(fd, "(name = %s)\n", n->file.files[0]);
- dumpfilestabs(file, depth + 1, fd);
- for (i = 0; i < n->file.nuses; i++)
- outnode(n->file.uses[i], fd, depth + 1);
- for (i = 0; i < n->file.nstmts; i++)
- outnode(n->file.stmts[i], fd, depth + 1);
- break;
- case Ndecl:
- tr = "";
- if (n->decl.trait)
- tr = namestr(n->decl.trait->name);
- fprintf(fd, "(did = %zd, trait=%s, vis = %d)\n",
- n->decl.did, tr, n->decl.vis);
- findentf(fd, depth + 1, "isglobl=%d\n", n->decl.isglobl);
- findentf(fd, depth + 1, "isconst=%d\n", n->decl.isconst);
- findentf(fd, depth + 1, "isgeneric=%d\n", n->decl.isgeneric);
- findentf(fd, depth + 1, "isextern=%d\n", n->decl.isextern);
- findentf(fd, depth + 1, "ispkglocal=%d\n", n->decl.ispkglocal);
- findentf(fd, depth + 1, "ishidden=%d\n", n->decl.ishidden);
- findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
- findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
- findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
- findentf(fd, depth, ")\n");
- outsym(n, fd, depth + 1);
- outnode(n->decl.init, fd, depth + 1);
- break;
- case Nblock:
- fprintf(fd, "\n");
- outstab(n->block.scope, fd, depth + 1);
- for (i = 0; i < n->block.nstmts; i++)
- outnode(n->block.stmts[i], fd, depth+1);
- break;
- case Nifstmt:
- fprintf(fd, "\n");
- outnode(n->ifstmt.cond, fd, depth+1);
- outnode(n->ifstmt.iftrue, fd, depth+1);
- outnode(n->ifstmt.iffalse, fd, depth+1);
- break;
- case Nloopstmt:
- fprintf(fd, "\n");
- outnode(n->loopstmt.init, fd, depth+1);
- outnode(n->loopstmt.cond, fd, depth+1);
- outnode(n->loopstmt.step, fd, depth+1);
- outnode(n->loopstmt.body, fd, depth+1);
- break;
- case Niterstmt:
- fprintf(fd, "\n");
- outnode(n->iterstmt.elt, fd, depth+1);
- outnode(n->iterstmt.seq, fd, depth+1);
- outnode(n->iterstmt.body, fd, depth+1);
- break;
- case Nmatchstmt:
- fprintf(fd, "\n");
- outnode(n->matchstmt.val, fd, depth+1);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- outnode(n->matchstmt.matches[i], fd, depth+1);
- break;
- case Nmatch:
- fprintf(fd, "\n");
- outnode(n->match.pat, fd, depth+1);
- outnode(n->match.block, fd, depth+1);
- break;
- case Nuse:
- fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal);
- break;
- case Nexpr:
- if (exprop(n) == Ovar)
- assert(decls[n->expr.did]->decl.did == n->expr.did);
- ty = tystr(n->expr.type);
- if (n->expr.type)
- tid = n->expr.type->tid;
- else
- tid = -1;
- fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n",
- ty, tid, opstr[n->expr.op], n->expr.isconst, n->expr.did);
- free(ty);
- outnode(n->expr.idx, fd, depth + 1);
- for (i = 0; i < n->expr.nargs; i++)
- outnode(n->expr.args[i], fd, depth+1);
- break;
- case Nlit:
- switch (n->lit.littype) {
- case Lchr: fprintf(fd, " Lchr %c\n", n->lit.chrval); break;
- case Lbool: fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
- case Lint: fprintf(fd, " Lint %llu\n", n->lit.intval); break;
- case Lflt: fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
- case Lstr: fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf); break;
- case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
- case Lfunc:
- fprintf(fd, " Lfunc\n");
- outnode(n->lit.fnval, fd, depth+1);
- break;
- }
- break;
- case Nfunc:
- fprintf(fd, " (args =\n");
- for (i = 0; i < n->func.nargs; i++)
- outnode(n->func.args[i], fd, depth+1);
- findentf(fd, depth, ")\n");
- outstab(n->func.scope, fd, depth + 1);
- outnode(n->func.body, fd, depth+1);
- break;
- case Nname:
- fprintf(fd, "(");
- if (n->name.ns)
- fprintf(fd, "%s.", n->name.ns);
- fprintf(fd, "%s", n->name.name);
- fprintf(fd, ")\n");
- break;
- case Nimpl:
- fprintf(fd, "(name = %s, type = %s)\n", namestr(n->impl.traitname), tyfmt(buf, sizeof buf, n->impl.type));
- findentf(fd, depth, "");
- outnode(n->impl.traitname, fd, depth + 1);
- for (i = 0; i < n->impl.ndecls; i++)
- outnode(n->impl.decls[i], fd, depth+1);
- break;
- case Nnone:
- fprintf(stderr, "Nnone not a real node type!");
- fprintf(fd, "Nnone\n");
- break;
- }
+ if (!n) {
+ findentf(fd, depth, "Nil\n");
+ return;
+ }
+ findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
+ switch (n->type) {
+ case Nfile:
+ fprintf(fd, "(name = %s)\n", n->file.files[0]);
+ dumpfilestabs(file, depth + 1, fd);
+ for (i = 0; i < n->file.nuses; i++)
+ outnode(n->file.uses[i], fd, depth + 1);
+ for (i = 0; i < n->file.nstmts; i++)
+ outnode(n->file.stmts[i], fd, depth + 1);
+ break;
+ case Ndecl:
+ tr = "";
+ if (n->decl.trait)
+ tr = namestr(n->decl.trait->name);
+ fprintf(fd, "(did = %zd, trait=%s, vis = %d)\n", n->decl.did, tr, n->decl.vis);
+ findentf(fd, depth + 1, "isglobl=%d\n", n->decl.isglobl);
+ findentf(fd, depth + 1, "isconst=%d\n", n->decl.isconst);
+ findentf(fd, depth + 1, "isgeneric=%d\n", n->decl.isgeneric);
+ findentf(fd, depth + 1, "isextern=%d\n", n->decl.isextern);
+ findentf(fd, depth + 1, "ispkglocal=%d\n", n->decl.ispkglocal);
+ findentf(fd, depth + 1, "ishidden=%d\n", n->decl.ishidden);
+ findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
+ findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
+ findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
+ findentf(fd, depth, ")\n");
+ outsym(n, fd, depth + 1);
+ outnode(n->decl.init, fd, depth + 1);
+ break;
+ case Nblock:
+ fprintf(fd, "\n");
+ outstab(n->block.scope, fd, depth + 1);
+ for (i = 0; i < n->block.nstmts; i++)
+ outnode(n->block.stmts[i], fd, depth + 1);
+ break;
+ case Nifstmt:
+ fprintf(fd, "\n");
+ outnode(n->ifstmt.cond, fd, depth + 1);
+ outnode(n->ifstmt.iftrue, fd, depth + 1);
+ outnode(n->ifstmt.iffalse, fd, depth + 1);
+ break;
+ case Nloopstmt:
+ fprintf(fd, "\n");
+ outnode(n->loopstmt.init, fd, depth + 1);
+ outnode(n->loopstmt.cond, fd, depth + 1);
+ outnode(n->loopstmt.step, fd, depth + 1);
+ outnode(n->loopstmt.body, fd, depth + 1);
+ break;
+ case Niterstmt:
+ fprintf(fd, "\n");
+ outnode(n->iterstmt.elt, fd, depth + 1);
+ outnode(n->iterstmt.seq, fd, depth + 1);
+ outnode(n->iterstmt.body, fd, depth + 1);
+ break;
+ case Nmatchstmt:
+ fprintf(fd, "\n");
+ outnode(n->matchstmt.val, fd, depth + 1);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ outnode(n->matchstmt.matches[i], fd, depth + 1);
+ break;
+ case Nmatch:
+ fprintf(fd, "\n");
+ outnode(n->match.pat, fd, depth + 1);
+ outnode(n->match.block, fd, depth + 1);
+ break;
+ case Nuse: fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal); break;
+ case Nexpr:
+ if (exprop(n) == Ovar)
+ assert(decls[n->expr.did]->decl.did == n->expr.did);
+ ty = tystr(n->expr.type);
+ if (n->expr.type)
+ tid = n->expr.type->tid;
+ else
+ tid = -1;
+ fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n", ty, tid,
+ opstr[n->expr.op], n->expr.isconst, n->expr.did);
+ free(ty);
+ outnode(n->expr.idx, fd, depth + 1);
+ for (i = 0; i < n->expr.nargs; i++)
+ outnode(n->expr.args[i], fd, depth + 1);
+ break;
+ case Nlit:
+ switch (n->lit.littype) {
+ case Lchr: fprintf(fd, " Lchr %c\n", n->lit.chrval); break;
+ case Lbool: fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
+ case Lint: fprintf(fd, " Lint %llu\n", n->lit.intval); break;
+ case Lflt: fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
+ case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
+ case Lstr:
+ fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf);
+ break;
+ case Lfunc:
+ fprintf(fd, " lfunc\n");
+ outnode(n->lit.fnval, fd, depth + 1);
+ break;
+ }
+ break;
+ case Nfunc:
+ fprintf(fd, " (args =\n");
+ for (i = 0; i < n->func.nargs; i++)
+ outnode(n->func.args[i], fd, depth + 1);
+ findentf(fd, depth, ")\n");
+ outstab(n->func.scope, fd, depth + 1);
+ outnode(n->func.body, fd, depth + 1);
+ break;
+ case Nname:
+ fprintf(fd, "(");
+ if (n->name.ns)
+ fprintf(fd, "%s.", n->name.ns);
+ fprintf(fd, "%s", n->name.name);
+ fprintf(fd, ")\n");
+ break;
+ case Nimpl:
+ fprintf(fd, "(name = %s, type = %s)\n", namestr(n->impl.traitname),
+ tyfmt(buf, sizeof buf, n->impl.type));
+ findentf(fd, depth, "");
+ outnode(n->impl.traitname, fd, depth + 1);
+ for (i = 0; i < n->impl.ndecls; i++)
+ outnode(n->impl.decls[i], fd, depth + 1);
+ break;
+ case Nnone:
+ fprintf(stderr, "Nnone not a real node type!");
+ fprintf(fd, "Nnone\n");
+ break;
+ }
}
-void dump(Node *n, FILE *fd)
-{
- outnode(n, fd, 0);
-}
+void dump(Node *n, FILE *fd) { outnode(n, fd, 0); }
-void dumpn(Node *n)
-{
- dump(n, stdout);
-}
+void dumpn(Node *n) { dump(n, stdout); }
diff --git a/parse/gram.y b/parse/gram.y
index f082be1..64e0da6 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -163,911 +163,910 @@ static void setupinit(Node *n);
%type <uconlist> unionbody
%union {
- struct {
- Srcloc loc;
- Node **nl;
- size_t nn;
- } nodelist;
- struct {
- char **str;
- size_t nstr;
- } strlist;
- struct {
- Srcloc loc;
- Ucon **ucl;
- size_t nucl;
- } uconlist;
- struct {
- Srcloc loc;
- Type **types;
- size_t ntypes;
- } tylist;
- struct { /* FIXME: unused */
- Srcloc loc;
- char *name;
- Type *type;
- Type **params;
- size_t nparams;
- } tydef;
- Trait *trait;
- Node *node;
- Tok *tok;
- Type *ty;
- Ucon *ucon;
+ struct {
+ Srcloc loc;
+ Node **nl;
+ size_t nn;
+ } nodelist;
+ struct {
+ char **str;
+ size_t nstr;
+ } strlist;
+ struct {
+ Srcloc loc;
+ Ucon **ucl;
+ size_t nucl;
+ } uconlist;
+ struct {
+ Srcloc loc;
+ Type **types;
+ size_t ntypes;
+ } tylist;
+ struct { /* FIXME: unused */
+ Srcloc loc;
+ char *name;
+ Type *type;
+ Type **params;
+ size_t nparams;
+ } tydef;
+ Trait *trait;
+ Node *node;
+ Tok *tok;
+ Type *ty;
+ Ucon *ucon;
}
%%
file : toplev
- | file Tendln toplev
- ;
-
-toplev : package
- | use {lappend(&file->file.uses, &file->file.nuses, $1);}
- | implstmt {
- lappend(&file->file.stmts, &file->file.nstmts, $1);
- }
- | traitdef {
- size_t i;
- puttrait(file->file.globls, $1->name, $1);
- for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.globls, $1->funcs[i]);
- }
- | tydef {
- puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.globls, $1.type);
- }
- | decl {
- size_t i;
- Node *n;
-
- for (i = 0; i < $1.nn; i++) {
- if (!strcmp(declname($1.nl[i]), "__init__"))
- setupinit($1.nl[i]);
- /* putdcl can merge, so we need to getdcl after */
- putdcl(file->file.globls, $1.nl[i]);
- n = getdcl(file->file.globls, $1.nl[i]->decl.name);
- lappend(&file->file.stmts, &file->file.nstmts, n);
- $1.nl[i]->decl.isglobl = 1;
- if ($1.nl[i]->decl.isinit)
- file->file.localinit = $1.nl[i];
- }
- }
- | /* empty */
- ;
+ | file Tendln toplev
+ ;
+
+toplev : package
+ | use {lappend(&file->file.uses, &file->file.nuses, $1);}
+ | implstmt {
+ lappend(&file->file.stmts, &file->file.nstmts, $1);
+ }
+ | traitdef {
+ size_t i;
+ puttrait(file->file.globls, $1->name, $1);
+ for (i = 0; i < $1->nfuncs; i++)
+ putdcl(file->file.globls, $1->funcs[i]);
+ }
+ | tydef {
+ puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);
+ }
+ | decl {
+ size_t i;
+ Node *n;
+
+ for (i = 0; i < $1.nn; i++) {
+ if (!strcmp(declname($1.nl[i]), "__init__"))
+ setupinit($1.nl[i]);
+ /* putdcl can merge, so we need to getdcl after */
+ putdcl(file->file.globls, $1.nl[i]);
+ n = getdcl(file->file.globls, $1.nl[i]->decl.name);
+ lappend(&file->file.stmts, &file->file.nstmts, n);
+ $1.nl[i]->decl.isglobl = 1;
+ if ($1.nl[i]->decl.isinit)
+ file->file.localinit = $1.nl[i];
+ }
+ }
+ | /* empty */
+ ;
decl : attrs Tvar decllist {
- size_t i;
-
- for (i = 0; i < $3.nn; i++)
- setattrs($3.nl[i], $1.str, $1.nstr);
- $$ = $3;
- }
- | attrs Tconst decllist {
- size_t i;
- for (i = 0; i < $3.nn; i++) {
- setattrs($3.nl[i], $1.str, $1.nstr);
- $3.nl[i]->decl.isconst = 1;
- }
- $$ = $3;
- }
- | attrs Tgeneric decllist {
- size_t i;
-
- for (i = 0; i < $3.nn; i++) {
- setattrs($3.nl[i], $1.str, $1.nstr);
- $3.nl[i]->decl.isconst = 1;
- $3.nl[i]->decl.isgeneric = 1;
- }
- $$ = $3;
- }
+ size_t i;
+
+ for (i = 0; i < $3.nn; i++)
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $$ = $3;
+ }
+ | attrs Tconst decllist {
+ size_t i;
+ for (i = 0; i < $3.nn; i++) {
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $3.nl[i]->decl.isconst = 1;
+ }
+ $$ = $3;
+ }
+ | attrs Tgeneric decllist {
+ size_t i;
+
+ for (i = 0; i < $3.nn; i++) {
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $3.nl[i]->decl.isconst = 1;
+ $3.nl[i]->decl.isgeneric = 1;
+ }
+ $$ = $3;
+ }
attrs : /* empty */ {$$.nstr = 0; $$.str = NULL;}
- | Tattr attrs {
- $$ = $2;
- lappend(&$$.str, &$$.nstr, strdup($1->id));
- }
- ;
+ | Tattr attrs {
+ $$ = $2;
+ lappend(&$$.str, &$$.nstr, strdup($1->id));
+ }
+ ;
decllist: declbody {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | declbody Tcomma decllist {
- linsert(&$3.nl, &$3.nn, 0, $1);
- $$=$3;
- }
- ;
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | declbody Tcomma decllist {
+ linsert(&$3.nl, &$3.nn, 0, $1);
+ $$=$3;
+ }
+ ;
use : Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);}
- | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
- ;
+ | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
+ ;
optident: Tident {$$ = $1;}
- | /* empty */ {$$ = NULL;}
- ;
+ | /* empty */ {$$ = NULL;}
+ ;
package : Tpkg optident Tasn pkgbody Tendblk {
- if (file->file.globls->name)
- lfatal($1->loc, "Package already declared\n");
- if ($2) {
- updatens(file->file.globls, $2->id);
- }
- }
- ;
+ if (file->file.globls->name)
+ lfatal($1->loc, "Package already declared\n");
+ if ($2) {
+ updatens(file->file.globls, $2->id);
+ }
+ }
+ ;
pkgbody : pkgitem
- | pkgbody Tendln pkgitem
- ;
+ | pkgbody Tendln pkgitem
+ ;
pkgitem : decl {
- size_t i;
- for (i = 0; i < $1.nn; i++) {
- $1.nl[i]->decl.vis = Visexport;
- $1.nl[i]->decl.isglobl = 1;
- putdcl(file->file.globls, $1.nl[i]);
- if ($1.nl[i]->decl.init)
- lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
- }
- }
- | pkgtydef {
- /* the type may only be null in a package context, so we
- can set the type when merging in this case.
-
- FIXME: clean up the fucking special cases. */
- if ($1.type)
- $1.type->vis = Visexport;
- puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.globls, $1.type);
- }
- | traitdef {
- size_t i;
- $1->vis = Visexport;
- puttrait(file->file.globls, $1->name, $1);
- for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.globls, $1->funcs[i]);
- }
- | implstmt {
- $1->impl.vis = Visexport;
- lappend(&file->file.stmts, &file->file.nstmts, $1);
- }
- | /* empty */
- ;
+ size_t i;
+ for (i = 0; i < $1.nn; i++) {
+ $1.nl[i]->decl.vis = Visexport;
+ $1.nl[i]->decl.isglobl = 1;
+ putdcl(file->file.globls, $1.nl[i]);
+ if ($1.nl[i]->decl.init)
+ lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
+ }
+ }
+ | pkgtydef {
+ /* the type may only be null in a package context, so we
+ can set the type when merging in this case.
+
+ FIXME: clean up the fucking special cases. */
+ if ($1.type)
+ $1.type->vis = Visexport;
+ puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);
+ }
+ | traitdef {
+ size_t i;
+ $1->vis = Visexport;
+ puttrait(file->file.globls, $1->name, $1);
+ for (i = 0; i < $1->nfuncs; i++)
+ putdcl(file->file.globls, $1->funcs[i]);
+ }
+ | implstmt {
+ $1->impl.vis = Visexport;
+ lappend(&file->file.stmts, &file->file.nstmts, $1);
+ }
+ | /* empty */
+ ;
pkgtydef: attrs tydef {
- size_t i;
- $$ = $2;
- for (i = 0; i < $1.nstr; i++) {
- if (!strcmp($1.str[i], "pkglocal"))
- $$.type->ispkglocal = 1;
- else
- lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);
- }
- }
- ;
+ size_t i;
+ $$ = $2;
+ for (i = 0; i < $1.nstr; i++) {
+ if (!strcmp($1.str[i], "pkglocal"))
+ $$.type->ispkglocal = 1;
+ else
+ lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);
+ }
+ }
+ ;
declbody: declcore Tasn expr {$$ = $1; $1->decl.init = $3;}
- | declcore
- ;
+ | declcore
+ ;
declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));}
- | typedeclcore {$$ = $1;}
- ;
+ | typedeclcore {$$ = $1;}
+ ;
typedeclcore
- : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
- ;
+ : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
+ ;
name : Tident {$$ = mkname($1->loc, $1->id);}
- | Tident Tdot name {$$ = $3; setns($3, $1->id);}
- ;
+ | Tident Tdot name {$$ = $3; setns($3, $1->id);}
+ ;
implstmt: Timpl name type {
- $$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
- $$->impl.isproto = 1;
- }
- | Timpl name type Tasn Tendln implbody Tendblk {
- $$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
- }
- ;
+ $$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
+ $$->impl.isproto = 1;
+ }
+ | Timpl name type Tasn Tendln implbody Tendblk {
+ $$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
+ }
+ ;
implbody
- : optendlns {$$.nl = NULL; $$.nn = 0;}
- | implbody Tident Tasn exprln optendlns {
- Node *d;
- $$ = $1;
- d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
- d->decl.init = $4;
- d->decl.isconst = 1;
- d->decl.isglobl = 1;
- lappend(&$$.nl, &$$.nn, d);
- }
- ;
+ : optendlns {$$.nl = NULL; $$.nn = 0;}
+ | implbody Tident Tasn exprln optendlns {
+ Node *d;
+ $$ = $1;
+ d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
+ d->decl.init = $4;
+ d->decl.isconst = 1;
+ d->decl.isglobl = 1;
+ lappend(&$$.nl, &$$.nn, d);
+ }
+ ;
traitdef: Ttrait Tident generictype /* trait prototype */ {
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
- }
- | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
- size_t i;
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
- for (i = 0; i < $5.nn; i++) {
- $5.nl[i]->decl.trait = $$;
- $5.nl[i]->decl.isgeneric = 1;
- }
- }
- ;
+ $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
+ }
+ | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
+ size_t i;
+ $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
+ for (i = 0; i < $5.nn; i++) {
+ $5.nl[i]->decl.trait = $$;
+ $5.nl[i]->decl.isgeneric = 1;
+ }
+ }
+ ;
traitbody
- : optendlns {$$.nl = NULL; $$.nn = 0;}
- | traitbody Tident Tcolon type optendlns {
- Node *d;
- $$ = $1;
- d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
- d->decl.isgeneric = 1;
- d->decl.isconst = 1;
- lappend(&$$.nl, &$$.nn, d);
- }
- ;
+ : optendlns {$$.nl = NULL; $$.nn = 0;}
+ | traitbody Tident Tcolon type optendlns {
+ Node *d;
+ $$ = $1;
+ d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
+ d->decl.isgeneric = 1;
+ d->decl.isconst = 1;
+ lappend(&$$.nl, &$$.nn, d);
+ }
+ ;
tydef : Ttype typeid {$$ = $2;}
- | Ttype typeid Tasn type {
- $$ = $2;
- if ($$.nparams == 0) {
- $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
- } else {
- $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
- }
- }
- ;
+ | Ttype typeid Tasn type {
+ $$ = $2;
+ if ($$.nparams == 0) {
+ $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
+ } else {
+ $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
+ }
+ }
+ ;
typeid : Tident {
- $$.loc = $1->loc;
- $$.name = $1->id;
- $$.params = NULL;
- $$.type = NULL;
- }
- | Tident Toparen typarams Tcparen {
- $$.loc = $1->loc;
- $$.name = $1->id;
- $$.params = $3.types;
- $$.nparams = $3.ntypes;
- $$.type = NULL;
- }
- ;
+ $$.loc = $1->loc;
+ $$.name = $1->id;
+ $$.params = NULL;
+ $$.type = NULL;
+ }
+ | Tident Toparen typarams Tcparen {
+ $$.loc = $1->loc;
+ $$.name = $1->id;
+ $$.params = $3.types;
+ $$.nparams = $3.ntypes;
+ $$.type = NULL;
+ }
+ ;
typarams: generictype {
- $$.types = NULL; $$.ntypes = 0;
- lappend(&$$.types, &$$.ntypes, $1);
- }
- | typarams Tcomma generictype {lappend(&$$.types, &$$.ntypes, $3);}
- ;
+ $$.types = NULL; $$.ntypes = 0;
+ lappend(&$$.types, &$$.ntypes, $1);
+ }
+ | typarams Tcomma generictype {lappend(&$$.types, &$$.ntypes, $3);}
+ ;
type : structdef
- | tupledef
- | uniondef
- | compoundtype
- | generictype
- | Tellipsis {$$ = mktype($1->loc, Tyvalist);}
- ;
+ | tupledef
+ | uniondef
+ | compoundtype
+ | generictype
+ | Tellipsis {$$ = mktype($1->loc, Tyvalist);}
+ ;
generictype
- : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
- | Ttyparam Twith name {
- $$ = mktyparam($1->loc, $1->id);
- addtrait($$, $3->name.name);
- }
- | Ttyparam Twith Toparen typaramlist Tcparen {
- size_t i;
- $$ = mktyparam($1->loc, $1->id);
- for (i = 0; i < $4.nn; i++)
- addtrait($$, $4.nl[i]->name.name);
- }
- ;
+ : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
+ | Ttyparam Twith name {
+ $$ = mktyparam($1->loc, $1->id);
+ addtrait($$, $3->name.name);
+ }
+ | Ttyparam Twith Toparen typaramlist Tcparen {
+ size_t i;
+ $$ = mktyparam($1->loc, $1->id);
+ for (i = 0; i < $4.nn; i++)
+ addtrait($$, $4.nl[i]->name.name);
+ }
+ ;
typaramlist
- : name {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | typaramlist Tcomma name {lappend(&$$.nl, &$$.nn, $3);}
- ;
+ : name {
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | typaramlist Tcomma name {lappend(&$$.nl, &$$.nn, $3);}
+ ;
compoundtype
- : functype {$$ = $1;}
- | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
- | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
- | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
- | type Tderef {$$ = mktyptr($2->loc, $1);}
- | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
- | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
- | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
- ;
+ : functype {$$ = $1;}
+ | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
+ | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
+ | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
+ | type Tderef {$$ = mktyptr($2->loc, $1);}
+ | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
+ | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
+ | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
+ ;
functype: Toparen funcsig Tcparen {$$ = $2;}
- ;
+ ;
funcsig : argdefs Tret type
- {$$ = mktyfunc($2->loc, $1.nl, $1.nn, $3);}
- ;
+ {$$ = mktyfunc($2->loc, $1.nl, $1.nn, $3);}
+ ;
argdefs : typedeclcore {
- $$.loc = $1->loc;
- $$.nl = NULL;
- $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);
- }
- | argdefs Tcomma declcore {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */ {
- $$.loc.line = 0;
- $$.loc.file = 0;
- $$.nl = NULL;
- $$.nn = 0;
- }
- ;
+ $$.loc = $1->loc;
+ $$.nl = NULL;
+ $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);
+ }
+ | argdefs Tcomma declcore {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */ {
+ $$.loc.line = 0;
+ $$.loc.file = 0;
+ $$.nl = NULL;
+ $$.nn = 0;
+ }
+ ;
tupledef: Toparen typelist Tcparen
- {$$ = mktytuple($1->loc, $2.types, $2.ntypes);}
- ;
+ {$$ = mktytuple($1->loc, $2.types, $2.ntypes);}
+ ;
typelist: type {
- $$.types = NULL; $$.ntypes = 0;
- lappend(&$$.types, &$$.ntypes, $1);
- }
- | typelist Tcomma type
- {lappend(&$$.types, &$$.ntypes, $3);}
- ;
+ $$.types = NULL; $$.ntypes = 0;
+ lappend(&$$.types, &$$.ntypes, $1);
+ }
+ | typelist Tcomma type
+ {lappend(&$$.types, &$$.ntypes, $3);}
+ ;
structdef
- : Tstruct structbody Tendblk
- {$$ = mktystruct($1->loc, $2.nl, $2.nn);}
- ;
+ : Tstruct structbody Tendblk
+ {$$ = mktystruct($1->loc, $2.nl, $2.nn);}
+ ;
structbody
- : structent {
- if ($1) {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- }
- | structbody structent {
- if ($2)
- lappend(&$$.nl, &$$.nn, $2);
- }
- ;
+ : structent {
+ if ($1) {
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ }
+ | structbody structent {
+ if ($2)
+ lappend(&$$.nl, &$$.nn, $2);
+ }
+ ;
structent
- : declcore Tendln {$$ = $1;}
- | Tendln {$$ = NULL;}
- ;
+ : declcore Tendln {$$ = $1;}
+ | Tendln {$$ = NULL;}
+ ;
uniondef
- : Tunion unionbody Tendblk
- {$$ = mktyunion($1->loc, $2.ucl, $2.nucl);}
- ;
+ : Tunion unionbody Tendblk
+ {$$ = mktyunion($1->loc, $2.ucl, $2.nucl);}
+ ;
unionbody
- : unionelt {
- $$.ucl = NULL;
- $$.nucl = 0;
- if ($1)
- lappend(&$$.ucl, &$$.nucl, $1);
- }
- | unionbody unionelt {
- if ($2)
- lappend(&$$.ucl, &$$.nucl, $2);
- }
- ;
+ : unionelt {
+ $$.ucl = NULL;
+ $$.nucl = 0;
+ if ($1)
+ lappend(&$$.ucl, &$$.nucl, $1);
+ }
+ | unionbody unionelt {
+ if ($2)
+ lappend(&$$.ucl, &$$.nucl, $2);
+ }
+ ;
unionelt /* nb: the ucon union type gets filled in when we have context */
- : Ttick name type Tendln {$$ = mkucon($2->loc, $2, NULL, $3);}
- | Ttick name Tendln {$$ = mkucon($2->loc, $2, NULL, NULL);}
- | Tendln {$$ = NULL;}
- ;
+ : Ttick name type Tendln {$$ = mkucon($2->loc, $2, NULL, $3);}
+ | Ttick name Tendln {$$ = mkucon($2->loc, $2, NULL, NULL);}
+ | Tendln {$$ = NULL;}
+ ;
goto : Tgoto Tident {$$ = mkexpr($1->loc, Ojmp, mklbl($2->loc, $2->id), NULL);}
- ;
+ ;
retexpr : Tret expr {$$ = mkexpr($1->loc, Oret, $2, NULL);}
- | Tret {$$ = mkexpr($1->loc, Oret, NULL);}
- | expr
- ;
+ | Tret {$$ = mkexpr($1->loc, Oret, NULL);}
+ | expr
+ ;
optexpr : expr {$$ = $1;}
- | /* empty */ {$$ = NULL;}
- ;
+ | /* empty */ {$$ = NULL;}
+ ;
optexprln: exprln {$$ = $1;}
- | Tendln {$$ = NULL;}
- ;
+ | Tendln {$$ = NULL;}
+ ;
exprln : expr Tendln
- ;
+ ;
expr : asnexpr
- ;
+ ;
asnexpr : lorexpr asnop asnexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | lorexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | lorexpr
+ ;
asnop : Tasn
- | Taddeq /* += */
- | Tsubeq /* -= */
- | Tmuleq /* *= */
- | Tdiveq /* /= */
- | Tmodeq /* %= */
- | Tboreq /* |= */
- | Tbxoreq /* ^= */
- | Tbandeq /* &= */
- | Tbsleq /* <<= */
- | Tbsreq /* >>= */
- ;
+ | Taddeq /* += */
+ | Tsubeq /* -= */
+ | Tmuleq /* *= */
+ | Tdiveq /* /= */
+ | Tmodeq /* %= */
+ | Tboreq /* |= */
+ | Tbxoreq /* ^= */
+ | Tbandeq /* &= */
+ | Tbsleq /* <<= */
+ | Tbsreq /* >>= */
+ ;
lorexpr : lorexpr Tlor landexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | landexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | landexpr
+ ;
landexpr: landexpr Tland cmpexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | cmpexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | cmpexpr
+ ;
cmpexpr : cmpexpr cmpop castexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | unionexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | unionexpr
+ ;
cmpop : Teq | Tgt | Tlt | Tge | Tle | Tne ;
unionexpr
- : Ttick name unionexpr {$$ = mkexpr($1->loc, Oucon, $2, $3, NULL);}
- | Ttick name {$$ = mkexpr($1->loc, Oucon, $2, NULL);}
- | castexpr
- ;
+ : Ttick name unionexpr {$$ = mkexpr($1->loc, Oucon, $2, $3, NULL);}
+ | Ttick name {$$ = mkexpr($1->loc, Oucon, $2, NULL);}
+ | castexpr
+ ;
castexpr: castexpr Tcast Toparen type Tcparen {
- $$ = mkexpr($1->loc, Ocast, $1, NULL);
- $$->expr.type = $4;
- }
- | borexpr
- ;
+ $$ = mkexpr($1->loc, Ocast, $1, NULL);
+ $$->expr.type = $4;
+ }
+ | borexpr
+ ;
borexpr : borexpr Tbor bandexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | borexpr Tbxor bandexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | bandexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | borexpr Tbxor bandexpr
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | bandexpr
+ ;
bandexpr: bandexpr Tband addexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | addexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | addexpr
+ ;
addexpr : addexpr addop mulexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | mulexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | mulexpr
+ ;
addop : Tplus | Tminus ;
mulexpr : mulexpr mulop shiftexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | shiftexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | shiftexpr
+ ;
mulop : Tmul | Tdiv | Tmod
- ;
+ ;
shiftexpr
- : shiftexpr shiftop prefixexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | prefixexpr
- ;
+ : shiftexpr shiftop prefixexpr
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | prefixexpr
+ ;
shiftop : Tbsl | Tbsr;
prefixexpr
- : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
- | Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
- | Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
- | Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
- | Tbnot prefixexpr {$$ = mkexpr($1->loc, Obnot, $2, NULL);}
- | Tminus prefixexpr {$$ = mkexpr($1->loc, Oneg, $2, NULL);}
- | Tplus prefixexpr {$$ = $2;} /* positive is a nop */
- | postfixexpr
- ;
+ : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
+ | Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
+ | Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
+ | Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
+ | Tbnot prefixexpr {$$ = mkexpr($1->loc, Obnot, $2, NULL);}
+ | Tminus prefixexpr {$$ = mkexpr($1->loc, Oneg, $2, NULL);}
+ | Tplus prefixexpr {$$ = $2;} /* positive is a nop */
+ | postfixexpr
+ ;
postfixexpr
- : postfixexpr Tdot Tident
- {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
- | postfixexpr Tinc
- {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
- | postfixexpr Tdec
- {$$ = mkexpr($1->loc, Opostdec, $1, NULL);}
- | postfixexpr Tosqbrac expr Tcsqbrac
- {$$ = mkexpr($1->loc, Oidx, $1, $3, NULL);}
- | postfixexpr Tosqbrac optexpr Tcolon optexpr Tcsqbrac
- {$$ = mksliceexpr($1->loc, $1, $3, $5);}
- | postfixexpr Tderef
- {$$ = mkexpr($1->loc, Oderef, $1, NULL);}
- | postfixexpr Toparen arglist Tcparen
- {$$ = mkcall($1->loc, $1, $3.nl, $3.nn);}
- | atomicexpr
- ;
+ : postfixexpr Tdot Tident
+ {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
+ | postfixexpr Tinc
+ {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
+ | postfixexpr Tdec
+ {$$ = mkexpr($1->loc, Opostdec, $1, NULL);}
+ | postfixexpr Tosqbrac expr Tcsqbrac
+ {$$ = mkexpr($1->loc, Oidx, $1, $3, NULL);}
+ | postfixexpr Tosqbrac optexpr Tcolon optexpr Tcsqbrac
+ {$$ = mksliceexpr($1->loc, $1, $3, $5);}
+ | postfixexpr Tderef
+ {$$ = mkexpr($1->loc, Oderef, $1, NULL);}
+ | postfixexpr Toparen arglist Tcparen
+ {$$ = mkcall($1->loc, $1, $3.nl, $3.nn);}
+ | atomicexpr
+ ;
arglist : asnexpr
- {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
- | arglist Tcomma asnexpr
- {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */
- {$$.nl = NULL; $$.nn = 0;}
- ;
+ {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
+ | arglist Tcomma asnexpr
+ {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */
+ {$$.nl = NULL; $$.nn = 0;}
+ ;
atomicexpr
- : Tident
- {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
- | Tgap
- {$$ = mkexpr($1->loc, Ogap, NULL);}
- | Tidxlen
- {$$ = mkexpr($1->loc, Oidxlen, NULL);}
- | literal
- | Toparen expr Tcparen
- {$$ = $2;}
- | Tsizeof Toparen type Tcparen
- {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);}
- ;
+ : Tident
+ {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
+ | Tgap
+ {$$ = mkexpr($1->loc, Ogap, NULL);}
+ | Tidxlen
+ {$$ = mkexpr($1->loc, Oidxlen, NULL);}
+ | literal
+ | Toparen expr Tcparen
+ {$$ = $2;}
+ | Tsizeof Toparen type Tcparen
+ {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);}
+ ;
tupbody : tuphead tuprest
- {$$ = $2;
- linsert(&$$.nl, &$$.nn, 0, $1);}
- ;
+ {$$ = $2;
+ linsert(&$$.nl, &$$.nn, 0, $1);}
+ ;
tuphead : expr Tcomma {$$ = $1;}
- ;
+ ;
tuprest : /*empty */
- {$$.nl = NULL; $$.nn = 0;}
- | expr {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | tuprest Tcomma expr {lappend(&$$.nl, &$$.nn, $3);}
- ;
+ {$$.nl = NULL; $$.nn = 0;}
+ | expr {
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | tuprest Tcomma expr {lappend(&$$.nl, &$$.nn, $3);}
+ ;
literal : funclit {$$ = mkexpr($1->loc, Olit, $1, NULL);}
- | littok {$$ = mkexpr($1->loc, Olit, $1, NULL);}
- | seqlit {$$ = $1;}
- | tuplit {$$ = $1;}
- ;
+ | littok {$$ = mkexpr($1->loc, Olit, $1, NULL);}
+ | seqlit {$$ = $1;}
+ | tuplit {$$ = $1;}
+ ;
tuplit : Toparen tupbody Tcparen
- {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
+ {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
littok : Tstrlit {$$ = mkstr($1->loc, $1->strval);}
- | Tchrlit {$$ = mkchar($1->loc, $1->chrval);}
- | Tfloatlit {$$ = mkfloat($1->loc, $1->fltval);}
- | Tboollit {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
- | Tintlit {
- $$ = mkint($1->loc, $1->intval);
- if ($1->inttype)
- $$->lit.type = mktype($1->loc, $1->inttype);
- }
- ;
+ | Tchrlit {$$ = mkchar($1->loc, $1->chrval);}
+ | Tfloatlit {$$ = mkfloat($1->loc, $1->fltval);}
+ | Tboollit {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
+ | Tintlit {
+ $$ = mkint($1->loc, $1->intval);
+ if ($1->inttype)
+ $$->lit.type = mktype($1->loc, $1->inttype);
+ }
+ ;
funclit : Tobrace params Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
- | Tobrace params Tret type Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
- ;
+ {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
+ | Tobrace params Tret type Tendln blkbody Tcbrace
+ {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
+ ;
params : fnparam {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | params Tcomma fnparam {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */ {$$.nl = NULL; $$.nn = 0;}
- ;
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | params Tcomma fnparam {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */ {$$.nl = NULL; $$.nn = 0;}
+ ;
fnparam : declcore {$$ = $1;}
- | Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
- | Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
- ;
+ | Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
+ | Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
+ ;
seqlit : Tosqbrac arrayelts optcomma Tcsqbrac
- {$$ = mkexprl($1->loc, Oarr, $2.nl, $2.nn);}
- | Tosqbrac structelts optcomma Tcsqbrac
- {$$ = mkexprl($1->loc, Ostruct, $2.nl, $2.nn);}
- | Tosqbrac optendlns optcomma Tcsqbrac /* [] is the empty array. */
- {$$ = mkexprl($1->loc, Oarr, NULL, 0);}
- ;
+ {$$ = mkexprl($1->loc, Oarr, $2.nl, $2.nn);}
+ | Tosqbrac structelts optcomma Tcsqbrac
+ {$$ = mkexprl($1->loc, Ostruct, $2.nl, $2.nn);}
+ | Tosqbrac optendlns optcomma Tcsqbrac /* [] is the empty array. */
+ {$$ = mkexprl($1->loc, Oarr, NULL, 0);}
+ ;
optcomma: Tcomma optendlns
- | /* empty */
- ;
+ | /* empty */
+ ;
arrayelts
- : optendlns arrayelt {
- $$.nl = NULL;
- $$.nn = 0;
- if ($2->expr.idx)
- lappend(&$$.nl, &$$.nn, $2);
- else
- lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
- }
- | arrayelts Tcomma optendlns arrayelt {
- if ($4->expr.idx)
- lappend(&$$.nl, &$$.nn, $4);
- else
- lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
- }
- ;
+ : optendlns arrayelt {
+ $$.nl = NULL;
+ $$.nn = 0;
+ if ($2->expr.idx)
+ lappend(&$$.nl, &$$.nn, $2);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
+ }
+ | arrayelts Tcomma optendlns arrayelt {
+ if ($4->expr.idx)
+ lappend(&$$.nl, &$$.nn, $4);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
+ }
+ ;
arrayelt: expr optendlns {$$ = $1;}
- | expr Tcolon expr optendlns {
- $$ = mkidxinit($2->loc, $1, $3);
- }
- ;
+ | expr Tcolon expr optendlns {
+ $$ = mkidxinit($2->loc, $1, $3);
+ }
+ ;
structelts
- : optendlns structelt {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $2);
- }
- | structelts Tcomma optendlns structelt {
- lappend(&$$.nl, &$$.nn, $4);
- }
- ;
+ : optendlns structelt {
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $2);
+ }
+ | structelts Tcomma optendlns structelt {
+ lappend(&$$.nl, &$$.nn, $4);
+ }
+ ;
structelt: Tdot Tident Tasn expr optendlns {
- $$ = $4;
- mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
- }
- ;
+ $$ = $4;
+ mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
+ }
+ ;
optendlns : /* none */
- | optendlns Tendln
- ;
+ | optendlns Tendln
+ ;
stmt : goto
- | break
- | continue
- | retexpr
- | label
- | ifstmt
- | forstmt
- | whilestmt
- | matchstmt
- | /* empty */ {$$ = NULL;}
- ;
+ | break
+ | continue
+ | retexpr
+ | label
+ | ifstmt
+ | forstmt
+ | whilestmt
+ | matchstmt
+ | /* empty */ {$$ = NULL;}
+ ;
break : Tbreak
- {$$ = mkexpr($1->loc, Obreak, NULL);}
- ;
+ {$$ = mkexpr($1->loc, Obreak, NULL);}
+ ;
continue : Tcontinue
- {$$ = mkexpr($1->loc, Ocontinue, NULL);}
- ;
+ {$$ = mkexpr($1->loc, Ocontinue, NULL);}
+ ;
forstmt : Tfor optexprln optexprln optexprln block
- {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
- | Tfor expr Tin exprln block
- {$$ = mkiterstmt($1->loc, $2, $4, $5);}
- | Tfor decl Tendln optexprln optexprln block {
- //Node *init;
- if ($2.nn != 1)
- lfatal($1->loc, "only one declaration is allowed in for loop");
- $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
- putdcl($$->loopstmt.scope, $2.nl[0]);
- }
-
- ;
+ {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
+ | Tfor expr Tin exprln block
+ {$$ = mkiterstmt($1->loc, $2, $4, $5);}
+ | Tfor decl Tendln optexprln optexprln block {
+ //Node *init;
+ if ($2.nn != 1)
+ lfatal($1->loc, "only one declaration is allowed in for loop");
+ $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
+ putdcl($$->loopstmt.scope, $2.nl[0]);
+ }
+
+ ;
whilestmt
- : Twhile exprln block
- {$$ = mkloopstmt($1->loc, NULL, $2, NULL, $3);}
- ;
+ : Twhile exprln block
+ {$$ = mkloopstmt($1->loc, NULL, $2, NULL, $3);}
+ ;
ifstmt : Tif exprln blkbody elifs
- {$$ = mkifstmt($1->loc, $2, $3, $4);}
- ;
+ {$$ = mkifstmt($1->loc, $2, $3, $4);}
+ ;
elifs : Telif exprln blkbody elifs
- {$$ = mkifstmt($1->loc, $2, $3, $4);}
- | Telse block
- {$$ = $2;}
- | Tendblk
- {$$ = NULL;}
- ;
+ {$$ = mkifstmt($1->loc, $2, $3, $4);}
+ | Telse block
+ {$$ = $2;}
+ | Tendblk
+ {$$ = NULL;}
+ ;
matchstmt: Tmatch exprln optendlns Tbor matches Tendblk
- {$$ = mkmatchstmt($1->loc, $2, $5.nl, $5.nn);}
- ;
+ {$$ = mkmatchstmt($1->loc, $2, $5.nl, $5.nn);}
+ ;
matches : match {
- $$.nl = NULL;
- $$.nn = 0;
- if ($1)
- lappend(&$$.nl, &$$.nn, $1);
- }
- | matches Tbor match {
- if ($2)
- lappend(&$$.nl, &$$.nn, $3);
- }
- ;
+ $$.nl = NULL;
+ $$.nn = 0;
+ if ($1)
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | matches Tbor match {
+ if ($2)
+ lappend(&$$.nl, &$$.nn, $3);
+ }
+ ;
match : expr Tcolon blkbody Tendln {$$ = mkmatch($1->loc, $1, $3);}
- ;
+ ;
block : blkbody Tendblk
- ;
+ ;
blkbody : decl {
- size_t i;
- Node *n, *d, *u;
-
- $$ = mkblock($1.loc, mkstab(0));
- for (i = 0; i < $1.nn; i++) {
- d = $1.nl[i];
- putdcl($$->block.scope, d);
- if (!d->decl.init) {
- n = mkexpr(d->loc, Ovar, d->decl.name, NULL);
- u = mkexpr(n->loc, Oundef, n, NULL);
- n->expr.did = d->decl.did;
- lappend(&$$->block.stmts, &$$->block.nstmts, u);
- }
- lappend(&$$->block.stmts, &$$->block.nstmts, d);
- }
- }
- | stmt {
- $$ = mkblock(curloc, mkstab(0));
- if ($1)
- lappend(&$$->block.stmts, &$$->block.nstmts, $1);
- }
- | blkbody Tendln stmt {
- if ($3)
- lappend(&$1->block.stmts, &$1->block.nstmts, $3);
- $$ = $1;
- }
- | blkbody Tendln decl {
- size_t i;
- for (i = 0; i < $3.nn; i++){
- putdcl($$->block.scope, $3.nl[i]);
- lappend(&$1->block.stmts, &$1->block.nstmts, $3.nl[i]);
- }
- }
- ;
-
-label : Tcolon Tident
- {$$ = mklbl($2->loc, $2->id);}
- ;
+ size_t i;
+ Node *n, *d, *u;
+
+ $$ = mkblock($1.loc, mkstab(0));
+ for (i = 0; i < $1.nn; i++) {
+ d = $1.nl[i];
+ putdcl($$->block.scope, d);
+ if (!d->decl.init) {
+ n = mkexpr(d->loc, Ovar, d->decl.name, NULL);
+ u = mkexpr(n->loc, Oundef, n, NULL);
+ n->expr.did = d->decl.did;
+ lappend(&$$->block.stmts, &$$->block.nstmts, u);
+ }
+ lappend(&$$->block.stmts, &$$->block.nstmts, d);
+ }
+ }
+ | stmt {
+ $$ = mkblock(curloc, mkstab(0));
+ if ($1)
+ lappend(&$$->block.stmts, &$$->block.nstmts, $1);
+ }
+ | blkbody Tendln stmt {
+ if ($3)
+ lappend(&$1->block.stmts, &$1->block.nstmts, $3);
+ $$ = $1;
+ }
+ | blkbody Tendln decl {
+ size_t i;
+ for (i = 0; i < $3.nn; i++){
+ putdcl($$->block.scope, $3.nl[i]);
+ lappend(&$1->block.stmts, &$1->block.nstmts, $3.nl[i]);
+ }
+ }
+ ;
+
+label : Tcolon Tident {$$ = mklbl($2->loc, $2->id);}
+ ;
%%
static void setupinit(Node *n)
{
- char name[1024];
- char *p;
-
- bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
- p = name;
- while (*p) {
- if (!isalnum(*p) && *p != '_')
- *p = '$';
- p++;
- }
- n->decl.isinit = 1;
- n->decl.vis = Vishidden;
- n->decl.name->name.name = strdup(name);
+ char name[1024];
+ char *p;
+
+ bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
+ p = name;
+ while (*p) {
+ if (!isalnum(*p) && *p != '_')
+ *p = '$';
+ p++;
+ }
+ n->decl.isinit = 1;
+ n->decl.vis = Vishidden;
+ n->decl.name->name.name = strdup(name);
}
static void addtrait(Type *t, char *str)
{
- size_t i;
-
- for (i = 0; i < ntraittab; i++) {
- if (!strcmp(namestr(traittab[i]->name), str)) {
- settrait(t, traittab[i]);
- return;
- }
- }
- lfatal(t->loc, "Constraint %s does not exist", str);
+ size_t i;
+
+ for (i = 0; i < ntraittab; i++) {
+ if (!strcmp(namestr(traittab[i]->name), str)) {
+ settrait(t, traittab[i]);
+ return;
+ }
+ }
+ lfatal(t->loc, "Constraint %s does not exist", str);
}
static Node *mkpseudodecl(Srcloc l, Type *t)
{
- static int nextpseudoid;
- char buf[128];
+ static int nextpseudoid;
+ char buf[128];
- bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
- return mkdecl(l, mkname(l, buf), t);
+ bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
+ return mkdecl(l, mkname(l, buf), t);
}
static void setattrs(Node *dcl, char **attrs, size_t nattrs)
{
- size_t i;
-
- for (i = 0; i < nattrs; i++) {
- if (!strcmp(attrs[i], "extern"))
- dcl->decl.isextern = 1;
- else if (!strcmp(attrs[i], "$noret"))
- dcl->decl.isnoret = 1;
- else if (!strcmp(attrs[i], "pkglocal"))
- dcl->decl.ispkglocal = 1;
- }
+ size_t i;
+
+ for (i = 0; i < nattrs; i++) {
+ if (!strcmp(attrs[i], "extern"))
+ dcl->decl.isextern = 1;
+ else if (!strcmp(attrs[i], "$noret"))
+ dcl->decl.isnoret = 1;
+ else if (!strcmp(attrs[i], "pkglocal"))
+ dcl->decl.ispkglocal = 1;
+ }
}
static void installucons(Stab *st, Type *t)
{
- Type *b;
- size_t i;
-
- if (!t)
- return;
- b = tybase(t);
- switch (b->type) {
- case Tystruct:
- for (i = 0; i < b->nmemb; i++)
- installucons(st, b->sdecls[i]->decl.type);
- break;
- case Tyunion:
- for (i = 0; i < b->nmemb; i++) {
- b->udecls[i]->utype = b;
- b->udecls[i]->id = i;
- putucon(st, b->udecls[i]);
- }
- break;
- default:
- break;
- }
+ Type *b;
+ size_t i;
+
+ if (!t)
+ return;
+ b = tybase(t);
+ switch (b->type) {
+ case Tystruct:
+ for (i = 0; i < b->nmemb; i++)
+ installucons(st, b->sdecls[i]->decl.type);
+ break;
+ case Tyunion:
+ for (i = 0; i < b->nmemb; i++) {
+ b->udecls[i]->utype = b;
+ b->udecls[i]->id = i;
+ putucon(st, b->udecls[i]);
+ }
+ break;
+ default:
+ break;
+ }
}
static Op binop(int tt)
{
- Op o;
-
- o = Obad;
- switch (tt) {
- case Tplus: o = Oadd; break;
- case Tminus: o = Osub; break;
- case Tmul: o = Omul; break;
- case Tdiv: o = Odiv; break;
- case Tmod: o = Omod; break;
- case Tasn: o = Oasn; break;
- case Taddeq: o = Oaddeq; break;
- case Tsubeq: o = Osubeq; break;
- case Tmuleq: o = Omuleq; break;
- case Tdiveq: o = Odiveq; break;
- case Tmodeq: o = Omodeq; break;
- case Tboreq: o = Oboreq; break;
- case Tbxoreq: o = Obxoreq; break;
- case Tbandeq: o = Obandeq; break;
- case Tbsleq: o = Obsleq; break;
- case Tbsreq: o = Obsreq; break;
- case Tbor: o = Obor; break;
- case Tbxor: o = Obxor; break;
- case Tband: o = Oband; break;
- case Tbsl: o = Obsl; break;
- case Tbsr: o = Obsr; break;
- case Teq: o = Oeq; break;
- case Tgt: o = Ogt; break;
- case Tlt: o = Olt; break;
- case Tge: o = Oge; break;
- case Tle: o = Ole; break;
- case Tne: o = One; break;
- case Tlor: o = Olor; break;
- case Tland: o = Oland; break;
- default:
- die("Unimplemented binop\n");
- break;
- }
- return o;
+ Op o;
+
+ o = Obad;
+ switch (tt) {
+ case Tplus: o = Oadd; break;
+ case Tminus: o = Osub; break;
+ case Tmul: o = Omul; break;
+ case Tdiv: o = Odiv; break;
+ case Tmod: o = Omod; break;
+ case Tasn: o = Oasn; break;
+ case Taddeq: o = Oaddeq; break;
+ case Tsubeq: o = Osubeq; break;
+ case Tmuleq: o = Omuleq; break;
+ case Tdiveq: o = Odiveq; break;
+ case Tmodeq: o = Omodeq; break;
+ case Tboreq: o = Oboreq; break;
+ case Tbxoreq: o = Obxoreq; break;
+ case Tbandeq: o = Obandeq; break;
+ case Tbsleq: o = Obsleq; break;
+ case Tbsreq: o = Obsreq; break;
+ case Tbor: o = Obor; break;
+ case Tbxor: o = Obxor; break;
+ case Tband: o = Oband; break;
+ case Tbsl: o = Obsl; break;
+ case Tbsr: o = Obsr; break;
+ case Teq: o = Oeq; break;
+ case Tgt: o = Ogt; break;
+ case Tlt: o = Olt; break;
+ case Tge: o = Oge; break;
+ case Tle: o = Ole; break;
+ case Tne: o = One; break;
+ case Tlor: o = Olor; break;
+ case Tland: o = Oland; break;
+ default:
+ die("Unimplemented binop\n");
+ break;
+ }
+ return o;
}
diff --git a/parse/htab.c b/parse/htab.c
index 1bdad3a..a8f3633 100644
--- a/parse/htab.c
+++ b/parse/htab.c
@@ -15,45 +15,45 @@
* hash collisions. */
Htab *mkht(ulong (*hash)(void *key), int (*cmp)(void *k1, void *k2))
{
- Htab *ht;
-
- ht = xalloc(sizeof(Htab));
- ht->nelt = 0;
- ht->ndead = 0;
- ht->sz = Initsz;
- ht->hash = hash;
- ht->cmp = cmp;
- ht->keys = zalloc(Initsz*sizeof(void*));
- ht->vals = zalloc(Initsz*sizeof(void*));
- ht->hashes = zalloc(Initsz*sizeof(void*));
- ht->dead = zalloc(Initsz*sizeof(char));
-
- return ht;
+ Htab *ht;
+
+ ht = xalloc(sizeof(Htab));
+ ht->nelt = 0;
+ ht->ndead = 0;
+ ht->sz = Initsz;
+ ht->hash = hash;
+ ht->cmp = cmp;
+ ht->keys = zalloc(Initsz * sizeof(void *));
+ ht->vals = zalloc(Initsz * sizeof(void *));
+ ht->hashes = zalloc(Initsz * sizeof(void *));
+ ht->dead = zalloc(Initsz * sizeof(char));
+
+ return ht;
}
/* Frees a hash table. Passing this function
* NULL is a no-op. */
void htfree(Htab *ht)
{
- if (!ht)
- return;
- free(ht->keys);
- free(ht->vals);
- free(ht->hashes);
- free(ht->dead);
- free(ht);
+ if (!ht)
+ return;
+ free(ht->keys);
+ free(ht->vals);
+ free(ht->hashes);
+ free(ht->dead);
+ free(ht);
}
/* Offsets the hash so that '0' can be
* used as a 'no valid value */
static ulong hash(Htab *ht, void *k)
{
- ulong h;
- h = ht->hash(k);
- if (h == 0)
- return 1;
- else
- return h;
+ ulong h;
+ h = ht->hash(k);
+ if (h == 0)
+ return 1;
+ else
+ return h;
}
/* Resizes the hash table by copying all
@@ -61,35 +61,35 @@ static ulong hash(Htab *ht, void *k)
* new table. */
static void grow(Htab *ht, int sz)
{
- void **oldk;
- void **oldv;
- ulong *oldh;
- char *oldd;
- int oldsz;
- int i;
-
- oldk = ht->keys;
- oldv = ht->vals;
- oldh = ht->hashes;
- oldd = ht->dead;
- oldsz = ht->sz;
-
- ht->nelt = 0;
- ht->ndead = 0;
- ht->sz = sz;
- ht->keys = zalloc(sz*sizeof(void*));
- ht->vals = zalloc(sz*sizeof(void*));
- ht->hashes = zalloc(sz*sizeof(void*));
- ht->dead = zalloc(sz*sizeof(void*));
-
- for (i = 0; i < oldsz; i++)
- if (oldh[i] && !oldd[i])
- htput(ht, oldk[i], oldv[i]);
-
- free(oldh);
- free(oldk);
- free(oldv);
- free(oldd);
+ void **oldk;
+ void **oldv;
+ ulong *oldh;
+ char *oldd;
+ int oldsz;
+ int i;
+
+ oldk = ht->keys;
+ oldv = ht->vals;
+ oldh = ht->hashes;
+ oldd = ht->dead;
+ oldsz = ht->sz;
+
+ ht->nelt = 0;
+ ht->ndead = 0;
+ ht->sz = sz;
+ ht->keys = zalloc(sz * sizeof(void *));
+ ht->vals = zalloc(sz * sizeof(void *));
+ ht->hashes = zalloc(sz * sizeof(void *));
+ ht->dead = zalloc(sz * sizeof(void *));
+
+ for (i = 0; i < oldsz; i++)
+ if (oldh[i] && !oldd[i])
+ htput(ht, oldk[i], oldv[i]);
+
+ free(oldh);
+ free(oldk);
+ free(oldv);
+ free(oldd);
}
/* Inserts 'k' into the hash table, possibly
@@ -97,62 +97,62 @@ static void grow(Htab *ht, int sz)
* as equal. */
int htput(Htab *ht, void *k, void *v)
{
- int i;
- ulong h;
- int di;
-
- di = 0;
- h = hash(ht, k);
- i = h & (ht->sz - 1);
- while (ht->hashes[i] && !ht->dead[i]) {
- /* second insertion overwrites first. nb, we shouldn't touch the
- * keys for dead values */
- if (ht->hashes[i] == h) {
- if (ht->dead[i])
- break;
- else if (ht->cmp(ht->keys[i], k))
- goto conflicted;
- }
- di++;
- i = (h + di) & (ht->sz - 1);
- }
- ht->nelt++;
+ int i;
+ ulong h;
+ int di;
+
+ di = 0;
+ h = hash(ht, k);
+ i = h & (ht->sz - 1);
+ while (ht->hashes[i] && !ht->dead[i]) {
+ /* second insertion overwrites first. nb, we shouldn't touch the
+ * keys for dead values */
+ if (ht->hashes[i] == h) {
+ if (ht->dead[i])
+ break;
+ else if (ht->cmp(ht->keys[i], k))
+ goto conflicted;
+ }
+ di++;
+ i = (h + di) & (ht->sz - 1);
+ }
+ ht->nelt++;
conflicted:
- if (ht->dead[i])
- ht->ndead--;
- ht->hashes[i] = h;
- ht->keys[i] = k;
- ht->vals[i] = v;
- ht->dead[i] = 0;
-
- if (ht->sz < ht->nelt * 2)
- grow(ht, ht->sz * 2);
- if (ht->sz < ht->ndead * 4)
- grow(ht, ht->sz);
- return 1;
+ if (ht->dead[i])
+ ht->ndead--;
+ ht->hashes[i] = h;
+ ht->keys[i] = k;
+ ht->vals[i] = v;
+ ht->dead[i] = 0;
+
+ if (ht->sz < ht->nelt * 2)
+ grow(ht, ht->sz * 2);
+ if (ht->sz < ht->ndead * 4)
+ grow(ht, ht->sz);
+ return 1;
}
/* Finds the index that we would insert
* the key into */
static ssize_t htidx(Htab *ht, void *k)
{
- ssize_t i;
- ulong h;
- int di;
-
- di = 0;
- h = hash(ht, k);
- i = h & (ht->sz - 1);
- while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) {
+ ssize_t i;
+ ulong h;
+ int di;
+
+ di = 0;
+ h = hash(ht, k);
+ i = h & (ht->sz - 1);
+ while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) {
searchmore:
- di++;
- i = (h + di) & (ht->sz - 1);
- }
- if (!ht->hashes[i])
- return -1;
- if ((ht->hashes[i] == h && ht->dead[i]) || !ht->cmp(ht->keys[i], k))
- goto searchmore; /* collision */
- return i;
+ di++;
+ i = (h + di) & (ht->sz - 1);
+ }
+ if (!ht->hashes[i])
+ return -1;
+ if ((ht->hashes[i] == h && ht->dead[i]) || !ht->cmp(ht->keys[i], k))
+ goto searchmore; /* collision */
+ return i;
}
/* Looks up a key, returning NULL if
@@ -162,35 +162,31 @@ searchmore:
* not there */
void *htget(Htab *ht, void *k)
{
- ssize_t i;
+ ssize_t i;
- i = htidx(ht, k);
- if (i < 0)
- return NULL;
- else
- return ht->vals[i];
+ i = htidx(ht, k);
+ if (i < 0)
+ return NULL;
+ else
+ return ht->vals[i];
}
void htdel(Htab *ht, void *k)
{
- ssize_t i;
-
- i = htidx(ht, k);
- if (i < 0)
- return;
- assert(!ht->dead[i]);
- assert(ht->hashes[i]);
- ht->dead[i] = 1;
- ht->nelt--;
- ht->ndead++;
+ ssize_t i;
+
+ i = htidx(ht, k);
+ if (i < 0)
+ return;
+ assert(!ht->dead[i]);
+ assert(ht->hashes[i]);
+ ht->dead[i] = 1;
+ ht->nelt--;
+ ht->ndead++;
}
-
/* Tests for 'k's presence in 'ht' */
-int hthas(Htab *ht, void *k)
-{
- return htidx(ht, k) >= 0;
-}
+int hthas(Htab *ht, void *k) { return htidx(ht, k) >= 0; }
/* Returns a list of all keys in the hash
* table, storing the size of the returned
@@ -199,103 +195,94 @@ int hthas(Htab *ht, void *k)
* job of the caller to free it */
void **htkeys(Htab *ht, size_t *nkeys)
{
- void **k;
- size_t i, j;
-
- j = 0;
- k = xalloc(sizeof(void*)*ht->nelt);
- for (i = 0; i < ht->sz; i++)
- if (ht->hashes[i] && !ht->dead[i])
- k[j++] = ht->keys[i];
- *nkeys = ht->nelt;
- return k;
+ void **k;
+ size_t i, j;
+
+ j = 0;
+ k = xalloc(sizeof(void *) * ht->nelt);
+ for (i = 0; i < ht->sz; i++)
+ if (ht->hashes[i] && !ht->dead[i])
+ k[j++] = ht->keys[i];
+ *nkeys = ht->nelt;
+ return k;
}
ulong strhash(void *_s)
{
- char *s;
- ulong h;
- ulong g;
+ char *s;
+ ulong h;
+ ulong g;
- s = _s;
- h = 0;
- while (s && *s) {
- h = ((h << 4) + *s++);
+ s = _s;
+ h = 0;
+ while (s && *s) {
+ h = ((h << 4) + *s++);
- if ((g = (h & 0xF0000000)))
- h ^= (g >> 24);
+ if ((g = (h & 0xF0000000)))
+ h ^= (g >> 24);
- h &= ~g;
- }
- return h;
+ h &= ~g;
+ }
+ return h;
}
int streq(void *a, void *b)
{
- if (a == b)
- return 1;
- if (a == NULL || b == NULL)
- return 0;
- return !strcmp(a, b);
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ return !strcmp(a, b);
}
ulong strlithash(void *_s)
{
- Str *s;
- ulong h, g, i;
+ Str *s;
+ ulong h, g, i;
- s = _s;
- h = 0;
- for (i = 0; i < s->len; i++) {
- h = ((h << 4) + s->buf[i]);
+ s = _s;
+ h = 0;
+ for (i = 0; i < s->len; i++) {
+ h = ((h << 4) + s->buf[i]);
- if ((g = (h & 0xF0000000)))
- h ^= (g >> 24);
+ if ((g = (h & 0xF0000000)))
+ h ^= (g >> 24);
- h &= ~g;
- }
- return h;
+ h &= ~g;
+ }
+ return h;
}
int strliteq(void *_a, void *_b)
{
- Str *a, *b;
-
- a = _a;
- b = _b;
- if (a == b)
- return 1;
- if (a == NULL || b == NULL)
- return 0;
- if (a->len != b->len)
- return 0;
- return !memcmp(a, b, a->len);
+ Str *a, *b;
+
+ a = _a;
+ b = _b;
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ if (a->len != b->len)
+ return 0;
+ return !memcmp(a, b, a->len);
}
-ulong ptrhash(void *key)
-{
- return inthash((uintptr_t)key);
-}
+ulong ptrhash(void *key) { return inthash((uintptr_t)key); }
ulong inthash(uint64_t key)
{
- uintptr_t h;
-
- h = (uintptr_t) key;
- h *= 357913941;
- h ^= h << 24;
- h += ~357913941;
- h ^= h >> 31;
- h ^= h << 31;
- return h;
+ uintptr_t h;
+
+ h = (uintptr_t)key;
+ h *= 357913941;
+ h ^= h << 24;
+ h += ~357913941;
+ h ^= h >> 31;
+ h ^= h << 31;
+ return h;
}
-int inteq(uint64_t a, uint64_t b)
-{
- return a == b;
-}
+int inteq(uint64_t a, uint64_t b) { return a == b; }
-int ptreq(void *a, void *b)
-{
- return a == b;
-}
+int ptreq(void *a, void *b) { return a == b; }
diff --git a/parse/infer.c b/parse/infer.c
index 7f5de51..3b5e413 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -16,36 +16,36 @@
typedef struct Inferstate Inferstate;
struct Inferstate {
- int ingeneric;
- int inaggr;
- int innamed;
- int sawret;
- int indentdepth;
- Type *ret;
-
- /* bound by patterns turn into decls in the action block */
- Node **binds;
- size_t nbinds;
- /* nodes that need post-inference checking/unification */
- Node **postcheck;
- size_t npostcheck;
- Stab **postcheckscope;
- size_t npostcheckscope;
- /* the type params bound at the current point */
- Htab **tybindings;
- size_t ntybindings;
- /* generic declarations to be specialized */
- Node **genericdecls;
- size_t ngenericdecls;
- /* delayed unification -- we fall back to these types in a post pass if we
- * haven't unifed to something more specific */
- Htab *delayed;
- /* the nodes that we've specialized them to, and the scopes they
- * appear in */
- Node **specializations;
- size_t nspecializations;
- Stab **specializationscope;
- size_t nspecializationscope;
+ int ingeneric;
+ int inaggr;
+ int innamed;
+ int sawret;
+ int indentdepth;
+ Type *ret;
+
+ /* bound by patterns turn into decls in the action block */
+ Node **binds;
+ size_t nbinds;
+ /* nodes that need post-inference checking/unification */
+ Node **postcheck;
+ size_t npostcheck;
+ Stab **postcheckscope;
+ size_t npostcheckscope;
+ /* the type params bound at the current point */
+ Htab **tybindings;
+ size_t ntybindings;
+ /* generic declarations to be specialized */
+ Node **genericdecls;
+ size_t ngenericdecls;
+ /* delayed unification -- we fall back to these types in a post pass if we
+ * haven't unifed to something more specific */
+ Htab *delayed;
+ /* the nodes that we've specialized them to, and the scopes they
+ * appear in */
+ Node **specializations;
+ size_t nspecializations;
+ Stab **specializationscope;
+ size_t nspecializationscope;
};
static void infernode(Inferstate *st, Node **np, Type *ret, int *sawret);
@@ -62,211 +62,195 @@ static Type *tf(Inferstate *st, Type *t);
static void ctxstrcall(char *buf, size_t sz, Inferstate *st, Node *n)
{
- char *p, *end, *sep, *t;
- size_t nargs, i;
- Node **args;
- Type *et;
-
- args = n->expr.args;
- nargs = n->expr.nargs;
- p = buf;
- end = buf + sz;
- sep = "";
-
- if (exprop(args[0]) == Ovar)
- p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
- else
- p += bprintf(p, end - p, "<e>(");
- for (i = 1; i < nargs; i++) {
- et = tyfix(st, NULL, exprtype(args[i]), 1);
- if (et != NULL)
- t = tystr(et);
- else
- t = strdup("?");
-
- if (exprop(args[i]) == Ovar)
- p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
- else
- p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
- sep = ", ";
- free(t);
- }
- if (exprtype(args[0])->nsub)
- t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
- else
- t = strdup("unknown");
- p += bprintf(p, end - p, "): %s", t);
- free(t);
+ char *p, *end, *sep, *t;
+ size_t nargs, i;
+ Node **args;
+ Type *et;
+
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ p = buf;
+ end = buf + sz;
+ sep = "";
+
+ if (exprop(args[0]) == Ovar)
+ p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
+ else
+ p += bprintf(p, end - p, "<e>(");
+ for (i = 1; i < nargs; i++) {
+ et = tyfix(st, NULL, exprtype(args[i]), 1);
+ if (et != NULL)
+ t = tystr(et);
+ else
+ t = strdup("?");
+
+ if (exprop(args[i]) == Ovar)
+ p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
+ else
+ p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
+ sep = ", ";
+ free(t);
+ }
+ if (exprtype(args[0])->nsub)
+ t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
+ else
+ t = strdup("unknown");
+ p += bprintf(p, end - p, "): %s", t);
+ free(t);
}
static char *nodetystr(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- t = NULL;
- if (n->type == Nexpr && exprtype(n) != NULL)
- t = tyfix(st, NULL, exprtype(n), 1);
- else if (n->type == Ndecl && decltype(n) != NULL)
- t = tyfix(st, NULL, decltype(n), 1);
+ t = NULL;
+ if (n->type == Nexpr && exprtype(n) != NULL)
+ t = tyfix(st, NULL, exprtype(n), 1);
+ else if (n->type == Ndecl && decltype(n) != NULL)
+ t = tyfix(st, NULL, decltype(n), 1);
- if (t && tybase(t)->type != Tyvar)
- return tystr(t);
- else
- return strdup("unknown");
+ if (t && tybase(t)->type != Tyvar)
+ return tystr(t);
+ else
+ return strdup("unknown");
}
/* Tries to give a good string describing the context
* for the sake of error messages. */
static char *ctxstr(Inferstate *st, Node *n)
{
- char *t, *t1, *t2, *t3;
- char *s, *d;
- size_t nargs;
- Node **args;
- char buf[512];
-
- switch (n->type) {
- default:
- s = strdup(nodestr[n->type]);
- break;
- case Ndecl:
- d = declname(n);
- t = nodetystr(st, n);
- bprintf(buf, sizeof buf, "%s:%s", d, t);
- s = strdup(buf);
- free(t);
- break;
- case Nname:
- s = strdup(namestr(n));
- break;
- case Nexpr:
- args = n->expr.args;
- nargs = n->expr.nargs;
- t1 = NULL;
- t2 = NULL;
- t3 = NULL;
- if (exprop(n) == Ovar)
- d = namestr(args[0]);
- else
- d = opstr[exprop(n)];
- t = nodetystr(st, n);
- if (nargs >= 1)
- t1 = nodetystr(st, args[0]);
- if (nargs >= 2)
- t2 = nodetystr(st, args[1]);
- if (nargs >= 3)
- t3 = nodetystr(st, args[2]);
- switch (opclass[exprop(n)]) {
- case OTbin:
- bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
- break;
- case OTpre:
- bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]);
- break;
- case OTpost:
- bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]);
- break;
- case OTzarg:
- bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]);
- break;
- case OTmisc:
- switch (exprop(n)) {
- case Ovar:
- bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t);
- break;
- case Ocall:
- ctxstrcall(buf, sizeof buf, st, n);
- break;
- case Oidx:
- if (exprop(args[0]) == Ovar)
- bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
- else
- bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
- break;
- case Oslice:
- if (exprop(args[0]) == Ovar)
- bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
- else
- bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
- break;
- case Omemb:
- bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
- break;
- default:
- bprintf(buf, sizeof buf, "%s:%s", d, t);
- break;
- }
- break;
- default:
- bprintf(buf, sizeof buf, "%s", d);
- break;
- }
- free(t);
- free(t1);
- free(t2);
- free(t3);
- s = strdup(buf);
- break;
- }
- return s;
+ char *t, *t1, *t2, *t3;
+ char *s, *d;
+ size_t nargs;
+ Node **args;
+ char buf[512];
+
+ switch (n->type) {
+ default: s = strdup(nodestr[n->type]); break;
+ case Ndecl:
+ d = declname(n);
+ t = nodetystr(st, n);
+ bprintf(buf, sizeof buf, "%s:%s", d, t);
+ s = strdup(buf);
+ free(t);
+ break;
+ case Nname: s = strdup(namestr(n)); break;
+ case Nexpr:
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ t1 = NULL;
+ t2 = NULL;
+ t3 = NULL;
+ if (exprop(n) == Ovar)
+ d = namestr(args[0]);
+ else
+ d = opstr[exprop(n)];
+ t = nodetystr(st, n);
+ if (nargs >= 1)
+ t1 = nodetystr(st, args[0]);
+ if (nargs >= 2)
+ t2 = nodetystr(st, args[1]);
+ if (nargs >= 3)
+ t3 = nodetystr(st, args[2]);
+
+ switch (opclass[exprop(n)]) {
+ case OTpre: bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]); break;
+ case OTpost: bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]); break;
+ case OTzarg: bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]); break;
+ case OTmisc:
+ case OTbin:
+ bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
+ break;
+ switch (exprop(n)) {
+ case Ovar: bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t); break;
+ case Ocall: ctxstrcall(buf, sizeof buf, st, n); break;
+ case Oidx:
+ if (exprop(args[0]) == Ovar)
+ bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
+ else
+ bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
+ break;
+ case Oslice:
+ if (exprop(args[0]) == Ovar)
+ bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
+ else
+ bprintf( buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
+ break;
+ case Omemb:
+ bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
+ break;
+ default:
+ bprintf(buf, sizeof buf, "%s:%s", d, t);
+ break;
+ }
+ break;
+ default: bprintf(buf, sizeof buf, "%s", d); break;
+ }
+ free(t);
+ free(t1);
+ free(t2);
+ free(t3);
+ s = strdup(buf);
+ break;
+ }
+ return s;
}
static void addspecialization(Inferstate *st, Node *n, Stab *stab)
{
- Node *dcl;
+ Node *dcl;
- dcl = decls[n->expr.did];
- lappend(&st->specializationscope, &st->nspecializationscope, stab);
- lappend(&st->specializations, &st->nspecializations, n);
- lappend(&st->genericdecls, &st->ngenericdecls, dcl);
+ dcl = decls[n->expr.did];
+ lappend(&st->specializationscope, &st->nspecializationscope, stab);
+ lappend(&st->specializations, &st->nspecializations, n);
+ lappend(&st->genericdecls, &st->ngenericdecls, dcl);
}
static void delayedcheck(Inferstate *st, Node *n, Stab *s)
{
- lappend(&st->postcheck, &st->npostcheck, n);
- lappend(&st->postcheckscope, &st->npostcheckscope, s);
+ lappend(&st->postcheck, &st->npostcheck, n);
+ lappend(&st->postcheckscope, &st->npostcheckscope, s);
}
static void typeerror(Inferstate *st, Type *a, Type *b, Node *ctx, char *msg)
{
- char *t1, *t2, *c;
+ char *t1, *t2, *c;
- t1 = tystr(tyfix(st, NULL, a, 1));
- t2 = tystr(tyfix(st, NULL, b, 1));
- c = ctxstr(st, ctx);
- if (msg)
- fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
- else
- fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
- free(t1);
- free(t2);
- free(c);
+ t1 = tystr(tyfix(st, NULL, a, 1));
+ t2 = tystr(tyfix(st, NULL, b, 1));
+ c = ctxstr(st, ctx);
+ if (msg)
+ fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
+ else
+ fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
+ free(t1);
+ free(t2);
+ free(c);
}
-
/* Set a scope's enclosing scope up correctly.
* We don't do this in the parser for some reason. */
static void setsuper(Stab *st, Stab *super)
{
- Stab *s;
+ Stab *s;
- /* verify that we don't accidentally create loops */
- for (s = super; s; s = s->super)
- assert(s->super != st);
- st->super = super;
+ /* verify that we don't accidentally create loops */
+ for (s = super; s; s = s->super)
+ assert(s->super != st);
+ st->super = super;
}
/* If the current environment binds a type,
* we return true */
static int isbound(Inferstate *st, Type *t)
{
- ssize_t i;
+ ssize_t i;
- for (i = st->ntybindings - 1; i >= 0; i--) {
- if (htget(st->tybindings[i], t->pname))
- return 1;
- }
- return 0;
+ for (i = st->ntybindings - 1; i >= 0; i--) {
+ if (htget(st->tybindings[i], t->pname))
+ return 1;
+ }
+ return 0;
}
/* Checks if a type that directly contains itself.
@@ -275,451 +259,452 @@ static int isbound(Inferstate *st, Type *t)
* would lead to a value of infinite size */
static int tyinfinite(Inferstate *st, Type *t, Type *sub)
{
- size_t i;
-
- assert(t != NULL);
- if (t == sub) /* FIXME: is this actually right? */
- return 1;
- /* if we're on the first iteration, the subtype is the type
- * itself. The assignment must come after the equality check
- * for obvious reasons. */
- if (!sub)
- sub = t;
-
- switch (sub->type) {
- case Tystruct:
- for (i = 0; i < sub->nmemb; i++)
- if (tyinfinite(st, t, decltype(sub->sdecls[i])))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < sub->nmemb; i++) {
- if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
- return 1;
- }
- break;
-
- case Typtr:
- case Tyslice:
- return 0;
- default:
- for (i = 0; i < sub->nsub; i++)
- if (tyinfinite(st, t, sub->sub[i]))
- return 1;
- break;
- }
- return 0;
+ size_t i;
+
+ assert(t != NULL);
+ if (t == sub) /* FIXME: is this actually right? */
+ return 1;
+ /* if we're on the first iteration, the subtype is the type
+ * itself. The assignment must come after the equality check
+ * for obvious reasons. */
+ if (!sub)
+ sub = t;
+
+ switch (sub->type) {
+ case Tystruct:
+ for (i = 0; i < sub->nmemb; i++)
+ if (tyinfinite(st, t, decltype(sub->sdecls[i])))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < sub->nmemb; i++) {
+ if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
+ return 1;
+ }
+ break;
+ case Typtr:
+ case Tyslice: return 0;
+ default:
+ for (i = 0; i < sub->nsub; i++)
+ if (tyinfinite(st, t, sub->sub[i]))
+ return 1;
+ break;
+ }
+ return 0;
}
-
static int needfreshenrec(Inferstate *st, Type *t, Bitset *visited)
{
- size_t i;
-
- if (bshas(visited, t->tid))
- return 0;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram: return 1;
- case Tygeneric: return 1;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- if (needfreshenrec(st, t->arg[i], visited))
- return 1;
- return needfreshenrec(st, t->sub[0], visited);
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- if (needfreshenrec(st, decltype(t->sdecls[i]), visited))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype && needfreshenrec(st, t->udecls[i]->etype, visited))
- return 1;
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- if (needfreshenrec(st, t->sub[i], visited))
- return 1;
- break;
- }
- return 0;
+ size_t i;
+
+ if (bshas(visited, t->tid))
+ return 0;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram: return 1;
+ case Tygeneric: return 1;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ if (needfreshenrec(st, t->arg[i], visited))
+ return 1;
+ return needfreshenrec(st, t->sub[0], visited);
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ if (needfreshenrec(st, decltype(t->sdecls[i]), visited))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype && needfreshenrec(st, t->udecls[i]->etype, visited))
+ return 1;
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ if (needfreshenrec(st, t->sub[i], visited))
+ return 1;
+ break;
+ }
+ return 0;
}
static int needfreshen(Inferstate *st, Type *t)
{
- Bitset *visited;
- int ret;
+ Bitset *visited;
+ int ret;
- visited = mkbs();
- ret = needfreshenrec(st, t, visited);
- bsfree(visited);
- return ret;
+ visited = mkbs();
+ ret = needfreshenrec(st, t, visited);
+ bsfree(visited);
+ return ret;
}
/* Freshens the type of a declaration. */
static Type *tyfreshen(Inferstate *st, Htab *subst, Type *t)
{
- char *from, *to;
-
- if (!needfreshen(st, t)) {
- if (debugopt['u'])
- indentf(st->indentdepth, "%s isn't generic: skipping freshen\n", tystr(t));
- return t;
- }
-
- from = tystr(t);
- tybind(st, t);
- if (!subst) {
- subst = mkht(tyhash, tyeq);
- t = tyspecialize(t, subst, st->delayed);
- htfree(subst);
- } else {
- t = tyspecialize(t, subst, st->delayed);
- }
- tyunbind(st, t);
- if (debugopt['u']) {
- to = tystr(t);
- indentf(st->indentdepth, "Freshen %s => %s\n", from, to);
- free(from);
- free(to);
- }
-
- return t;
+ char *from, *to;
+
+ if (!needfreshen(st, t)) {
+ if (debugopt['u'])
+ indentf(st->indentdepth, "%s isn't generic: skipping freshen\n", tystr(t));
+ return t;
+ }
+
+ from = tystr(t);
+ tybind(st, t);
+ if (!subst) {
+ subst = mkht(tyhash, tyeq);
+ t = tyspecialize(t, subst, st->delayed);
+ htfree(subst);
+ }
+ else {
+ t = tyspecialize(t, subst, st->delayed);
+ }
+ tyunbind(st, t);
+ if (debugopt['u']) {
+ to = tystr(t);
+ indentf(st->indentdepth, "Freshen %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
+
+ return t;
}
/* Resolves a type and all it's subtypes recursively.*/
static void tyresolve(Inferstate *st, Type *t)
{
- size_t i;
- Type *base;
-
- if (t->resolved)
- return;
- /* type resolution should never throw errors about non-generics
- * showing up within a generic type, so we push and pop a generic
- * around resolution */
- st->ingeneric++;
- t->resolved = 1;
- /* Walk through aggregate type members */
- if (t->type == Tystruct) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++)
- infernode(st, &t->sdecls[i], NULL, NULL);
- st->inaggr--;
- } else if (t->type == Tyunion) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++) {
- t->udecls[i]->utype = t;
- t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
- if (t->udecls[i]->etype) {
- tyresolve(st, t->udecls[i]->etype);
- t->udecls[i]->etype = tf(st, t->udecls[i]->etype);
- }
- }
- st->inaggr--;
- } else if (t->type == Tyarray) {
- if (!st->inaggr && !t->asize)
- lfatal(t->loc, "unsized array type outside of struct");
- infernode(st, &t->asize, NULL, NULL);
- } else if (t->type == Typaram && st->innamed) {
- if (!isbound(st, t))
- lfatal(t->loc, "type parameter %s is undefined in generic context", tystr(t));
- }
-
- if (t->type == Tyname || t->type == Tygeneric) {
- tybind(st, t);
- st->innamed++;
- }
- for (i = 0; i < t->nsub; i++)
- t->sub[i] = tf(st, t->sub[i]);
- base = tybase(t);
- /* no-ops if base == t */
- if (t->traits)
- bsunion(t->traits, base->traits);
- else
- t->traits = bsdup(base->traits);
- if (tyinfinite(st, t, NULL))
- lfatal(t->loc, "type %s includes itself", tystr(t));
- st->ingeneric--;
- if (t->type == Tyname || t->type == Tygeneric) {
- tyunbind(st, t);
- st->innamed--;
- }
+ size_t i;
+ Type *base;
+
+ if (t->resolved)
+ return;
+ /* type resolution should never throw errors about non-generics
+ * showing up within a generic type, so we push and pop a generic
+ * around resolution */
+ st->ingeneric++;
+ t->resolved = 1;
+ /* Walk through aggregate type members */
+ if (t->type == Tystruct) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++)
+ infernode(st, &t->sdecls[i], NULL, NULL);
+ st->inaggr--;
+ }
+ else if (t->type == Tyunion) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++) {
+ t->udecls[i]->utype = t;
+ t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
+ if (t->udecls[i]->etype) {
+ tyresolve(st, t->udecls[i]->etype);
+ t->udecls[i]->etype = tf(st, t->udecls[i]->etype);
+ }
+ }
+ st->inaggr--;
+ }
+ else if (t->type == Tyarray) {
+ if (!st->inaggr && !t->asize)
+ lfatal(t->loc, "unsized array type outside of struct");
+ infernode(st, &t->asize, NULL, NULL);
+ }
+ else if (t->type == Typaram && st->innamed) {
+ if (!isbound(st, t))
+ lfatal(
+ t->loc, "type parameter %s is undefined in generic context", tystr(t));
+ }
+
+ if (t->type == Tyname || t->type == Tygeneric) {
+ tybind(st, t);
+ st->innamed++;
+ }
+ for (i = 0; i < t->nsub; i++)
+ t->sub[i] = tf(st, t->sub[i]);
+ base = tybase(t);
+ /* no-ops if base == t */
+ if (t->traits)
+ bsunion(t->traits, base->traits);
+ else
+ t->traits = bsdup(base->traits);
+ if (tyinfinite(st, t, NULL))
+ lfatal(t->loc, "type %s includes itself", tystr(t));
+ st->ingeneric--;
+ if (t->type == Tyname || t->type == Tygeneric) {
+ tyunbind(st, t);
+ st->innamed--;
+ }
}
/* Look up the best type to date in the unification table, returning it */
Type *tysearch(Type *t)
{
- Type *lu;
- Stab *ns;
-
- assert(t != NULL);
- lu = NULL;
- while (1) {
- if (!tytab[t->tid] && t->type == Tyunres) {
- ns = curstab();
- if (t->name->name.ns) {
- ns = getns(file, t->name->name.ns);
- }
- if (!ns)
- fatal(t->name, "could not resolve namespace \"%s\"", t->name->name.ns);
- if (!(lu = gettype(ns, t->name)))
- fatal(t->name, "could not resolve type %s", tystr(t));
- tytab[t->tid] = lu;
- }
-
- if (!tytab[t->tid])
- break;
- /* compress paths: shift the link up one level */
- if (tytab[tytab[t->tid]->tid])
- tytab[t->tid] = tytab[tytab[t->tid]->tid];
- t = tytab[t->tid];
- }
- return t;
+ Type *lu;
+ Stab *ns;
+
+ assert(t != NULL);
+ lu = NULL;
+ while (1) {
+ if (!tytab[t->tid] && t->type == Tyunres) {
+ ns = curstab();
+ if (t->name->name.ns) {
+ ns = getns(file, t->name->name.ns);
+ }
+ if (!ns)
+ fatal(t->name, "could not resolve namespace \"%s\"",
+ t->name->name.ns);
+ if (!(lu = gettype(ns, t->name)))
+ fatal(t->name, "could not resolve type %s", tystr(t));
+ tytab[t->tid] = lu;
+ }
+
+ if (!tytab[t->tid])
+ break;
+ /* compress paths: shift the link up one level */
+ if (tytab[tytab[t->tid]->tid])
+ tytab[t->tid] = tytab[tytab[t->tid]->tid];
+ t = tytab[t->tid];
+ }
+ return t;
}
static Type *tysubst(Inferstate *st, Type *t, Type *orig)
{
- Htab *subst;
- size_t i;
+ Htab *subst;
+ size_t i;
- subst = mkht(tyhash, tyeq);
- for (i = 0; i < t->ngparam; i++) {
- htput(subst, t->gparam[i], tf(st, orig->arg[i]));
- }
- t = tyfreshen(st, subst, t);
- htfree(subst);
- return t;
+ subst = mkht(tyhash, tyeq);
+ for (i = 0; i < t->ngparam; i++) {
+ htput(subst, t->gparam[i], tf(st, orig->arg[i]));
+ }
+ t = tyfreshen(st, subst, t);
+ htfree(subst);
+ return t;
}
/* fixd the most accurate type mapping we have (ie,
* the end of the unification chain */
static Type *tf(Inferstate *st, Type *orig)
{
- int isgeneric;
- Type *t;
-
- assert(orig != NULL);
- t = tysearch(orig);
- isgeneric = t->type == Tygeneric;
- st->ingeneric += isgeneric;
- tyresolve(st, t);
- /* If this is an instantiation of a generic type, we want the params to
- * match the instantiation */
- if (orig->type == Tyunres && t->type == Tygeneric) {
- if (t->ngparam != orig->narg) {
- lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
- tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
- }
- t = tysubst(st, t, orig);
- }
- st->ingeneric -= isgeneric;
- return t;
+ int isgeneric;
+ Type *t;
+
+ assert(orig != NULL);
+ t = tysearch(orig);
+ isgeneric = t->type == Tygeneric;
+ st->ingeneric += isgeneric;
+ tyresolve(st, t);
+ /* If this is an instantiation of a generic type, we want the params to
+ * match the instantiation */
+ if (orig->type == Tyunres && t->type == Tygeneric) {
+ if (t->ngparam != orig->narg) {
+ lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
+ tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
+ }
+ t = tysubst(st, t, orig);
+ }
+ st->ingeneric -= isgeneric;
+ return t;
}
/* set the type of any typable node */
static void settype(Inferstate *st, Node *n, Type *t)
{
- t = tf(st, t);
- switch (n->type) {
- case Nexpr: n->expr.type = t; break;
- case Ndecl: n->decl.type = t; break;
- case Nlit: n->lit.type = t; break;
- case Nfunc: n->func.type = t; break;
- default:
- die("untypable node %s", nodestr[n->type]);
- break;
- }
+ t = tf(st, t);
+ switch (n->type) {
+ case Nexpr: n->expr.type = t; break;
+ case Ndecl: n->decl.type = t; break;
+ case Nlit: n->lit.type = t; break;
+ case Nfunc: n->func.type = t; break;
+ default: die("untypable node %s", nodestr[n->type]); break;
+ }
}
/* Gets the type of a literal value */
static Type *littype(Node *n)
{
- Type *t;
+ Type *t;
- t = NULL;
- if (!n->lit.type) {
- switch (n->lit.littype) {
- case Lchr: t = mktype(n->loc, Tychar); break;
- case Lbool: t = mktype(n->loc, Tybool); break;
- case Lint: t = mktylike(n->loc, Tyint); break;
- case Lflt: t = mktylike(n->loc, Tyflt64); break;
- case Lstr: t = mktyslice(n->loc, mktype(n->loc, Tybyte)); break;
- case Llbl: t = mktyptr(n->loc, mktype(n->loc, Tyvoid)); break;
- case Lfunc: t = n->lit.fnval->func.type; break;
- }
- n->lit.type = t;
- }
- return n->lit.type;
+ t = NULL;
+ if (!n->lit.type) {
+ switch (n->lit.littype) {
+ case Lchr: t = mktype(n->loc, Tychar); break;
+ case Lbool: t = mktype(n->loc, Tybool); break;
+ case Lint: t = mktylike(n->loc, Tyint); break;
+ case Lflt: t = mktylike(n->loc, Tyflt64); break;
+ case Lstr: t = mktyslice(n->loc, mktype(n->loc, Tybyte)); break;
+ case Llbl: t = mktyptr(n->loc, mktype(n->loc, Tyvoid)); break;
+ case Lfunc: t = n->lit.fnval->func.type; break;
+ }
+ n->lit.type = t;
+ }
+ return n->lit.type;
}
static Type *delayeducon(Inferstate *st, Type *fallback)
{
- Type *t;
- char *from, *to;
+ Type *t;
+ char *from, *to;
- if (fallback->type != Tyunion)
- return fallback;
- t = mktylike(fallback->loc, fallback->type);
- htput(st->delayed, t, fallback);
- if (debugopt['u']) {
- from = tystr(t);
- to = tystr(fallback);
- indentf(st->indentdepth, "Delay %s -> %s\n", from, to);
- free(from);
- free(to);
- }
- return t;
+ if (fallback->type != Tyunion)
+ return fallback;
+ t = mktylike(fallback->loc, fallback->type);
+ htput(st->delayed, t, fallback);
+ if (debugopt['u']) {
+ from = tystr(t);
+ to = tystr(fallback);
+ indentf(st->indentdepth, "Delay %s -> %s\n", from, to);
+ free(from);
+ free(to);
+ }
+ return t;
}
/* Finds the type of any typable node */
static Type *type(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- switch (n->type) {
- case Nlit: t = littype(n); break;
- case Nexpr: t = n->expr.type; break;
- case Ndecl: t = decltype(n); break;
- case Nfunc: t = n->func.type; break;
- default:
- t = NULL;
- die("untypeable node %s", nodestr[n->type]);
- break;
- };
- return tf(st, t);
+ switch (n->type) {
+ case Nlit: t = littype(n); break;
+ case Nexpr: t = n->expr.type; break;
+ case Ndecl: t = decltype(n); break;
+ case Nfunc: t = n->func.type; break;
+ default:
+ t = NULL;
+ die("untypeable node %s", nodestr[n->type]);
+ break;
+ };
+ return tf(st, t);
}
static Ucon *uconresolve(Inferstate *st, Node *n)
{
- Ucon *uc;
- Node **args;
- Stab *ns;
-
- args = n->expr.args;
- ns = curstab();
- if (args[0]->name.ns)
- ns = getns(file, args[0]->name.ns);
- if (!ns)
- fatal(n, "no namespace %s\n", args[0]->name.ns);
- uc = getucon(ns, args[0]);
- if (!uc)
- fatal(n, "no union constructor `%s", ctxstr(st, args[0]));
- if (!uc->etype && n->expr.nargs > 1)
- fatal(n, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
- else if (uc->etype && n->expr.nargs != 2)
- fatal(n, "union constructor `%s needs arg ", ctxstr(st, args[0]));
- return uc;
+ Ucon *uc;
+ Node **args;
+ Stab *ns;
+
+ args = n->expr.args;
+ ns = curstab();
+ if (args[0]->name.ns)
+ ns = getns(file, args[0]->name.ns);
+ if (!ns)
+ fatal(n, "no namespace %s\n", args[0]->name.ns);
+ uc = getucon(ns, args[0]);
+ if (!uc)
+ fatal(n, "no union constructor `%s", ctxstr(st, args[0]));
+ if (!uc->etype && n->expr.nargs > 1)
+ fatal(n, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
+ else if (uc->etype && n->expr.nargs != 2)
+ fatal(n, "union constructor `%s needs arg ", ctxstr(st, args[0]));
+ return uc;
}
static void putbindingsrec(Inferstate *st, Htab *bt, Type *t, Bitset *visited)
{
- size_t i;
-
- if (bshas(visited, t->tid))
- return;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram:
- if (hthas(bt, t->pname))
- unify(st, NULL, htget(bt, t->pname), t);
- else if (!isbound(st, t))
- htput(bt, t->pname, t);
- break;
- case Tygeneric:
- for (i = 0; i < t->ngparam; i++)
- putbindingsrec(st, bt, t->gparam[i], visited);
- break;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- putbindingsrec(st, bt, t->arg[i], visited);
- break;
- case Tyunres:
- for (i = 0; i < t->narg; i++)
- putbindingsrec(st, bt, t->arg[i], visited);
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- putbindingsrec(st, bt, t->sdecls[i]->decl.type, visited);
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- putbindingsrec(st, bt, t->udecls[i]->etype, visited);
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- putbindingsrec(st, bt, t->sub[i], visited);
- break;
- }
+ size_t i;
+
+ if (bshas(visited, t->tid))
+ return;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram:
+ if (hthas(bt, t->pname))
+ unify(st, NULL, htget(bt, t->pname), t);
+ else if (!isbound(st, t))
+ htput(bt, t->pname, t);
+ break;
+ case Tygeneric:
+ for (i = 0; i < t->ngparam; i++)
+ putbindingsrec(st, bt, t->gparam[i], visited);
+ break;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ putbindingsrec(st, bt, t->arg[i], visited);
+ break;
+ case Tyunres:
+ for (i = 0; i < t->narg; i++)
+ putbindingsrec(st, bt, t->arg[i], visited);
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ putbindingsrec(st, bt, t->sdecls[i]->decl.type, visited);
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ putbindingsrec(st, bt, t->udecls[i]->etype, visited);
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ putbindingsrec(st, bt, t->sub[i], visited);
+ break;
+ }
}
/* Binds the type parameters present in the
* current type into the type environment */
static void putbindings(Inferstate *st, Htab *bt, Type *t)
{
- Bitset *visited;
+ Bitset *visited;
- if (!t)
- return;
- visited = mkbs();
- putbindingsrec(st, bt, t, visited);
- bsfree(visited);
+ if (!t)
+ return;
+ visited = mkbs();
+ putbindingsrec(st, bt, t, visited);
+ bsfree(visited);
}
static void tybind(Inferstate *st, Type *t)
{
- Htab *bt;
- char *s;
+ Htab *bt;
+ char *s;
- if (debugopt['u']) {
- s = tystr(t);
- indentf(st->indentdepth, "Binding %s\n", s);
- free(s);
- }
- bt = mkht(strhash, streq);
- lappend(&st->tybindings, &st->ntybindings, bt);
- putbindings(st, bt, t);
+ if (debugopt['u']) {
+ s = tystr(t);
+ indentf(st->indentdepth, "Binding %s\n", s);
+ free(s);
+ }
+ bt = mkht(strhash, streq);
+ lappend(&st->tybindings, &st->ntybindings, bt);
+ putbindings(st, bt, t);
}
/* Binds the type parameters in the
* declaration into the type environment */
static void bind(Inferstate *st, Node *n)
{
- Htab *bt;
+ Htab *bt;
- assert(n->type == Ndecl);
- if (!n->decl.isgeneric)
- return;
- if (!n->decl.init)
- fatal(n, "generic %s has no initializer", n->decl);
+ assert(n->type == Ndecl);
+ if (!n->decl.isgeneric)
+ return;
+ if (!n->decl.init)
+ fatal(n, "generic %s has no initializer", n->decl);
- st->ingeneric++;
- bt = mkht(strhash, streq);
- lappend(&st->tybindings, &st->ntybindings, bt);
+ st->ingeneric++;
+ bt = mkht(strhash, streq);
+ lappend(&st->tybindings, &st->ntybindings, bt);
- putbindings(st, bt, n->decl.type);
- putbindings(st, bt, n->decl.init->expr.type);
+ putbindings(st, bt, n->decl.type);
+ putbindings(st, bt, n->decl.init->expr.type);
}
/* Rolls back the binding of type parameters in
* the type environment */
static void unbind(Inferstate *st, Node *n)
{
- if (!n->decl.isgeneric)
- return;
- htfree(st->tybindings[st->ntybindings - 1]);
- lpop(&st->tybindings, &st->ntybindings);
- st->ingeneric--;
+ if (!n->decl.isgeneric)
+ return;
+ htfree(st->tybindings[st->ntybindings - 1]);
+ lpop(&st->tybindings, &st->ntybindings);
+ st->ingeneric--;
}
static void tyunbind(Inferstate *st, Type *t)
{
- if (t->type != Tygeneric)
- return;
- htfree(st->tybindings[st->ntybindings - 1]);
- lpop(&st->tybindings, &st->ntybindings);
+ if (t->type != Tygeneric)
+ return;
+ htfree(st->tybindings[st->ntybindings - 1]);
+ lpop(&st->tybindings, &st->ntybindings);
}
/* Constrains a type to implement the required constraints. On
@@ -728,87 +713,91 @@ static void tyunbind(Inferstate *st, Type *t)
* if it has the required constraint */
static void constrain(Inferstate *st, Node *ctx, Type *a, Trait *c)
{
- if (a->type == Tyvar) {
- if (!a->traits)
- a->traits = mkbs();
- settrait(a, c);
- } else if (!a->traits || !bshas(a->traits, c->uid)) {
- fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(st, ctx));
- }
+ if (a->type == Tyvar) {
+ if (!a->traits)
+ a->traits = mkbs();
+ settrait(a, c);
+ }
+ else if (!a->traits || !bshas(a->traits, c->uid)) {
+ fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(st, ctx));
+ }
}
/* does b satisfy all the constraints of a? */
static int checktraits(Type *a, Type *b)
{
- /* a has no traits to satisfy */
- if (!a->traits)
- return 1;
- /* b satisfies no traits; only valid if a requires none */
- if (!b->traits)
- return bscount(a->traits) == 0;
- /* if a->traits is a subset of b->traits, all of
- * a's constraints are satisfied by b. */
- return bsissubset(a->traits, b->traits);
+ /* a has no traits to satisfy */
+ if (!a->traits)
+ return 1;
+ /* b satisfies no traits; only valid if a requires none */
+ if (!b->traits)
+ return bscount(a->traits) == 0;
+ /* if a->traits is a subset of b->traits, all of
+ * a's constraints are satisfied by b. */
+ return bsissubset(a->traits, b->traits);
}
static void verifytraits(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- size_t i, n;
- char *sep;
- char traitbuf[1024], abuf[1024], bbuf[1024];
-
- if (!checktraits(a, b)) {
- sep = "";
- n = 0;
- for (i = 0; bsiter(a->traits, &i); i++) {
- if (!b->traits || !bshas(b->traits, i))
- n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep, namestr(traittab[i]->name));
- sep = ",";
- }
- tyfmt(abuf, sizeof abuf, a);
- tyfmt(bbuf, sizeof bbuf, b);
- fatal(ctx, "%s missing traits %s for %s near %s", bbuf, traitbuf, abuf, ctxstr(st, ctx));
- }
+ size_t i, n;
+ char *sep;
+ char traitbuf[1024], abuf[1024], bbuf[1024];
+
+ if (!checktraits(a, b)) {
+ sep = "";
+ n = 0;
+ for (i = 0; bsiter(a->traits, &i); i++) {
+ if (!b->traits || !bshas(b->traits, i))
+ n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep,
+ namestr(traittab[i]->name));
+ sep = ",";
+ }
+ tyfmt(abuf, sizeof abuf, a);
+ tyfmt(bbuf, sizeof bbuf, b);
+ fatal(ctx, "%s missing traits %s for %s near %s", bbuf, traitbuf, abuf,
+ ctxstr(st, ctx));
+ }
}
/* Merges the constraints on types */
static void mergetraits(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- if (b->type == Tyvar) {
- /* make sure that if a = b, both have same traits */
- if (a->traits && b->traits)
- bsunion(b->traits, a->traits);
- else if (a->traits)
- b->traits = bsdup(a->traits);
- else if (b->traits)
- a->traits = bsdup(b->traits);
- } else {
- verifytraits(st, ctx, a, b);
- }
+ if (b->type == Tyvar) {
+ /* make sure that if a = b, both have same traits */
+ if (a->traits && b->traits)
+ bsunion(b->traits, a->traits);
+ else if (a->traits)
+ b->traits = bsdup(a->traits);
+ else if (b->traits)
+ a->traits = bsdup(b->traits);
+ }
+ else {
+ verifytraits(st, ctx, a, b);
+ }
}
/* Tells us if we have an index hack on the type */
static int idxhacked(Type *a, Type *b)
{
- if (a->type == Tyvar && a->nsub > 0)
- return 1;
- if (a->type == Tyarray || a->type == Tyslice)
- return a->type == b->type;
- return 0;
+ if (a->type == Tyvar && a->nsub > 0)
+ return 1;
+ if (a->type == Tyarray || a->type == Tyslice)
+ return a->type == b->type;
+ return 0;
}
/* prevents types that contain themselves in the unification;
* eg @a U (@a -> foo) */
static int occurs(Type *a, Type *b)
{
- size_t i;
+ size_t i;
- if (a == b)
- return 1;
- for (i = 0; i < b->nsub; i++)
- if (occurs(a, b->sub[i]))
- return 1;
- return 0;
+ if (a == b)
+ return 1;
+ for (i = 0; i < b->nsub; i++)
+ if (occurs(a, b->sub[i]))
+ return 1;
+ return 0;
}
/* Computes the 'rank' of the type; ie, in which
@@ -817,173 +806,177 @@ static int occurs(Type *a, Type *b)
* specific) type. */
static int tyrank(Type *t)
{
- /* plain tyvar */
- if (t->type == Tyvar && t->nsub == 0)
- return 0;
- /* parameterized tyvar */
- if (t->type == Tyvar && t->nsub > 0)
- return 1;
- /* concrete type */
- return 2;
+ /* plain tyvar */
+ if (t->type == Tyvar && t->nsub == 0)
+ return 0;
+ /* parameterized tyvar */
+ if (t->type == Tyvar && t->nsub > 0)
+ return 1;
+ /* concrete type */
+ return 2;
}
-static int hasparam(Type *t)
-{
- return t->type == Tyname && t->narg > 0;
-}
+static int hasparam(Type *t) { return t->type == Tyname && t->narg > 0; }
static void unionunify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- size_t i, j;
- int found;
-
- if (u->nmemb != v->nmemb)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
-
- for (i = 0; i < u->nmemb; i++) {
- found = 0;
- for (j = 0; j < v->nmemb; j++) {
- if (strcmp(namestr(u->udecls[i]->name), namestr(v->udecls[i]->name)) != 0)
- continue;
- found = 1;
- if (u->udecls[i]->etype == NULL && v->udecls[i]->etype == NULL)
- continue;
- else if (u->udecls[i]->etype && v->udecls[i]->etype)
- unify(st, ctx, u->udecls[i]->etype, v->udecls[i]->etype);
- else
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
- if (!found)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
+ size_t i, j;
+ int found;
+
+ if (u->nmemb != v->nmemb)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
+
+ for (i = 0; i < u->nmemb; i++) {
+ found = 0;
+ for (j = 0; j < v->nmemb; j++) {
+ if (strcmp(namestr(u->udecls[i]->name), namestr(v->udecls[i]->name)) != 0)
+ continue;
+ found = 1;
+ if (u->udecls[i]->etype == NULL && v->udecls[i]->etype == NULL)
+ continue;
+ else if (u->udecls[i]->etype && v->udecls[i]->etype)
+ unify(st, ctx, u->udecls[i]->etype, v->udecls[i]->etype);
+ else
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
+ if (!found)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
}
static void structunify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- size_t i, j;
- int found;
-
- if (u->nmemb != v->nmemb)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
-
- for (i = 0; i < u->nmemb; i++) {
- found = 0;
- for (j = 0; j < v->nmemb; j++) {
- if (strcmp(namestr(u->sdecls[i]->decl.name), namestr(v->sdecls[i]->decl.name)) != 0)
- continue;
- found = 1;
- unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
- }
- if (!found)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
-}
-
-static void membunify(Inferstate *st, Node *ctx, Type *u, Type *v) {
- if (hthas(st->delayed, u))
- u = htget(st->delayed, u);
- u = tybase(u);
- if (hthas(st->delayed, v))
- v = htget(st->delayed, v);
- v = tybase(v);
- if (u->type == Tyunion && v->type == Tyunion && u != v)
- unionunify(st, ctx, u, v);
- else if (u->type == Tystruct && v->type == Tystruct && u != v)
- structunify(st, ctx, u, v);
+ size_t i, j;
+ int found;
+
+ if (u->nmemb != v->nmemb)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
+
+ for (i = 0; i < u->nmemb; i++) {
+ found = 0;
+ for (j = 0; j < v->nmemb; j++) {
+ if (strcmp(namestr(u->sdecls[i]->decl.name),
+ namestr(v->sdecls[i]->decl.name)) != 0)
+ continue;
+ found = 1;
+ unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
+ }
+ if (!found)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
+}
+
+static void membunify(Inferstate *st, Node *ctx, Type *u, Type *v)
+{
+ if (hthas(st->delayed, u))
+ u = htget(st->delayed, u);
+ u = tybase(u);
+ if (hthas(st->delayed, v))
+ v = htget(st->delayed, v);
+ v = tybase(v);
+ if (u->type == Tyunion && v->type == Tyunion && u != v)
+ unionunify(st, ctx, u, v);
+ else if (u->type == Tystruct && v->type == Tystruct && u != v)
+ structunify(st, ctx, u, v);
}
/* Unifies two types, or errors if the types are not unifiable. */
static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- Type *t, *r;
- Type *a, *b;
- char *from, *to;
- size_t i;
-
- /* a ==> b */
- a = tf(st, u);
- b = tf(st, v);
- if (a == b)
- return a;
-
- /* we unify from lower to higher ranked types */
- if (tyrank(b) < tyrank(a)) {
- t = a;
- a = b;
- b = t;
- }
-
- if (debugopt['u']) {
- from = tystr(a);
- to = tystr(b);
- indentf(st->indentdepth, "Unify %s => %s\n", from, to);
- free(from);
- free(to);
- }
-
- r = NULL;
- if (a->type == Tyvar) {
- tytab[a->tid] = b;
- r = b;
- }
-
- /* Disallow recursive types */
- if (a->type == Tyvar && b->type != Tyvar) {
- if (occurs(a, b))
- typeerror(st, a, b, ctx, "Infinite type\n");
- }
-
- /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
- * Otherwise, match up subtypes. */
- if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
- if (hasparam(a) && hasparam(b)) {
- /* Only Tygeneric and Tyname should be able to unify. And they
- * should have the same names for this to be true. */
- if (!nameeq(a->name, b->name))
- typeerror(st, a, b, ctx, NULL);
- if (a->narg != b->narg)
- typeerror(st, a, b, ctx, "Incompatible parameter lists");
- for (i = 0; i < a->narg; i++)
- unify(st, ctx, a->arg[i], b->arg[i]);
- r = b;
- }
- if (a->nsub != b->nsub) {
- verifytraits(st, ctx, a, b);
- if (tybase(a)->type == Tyfunc)
- typeerror(st, a, b, ctx, "function arity mismatch");
- else
- typeerror(st, a, b, ctx, "subtype counts incompatible");
- }
- for (i = 0; i < b->nsub; i++)
- unify(st, ctx, a->sub[i], b->sub[i]);
- r = b;
- } else if (a->type != Tyvar) {
- typeerror(st, a, b, ctx, NULL);
- }
- mergetraits(st, ctx, a, b);
- if (a->isreflect || b->isreflect)
- r->isreflect = a->isreflect = b->isreflect = 1;
- membunify(st, ctx, a, b);
-
- /* if we have delayed types for a tyvar, transfer it over. */
- if (a->type == Tyvar && b->type == Tyvar) {
- if (hthas(st->delayed, a) && !hthas(st->delayed, b))
- htput(st->delayed, b, htget(st->delayed, a));
- else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
- htput(st->delayed, a, htget(st->delayed, b));
- } else if (hthas(st->delayed, a)) {
- unify(st, ctx, htget(st->delayed, a), tybase(b));
- }
-
- return r;
+ Type *t, *r;
+ Type *a, *b;
+ char *from, *to;
+ size_t i;
+
+ /* a ==> b */
+ a = tf(st, u);
+ b = tf(st, v);
+ if (a == b)
+ return a;
+
+ /* we unify from lower to higher ranked types */
+ if (tyrank(b) < tyrank(a)) {
+ t = a;
+ a = b;
+ b = t;
+ }
+
+ if (debugopt['u']) {
+ from = tystr(a);
+ to = tystr(b);
+ indentf(st->indentdepth, "Unify %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
+
+ r = NULL;
+ if (a->type == Tyvar) {
+ tytab[a->tid] = b;
+ r = b;
+ }
+
+ /* Disallow recursive types */
+ if (a->type == Tyvar && b->type != Tyvar) {
+ if (occurs(a, b))
+ typeerror(st, a, b, ctx, "Infinite type\n");
+ }
+
+ /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
+ * Otherwise, match up subtypes. */
+ if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
+ if (hasparam(a) && hasparam(b)) {
+ /* Only Tygeneric and Tyname should be able to unify. And they
+ * should have the same names for this to be true. */
+ if (!nameeq(a->name, b->name))
+ typeerror(st, a, b, ctx, NULL);
+ if (a->narg != b->narg)
+ typeerror(st, a, b, ctx, "Incompatible parameter lists");
+ for (i = 0; i < a->narg; i++)
+ unify(st, ctx, a->arg[i], b->arg[i]);
+ r = b;
+ }
+ if (a->nsub != b->nsub) {
+ verifytraits(st, ctx, a, b);
+ if (tybase(a)->type == Tyfunc)
+ typeerror(st, a, b, ctx, "function arity mismatch");
+ else
+ typeerror(st, a, b, ctx, "subtype counts incompatible");
+ }
+ for (i = 0; i < b->nsub; i++)
+ unify(st, ctx, a->sub[i], b->sub[i]);
+ r = b;
+ }
+ else if (a->type != Tyvar) {
+ typeerror(st, a, b, ctx, NULL);
+ }
+ mergetraits(st, ctx, a, b);
+ if (a->isreflect || b->isreflect)
+ r->isreflect = a->isreflect = b->isreflect = 1;
+ membunify(st, ctx, a, b);
+
+ /* if we have delayed types for a tyvar, transfer it over. */
+ if (a->type == Tyvar && b->type == Tyvar) {
+ if (hthas(st->delayed, a) && !hthas(st->delayed, b))
+ htput(st->delayed, b, htget(st->delayed, a));
+ else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
+ htput(st->delayed, a, htget(st->delayed, b));
+ }
+ else if (hthas(st->delayed, a)) {
+ unify(st, ctx, htget(st->delayed, a), tybase(b));
+ }
+
+ return r;
}
static void markvatypes(Type **types, size_t ntypes)
{
- size_t i;
+ size_t i;
- for (i = 0; i < ntypes; i++)
- types[i]->isreflect = 1;
+ for (i = 0; i < ntypes; i++)
+ types[i]->isreflect = 1;
}
/* Applies unifications to function calls.
@@ -991,103 +984,107 @@ static void markvatypes(Type **types, size_t ntypes)
* different approach to unification. */
static void unifycall(Inferstate *st, Node *n)
{
- size_t i;
- Type *ft;
- char *ret, *ctx;
-
- ft = type(st, n->expr.args[0]);
-
- if (ft->type == Tyvar) {
- /* the first arg is the function itself, so it shouldn't be counted */
- ft = mktyfunc(n->loc, &n->expr.args[1], n->expr.nargs - 1, mktyvar(n->loc));
- unify(st, n, ft, type(st, n->expr.args[0]));
- } else if (tybase(ft)->type != Tyfunc) {
- fatal(n, "calling uncallable type %s", tystr(ft));
- }
- /* first arg: function itself */
- for (i = 1; i < n->expr.nargs; i++)
- if (exprtype(n->expr.args[i])->type == Tyvoid)
- fatal(n, "void passed where value expected, near %s", ctxstr(st, n));
- for (i = 1; i < n->expr.nargs; i++) {
- if (i == ft->nsub)
- fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
- ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
-
- if (ft->sub[i]->type == Tyvalist) {
- markvatypes(&ft->sub[i], ft->nsub - i);
- break;
- }
- inferexpr(st, &n->expr.args[i], NULL, NULL);
- unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
- }
- if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
- fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
- ctxstr(st, n->expr.args[0]), ft->nsub - 1, i - 1);
- if (debugopt['u']) {
- ret = tystr(ft->sub[0]);
- ctx = ctxstr(st, n->expr.args[0]);
- indentf(st->indentdepth, "Call of %s returns %s\n", ctx, ret);
- free(ctx);
- free(ret);
- }
-
- settype(st, n, ft->sub[0]);
+ size_t i;
+ Type *ft;
+ char *ret, *ctx;
+
+ ft = type(st, n->expr.args[0]);
+
+ if (ft->type == Tyvar) {
+ /* the first arg is the function itself, so it shouldn't be counted */
+ ft = mktyfunc(n->loc, &n->expr.args[1], n->expr.nargs - 1, mktyvar(n->loc));
+ unify(st, n, ft, type(st, n->expr.args[0]));
+ }
+ else if (tybase(ft)->type != Tyfunc) {
+ fatal(n, "calling uncallable type %s", tystr(ft));
+ }
+ /* first arg: function itself */
+ for (i = 1; i < n->expr.nargs; i++)
+ if (exprtype(n->expr.args[i])->type == Tyvoid)
+ fatal(n, "void passed where value expected, near %s", ctxstr(st, n));
+ for (i = 1; i < n->expr.nargs; i++) {
+ if (i == ft->nsub)
+ fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
+ ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
+
+ if (ft->sub[i]->type == Tyvalist) {
+ markvatypes(&ft->sub[i], ft->nsub - i);
+ break;
+ }
+ inferexpr(st, &n->expr.args[i], NULL, NULL);
+ unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
+ }
+ if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
+ fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
+ ctxstr(st, n->expr.args[0]), ft->nsub - 1, i - 1);
+ if (debugopt['u']) {
+ ret = tystr(ft->sub[0]);
+ ctx = ctxstr(st, n->expr.args[0]);
+ indentf(st->indentdepth, "Call of %s returns %s\n", ctx, ret);
+ free(ctx);
+ free(ret);
+ }
+
+ settype(st, n, ft->sub[0]);
}
static void unifyparams(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- size_t i;
+ size_t i;
- /* The only types with unifiable params are Tyunres and Tyname.
- * Tygeneric should always be freshened, and no other types have
- * parameters attached.
- *
- * FIXME: Is it possible to have parameterized typarams? */
- if (a->type != Tyunres && a->type != Tyname)
- return;
- if (b->type != Tyunres && b->type != Tyname)
- return;
+ /* The only types with unifiable params are Tyunres and Tyname.
+ * Tygeneric should always be freshened, and no other types have
+ * parameters attached.
+ *
+ * FIXME: Is it possible to have parameterized typarams? */
+ if (a->type != Tyunres && a->type != Tyname)
+ return;
+ if (b->type != Tyunres && b->type != Tyname)
+ return;
- if (a->narg != b->narg)
- fatal(ctx, "mismatched arg list sizes: %s with %s near %s", tystr(a), tystr(b), ctxstr(st, ctx));
- for (i = 0; i < a->narg; i++)
- unify(st, ctx, a->arg[i], b->arg[i]);
+ if (a->narg != b->narg)
+ fatal(ctx, "mismatched arg list sizes: %s with %s near %s", tystr(a), tystr(b),
+ ctxstr(st, ctx));
+ for (i = 0; i < a->narg; i++)
+ unify(st, ctx, a->arg[i], b->arg[i]);
}
static void loaduses(Node *n)
{
- size_t i;
+ size_t i;
- /* uses only allowed at top level. Do we want to keep it this way? */
- for (i = 0; i < n->file.nuses; i++)
- readuse(n->file.uses[i], n->file.globls, Visintern);
+ /* uses only allowed at top level. Do we want to keep it this way? */
+ for (i = 0; i < n->file.nuses; i++)
+ readuse(n->file.uses[i], n->file.globls, Visintern);
}
static Type *initvar(Inferstate *st, Node *n, Node *s)
{
- Type *t;
-
- if (s->decl.ishidden)
- fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
- if (s->decl.isgeneric)
- t = tysubst(st, tf(st, s->decl.type), s->decl.type);
- else
- t = s->decl.type;
- n->expr.did = s->decl.did;
- n->expr.isconst = s->decl.isconst;
- if (s->decl.isgeneric && !st->ingeneric) {
- t = tyfreshen(st, NULL, t);
- addspecialization(st, n, curstab());
- if (t->type == Tyvar) {
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
- } else {
- settype(st, n, t);
- }
- } else {
- settype(st, n, t);
- }
- return t;
+ Type *t;
+
+ if (s->decl.ishidden)
+ fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
+ if (s->decl.isgeneric)
+ t = tysubst(st, tf(st, s->decl.type), s->decl.type);
+ else
+ t = s->decl.type;
+ n->expr.did = s->decl.did;
+ n->expr.isconst = s->decl.isconst;
+ if (s->decl.isgeneric && !st->ingeneric) {
+ t = tyfreshen(st, NULL, t);
+ addspecialization(st, n, curstab());
+ if (t->type == Tyvar) {
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
+ }
+ else {
+ settype(st, n, t);
+ }
+ }
+ else {
+ settype(st, n, t);
+ }
+ return t;
}
/* Finds out if the member reference is actually
@@ -1097,869 +1094,900 @@ static Type *initvar(Inferstate *st, Node *n, Node *s)
* that we do have */
static Node *checkns(Inferstate *st, Node *n, Node **ret)
{
- Node *var, *name, *nsname;
- Node **args;
- Stab *stab;
- Node *s;
-
- /* check that this is a namespaced declaration */
- if (n->type != Nexpr)
- return n;
- if (exprop(n) != Omemb)
- return n;
- if (!n->expr.nargs)
- return n;
- args = n->expr.args;
- if (args[0]->type != Nexpr || exprop(args[0]) != Ovar)
- return n;
- name = args[0]->expr.args[0];
- stab = getns(file, namestr(name));
- if (!stab)
- return n;
-
- /* substitute the namespaced name */
- nsname = mknsname(n->loc, namestr(name), namestr(args[1]));
- s = getdcl(stab, args[1]);
- if (!s)
- fatal(n, "undeclared var %s.%s", nsname->name.ns, nsname->name.name);
- var = mkexpr(n->loc, Ovar, nsname, NULL);
- var->expr.idx = n->expr.idx;
- initvar(st, var, s);
- *ret = var;
- return var;
+ Node *var, *name, *nsname;
+ Node **args;
+ Stab *stab;
+ Node *s;
+
+ /* check that this is a namespaced declaration */
+ if (n->type != Nexpr)
+ return n;
+ if (exprop(n) != Omemb)
+ return n;
+ if (!n->expr.nargs)
+ return n;
+ args = n->expr.args;
+ if (args[0]->type != Nexpr || exprop(args[0]) != Ovar)
+ return n;
+ name = args[0]->expr.args[0];
+ stab = getns(file, namestr(name));
+ if (!stab)
+ return n;
+
+ /* substitute the namespaced name */
+ nsname = mknsname(n->loc, namestr(name), namestr(args[1]));
+ s = getdcl(stab, args[1]);
+ if (!s)
+ fatal(n, "undeclared var %s.%s", nsname->name.ns, nsname->name.name);
+ var = mkexpr(n->loc, Ovar, nsname, NULL);
+ var->expr.idx = n->expr.idx;
+ initvar(st, var, s);
+ *ret = var;
+ return var;
}
static void inferstruct(Inferstate *st, Node *n, int *isconst)
{
- size_t i;
+ size_t i;
- *isconst = 1;
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- if (!n->expr.args[i]->expr.isconst)
- *isconst = 0;
- }
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
+ *isconst = 1;
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ if (!n->expr.args[i]->expr.isconst)
+ *isconst = 0;
+ }
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
}
static void inferarray(Inferstate *st, Node *n, int *isconst)
{
- size_t i;
- Type *t;
- Node *len;
+ size_t i;
+ Type *t;
+ Node *len;
- *isconst = 1;
- len = mkintlit(n->loc, n->expr.nargs);
- t = mktyarray(n->loc, mktyvar(n->loc), len);
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- unify(st, n, t->sub[0], type(st, n->expr.args[i]));
- if (!n->expr.args[i]->expr.isconst)
- *isconst = 0;
- }
- settype(st, n, t);
+ *isconst = 1;
+ len = mkintlit(n->loc, n->expr.nargs);
+ t = mktyarray(n->loc, mktyvar(n->loc), len);
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ unify(st, n, t->sub[0], type(st, n->expr.args[i]));
+ if (!n->expr.args[i]->expr.isconst)
+ *isconst = 0;
+ }
+ settype(st, n, t);
}
static void infertuple(Inferstate *st, Node *n, int *isconst)
{
- Type **types;
- size_t i;
+ Type **types;
+ size_t i;
- *isconst = 1;
- types = xalloc(sizeof(Type *)*n->expr.nargs);
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
- types[i] = type(st, n->expr.args[i]);
- }
- *isconst = n->expr.isconst;
- settype(st, n, mktytuple(n->loc, types, n->expr.nargs));
+ *isconst = 1;
+ types = xalloc(sizeof(Type *) * n->expr.nargs);
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
+ types[i] = type(st, n->expr.args[i]);
+ }
+ *isconst = n->expr.isconst;
+ settype(st, n, mktytuple(n->loc, types, n->expr.nargs));
}
static void inferucon(Inferstate *st, Node *n, int *isconst)
{
- Ucon *uc;
- Type *t;
+ Ucon *uc;
+ Type *t;
- *isconst = 1;
- uc = uconresolve(st, n);
- t = tysubst(st, tf(st, uc->utype), uc->utype);
- uc = tybase(t)->udecls[uc->id];
- if (uc->etype) {
- inferexpr(st, &n->expr.args[1], NULL, NULL);
- unify(st, n, uc->etype, type(st, n->expr.args[1]));
- *isconst = n->expr.args[1]->expr.isconst;
- }
- settype(st, n, delayeducon(st, t));
+ *isconst = 1;
+ uc = uconresolve(st, n);
+ t = tysubst(st, tf(st, uc->utype), uc->utype);
+ uc = tybase(t)->udecls[uc->id];
+ if (uc->etype) {
+ inferexpr(st, &n->expr.args[1], NULL, NULL);
+ unify(st, n, uc->etype, type(st, n->expr.args[1]));
+ *isconst = n->expr.args[1]->expr.isconst;
+ }
+ settype(st, n, delayeducon(st, t));
}
static void inferpat(Inferstate *st, Node **np, Node *val, Node ***bind, size_t *nbind)
{
- size_t i;
- Node **args;
- Node *s, *n;
- Stab *ns;
- Type *t;
-
- n = *np;
- n = checkns(st, n, np);
- args = n->expr.args;
- for (i = 0; i < n->expr.nargs; i++)
- if (args[i]->type == Nexpr)
- inferpat(st, &args[i], val, bind, nbind);
- switch (exprop(n)) {
- case Otup:
- case Ostruct:
- case Oarr:
- case Olit:
- case Omemb:
- infernode(st, np, NULL, NULL);
- break;
- /* arithmetic expressions just need to be constant */
- case Oneg:
- case Oadd:
- case Osub:
- case Omul:
- case Odiv:
- case Obsl:
- case Obsr:
- case Oband:
- case Obor:
- case Obxor:
- case Obnot:
- infernode(st, np, NULL, NULL);
- if (!n->expr.isconst)
- fatal(n, "matching against non-constant expression near %s", ctxstr(st, n));
- break;
- case Oucon: inferucon(st, n, &n->expr.isconst); break;
- case Ovar:
- ns = curstab();
- if (args[0]->name.ns)
- ns = getns(file, args[0]->name.ns);
- s = getdcl(ns, args[0]);
- if (s && !s->decl.ishidden) {
- if (s->decl.isgeneric)
- t = tysubst(st, s->decl.type, s->decl.type);
- else if (s->decl.isconst)
- t = s->decl.type;
- else
- fatal(n, "pattern shadows variable declared on %s:%d near %s", fname(s->loc), lnum(s->loc), ctxstr(st, s));
- } else {
- t = mktyvar(n->loc);
- s = mkdecl(n->loc, n->expr.args[0], t);
- s->decl.init = val;
- settype(st, n, t);
- lappend(bind, nbind, s);
- }
- settype(st, n, t);
- n->expr.did = s->decl.did;
- break;
- case Ogap:
- infernode(st, np, NULL, NULL);
- break;
- default:
- fatal(n, "invalid pattern");
- break;
- }
+ size_t i;
+ Node **args;
+ Node *s, *n;
+ Stab *ns;
+ Type *t;
+
+ n = *np;
+ n = checkns(st, n, np);
+ args = n->expr.args;
+ for (i = 0; i < n->expr.nargs; i++)
+ if (args[i]->type == Nexpr)
+ inferpat(st, &args[i], val, bind, nbind);
+ switch (exprop(n)) {
+ case Otup:
+ case Ostruct:
+ case Oarr:
+ case Olit:
+ case Omemb:
+ infernode(st, np, NULL, NULL);
+ break;
+ /* arithmetic expressions just need to be constant */
+ case Oneg:
+ case Oadd:
+ case Osub:
+ case Omul:
+ case Odiv:
+ case Obsl:
+ case Obsr:
+ case Oband:
+ case Obor:
+ case Obxor:
+ case Obnot:
+ infernode(st, np, NULL, NULL);
+ if (!n->expr.isconst)
+ fatal(n, "matching against non-constant expression near %s", ctxstr(st, n));
+ break;
+ case Oucon:
+ inferucon(st, n, &n->expr.isconst);
+ break;
+ case Ovar:
+ ns = curstab();
+ if (args[0]->name.ns)
+ ns = getns(file, args[0]->name.ns);
+ s = getdcl(ns, args[0]);
+ if (s && !s->decl.ishidden) {
+ if (s->decl.isgeneric)
+ t = tysubst(st, s->decl.type, s->decl.type);
+ else if (s->decl.isconst)
+ t = s->decl.type;
+ else
+ fatal(n, "pattern shadows variable declared on %s:%d near %s",
+ fname(s->loc), lnum(s->loc), ctxstr(st, s));
+ }
+ else {
+ t = mktyvar(n->loc);
+ s = mkdecl(n->loc, n->expr.args[0], t);
+ s->decl.init = val;
+ settype(st, n, t);
+ lappend(bind, nbind, s);
+ }
+ settype(st, n, t);
+ n->expr.did = s->decl.did;
+ break;
+ case Ogap: infernode(st, np, NULL, NULL); break;
+ default: fatal(n, "invalid pattern"); break;
+ }
}
void addbindings(Inferstate *st, Node *n, Node **bind, size_t nbind)
{
- size_t i;
+ size_t i;
- /* order of binding shouldn't matter, so push them into the block
- * in reverse order. */
- for (i = 0; i < nbind; i++) {
- putdcl(n->block.scope, bind[i]);
- linsert(&n->block.stmts, &n->block.nstmts, 0, bind[i]);
- }
+ /* order of binding shouldn't matter, so push them into the block
+ * in reverse order. */
+ for (i = 0; i < nbind; i++) {
+ putdcl(n->block.scope, bind[i]);
+ linsert(&n->block.stmts, &n->block.nstmts, 0, bind[i]);
+ }
}
static void infersub(Inferstate *st, Node *n, Type *ret, int *sawret, int *exprconst)
{
- Node **args;
- size_t i, nargs;
- int isconst;
-
- args = n->expr.args;
- nargs = n->expr.nargs;
- isconst = 1;
- for (i = 0; i < nargs; i++) {
- /* Nlit, Nvar, etc should not be inferred as exprs */
- if (args[i]->type == Nexpr) {
- /* Omemb can sometimes resolve to a namespace. We have to check
- * this. Icky. */
- checkns(st, args[i], &args[i]);
- inferexpr(st, &args[i], ret, sawret);
- isconst = isconst && args[i]->expr.isconst;
- }
- }
- if (exprop(n) == Ovar)
- n->expr.isconst = decls[n->expr.did]->decl.isconst;
- else if (opispure[exprop(n)])
- n->expr.isconst = isconst;
- *exprconst = n->expr.isconst;
+ Node **args;
+ size_t i, nargs;
+ int isconst;
+
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ isconst = 1;
+ for (i = 0; i < nargs; i++) {
+ /* Nlit, Nvar, etc should not be inferred as exprs */
+ if (args[i]->type == Nexpr) {
+ /* Omemb can sometimes resolve to a namespace. We have to check
+ * this. Icky. */
+ checkns(st, args[i], &args[i]);
+ inferexpr(st, &args[i], ret, sawret);
+ isconst = isconst && args[i]->expr.isconst;
+ }
+ }
+ if (exprop(n) == Ovar)
+ n->expr.isconst = decls[n->expr.did]->decl.isconst;
+ else if (opispure[exprop(n)])
+ n->expr.isconst = isconst;
+ *exprconst = n->expr.isconst;
}
static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret)
{
- Node **args;
- size_t i, nargs;
- Node *s, *n;
- Type *t;
- int isconst;
-
- n = *np;
- assert(n->type == Nexpr);
- args = n->expr.args;
- nargs = n->expr.nargs;
- infernode(st, &n->expr.idx, NULL, NULL);
- n = checkns(st, n, np);
- switch (exprop(n)) {
- /* all operands are same type */
- case Oadd: /* @a + @a -> @a */
- case Osub: /* @a - @a -> @a */
- case Omul: /* @a * @a -> @a */
- case Odiv: /* @a / @a -> @a */
- case Oneg: /* -@a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- constrain(st, n, type(st, args[0]), traittab[Tcnum]);
- isconst = args[0]->expr.isconst;
- for (i = 1; i < nargs; i++) {
- isconst = isconst && args[i]->expr.isconst;
- t = unify(st, n, t, type(st, args[i]));
- }
- n->expr.isconst = isconst;
- settype(st, n, t);
- break;
- case Omod: /* @a % @a -> @a */
- case Obor: /* @a | @a -> @a */
- case Oband: /* @a & @a -> @a */
- case Obxor: /* @a ^ @a -> @a */
- case Obsl: /* @a << @a -> @a */
- case Obsr: /* @a >> @a -> @a */
- case Obnot: /* ~@a -> @a */
- case Opreinc: /* ++@a -> @a */
- case Opredec: /* --@a -> @a */
- case Opostinc: /* @a++ -> @a */
- case Opostdec: /* @a-- -> @a */
- case Oaddeq: /* @a += @a -> @a */
- case Osubeq: /* @a -= @a -> @a */
- case Omuleq: /* @a *= @a -> @a */
- case Odiveq: /* @a /= @a -> @a */
- case Omodeq: /* @a %= @a -> @a */
- case Oboreq: /* @a |= @a -> @a */
- case Obandeq: /* @a &= @a -> @a */
- case Obxoreq: /* @a ^= @a -> @a */
- case Obsleq: /* @a <<= @a -> @a */
- case Obsreq: /* @a >>= @a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- constrain(st, n, type(st, args[0]), traittab[Tcnum]);
- constrain(st, n, type(st, args[0]), traittab[Tcint]);
- isconst = args[0]->expr.isconst;
- for (i = 1; i < nargs; i++) {
- isconst = isconst && args[i]->expr.isconst;
- t = unify(st, n, t, type(st, args[i]));
- }
- n->expr.isconst = isconst;
- settype(st, n, t);
- break;
- case Oasn: /* @a = @a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- for (i = 1; i < nargs; i++)
- t = unify(st, n, t, type(st, args[i]));
- settype(st, n, t);
- if (args[0]->expr.isconst)
- fatal(n, "attempting to assign constant \"%s\"", ctxstr(st, args[0]));
- break;
-
- /* operands same type, returning bool */
- case Olor: /* @a || @b -> bool */
- case Oland: /* @a && @b -> bool */
- case Oeq: /* @a == @a -> bool */
- case One: /* @a != @a -> bool */