summaryrefslogtreecommitdiff
path: root/6
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-11-17 20:53:32 -0800
committerOri Bernstein <ori@eigenstate.org>2015-11-17 20:53:32 -0800
commit8531896f8d21ba1e727262aaf5cd96043590b480 (patch)
tree7c01441755f56ab66d33c37d3ac41642ddc46c0b /6
parentc20862cda53c711fe476f6c7d0f6631af47a4933 (diff)
downloadmc-8531896f8d21ba1e727262aaf5cd96043590b480.tar.gz
MEGAPATCH: Tabification.
Tabs > spaces. By 4 spaces, to be precise. Let's use them.
Diffstat (limited to '6')
-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
12 files changed, 5311 insertions, 5311 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);
}