ref: 8531896f8d21ba1e727262aaf5cd96043590b480
parent: c20862cda53c711fe476f6c7d0f6631af47a4933
author: Ori Bernstein <[email protected]>
date: Tue Nov 17 15:53:32 EST 2015
MEGAPATCH: Tabification. Tabs > spaces. By 4 spaces, to be precise. Let's use them.
--- a/6/asm.h
+++ b/6/asm.h
@@ -21,218 +21,218 @@
#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 */
+ 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 */
+ 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? */
+ 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 */
+ 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 */
+ 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 */
--- a/6/blob.c
+++ b/6/blob.c
@@ -19,260 +19,260 @@
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;
+ Blob *b;
- b = zalloc(sizeof(Blob));
- b->type = Btref;
- b->ref.str = strdup(lbl);
- b->ref.isextern = isextern;
- b->ref.off = off;
- return 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;
+ 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);
+ 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;
+ 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;
-}
+ 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;
+ 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];
+ 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]);
+ /* 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
}
--- 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;
+ 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);
+ 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);
+ 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;
+ 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;
+ 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 @@
*/
char *asmname(Node *dcl)
{
- char buf[1024];
- char *vis, *pf, *ns, *name, *sep;
- Node *n;
+ 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 = "";
+ 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);
+ 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;
+ 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;
+ 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;
+ }
}
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -30,12 +30,12 @@
};
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);
@@ -42,300 +42,300 @@
static void initconsts(Htab *globls)
{
- Type *ty;
- Node *name;
- Node *dcl;
+ Type *ty;
+ Node *name;
+ Node *dcl;
- tyintptr = mktype(Zloc, Tyuint64);
- tyword = mktype(Zloc, Tyuint);
- tyvoid = mktype(Zloc, Tyvoid);
+ 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));
+ 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;
+ 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;
+ 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;
- }
+ /* 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;
+ /* %-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;
+ 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");
- }
+ 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;
+ 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);
- }
+ 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;
+ 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]);
- }
+ 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;
+ size_t i, shift;
+ uint8_t b;
- if (val < 128) {
- fprintf(fd, "\t.byte %zd\n", val);
- return;
- }
+ 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;
- }
+ 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;
+ 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;
+ 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 @@
* operations on x32, no structures, and so on. */
static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
{
- Isel is = {0,};
+ 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);
+ 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);
+ 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;
+ char *lbl;
+ Blob *b;
- /* lits and such also get wrapped in decls */
- assert(blob->type == Ndecl);
+ /* 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);
+ 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;
+ 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);
+ /* 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);
+ 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);
+ /* 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();
+ 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);
+ 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");
+ 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");
+ 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");
+ 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);
+ 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);
}
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -29,12 +29,12 @@
};
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);
@@ -41,322 +41,322 @@
static void initconsts(Htab *globls)
{
- Type *ty;
- Node *name;
- Node *dcl;
+ Type *ty;
+ Node *name;
+ Node *dcl;
- tyintptr = mktype(Zloc, Tyuint64);
- tyword = mktype(Zloc, Tyuint);
- tyvoid = mktype(Zloc, Tyvoid);
+ 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));
+ 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;
+ 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;
+ 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;
- }
+ /* 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;
+ /* %-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;
+ 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");
- }
+ 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;
+ return sz;
}
static void genstrings(FILE *fd, Htab *strtab)
{
- void **k;
- char *lbl;
- Str *s;
- size_t i, nk;
+ 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);
- }
- }
+ 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;
+ 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]);
- }
+ 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;
+ 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;
- }
+ 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;
+ 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;
+ 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;
+ 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;
+ 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 @@
* operations on x32, no structures, and so on. */
static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
{
- Isel is = {0,};
+ 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);
+ 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);
+ 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];
+ 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);
+ 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;
+ char *lbl;
+ Blob *b;
- /* lits and such also get wrapped in decls */
- assert(blob->type == Ndecl);
+ /* 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);
+ 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;
+ 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);
+ /* 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);
+ 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);
+ /* 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();
+ 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);
+ 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);
+ 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);
+ fclose(fd);
}
--- a/6/isel.c
+++ b/6/isel.c
@@ -22,8 +22,8 @@
#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};
@@ -30,236 +30,236 @@
/* 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;
+ 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;
+ /* 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;
+ 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;
-}
+ 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;
+ 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;
+ 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_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_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;
+ 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);
+ 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;
+ 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);
+ 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;
+ 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;
+ 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 @@
* directly */
static void selcjmp(Isel *s, Node *n, Node **args)
{
- Loc *a, *b;
- Loc *l1, *l2;
- AsmOp cond, jmp;
+ 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;
- }
+ 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 */
+ /* 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);
+ 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 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 int ismergablemul(Node *n, int *r)
{
- int v;
+ 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;
+ 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;
+ 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]);
+ 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;
+ 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 */
+ 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);
+ 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);
- }
-
+ 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;
+ 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);
- }
+ 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;
+ 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);
+ 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;
+ 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;
+ 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;
+ 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);
+ 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;
+ /* 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;
+ 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]));
+ 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;
+ 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;
+ /* 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 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 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 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 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]));
+ 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;
+ 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;
+ 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;
+ 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;
+ /* 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;
+ 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;
+ /* 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;
+ 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);
- }
- }
+ 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;
+ 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 */
+ 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;
+ 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);
+ 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;
+ 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;
+ 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];
+ 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]));
+ 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);
+ 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);
}
--- a/6/locs.c
+++ b/6/locs.c
@@ -23,44 +23,44 @@
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 @@
static Loc *locregid(regid id, Mode m)
{
- Loc *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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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},
+ 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},
+ };
- [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]);
+ assert(crtab[r][m] != Rnone);
+ return locphysreg(crtab[r][m]);
}
--- a/6/main.c
+++ b/6/main.c
@@ -32,215 +32,215 @@
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;
+ 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);
+ 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");
- }
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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);
+ 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;
+ char buf[1024];
+ Stab *globls;
+ Optctx ctx;
+ size_t i;
- outfile = NULL;
+ 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;
- }
- }
+ 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");
+ 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;
+ 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();
+ 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);
+ /* 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]);
- }
+ 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;
+ return 0;
}
--- 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 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);
+ }
}
--- 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 @@
/* 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,
+ /* 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,
+ /* 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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]);
- }
+ 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;
+ 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);
- }
+ 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);
- }
- }
+ 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;
+ size_t i;
- for (i = 0; i < nwl; i++) {
- if (wl[i]->reg.id == v) {
- *idx = i;
- return 1;
- }
- }
- *idx = -1;
- return 0;
+ 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 degreechange(Isel *s, regid u, regid v)
{
- regid phys, virt, r;
- size_t i;
+ 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;
- }
+ 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;
+ 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;
+ 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);
- }
+ 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;
+ 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));
+ 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);
+ 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);
+ 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));
+ 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;
+ 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;
+ 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;
+ /* 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);
+ 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]);
- }
+ /* 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]);
- }
- }
+ /* 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 < 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);
- }
+ 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;
+ 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;
+ /* 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;
+ 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;
+ 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;
+ 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;
- }
+ 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;
+ 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);
- }
- }
- }
+ 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;
+ 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);
+ 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);
- }
+ 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]);
- }
- }
- }
+ /* 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;
+ 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);
- }
+ 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;
+ size_t i;
- if (bshas(s->prepainted, u))
- return;
- if (moverelated(s, u))
- return;
- if (!istrivial(s, u))
- return;
+ 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]);
+ 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;
+ 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])];
+ 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;
+ 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;
+ /* 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;
+ /* 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;
+ 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];
+ 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]);
- }
+ /* 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]);
- }
+ 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;
+ 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);
+ 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;
+ 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);
+ 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 (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);
- }
+ 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;
+ 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)];
+ 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);
+ 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);
- }
+ 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);
+ }
+ 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;
+ 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);
+ /* 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 int paint(Isel *s)
{
- int taken[Nreg];
- Loc *n, *w;
- regid l;
- size_t i, j;
- int spilled;
- int found;
+ 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);
+ 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;
- }
+ 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;
+ 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;
+ Loc *new;
+ Loc *base;
+ Loc *idx;
+ regid id;
- if (!old)
- return NULL;
+ 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;
+ 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 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;
+ 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;
- }
+ 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;
- }
+ 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;
+ 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;
+ 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)];
- }
- }
+ 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 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;
+ 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;
+ 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 rewrite(Isel *s, Loc **aliasmap)
{
- size_t i;
+ 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]);
+ 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);
+ /* 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 delnops(Isel *s)
{
- Insn *insn;
- Asmbb *bb;
- Insn **new;
- size_t nnew;
- size_t i, j;
+ 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);
+ 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;
+ 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);
+ /* 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);
+ 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;
+ 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");
+ 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;
+ 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");
+ 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;
+ 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");
+ 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;
+ 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, "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, "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");
+ 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");
}
--- a/6/simp.c
+++ b/6/simp.c
@@ -24,42 +24,42 @@
*/
typedef struct Simp Simp;
struct Simp {
- int isglobl;
+ int isglobl;
- Node **stmts;
- size_t nstmts;
+ Node **stmts;
+ size_t nstmts;
- /* return handling */
- Node *endlbl;
- Node *ret;
- int hasenv;
- int isbigret;
+ /* return handling */
+ Node *endlbl;
+ Node *ret;
+ int hasenv;
+ int isbigret;
- /* the array we're indexing for context within [] */
- Node **idxctx;
- size_t nidxctx;
+ /* the array we're indexing for context within [] */
+ Node **idxctx;
+ size_t nidxctx;
- /* pre/postinc handling */
- Node **incqueue;
- size_t nqueue;
+ /* pre/postinc handling */
+ Node **incqueue;
+ size_t nqueue;
- /* break/continue handling */
- Node **loopstep;
- size_t nloopstep;
- Node **loopexit;
- size_t nloopexit;
+ /* break/continue handling */
+ Node **loopstep;
+ size_t nloopstep;
+ Node **loopexit;
+ size_t nloopexit;
- /* location handling */
- Node **blobs;
- size_t nblobs;
- Htab *globls;
+ /* location handling */
+ Node **blobs;
+ size_t nblobs;
+ Htab *globls;
- Htab *stkoff;
- Htab *envoff;
- size_t stksz;
+ Htab *stkoff;
+ Htab *envoff;
+ size_t stksz;
- Node **args;
- size_t nargs;
+ Node **args;
+ size_t nargs;
};
static int envcmp(const void *pa, const void *pb);
@@ -83,132 +83,132 @@
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;
+ 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;
- }
+ 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));
+ 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
@@ -215,141 +215,141 @@
* 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;;
@@ -356,36 +356,36 @@
* => cjmp (foo) :bar :baz */
static void simpif(Simp *s, Node *n, Node *exit)
{
- Node *l1, *l2, *l3;
- Node *iftrue, *iffalse;
+ Node *l1, *l2, *l3;
+ Node *iftrue, *iffalse;
- l1 = genlbl(n->loc);
- l2 = genlbl(n->loc);
- if (exit)
- l3 = exit;
- else
- l3 = genlbl(n->loc);
+ 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;
+ 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);
- }
+ 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);
+ if (!exit)
+ simp(s, l3);
}
/* init; while cond; body;;
@@ -401,31 +401,31 @@
*/
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,399 +448,399 @@
*/
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;
+ 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);
+ 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);
+ lappend(&s->loopstep, &s->nloopstep, lstep);
+ lappend(&s->loopexit, &s->nloopexit, lend);
- zero = mkintlit(n->loc, 0);
- zero->expr.type = tyintptr;
+ 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);
+ 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);
+ /* 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));
+ /* 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);
+ /* 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--;
+ 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;
+ 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;
+ 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;
+ 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;
- }
+ 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;
+ 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;
+ 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;
+ /* 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;
+ 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;
- }
+ 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;
+ 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;
+ 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,
@@ -847,92 +847,92 @@
* 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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]);
- }
+ 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;
+ 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
@@ -939,63 +939,63 @@
* 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;
+ 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 (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;
+ /* 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 @@
* 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;
+ 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");
+ /* 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);
+ 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));
+ /* 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;
+ /* 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 *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;
+ 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];
+ 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;
+ 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];
+ 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;
+ 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;
+ /* 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 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);
+ /* 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;
+ 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;
+ 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));
+ 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);
+ 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]));
+ /* 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));
+ 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;
+ 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;
+ 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);
+ /* 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));
- }
+ 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)));
+ 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));
+ 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);
+ 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;
+ 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;
+ 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,
- };
+ 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;
+ 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;
+ /* 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)
+ * => 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;
-}
+ /* 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;
+ 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;
+ 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;
+ 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 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;
+ 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);
+ 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;
+ 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);
+ 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);
+ /* 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");
- }
- }
+ 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);
+ 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;
+ 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;
+ 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));
- }
+ 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;
+ 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 (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);
+ 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);
}
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -21,353 +21,354 @@
size_t blobsz(Blob *b)
{
- size_t n;
- size_t i;
+ 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");
+ 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;
+ 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;
+ 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));
+ 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;
+ 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;
+ 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;
+ 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;
+ /* 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));
- }
+ 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;
+ 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;
+ 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);
+ 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;
+ char buf[512];
+ Blob *b, *sz, *sub;
- if (ty->type == Tyname && hasparams(ty))
- return NULL;
+ 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;
+ 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;
+ 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;
+ 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 Typtr:
+ case Tyvalist: /* ptr to first element of valist */
+ return Ptrsz;
- case Tyint64:
- case Tyuint64:
- return 8;
+ case Tyint64:
+ case Tyuint64:
+ return 8;
- /*end integer types*/
- case Tyflt32:
- return 4;
- case Tyflt64:
- 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;
+ 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;
+ 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);
+ 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;
+ size_t i;
+ size_t off;
- ty = tybase(ty);
- if (ty->type == Typtr)
- ty = tybase(ty->sub[0]);
+ 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;
+ 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);
}
--- a/bench/runner.c
+++ /dev/null
@@ -1,84 +1,0 @@
-/* written in C instead of Myrddin because I don't have FP in Myrddin yet... */
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <err.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-
-#define Nsamp 10
-
-double run(char *prog)
-{
- struct rusage ru;
- double sec, usec;
- int in, out;
- char *cmd[2];
- int pid;
- int status;
-
- sec = 0;
- usec = 0;
- pid = fork();
- if (pid < 0) {
- err(1, "Could not fork\n");
- } else if (pid == 0) {
- if ((in = open("/dev/zero", O_RDONLY)) < 0)
- err(1, "could not open /dev/zero");
- if ((out = open("/dev/null", O_WRONLY)) < 0)
- err(1, "could not open /dev/null");
- if (dup2(in, 0) < 0)
- err(1, "could not reopen stdin");
- if (dup2(out, 1) < 0)
- err(1, "could not reopen stdout");
-
- cmd[0] = prog;
- cmd[1] = NULL;
- execv(prog, cmd);
- err(1, "Failed to exec\n");
- } else {
- wait4(pid, &status, 0, &ru);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- err(1, "Subprogram failed to execute\n");
- sec = ru.ru_utime.tv_sec;
- usec = ru.ru_utime.tv_usec / (1000.0 * 1000.0);
- }
- return sec + usec;
-}
-
-double timed_run(char *prog)
-{
- double avg, m, d, x;
- int i, n;
-
- avg = 0;
- m = 0;
- n = 0;
- for (i = 0; i < Nsamp; i++) {
- n++;
- x = run(prog);
- d = (x - avg);
- avg += d/n;
- m = m + d*(x - avg);
- }
- printf("%s:\t%fs (σ^2: %f)\n", prog, avg, m/(n-1));
- return avg;
-}
-
-int main(int argc, char **argv)
-{
- double tot;
- int i;
-
- printf("Running benchmarks: %d samples per binary\n", Nsamp);
- tot = 0;
- for (i = 1; i < argc; i++)
- tot += timed_run(argv[i]);
- printf("total:\t%fs\n", tot);
- return 0;
-}
-
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -16,298 +16,298 @@
static Bb *mkbb(Cfg *cfg)
{
- Bb *bb;
+ Bb *bb;
- bb = zalloc(sizeof(Bb));
- bb->id = cfg->nextbbid++;
- bb->pred = mkbs();
- bb->succ = mkbs();
- lappend(&cfg->bb, &cfg->nbb, bb);
- return bb;
+ bb = zalloc(sizeof(Bb));
+ bb->id = cfg->nextbbid++;
+ bb->pred = mkbs();
+ bb->succ = mkbs();
+ lappend(&cfg->bb, &cfg->nbb, bb);
+ return bb;
}
static void strlabel(Cfg *cfg, char *lbl, Bb *bb)
{
- htput(cfg->lblmap, lbl, bb);
- lappend(&bb->lbls, &bb->nlbls, lbl);
+ htput(cfg->lblmap, lbl, bb);
+ lappend(&bb->lbls, &bb->nlbls, lbl);
}
static void label(Cfg *cfg, Node *lbl, Bb *bb)
{
- strlabel(cfg, lblstr(lbl), bb);
+ strlabel(cfg, lblstr(lbl), bb);
}
static int isnonretcall(Node *fn)
{
- Node *dcl;
+ Node *dcl;
- if (exprop(fn) != Ovar)
- return 0;
- dcl = decls[fn->expr.did];
- return dcl->decl.isnoret;
+ if (exprop(fn) != Ovar)
+ return 0;
+ dcl = decls[fn->expr.did];
+ return dcl->decl.isnoret;
}
static int addnode(Cfg *cfg, Bb *bb, Node *n)
{
- switch (exprop(n)) {
- case Ojmp:
- case Ocjmp:
- case Oret:
- lappend(&bb->nl, &bb->nnl, n);
- lappend(&cfg->fixjmp, &cfg->nfixjmp, n);
- lappend(&cfg->fixblk, &cfg->nfixblk, bb);
- return 1;
- case Ocall:
- lappend(&bb->nl, &bb->nnl, n);
- return isnonretcall(n->expr.args[0]);
- case Odead:
- lappend(&bb->nl, &bb->nnl, n);
- return 1;
- default:
- lappend(&bb->nl, &bb->nnl, n);
- break;
- }
- return 0;
+ switch (exprop(n)) {
+ case Ojmp:
+ case Ocjmp:
+ case Oret:
+ lappend(&bb->nl, &bb->nnl, n);
+ lappend(&cfg->fixjmp, &cfg->nfixjmp, n);
+ lappend(&cfg->fixblk, &cfg->nfixblk, bb);
+ return 1;
+ case Ocall:
+ lappend(&bb->nl, &bb->nnl, n);
+ return isnonretcall(n->expr.args[0]);
+ case Odead:
+ lappend(&bb->nl, &bb->nnl, n);
+ return 1;
+ default:
+ lappend(&bb->nl, &bb->nnl, n);
+ break;
+ }
+ return 0;
}
static int islabel(Node *n)
{
- Node *l;
- if (n->type != Nexpr)
- return 0;
- if (exprop(n) != Olit)
- return 0;
- l = n->expr.args[0];
- if (l->type != Nlit)
- return 0;
- if (l->lit.littype != Llbl)
- return 0;
- return 1;
+ Node *l;
+ if (n->type != Nexpr)
+ return 0;
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->type != Nlit)
+ return 0;
+ if (l->lit.littype != Llbl)
+ return 0;
+ return 1;
}
static Bb *addlabel(Cfg *cfg, Bb *bb, Node **nl, size_t i, Srcloc loc)
{
- /* if the current block assumes fall-through, insert an explicit jump */
- if (i > 0 && nl[i - 1]->type == Nexpr) {
- if (exprop(nl[i - 1]) != Ocjmp && exprop(nl[i - 1]) != Ojmp)
- addnode(cfg, bb, mkexpr(loc, Ojmp, mklbl(loc, lblstr(nl[i])), NULL));
- }
- if (bb->nnl)
- bb = mkbb(cfg);
- label(cfg, nl[i], bb);
- return bb;
+ /* if the current block assumes fall-through, insert an explicit jump */
+ if (i > 0 && nl[i - 1]->type == Nexpr) {
+ if (exprop(nl[i - 1]) != Ocjmp && exprop(nl[i - 1]) != Ojmp)
+ addnode(cfg, bb, mkexpr(loc, Ojmp, mklbl(loc, lblstr(nl[i])), NULL));
+ }
+ if (bb->nnl)
+ bb = mkbb(cfg);
+ label(cfg, nl[i], bb);
+ return bb;
}
void delete(Cfg *cfg, Bb *bb)
{
- size_t i, j;
+ size_t i, j;
- if (bb == cfg->start || bb == cfg->end)
- return;
- for (i = 0; bsiter(bb->pred, &i); i++) {
- bsunion(cfg->bb[i]->succ, bb->succ);
- bsdel(cfg->bb[i]->succ, bb->id);
- }
- for (i = 0; bsiter(bb->succ, &i); i++) {
- bsunion(cfg->bb[i]->pred, bb->pred);
- bsdel(cfg->bb[i]->pred, bb->id);
- for (j = 0; j < bb->nlbls; j++)
- strlabel(cfg, bb->lbls[j], cfg->bb[i]);
- }
- cfg->bb[bb->id] = NULL;
+ if (bb == cfg->start || bb == cfg->end)
+ return;
+ for (i = 0; bsiter(bb->pred, &i); i++) {
+ bsunion(cfg->bb[i]->succ, bb->succ);
+ bsdel(cfg->bb[i]->succ, bb->id);
+ }
+ for (i = 0; bsiter(bb->succ, &i); i++) {
+ bsunion(cfg->bb[i]->pred, bb->pred);
+ bsdel(cfg->bb[i]->pred, bb->id);
+ for (j = 0; j < bb->nlbls; j++)
+ strlabel(cfg, bb->lbls[j], cfg->bb[i]);
+ }
+ cfg->bb[bb->id] = NULL;
}
void noexit(Cfg *cfg, Bb *bb)
{
- size_t i;
- for (i = 0; bsiter(bb->succ, &i); i++)
- bsdel(cfg->bb[i]->pred, bb->id);
- bsclear(bb->succ);
+ size_t i;
+ for (i = 0; bsiter(bb->succ, &i); i++)
+ bsdel(cfg->bb[i]->pred, bb->id);
+ bsclear(bb->succ);
}
void trimdead(Cfg *cfg, Bb *bb)
{
- size_t i;
+ size_t i;
- if (!bb)
- return;
- for (i = 0; i < bb->nnl; i++) {
- switch (exprop(bb->nl[i])) {
- /* if we're jumping, we can't keep going
- * within this BB */
- case Ojmp:
- case Ocjmp:
- case Oret:
- bb->nnl = i + 1;
- return;
- case Odead:
- noexit(cfg, bb);
- bb->nnl = i + 1;
- return;
- case Ocall:
- if (isnonretcall(bb->nl[i]->expr.args[0])) {
- noexit(cfg, bb);
- bb->nnl = i + 1;
- return;
- }
- break;
- default:
- /* nothing */
- break;
- }
- }
-}
+ if (!bb)
+ return;
+ for (i = 0; i < bb->nnl; i++) {
+ switch (exprop(bb->nl[i])) {
+ /* if we're jumping, we can't keep going
+ * within this BB */
+ case Ojmp:
+ case Ocjmp:
+ case Oret:
+ bb->nnl = i + 1;
+ return;
+ case Odead:
+ noexit(cfg, bb);
+ bb->nnl = i + 1;
+ return;
+ case Ocall:
+ if (isnonretcall(bb->nl[i]->expr.args[0])) {
+ noexit(cfg, bb);
+ bb->nnl = i + 1;
+ return;
+ }
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ }
+}
void trim(Cfg *cfg)
{
- Bb *bb;
- size_t i;
- int deleted;
+ Bb *bb;
+ size_t i;
+ int deleted;
- deleted = 1;
- while (deleted) {
- deleted = 0;
- for (i = 0; i < cfg->nbb; i++) {
- bb = cfg->bb[i];
- if (bb == cfg->start || bb == cfg->end)
- continue;
- trimdead(cfg, bb);
- if (bb && bsisempty(bb->pred)) {
- delete(cfg, bb);
- deleted = 1;
- }
- }
- }
+ deleted = 1;
+ while (deleted) {
+ deleted = 0;
+ for (i = 0; i < cfg->nbb; i++) {
+ bb = cfg->bb[i];
+ if (bb == cfg->start || bb == cfg->end)
+ continue;
+ trimdead(cfg, bb);
+ if (bb && bsisempty(bb->pred)) {
+ delete(cfg, bb);
+ deleted = 1;
+ }
+ }
+ }
}
Cfg *mkcfg(Node *fn, Node **nl, size_t nn)
{
- Cfg *cfg;
- Bb *pre, *post;
- Bb *bb, *targ;
- Node *a, *b;
- static int nextret;
- char buf[32];
- size_t i;
+ Cfg *cfg;
+ Bb *pre, *post;
+ Bb *bb, *targ;
+ Node *a, *b;
+ static int nextret;
+ char buf[32];
+ size_t i;
- cfg = zalloc(sizeof(Cfg));
- cfg->fn = fn;
- cfg->lblmap = mkht(strhash, streq);
- pre = mkbb(cfg);
- bb = mkbb(cfg);
- for (i = 0; i < nn; i++) {
- switch (nl[i]->type) {
- case Nexpr:
- if (islabel(nl[i]))
- bb = addlabel(cfg, bb, nl, i, nl[i]->loc);
- else if (addnode(cfg, bb, nl[i]))
- bb = mkbb(cfg);
- break;
- break;
- case Ndecl:
- break;
- default:
- die("Invalid node type %s in mkcfg", nodestr[nl[i]->type]);
- }
- }
- post = mkbb(cfg);
- bprintf(buf, sizeof buf, ".R%d", nextret++);
- label(cfg, mklbl(fn->loc, buf), post);
+ cfg = zalloc(sizeof(Cfg));
+ cfg->fn = fn;
+ cfg->lblmap = mkht(strhash, streq);
+ pre = mkbb(cfg);
+ bb = mkbb(cfg);
+ for (i = 0; i < nn; i++) {
+ switch (nl[i]->type) {
+ case Nexpr:
+ if (islabel(nl[i]))
+ bb = addlabel(cfg, bb, nl, i, nl[i]->loc);
+ else if (addnode(cfg, bb, nl[i]))
+ bb = mkbb(cfg);
+ break;
+ break;
+ case Ndecl:
+ break;
+ default:
+ die("Invalid node type %s in mkcfg", nodestr[nl[i]->type]);
+ }
+ }
+ post = mkbb(cfg);
+ bprintf(buf, sizeof buf, ".R%d", nextret++);
+ label(cfg, mklbl(fn->loc, buf), post);
- cfg->start = pre;
- cfg->end = post;
- bsput(pre->succ, cfg->bb[1]->id);
- bsput(cfg->bb[1]->pred, pre->id);
- bsput(cfg->bb[cfg->nbb - 2]->succ, post->id);
- bsput(post->pred, cfg->bb[cfg->nbb - 2]->id);
+ cfg->start = pre;
+ cfg->end = post;
+ bsput(pre->succ, cfg->bb[1]->id);
+ bsput(cfg->bb[1]->pred, pre->id);
+ bsput(cfg->bb[cfg->nbb - 2]->succ, post->id);
+ bsput(post->pred, cfg->bb[cfg->nbb - 2]->id);
- for (i = 0; i < cfg->nfixjmp; i++) {
- bb = cfg->fixblk[i];
- switch (exprop(cfg->fixjmp[i])) {
- case Ojmp:
- a = cfg->fixjmp[i]->expr.args[0];
- b = NULL;
- break;
- case Ocjmp:
- a = cfg->fixjmp[i]->expr.args[1];
- b = cfg->fixjmp[i]->expr.args[2];
- break;
- case Oret:
- a = mklbl(cfg->fixjmp[i]->loc, cfg->end->lbls[0]);
- b = NULL;
- break;
- default:
- die("Bad jump fix thingy");
- break;
- }
- if (a) {
- targ = htget(cfg->lblmap, lblstr(a));
- if (!targ)
- die("No bb with label \"%s\"", lblstr(a));
- bsput(bb->succ, targ->id);
- bsput(targ->pred, bb->id);
- }
- if (b) {
- targ = htget(cfg->lblmap, lblstr(b));
- if (!targ)
- die("No bb with label \"%s\"", lblstr(b));
- bsput(bb->succ, targ->id);
- bsput(targ->pred, bb->id);
- }
- }
- trim(cfg);
- return cfg;
+ for (i = 0; i < cfg->nfixjmp; i++) {
+ bb = cfg->fixblk[i];
+ switch (exprop(cfg->fixjmp[i])) {
+ case Ojmp:
+ a = cfg->fixjmp[i]->expr.args[0];
+ b = NULL;
+ break;
+ case Ocjmp:
+ a = cfg->fixjmp[i]->expr.args[1];
+ b = cfg->fixjmp[i]->expr.args[2];
+ break;
+ case Oret:
+ a = mklbl(cfg->fixjmp[i]->loc, cfg->end->lbls[0]);
+ b = NULL;
+ break;
+ default:
+ die("Bad jump fix thingy");
+ break;
+ }
+ if (a) {
+ targ = htget(cfg->lblmap, lblstr(a));
+ if (!targ)
+ die("No bb with label \"%s\"", lblstr(a));
+ bsput(bb->succ, targ->id);
+ bsput(targ->pred, bb->id);
+ }
+ if (b) {
+ targ = htget(cfg->lblmap, lblstr(b));
+ if (!targ)
+ die("No bb with label \"%s\"", lblstr(b));
+ bsput(bb->succ, targ->id);
+ bsput(targ->pred, bb->id);
+ }
+ }
+ trim(cfg);
+ return cfg;
}
void dumpbb(Bb *bb, FILE *fd)
{
- size_t i;
- char *sep;
+ size_t i;
+ char *sep;
- fprintf(fd, "Bb: %d labels=(", bb->id);
- sep = "";
- for (i = 0; i < bb->nlbls; i++) {;
- fprintf(fd, "%s%s", bb->lbls[i], sep);
- sep = ",";
- }
- fprintf(fd, ")\n");
+ fprintf(fd, "Bb: %d labels=(", bb->id);
+ sep = "";
+ for (i = 0; i < bb->nlbls; i++) {;
+ fprintf(fd, "%s%s", bb->lbls[i], sep);
+ sep = ",";
+ }
+ fprintf(fd, ")\n");
- /* in edges */
- fprintf(fd, "Pred: ");
- sep = "";
- for (i = 0; i < bsmax(bb->pred); i++) {
- if (bshas(bb->pred, i)) {
- fprintf(fd, "%s%zd", sep, i);
- sep = ",";
- }
- }
- fprintf(fd, "\n");
+ /* in edges */
+ fprintf(fd, "Pred: ");
+ sep = "";
+ for (i = 0; i < bsmax(bb->pred); i++) {
+ if (bshas(bb->pred, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
- /* out edges */
- fprintf(fd, "Succ: ");
- sep = "";
- for (i = 0; i < bsmax(bb->succ); i++) {
- if (bshas(bb->succ, i)) {
- fprintf(fd, "%s%zd", sep, i);
- sep = ",";
- }
- }
- fprintf(fd, "\n");
+ /* out edges */
+ fprintf(fd, "Succ: ");
+ sep = "";
+ for (i = 0; i < bsmax(bb->succ); i++) {
+ if (bshas(bb->succ, i)) {
+ fprintf(fd, "%s%zd", sep, i);
+ sep = ",";
+ }
+ }
+ fprintf(fd, "\n");
- for (i = 0; i < bb->nnl; i++)
- dump(bb->nl[i], fd);
- fprintf(fd, "\n");
+ for (i = 0; i < bb->nnl; i++)
+ dump(bb->nl[i], fd);
+ fprintf(fd, "\n");
}
void dumpcfg(Cfg *cfg, FILE *fd)
{
- size_t i;
+ size_t i;
- for (i = 0; i < cfg->nbb; i++) {
- if (!cfg->bb[i])
- continue;
- fprintf(fd, "\n");
- dumpbb(cfg->bb[i], fd);
- }
+ for (i = 0; i < cfg->nbb; i++) {
+ if (!cfg->bb[i])
+ continue;
+ fprintf(fd, "\n");
+ dumpbb(cfg->bb[i], fd);
+ }
}
--- a/mi/dfcheck.c
+++ b/mi/dfcheck.c
@@ -15,117 +15,117 @@
static void checkundef(Node *n, Reaching *r, Bitset *reach, Bitset *kill)
{
- size_t i, j, did;
- Node *def;
- Type *t;
+ size_t i, j, did;
+ Node *def;
+ Type *t;
- if (n->type != Nexpr)
- return;
- if (exprop(n) == Ovar) {
- did = n->expr.did;
- for (j = 0; j < r->ndefs[did]; j++) {
- t = tybase(exprtype(n));
- if (t->type == Tystruct || t->type == Tyunion || t->type == Tyarray || t->type == Tytuple)
- continue;
- if (bshas(kill, r->defs[did][j]))
- continue;
- if (!bshas(reach, r->defs[did][j]))
- continue;
- def = nodes[r->defs[did][j]];
- if (exprop(def) == Oundef)
- fatal(n, "%s used before definition", namestr(n->expr.args[0]));
- }
- } else {
- switch (exprop(n)) {
- case Oset:
- case Oasn:
- case Oblit:
- checkundef(n->expr.args[1], r, reach, kill);
- break;
- case Oaddr:
- case Oslice:
- /* these don't actually look at the of args[0], so they're ok. */
- for (i = 1; i < n->expr.nargs; i++)
- checkundef(n->expr.args[i], r, reach, kill);
- break;
- case Ocall:
- for (i = 1; i < n->expr.nargs; i++)
- if (exprop(n->expr.args[i]) != Oaddr)
- checkundef(n->expr.args[i], r, reach, kill);
- break;
- default:
- for (i = 0; i < n->expr.nargs; i++)
- checkundef(n->expr.args[i], r, reach, kill);
- break;
- }
- }
+ if (n->type != Nexpr)
+ return;
+ if (exprop(n) == Ovar) {
+ did = n->expr.did;
+ for (j = 0; j < r->ndefs[did]; j++) {
+ t = tybase(exprtype(n));
+ if (t->type == Tystruct || t->type == Tyunion || t->type == Tyarray || t->type == Tytuple)
+ continue;
+ if (bshas(kill, r->defs[did][j]))
+ continue;
+ if (!bshas(reach, r->defs[did][j]))
+ continue;
+ def = nodes[r->defs[did][j]];
+ if (exprop(def) == Oundef)
+ fatal(n, "%s used before definition", namestr(n->expr.args[0]));
+ }
+ } else {
+ switch (exprop(n)) {
+ case Oset:
+ case Oasn:
+ case Oblit:
+ checkundef(n->expr.args[1], r, reach, kill);
+ break;
+ case Oaddr:
+ case Oslice:
+ /* these don't actually look at the of args[0], so they're ok. */
+ for (i = 1; i < n->expr.nargs; i++)
+ checkundef(n->expr.args[i], r, reach, kill);
+ break;
+ case Ocall:
+ for (i = 1; i < n->expr.nargs; i++)
+ if (exprop(n->expr.args[i]) != Oaddr)
+ checkundef(n->expr.args[i], r, reach, kill);
+ break;
+ default:
+ for (i = 0; i < n->expr.nargs; i++)
+ checkundef(n->expr.args[i], r, reach, kill);
+ break;
+ }
+ }
}
static void checkreach(Cfg *cfg)
{
- Bitset *reach, *kill;
- size_t i, j, k;
- Reaching *r;
- Node *n, *m;
- Bb *bb;
+ Bitset *reach, *kill;
+ size_t i, j, k;
+ Reaching *r;
+ Node *n, *m;
+ Bb *bb;
- r = reaching(cfg);
- for (i = 0; i < cfg->nbb; i++) {
- bb = cfg->bb[i];
- if (!bb)
- continue;
- reach = bsdup(r->in[i]);
- kill = mkbs();
- for (j = 0; j < bb->nnl; j++) {
- n = bb->nl[j];
- if (exprop(n) == Oundef) {
- bsput(reach, n->nid);
- } else {
- m = assignee(n);
- if (m)
- for (k = 0; k < r->ndefs[m->expr.did]; k++)
- bsput(kill, r->defs[m->expr.did][k]);
- checkundef(n, r, reach, kill);
- }
- }
- bsfree(reach);
- bsfree(kill);
- }
+ r = reaching(cfg);
+ for (i = 0; i < cfg->nbb; i++) {
+ bb = cfg->bb[i];
+ if (!bb)
+ continue;
+ reach = bsdup(r->in[i]);
+ kill = mkbs();
+ for (j = 0; j < bb->nnl; j++) {
+ n = bb->nl[j];
+ if (exprop(n) == Oundef) {
+ bsput(reach, n->nid);
+ } else {
+ m = assignee(n);
+ if (m)
+ for (k = 0; k < r->ndefs[m->expr.did]; k++)
+ bsput(kill, r->defs[m->expr.did][k]);
+ checkundef(n, r, reach, kill);
+ }
+ }
+ bsfree(reach);
+ bsfree(kill);
+ }
}
static void checkpredret(Cfg *cfg, Bb *bb)
{
- Bb *pred;
- Op op;
- size_t i;
+ Bb *pred;
+ Op op;
+ size_t i;
- for (i = 0; bsiter(bb->pred, &i); i++) {
- pred = cfg->bb[i];
- if (pred->nnl == 0) {
- checkpredret(cfg, pred);
- } else {
- op = exprop(pred->nl[pred->nnl - 1]);
- if (op != Oret && op != Odead) {
- fatal(pred->nl[pred->nnl-1], "Reaches end of function without return\n");
- }
- }
- }
+ for (i = 0; bsiter(bb->pred, &i); i++) {
+ pred = cfg->bb[i];
+ if (pred->nnl == 0) {
+ checkpredret(cfg, pred);
+ } else {
+ op = exprop(pred->nl[pred->nnl - 1]);
+ if (op != Oret && op != Odead) {
+ fatal(pred->nl[pred->nnl-1], "Reaches end of function without return\n");
+ }
+ }
+ }
}
static void checkret(Cfg *cfg)
{
- Type *ft;
+ Type *ft;
- ft = tybase(decltype(cfg->fn));
- assert(ft->type == Tyfunc || ft->type == Tycode);
- if (ft->sub[0]->type == Tyvoid)
- return;
+ ft = tybase(decltype(cfg->fn));
+ assert(ft->type == Tyfunc || ft->type == Tycode);
+ if (ft->sub[0]->type == Tyvoid)
+ return;
- checkpredret(cfg, cfg->end);
+ checkpredret(cfg, cfg->end);
}
void check(Cfg *cfg)
{
- checkret(cfg);
- if(0) checkreach(cfg);
+ checkret(cfg);
+ if(0) checkreach(cfg);
}
--- a/mi/fold.c
+++ b/mi/fold.c
@@ -15,226 +15,226 @@
static int getintlit(Node *n, vlong *v)
{
- Node *l;
+ Node *l;
- if (exprop(n) != Olit)
- return 0;
- l = n->expr.args[0];
- if (l->lit.littype != Lint)
- return 0;
- *v = l->lit.intval;
- return 1;
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->lit.littype != Lint)
+ return 0;
+ *v = l->lit.intval;
+ return 1;
}
static int isintval(Node *n, vlong val)
{
- vlong v;
+ vlong v;
- if (!getintlit(n, &v))
- return 0;
- return v == val;
+ if (!getintlit(n, &v))
+ return 0;
+ return v == val;
}
static Node *val(Srcloc loc, vlong val, Type *t)
{
- Node *l, *n;
+ Node *l, *n;
- l = mkint(loc, val);
- n = mkexpr(loc, Olit, l, NULL);
- l->lit.type = t;
- n->expr.type = t;
- return n;
+ l = mkint(loc, val);
+ n = mkexpr(loc, Olit, l, NULL);
+ l->lit.type = t;
+ n->expr.type = t;
+ return n;
}
static int issmallconst(Node *dcl)
{
- Type *t;
+ Type *t;
- if (!dcl->decl.isconst)
- return 0;
- if (!dcl->decl.init)
- return 0;
- t = tybase(exprtype(dcl->decl.init));
- if (t->type <= Tyflt64)
- return 1;
- return 0;
+ if (!dcl->decl.isconst)
+ return 0;
+ if (!dcl->decl.init)
+ return 0;
+ t = tybase(exprtype(dcl->decl.init));
+ if (t->type <= Tyflt64)
+ return 1;
+ return 0;
}
static Node *foldcast(Node *n)
{
- Type *to, *from;
- Node *sub;
+ Type *to, *from;
+ Node *sub;
- sub = n->expr.args[0];
- to = exprtype(n);
- from = exprtype(sub);
+ sub = n->expr.args[0];
+ to = exprtype(n);
+ from = exprtype(sub);
- switch (tybase(to)->type) {
- case Tybool:
- case Tyint8: case Tyint16: case Tyint32: case Tyint64:
- case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
- case Tyint: case Tyuint: case Tychar: case Tybyte:
- case Typtr:
- switch (tybase(from)->type) {
- case Tybool:
- case Tyint8: case Tyint16: case Tyint32: case Tyint64:
- case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
- case Tyint: case Tyuint: case Tychar: case Tybyte:
- case Typtr:
- if (exprop(sub) == Olit || tybase(from)->type == tybase(to)->type) {
- sub->expr.type = to;
- return sub;
- } else {
- return n;
- }
- default:
- return n;
- }
- default:
- return n;
- }
- return n;
+ switch (tybase(to)->type) {
+ case Tybool:
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyint: case Tyuint: case Tychar: case Tybyte:
+ case Typtr:
+ switch (tybase(from)->type) {
+ case Tybool:
+ case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
+ case Tyint: case Tyuint: case Tychar: case Tybyte:
+ case Typtr:
+ if (exprop(sub) == Olit || tybase(from)->type == tybase(to)->type) {
+ sub->expr.type = to;
+ return sub;
+ } else {
+ return n;
+ }
+ default:
+ return n;
+ }
+ default:
+ return n;
+ }
+ return n;
}
int idxcmp(const void *pa, const void *pb)
{
- Node *a, *b;
- vlong av, bv;
+ Node *a, *b;
+ vlong av, bv;
- a = *(Node **)pa;
- b = *(Node **)pb;
+ a = *(Node **)pa;
+ b = *(Node **)pb;
- assert(getintlit(a->expr.idx, &av));
- assert(getintlit(b->expr.idx, &bv));
+ assert(getintlit(a->expr.idx, &av));
+ assert(getintlit(b->expr.idx, &bv));
- /* don't trust overflow with int64 */
- if (av < bv)
- return -1;
- else if (av == bv)
- return 0;
- else
- return 1;
+ /* don't trust overflow with int64 */
+ if (av < bv)
+ return -1;
+ else if (av == bv)
+ return 0;
+ else
+ return 1;
}
Node *fold(Node *n, int foldvar)
{
- Node **args, *r;
- Type *t;
- vlong a, b;
- size_t i;
+ Node **args, *r;
+ Type *t;
+ vlong a, b;
+ size_t i;
- if (!n)
- return NULL;
- if (n->type != Nexpr)
- return n;
+ if (!n)
+ return NULL;
+ if (n->type != Nexpr)
+ return n;
- r = NULL;
- args = n->expr.args;
- if (n->expr.idx)
- n->expr.idx = fold(n->expr.idx, foldvar);
- for (i = 0; i < n->expr.nargs; i++)
- args[i] = fold(args[i], foldvar);
- switch (exprop(n)) {
- case Ovar:
- if (foldvar && issmallconst(decls[n->expr.did]))
- r = fold(decls[n->expr.did]->decl.init, foldvar);
- break;
- case Oadd:
- /* x + 0 = 0 */
- if (isintval(args[0], 0))
- r = args[1];
- if (isintval(args[1], 0))
- r = args[0];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a + b, exprtype(n));
- break;
- case Osub:
- /* x - 0 = 0 */
- if (isintval(args[1], 0))
- r = args[0];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a - b, exprtype(n));
- break;
- case Omul:
- /* 1 * x = x */
- if (isintval(args[0], 1))
- r = args[1];
- if (isintval(args[1], 1))
- r = args[0];
- /* 0 * x = 0 */
- if (isintval(args[0], 0))
- r = args[0];
- if (isintval(args[1], 0))
- r = args[1];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a * b, exprtype(n));
- break;
- case Odiv:
- /* x/0 = error */
- if (isintval(args[1], 0))
- fatal(args[1], "division by zero");
- /* x/1 = x */
- if (isintval(args[1], 1))
- r = args[0];
- /* 0/x = 0 */
- if (isintval(args[1], 0))
- r = args[1];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a / b, exprtype(n));
- break;
- case Omod:
- /* x%1 = x */
- if (isintval(args[1], 0))
- r = args[0];
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a % b, exprtype(n));
- break;
- case Oneg:
- if (getintlit(args[0], &a))
- r = val(n->loc, -a, exprtype(n));
- break;
- case Obsl:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a << b, exprtype(n));
- break;
- case Obsr:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a >> b, exprtype(n));
- break;
- case Obor:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a | b, exprtype(n));
- break;
- case Oband:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a & b, exprtype(n));
- break;
- case Obxor:
- if (getintlit(args[0], &a) && getintlit(args[1], &b))
- r = val(n->loc, a ^ b, exprtype(n));
- break;
- case Omemb:
- t = tybase(exprtype(args[0]));
- /* we only fold lengths right now */
- if (t->type == Tyarray && !strcmp(namestr(args[1]), "len"))
- r = t->asize;
- break;
- case Oarr:
- qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
- break;
- case Ocast:
- r = foldcast(n);
- break;
- default:
- break;
- }
+ r = NULL;
+ args = n->expr.args;
+ if (n->expr.idx)
+ n->expr.idx = fold(n->expr.idx, foldvar);
+ for (i = 0; i < n->expr.nargs; i++)
+ args[i] = fold(args[i], foldvar);
+ switch (exprop(n)) {
+ case Ovar:
+ if (foldvar && issmallconst(decls[n->expr.did]))
+ r = fold(decls[n->expr.did]->decl.init, foldvar);
+ break;
+ case Oadd:
+ /* x + 0 = 0 */
+ if (isintval(args[0], 0))
+ r = args[1];
+ if (isintval(args[1], 0))
+ r = args[0];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a + b, exprtype(n));
+ break;
+ case Osub:
+ /* x - 0 = 0 */
+ if (isintval(args[1], 0))
+ r = args[0];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a - b, exprtype(n));
+ break;
+ case Omul:
+ /* 1 * x = x */
+ if (isintval(args[0], 1))
+ r = args[1];
+ if (isintval(args[1], 1))
+ r = args[0];
+ /* 0 * x = 0 */
+ if (isintval(args[0], 0))
+ r = args[0];
+ if (isintval(args[1], 0))
+ r = args[1];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a * b, exprtype(n));
+ break;
+ case Odiv:
+ /* x/0 = error */
+ if (isintval(args[1], 0))
+ fatal(args[1], "division by zero");
+ /* x/1 = x */
+ if (isintval(args[1], 1))
+ r = args[0];
+ /* 0/x = 0 */
+ if (isintval(args[1], 0))
+ r = args[1];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a / b, exprtype(n));
+ break;
+ case Omod:
+ /* x%1 = x */
+ if (isintval(args[1], 0))
+ r = args[0];
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a % b, exprtype(n));
+ break;
+ case Oneg:
+ if (getintlit(args[0], &a))
+ r = val(n->loc, -a, exprtype(n));
+ break;
+ case Obsl:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a << b, exprtype(n));
+ break;
+ case Obsr:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a >> b, exprtype(n));
+ break;
+ case Obor:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a | b, exprtype(n));
+ break;
+ case Oband:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a & b, exprtype(n));
+ break;
+ case Obxor:
+ if (getintlit(args[0], &a) && getintlit(args[1], &b))
+ r = val(n->loc, a ^ b, exprtype(n));
+ break;
+ case Omemb:
+ t = tybase(exprtype(args[0]));
+ /* we only fold lengths right now */
+ if (t->type == Tyarray && !strcmp(namestr(args[1]), "len"))
+ r = t->asize;
+ break;
+ case Oarr:
+ qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
+ break;
+ case Ocast:
+ r = foldcast(n);
+ break;
+ default:
+ break;
+ }
- if (r && n->expr.idx)
- r->expr.idx = n->expr.idx;
+ if (r && n->expr.idx)
+ r->expr.idx = n->expr.idx;
- if (r)
- return r;
- else
- return n;
+ if (r)
+ return r;
+ else
+ return n;
}
--- a/mi/match.c
+++ b/mi/match.c
@@ -14,26 +14,26 @@
typedef struct Dtree Dtree;
struct Dtree {
- int id;
- Srcloc loc;
+ int id;
+ Srcloc loc;
- /* values for matching */
- Node *lbl;
- Node *load;
- size_t nconstructors;
- int accept;
- int emitted;
+ /* values for matching */
+ Node *lbl;
+ Node *load;
+ size_t nconstructors;
+ int accept;
+ int emitted;
- /* the decision tree step */
- Node **pat;
- size_t npat;
- Dtree **next;
- size_t nnext;
- Dtree *any;
+ /* the decision tree step */
+ Node **pat;
+ size_t npat;
+ Dtree **next;
+ size_t nnext;
+ Dtree *any;
- /* captured variables and action */
- Node **cap;
- size_t ncap;
+ /* captured variables and action */
+ Node **cap;
+ size_t ncap;
};
@@ -44,584 +44,584 @@
static Node *utag(Node *n)
{
- Node *tag;
+ Node *tag;
- tag = mkexpr(n->loc, Outag, n, NULL);
- tag->expr.type = mktype(n->loc, Tyint32);
- return tag;
+ tag = mkexpr(n->loc, Outag, n, NULL);
+ tag->expr.type = mktype(n->loc, Tyint32);
+ return tag;
}
static Node *uvalue(Node *n, Type *ty)
{
- Node *elt;
+ Node *elt;
- elt = mkexpr(n->loc, Oudata, n, NULL);
- elt->expr.type = ty;
- return elt;
+ elt = mkexpr(n->loc, Oudata, n, NULL);
+ elt->expr.type = ty;
+ return elt;
}
static Node *tupelt(Node *n, size_t i)
{
- Node *idx, *elt;
+ Node *idx, *elt;
- idx = mkintlit(n->loc, i);
- idx->expr.type = mktype(n->loc, Tyuint64);
- elt = mkexpr(n->loc, Otupget, n, idx, NULL);
- elt->expr.type = tybase(exprtype(n))->sub[i];
- return elt;
+ idx = mkintlit(n->loc, i);
+ idx->expr.type = mktype(n->loc, Tyuint64);
+ elt = mkexpr(n->loc, Otupget, n, idx, NULL);
+ elt->expr.type = tybase(exprtype(n))->sub[i];
+ return elt;
}
static Node *arrayelt(Node *n, size_t i)
{
- Node *idx, *elt;
+ Node *idx, *elt;
- idx = mkintlit(n->loc, i);
- idx->expr.type = mktype(n->loc, Tyuint64);
- elt = mkexpr(n->loc, Oidx, n, idx, NULL);
- elt->expr.type = tybase(exprtype(n))->sub[0];
- return elt;
+ idx = mkintlit(n->loc, i);
+ idx->expr.type = mktype(n->loc, Tyuint64);
+ elt = mkexpr(n->loc, Oidx, n, idx, NULL);
+ elt->expr.type = tybase(exprtype(n))->sub[0];
+ return elt;
}
static Node *findmemb(Node *pat, Node *name)
{
- Node *n;
- size_t i;
+ Node *n;
+ size_t i;
- for (i = 0; i < pat->expr.nargs; i++) {
- n = pat->expr.args[i];
- if (nameeq(n->expr.idx, name))
- return n;
- }
- return NULL;
+ for (i = 0; i < pat->expr.nargs; i++) {
+ n = pat->expr.args[i];
+ if (nameeq(n->expr.idx, name))
+ return n;
+ }
+ return NULL;
}
static Dtree *dtbytag(Dtree *t, Ucon *uc)
{
- uint32_t tagval;
- Node *taglit;
- size_t i;
+ uint32_t tagval;
+ Node *taglit;
+ size_t i;
- for (i = 0; i < t->npat; i++) {
- taglit = t->pat[i]->expr.args[0];
- tagval = taglit->lit.intval;
- if (tagval == uc->id) {
- return t->next[i];
- }
- }
- return NULL;
+ for (i = 0; i < t->npat; i++) {
+ taglit = t->pat[i]->expr.args[0];
+ tagval = taglit->lit.intval;
+ if (tagval == uc->id) {
+ return t->next[i];
+ }
+ }
+ return NULL;
}
static Node *structmemb(Node *n, Node *name, Type *ty)
{
- Node *elt;
+ Node *elt;
- elt = mkexpr(n->loc, Omemb, n, name, NULL);
- elt->expr.type = ty;
- return elt;
+ elt = mkexpr(n->loc, Omemb, n, name, NULL);
+ elt->expr.type = ty;
+ return elt;
}
static Node *addcapture(Node *n, Node **cap, size_t ncap)
{
- Node **blk;
- size_t nblk, i;
+ Node **blk;
+ size_t nblk, i;
- nblk = 0;
- blk = NULL;
+ nblk = 0;
+ blk = NULL;
- for (i = 0; i < ncap; i++)
- lappend(&blk, &nblk, cap[i]);
- for (i = 0; i < n->block.nstmts; i++)
- lappend(&blk, &nblk, n->block.stmts[i]);
- lfree(&n->block.stmts, &n->block.nstmts);
- n->block.stmts = blk;
- n->block.nstmts = nblk;
- return n;
+ for (i = 0; i < ncap; i++)
+ lappend(&blk, &nblk, cap[i]);
+ for (i = 0; i < n->block.nstmts; i++)
+ lappend(&blk, &nblk, n->block.stmts[i]);
+ lfree(&n->block.stmts, &n->block.nstmts);
+ n->block.stmts = blk;
+ n->block.nstmts = nblk;
+ return n;
}
static Dtree *mkdtree(Srcloc loc, Node *lbl)
{
- static int ndtree;
- Dtree *t;
+ static int ndtree;
+ Dtree *t;
- t = zalloc(sizeof(Dtree));
- t->lbl = lbl;
- t->loc = loc;
- t->id = ndtree++;
- return t;
+ t = zalloc(sizeof(Dtree));
+ t->lbl = lbl;
+ t->loc = loc;
+ t->id = ndtree++;
+ return t;
}
static Dtree *nextnode(Srcloc loc, size_t idx, size_t count, Dtree *accept)
{
- if (idx == count - 1)
- return accept;
- else
- return mkdtree(loc, genlbl(loc));
+ if (idx == count - 1)
+ return accept;
+ else
+ return mkdtree(loc, genlbl(loc));
}
static size_t nconstructors(Type *t)
{
- if (!t)
- return 0;
+ if (!t)
+ return 0;
- t = tybase(t);
- switch (t->type) {
- case Tyvoid: return 0; break;
- case Tybool: return 2; break;
- case Tychar: return 0x10ffff; break;
+ t = tybase(t);
+ switch (t->type) {
+ case Tyvoid: return 0; break;
+ case Tybool: return 2; break;
+ case Tychar: return 0x10ffff; break;
- /* signed ints */
- case Tyint8: return 0x100; break;
- case Tyint16: return 0x10000; break;
- case Tyint32: return 0x100000000; break;
- case Tyint: return 0x100000000; break;
- case Tyint64: return ~0ull; break;
+ /* signed ints */
+ case Tyint8: return 0x100; break;
+ case Tyint16: return 0x10000; break;
+ case Tyint32: return 0x100000000; break;
+ case Tyint: return 0x100000000; break;
+ case Tyint64: return ~0ull; break;
- /* unsigned ints */
- case Tybyte: return 0x100; break;
- case Tyuint8: return 0x100; break;
- case Tyuint16: return 0x10000; break;
- case Tyuint32: return 0x100000000; break;
- case Tyuint: return 0x100000000; break;
- case Tyuint64: return ~0ull; break;
+ /* unsigned ints */
+ case Tybyte: return 0x100; break;
+ case Tyuint8: return 0x100; break;
+ case Tyuint16: return 0x10000; break;
+ case Tyuint32: return 0x100000000; break;
+ case Tyuint: return 0x100000000; break;
+ case Tyuint64: return ~0ull; break;
- /* floats */
- case Tyflt32: return ~0ull; break;
- case Tyflt64: return ~0ull; break;
+ /* floats */
+ case Tyflt32: return ~0ull; break;
+ case Tyflt64: return ~0ull; break;
- /* complex types */
- case Typtr: return 1; break;
- case Tyarray: return 1; break;
- case Tytuple: return 1; break;
- case Tystruct: return 1;
- case Tyunion: return t->nmemb; break;
- case Tyslice: return ~0ULL; break;
+ /* complex types */
+ case Typtr: return 1; break;
+ case Tyarray: return 1; break;
+ case Tytuple: return 1; break;
+ case Tystruct: return 1;
+ case Tyunion: return t->nmemb; break;
+ case Tyslice: return ~0ULL; break;
- case Tyvar: case Typaram: case Tyunres: case Tyname:
- case Tybad: case Tyvalist: case Tygeneric: case Ntypes:
- case Tyfunc: case Tycode:
- die("Invalid constructor type %s in match", tystr(t));
- break;
- }
- return 0;
+ case Tyvar: case Typaram: case Tyunres: case Tyname:
+ case Tybad: case Tyvalist: case Tygeneric: case Ntypes:
+ case Tyfunc: case Tycode:
+ die("Invalid constructor type %s in match", tystr(t));
+ break;
+ }
+ return 0;
}
static int verifymatch(Dtree *t)
{
- size_t i;
- int ret;
+ size_t i;
+ int ret;
- if (t->accept)
- return 1;
+ if (t->accept)
+ return 1;
- ret = 0;
- if (t->nnext == t->nconstructors || t->any)
- ret = 1;
- for (i = 0; i < t->nnext; i++)
- if (!verifymatch(t->next[i]))
- ret = 0;
- return ret;
+ ret = 0;
+ if (t->nnext == t->nconstructors || t->any)
+ ret = 1;
+ for (i = 0; i < t->nnext; i++)
+ if (!verifymatch(t->next[i]))
+ ret = 0;
+ return ret;
}
static int acceptall(Dtree *t, Dtree *accept)
{
- size_t i;
- int ret;
+ size_t i;
+ int ret;
- if (t->any == accept)
- return 0;
+ if (t->any == accept)
+ return 0;
- ret = 0;
- if (t->any) {
- if (acceptall(t->any, accept))
- ret = 1;
- } else {
- t->any = accept;
- ret = 1;
- }
+ ret = 0;
+ if (t->any) {
+ if (acceptall(t->any, accept))
+ ret = 1;
+ } else {
+ t->any = accept;
+ ret = 1;
+ }
- for (i = 0; i < t->nnext; i++)
- if (acceptall(t->next[i], accept))
- ret = 1;
- return ret;
+ for (i = 0; i < t->nnext; i++)
+ if (acceptall(t->next[i], accept))
+ ret = 1;
+ return ret;
}
static int addwildrec(Srcloc loc, Type *ty, Dtree *start, Dtree *accept, Dtree ***end, size_t *nend)
{
- Dtree *next, **last, **tail;
- size_t i, j, nelt, nlast, ntail;
- Node *asize;
- Ucon *uc;
- int ret;
+ Dtree *next, **last, **tail;
+ size_t i, j, nelt, nlast, ntail;
+ Node *asize;
+ Ucon *uc;
+ int ret;
- tail = NULL;
- ntail = 0;
- ty = tybase(ty);
- if (istyprimitive(ty)) {
- for (i = 0; i < start->nnext; i++)
- lappend(end, nend, start->next[i]);
- if (start->any) {
- lappend(end, nend, start->any);
- return 0;
- } else {
- start->any = accept;
- lappend(end, nend, accept);
- return 1;
- }
- }
-
- ret = 0;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- switch (ty->type) {
- case Tytuple:
- for (i = 0; i < ty->nsub; i++) {
- next = nextnode(loc, i, ty->nsub, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addwildrec(loc, ty->sub[i], last[j], next, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- break;
- case Tyarray:
- asize = fold(ty->asize, 1);
- nelt = asize->expr.args[0]->lit.intval;
- for (i = 0; i < nelt; i++) {
- next = nextnode(loc, i, nelt, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addwildrec(loc, ty->sub[0], last[j], next, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- break;
- case Tystruct:
- for (i = 0; i < ty->nmemb; i++) {
- next = nextnode(loc, i, ty->nmemb, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addwildrec(loc, decltype(ty->sdecls[i]), last[j], next, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- break;
- case Tyunion:
- for (i = 0; i < ty->nmemb; i++) {
- uc = ty->udecls[i];
- next = dtbytag(start, uc);
- if (next) {
- if (uc->etype) {
- if (addwildrec(loc, uc->etype, next, accept, end, nend))
- ret = 1;
- } else {
- lappend(end, nend, next);
- }
- }
- }
- if (!start->any) {
- start->any = accept;
- ret = 1;
- }
- lappend(end, nend, start->any);
- break;
- case Tyslice:
- ret = acceptall(start, accept);
- lappend(&last, &nlast, accept);
- break;
- default:
- lappend(&last, &nlast, accept);
- break;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
-}
+ tail = NULL;
+ ntail = 0;
+ ty = tybase(ty);
+ if (istyprimitive(ty)) {
+ for (i = 0; i < start->nnext; i++)
+ lappend(end, nend, start->next[i]);
+ if (start->any) {
+ lappend(end, nend, start->any);
+ return 0;
+ } else {
+ start->any = accept;
+ lappend(end, nend, accept);
+ return 1;
+ }
+ }
+
+ ret = 0;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ switch (ty->type) {
+ case Tytuple:
+ for (i = 0; i < ty->nsub; i++) {
+ next = nextnode(loc, i, ty->nsub, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addwildrec(loc, ty->sub[i], last[j], next, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ break;
+ case Tyarray:
+ asize = fold(ty->asize, 1);
+ nelt = asize->expr.args[0]->lit.intval;
+ for (i = 0; i < nelt; i++) {
+ next = nextnode(loc, i, nelt, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addwildrec(loc, ty->sub[0], last[j], next, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ break;
+ case Tystruct:
+ for (i = 0; i < ty->nmemb; i++) {
+ next = nextnode(loc, i, ty->nmemb, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addwildrec(loc, decltype(ty->sdecls[i]), last[j], next, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ break;
+ case Tyunion:
+ for (i = 0; i < ty->nmemb; i++) {
+ uc = ty->udecls[i];
+ next = dtbytag(start, uc);
+ if (next) {
+ if (uc->etype) {
+ if (addwildrec(loc, uc->etype, next, accept, end, nend))
+ ret = 1;
+ } else {
+ lappend(end, nend, next);
+ }
+ }
+ }
+ if (!start->any) {
+ start->any = accept;
+ ret = 1;
+ }
+ lappend(end, nend, start->any);
+ break;
+ case Tyslice:
+ ret = acceptall(start, accept);
+ lappend(&last, &nlast, accept);
+ break;
+ default:
+ lappend(&last, &nlast, accept);
+ break;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
+}
static int addwild(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Node *asn;
+ Node *asn;
- asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
- asn->expr.type = exprtype(pat);
- if (cap && ncap) {
- asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
- asn->expr.type = exprtype(pat);
- lappend(cap, ncap, asn);
- }
- return addwildrec(pat->loc, exprtype(pat), start, accept, end, nend);
+ asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
+ asn->expr.type = exprtype(pat);
+ if (cap && ncap) {
+ asn = mkexpr(pat->loc, Oasn, pat, val, NULL);
+ asn->expr.type = exprtype(pat);
+ lappend(cap, ncap, asn);
+ }
+ return addwildrec(pat->loc, exprtype(pat), start, accept, end, nend);
}
static int addunion(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Node *tagid;
- Dtree *next;
- Ucon *uc;
+ Node *tagid;
+ Dtree *next;
+ Ucon *uc;
- if (start->any) {
- lappend(end, nend, start->any);
- return 0;
- }
+ if (start->any) {
+ lappend(end, nend, start->any);
+ return 0;
+ }
- uc = finducon(tybase(exprtype(pat)), pat->expr.args[0]);
- next = dtbytag(start, uc);
- if (next) {
- if (!uc->etype) {
- lappend(end, nend, next);
- return 0;
- } else {
- return addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
- }
- }
+ uc = finducon(tybase(exprtype(pat)), pat->expr.args[0]);
+ next = dtbytag(start, uc);
+ if (next) {
+ if (!uc->etype) {
+ lappend(end, nend, next);
+ return 0;
+ } else {
+ return addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
+ }
+ }
- if (!start->load) {
- start->load = utag(val);
- start->nconstructors = nconstructors(tybase(exprtype(pat)));
- }
+ if (!start->load) {
+ start->load = utag(val);
+ start->nconstructors = nconstructors(tybase(exprtype(pat)));
+ }
- tagid = mkintlit(pat->loc, uc->id);
- tagid->expr.type = mktype(pat->loc, Tyint32);
- lappend(&start->pat, &start->npat, tagid);
- if (uc->etype) {
- next = mkdtree(pat->loc, genlbl(pat->loc));
- lappend(&start->next, &start->nnext, next);
- addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
- } else {
- lappend(&start->next, &start->nnext, accept);
- lappend(end, nend, accept);
- }
- return 1;
+ tagid = mkintlit(pat->loc, uc->id);
+ tagid->expr.type = mktype(pat->loc, Tyint32);
+ lappend(&start->pat, &start->npat, tagid);
+ if (uc->etype) {
+ next = mkdtree(pat->loc, genlbl(pat->loc));
+ lappend(&start->next, &start->nnext, next);
+ addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend);
+ } else {
+ lappend(&start->next, &start->nnext, accept);
+ lappend(end, nend, accept);
+ }
+ return 1;
}
static int addstr(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Dtree **tail, **last, *next;
- size_t i, j, n, ntail, nlast;
- Node *p, *v, *lit;
- Type *ty;
- char *s;
- int ret;
+ Dtree **tail, **last, *next;
+ size_t i, j, n, ntail, nlast;
+ Node *p, *v, *lit;
+ Type *ty;
+ char *s;
+ int ret;
- lit = pat->expr.args[0];
- n = lit->lit.strval.len;
- s = lit->lit.strval.buf;
+ lit = pat->expr.args[0];
+ n = lit->lit.strval.len;
+ s = lit->lit.strval.buf;
- ty = mktype(pat->loc, Tyuint64);
- p = mkintlit(lit->loc, n);
- v = structmemb(val, mkname(pat->loc, "len"), ty);
- p->expr.type = ty;
+ ty = mktype(pat->loc, Tyuint64);
+ p = mkintlit(lit->loc, n);
+ v = structmemb(val, mkname(pat->loc, "len"), ty);
+ p->expr.type = ty;
- if (n == 0)
- next = accept;
- else
- next = mkdtree(pat->loc, genlbl(pat->loc));
+ if (n == 0)
+ next = accept;
+ else
+ next = mkdtree(pat->loc, genlbl(pat->loc));
- last = NULL;
- nlast = 0;
- if (addpat(p, v, start, next, cap, ncap, &last, &nlast))
- ret = 1;
+ last = NULL;
+ nlast = 0;
+ if (addpat(p, v, start, next, cap, ncap, &last, &nlast))
+ ret = 1;
- ty = mktype(pat->loc, Tybyte);
- for (i = 0; i < n; i++) {
- p = mkintlit(lit->loc, s[i]);
- p->expr.type = ty;
- v = arrayelt(val, i);
+ ty = mktype(pat->loc, Tybyte);
+ for (i = 0; i < n; i++) {
+ p = mkintlit(lit->loc, s[i]);
+ p->expr.type = ty;
+ v = arrayelt(val, i);
- tail = NULL;
- ntail = 0;
- next = nextnode(pat->loc, i, n, accept);
- for (j = 0; j < nlast; j++)
- if (addpat(p, v, last[j], next, NULL, NULL, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ tail = NULL;
+ ntail = 0;
+ next = nextnode(pat->loc, i, n, accept);
+ for (j = 0; j < nlast; j++)
+ if (addpat(p, v, last[j], next, NULL, NULL, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addlit(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- size_t i;
+ size_t i;
- if (pat->expr.args[0]->lit.littype == Lstr) {
- return addstr(pat, val, start, accept, cap, ncap, end, nend);
- } else {
- /* if we already have a match, we're not adding a new node */
- if (start->any) {
- lappend(end, nend, start->any);
- return 0;
- }
+ if (pat->expr.args[0]->lit.littype == Lstr) {
+ return addstr(pat, val, start, accept, cap, ncap, end, nend);
+ } else {
+ /* if we already have a match, we're not adding a new node */
+ if (start->any) {
+ lappend(end, nend, start->any);
+ return 0;
+ }
- for (i = 0; i < start->npat; i++) {
- if (liteq(start->pat[i]->expr.args[0], pat->expr.args[0])) {
- lappend(end, nend, start->next[i]);
- return 0;
- }
- }
+ for (i = 0; i < start->npat; i++) {
+ if (liteq(start->pat[i]->expr.args[0], pat->expr.args[0])) {
+ lappend(end, nend, start->next[i]);
+ return 0;
+ }
+ }
- /* wire up an edge from start to 'accept' */
- if (!start->load) {
- start->load = val;
- start->nconstructors = nconstructors(exprtype(pat));
- }
- lappend(&start->pat, &start->npat, pat);
- lappend(&start->next, &start->nnext, accept);
- lappend(end, nend, accept);
- return 1;
- }
+ /* wire up an edge from start to 'accept' */
+ if (!start->load) {
+ start->load = val;
+ start->nconstructors = nconstructors(exprtype(pat));
+ }
+ lappend(&start->pat, &start->npat, pat);
+ lappend(&start->next, &start->nnext, accept);
+ lappend(end, nend, accept);
+ return 1;
+ }
}
static int addtup(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- size_t nargs, nlast, ntail, i, j;
- Dtree *next, **last, **tail;
- Node **args;
- int ret;
+ size_t nargs, nlast, ntail, i, j;
+ Dtree *next, **last, **tail;
+ Node **args;
+ int ret;
- args = pat->expr.args;
- nargs = pat->expr.nargs;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- ret = 0;
+ args = pat->expr.args;
+ nargs = pat->expr.nargs;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ ret = 0;
- for (i = 0; i < nargs; i++) {
- next = nextnode(args[i]->loc, i, nargs, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addpat(pat->expr.args[i], tupelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ for (i = 0; i < nargs; i++) {
+ next = nextnode(args[i]->loc, i, nargs, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addpat(pat->expr.args[i], tupelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addarr(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- size_t nargs, nlast, ntail, i, j;
- Dtree *next, **last, **tail;
- Node **args;
- int ret;
+ size_t nargs, nlast, ntail, i, j;
+ Dtree *next, **last, **tail;
+ Node **args;
+ int ret;
- args = pat->expr.args;
- nargs = pat->expr.nargs;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- ret = 0;
+ args = pat->expr.args;
+ nargs = pat->expr.nargs;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ ret = 0;
- for (i = 0; i < nargs; i++) {
- next = nextnode(args[i]->loc, i, nargs, accept);
- tail = NULL;
- ntail = 0;
- for (j = 0; j < nlast; j++)
- if (addpat(pat->expr.args[i], arrayelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
- ret = 1;
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ for (i = 0; i < nargs; i++) {
+ next = nextnode(args[i]->loc, i, nargs, accept);
+ tail = NULL;
+ ntail = 0;
+ for (j = 0; j < nlast; j++)
+ if (addpat(pat->expr.args[i], arrayelt(val, i), last[j], next, cap, ncap, &tail, &ntail))
+ ret = 1;
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addstruct(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- Dtree *next, **last, **tail;
- Node *memb, *name;
- Type *ty, *mty;
- size_t i, j, ntail, nlast;
- int ret;
+ Dtree *next, **last, **tail;
+ Node *memb, *name;
+ Type *ty, *mty;
+ size_t i, j, ntail, nlast;
+ int ret;
- ret = 0;
- last = NULL;
- nlast = 0;
- lappend(&last, &nlast, start);
- ty = tybase(exprtype(pat));
+ ret = 0;
+ last = NULL;
+ nlast = 0;
+ lappend(&last, &nlast, start);
+ ty = tybase(exprtype(pat));
- for (i = 0; i < ty->nmemb; i++) {
- mty = decltype(ty->sdecls[i]);
- name = ty->sdecls[i]->decl.name;
- memb = findmemb(pat, name);
- next = nextnode(pat->loc, i, ty->nmemb, accept);
- tail = NULL;
- ntail = 0;
+ for (i = 0; i < ty->nmemb; i++) {
+ mty = decltype(ty->sdecls[i]);
+ name = ty->sdecls[i]->decl.name;
+ memb = findmemb(pat, name);
+ next = nextnode(pat->loc, i, ty->nmemb, accept);
+ tail = NULL;
+ ntail = 0;
- for (j = 0; j < nlast; j++) {
- /* add a _ capture if we don't specify the value */
- if (!memb) {
- if (addwild(memb, NULL, last[j], next, NULL, NULL, &tail, &ntail))
- ret = 1;
- } else {
- if (addpat(memb, structmemb(val, name, mty), last[j], next, cap, ncap, &tail, &ntail))
- ret = 1;
- }
- }
- lfree(&last, &nlast);
- last = tail;
- nlast = ntail;
- }
- lcat(end, nend, last, nlast);
- lfree(&last, &nlast);
- return ret;
+ for (j = 0; j < nlast; j++) {
+ /* add a _ capture if we don't specify the value */
+ if (!memb) {
+ if (addwild(memb, NULL, last[j], next, NULL, NULL, &tail, &ntail))
+ ret = 1;
+ } else {
+ if (addpat(memb, structmemb(val, name, mty), last[j], next, cap, ncap, &tail, &ntail))
+ ret = 1;
+ }
+ }
+ lfree(&last, &nlast);
+ last = tail;
+ nlast = ntail;
+ }
+ lcat(end, nend, last, nlast);
+ lfree(&last, &nlast);
+ return ret;
}
static int addpat(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
{
- int ret;
- Node *dcl;
+ int ret;
+ Node *dcl;
- pat = fold(pat, 1);
- ret = 0;
- switch (exprop(pat)) {
- case Ovar:
- dcl = decls[pat->expr.did];
- if (dcl->decl.isconst)
- ret = addpat(dcl->decl.init, val, start, accept, cap, ncap, end, nend);
- else
- ret = addwild(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Oucon:
- ret = addunion(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Olit:
- ret = addlit(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Otup:
- ret = addtup(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Oarr:
- ret = addarr(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Ostruct:
- ret = addstruct(pat, val, start, accept, cap, ncap, end, nend);
- break;
- case Ogap:
- ret = addwild(pat, NULL, start, accept, NULL, NULL, end, nend);
- break;
- default:
- fatal(pat, "unsupported pattern %s of type %s", opstr[exprop(pat)], tystr(exprtype(pat)));
- break;
- }
- return ret;
+ pat = fold(pat, 1);
+ ret = 0;
+ switch (exprop(pat)) {
+ case Ovar:
+ dcl = decls[pat->expr.did];
+ if (dcl->decl.isconst)
+ ret = addpat(dcl->decl.init, val, start, accept, cap, ncap, end, nend);
+ else
+ ret = addwild(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Oucon:
+ ret = addunion(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Olit:
+ ret = addlit(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Otup:
+ ret = addtup(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Oarr:
+ ret = addarr(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Ostruct:
+ ret = addstruct(pat, val, start, accept, cap, ncap, end, nend);
+ break;
+ case Ogap:
+ ret = addwild(pat, NULL, start, accept, NULL, NULL, end, nend);
+ break;
+ default:
+ fatal(pat, "unsupported pattern %s of type %s", opstr[exprop(pat)], tystr(exprtype(pat)));
+ break;
+ }
+ return ret;
}
@@ -628,168 +628,168 @@
/* val must be a pure, fully evaluated value */
Dtree *gendtree(Node *m, Node *val, Node **lbl, size_t nlbl)
{
- Dtree *start, *accept, **end;
- Node **pat, **cap;
- size_t npat, ncap, nend;
- size_t i;
+ Dtree *start, *accept, **end;
+ Node **pat, **cap;
+ size_t npat, ncap, nend;
+ size_t i;
- pat = m->matchstmt.matches;
- npat = m->matchstmt.nmatches;
+ pat = m->matchstmt.matches;
+ npat = m->matchstmt.nmatches;
- end = NULL;
- nend = 0;
- start = mkdtree(m->loc, genlbl(m->loc));
- for (i = 0; i < npat; i++) {
- cap = NULL;
- ncap = 0;
- accept = mkdtree(lbl[i]->loc, lbl[i]);
- accept->accept = 1;
+ end = NULL;
+ nend = 0;
+ start = mkdtree(m->loc, genlbl(m->loc));
+ for (i = 0; i < npat; i++) {
+ cap = NULL;
+ ncap = 0;
+ accept = mkdtree(lbl[i]->loc, lbl[i]);
+ accept->accept = 1;
- if (!addpat(pat[i]->match.pat, val, start, accept, &cap, &ncap, &end, &nend))
- fatal(pat[i], "pattern matched by earlier case");
- addcapture(pat[i]->match.block, cap, ncap);
- }
- if (!verifymatch(start))
- fatal(m, "nonexhaustive pattern set in match statement");
- return start;
+ if (!addpat(pat[i]->match.pat, val, start, accept, &cap, &ncap, &end, &nend))
+ fatal(pat[i], "pattern matched by earlier case");
+ addcapture(pat[i]->match.block, cap, ncap);
+ }
+ if (!verifymatch(start))
+ fatal(m, "nonexhaustive pattern set in match statement");
+ return start;
}
void genmatchcode(Dtree *dt, Node ***out, size_t *nout)
{
- Node *jmp, *eq, *fail;
- int emit;
- size_t i;
+ Node *jmp, *eq, *fail;
+ int emit;
+ size_t i;
- if (dt->emitted)
- return;
- dt->emitted = 1;
+ if (dt->emitted)
+ return;
+ dt->emitted = 1;
- /* the we jump to the accept label when generating the parent */
- if (dt->accept) {
- jmp = mkexpr(dt->loc, Ojmp, dt->lbl, NULL);
- jmp->expr.type = mktype(dt->loc, Tyvoid);
- lappend(out, nout, jmp);
- return;
- }
+ /* the we jump to the accept label when generating the parent */
+ if (dt->accept) {
+ jmp = mkexpr(dt->loc, Ojmp, dt->lbl, NULL);
+ jmp->expr.type = mktype(dt->loc, Tyvoid);
+ lappend(out, nout, jmp);
+ return;
+ }
- lappend(out, nout, dt->lbl);
- for (i = 0; i < dt->nnext; i++) {
- if (i == dt->nnext - 1 && dt->any) {
- fail = dt->any->lbl;
- emit = 0;
- } else {
- fail = genlbl(dt->loc);
- emit = 1;
- }
+ lappend(out, nout, dt->lbl);
+ for (i = 0; i < dt->nnext; i++) {
+ if (i == dt->nnext - 1 && dt->any) {
+ fail = dt->any->lbl;
+ emit = 0;
+ } else {
+ fail = genlbl(dt->loc);
+ emit = 1;
+ }
- eq = mkexpr(dt->loc, Oeq, dt->load, dt->pat[i], NULL);
- eq->expr.type = mktype(dt->loc, Tybool);
- jmp = mkexpr(dt->loc, Ocjmp, eq, dt->next[i]->lbl, fail, NULL);
- jmp->expr.type = mktype(dt->loc, Tyvoid);
- lappend(out, nout, jmp);
+ eq = mkexpr(dt->loc, Oeq, dt->load, dt->pat[i], NULL);
+ eq->expr.type = mktype(dt->loc, Tybool);
+ jmp = mkexpr(dt->loc, Ocjmp, eq, dt->next[i]->lbl, fail, NULL);
+ jmp->expr.type = mktype(dt->loc, Tyvoid);
+ lappend(out, nout, jmp);
- genmatchcode(dt->next[i], out, nout);
- if (emit)
- lappend(out, nout, fail);
- }
- if (dt->any) {
- jmp = mkexpr(dt->loc, Ojmp, dt->any->lbl, NULL);
- jmp->expr.type = mktype(dt->loc, Tyvoid);
- lappend(out, nout, jmp);
- genmatchcode(dt->any, out, nout);
- }
+ genmatchcode(dt->next[i], out, nout);
+ if (emit)
+ lappend(out, nout, fail);
+ }
+ if (dt->any) {
+ jmp = mkexpr(dt->loc, Ojmp, dt->any->lbl, NULL);
+ jmp->expr.type = mktype(dt->loc, Tyvoid);
+ lappend(out, nout, jmp);
+ genmatchcode(dt->any, out, nout);
+ }
}
void genonematch(Node *pat, Node *val, Node *iftrue, Node *iffalse, Node ***out, size_t *nout, Node ***cap, size_t *ncap)
{
- Dtree *start, *accept, *reject, **end;
- size_t nend;
+ Dtree *start, *accept, *reject, **end;
+ size_t nend;
- end = NULL;
- nend = 0;
+ end = NULL;
+ nend = 0;
- start = mkdtree(pat->loc, genlbl(pat->loc));
- accept = mkdtree(iftrue->loc, iftrue);
- accept->accept = 1;
- reject = mkdtree(iffalse->loc, iffalse);
- reject->accept = 1;
+ start = mkdtree(pat->loc, genlbl(pat->loc));
+ accept = mkdtree(iftrue->loc, iftrue);
+ accept->accept = 1;
+ reject = mkdtree(iffalse->loc, iffalse);
+ reject->accept = 1;
- assert(addpat(pat, val, start, accept, cap, ncap, &end, &nend));
- acceptall(start, reject);
- genmatchcode(start, out, nout);
+ assert(addpat(pat, val, start, accept, cap, ncap, &end, &nend));
+ acceptall(start, reject);
+ genmatchcode(start, out, nout);
}
void genmatch(Node *m, Node *val, Node ***out, size_t *nout)
{
- Node **pat, **lbl, *end, *endlbl;
- size_t npat, nlbl, i;
- Dtree *dt;
+ Node **pat, **lbl, *end, *endlbl;
+ size_t npat, nlbl, i;
+ Dtree *dt;
- lbl = NULL;
- nlbl = 0;
+ lbl = NULL;
+ nlbl = 0;
- pat = m->matchstmt.matches;
- npat = m->matchstmt.nmatches;
- for (i = 0; i < npat; i++)
- lappend(&lbl, &nlbl, genlbl(pat[i]->match.block->loc));
+ pat = m->matchstmt.matches;
+ npat = m->matchstmt.nmatches;
+ for (i = 0; i < npat; i++)
+ lappend(&lbl, &nlbl, genlbl(pat[i]->match.block->loc));
- endlbl = genlbl(m->loc);
- dt = gendtree(m, val, lbl, nlbl);
- genmatchcode(dt, out, nout);
+ endlbl = genlbl(m->loc);
+ dt = gendtree(m, val, lbl, nlbl);
+ genmatchcode(dt, out, nout);
- for (i = 0; i < npat; i++) {
- end = mkexpr(pat[i]->loc, Ojmp, endlbl, NULL);
- end->expr.type = mktype(end->loc, Tyvoid);
- lappend(out, nout, lbl[i]);
- lappend(out, nout, pat[i]->match.block);
- lappend(out, nout, end);
- }
- lappend(out, nout, endlbl);
-
- if (debugopt['m']) {
- dtreedump(stdout, dt);
- for (i = 0; i < *nout; i++)
- dump((*out)[i], stdout);
- }
+ for (i = 0; i < npat; i++) {
+ end = mkexpr(pat[i]->loc, Ojmp, endlbl, NULL);
+ end->expr.type = mktype(end->loc, Tyvoid);
+ lappend(out, nout, lbl[i]);
+ lappend(out, nout, pat[i]->match.block);
+ lappend(out, nout, end);
+ }
+ lappend(out, nout, endlbl);
+
+ if (debugopt['m']) {
+ dtreedump(stdout, dt);
+ for (i = 0; i < *nout; i++)
+ dump((*out)[i], stdout);
+ }
}
void dtreedumplit(FILE *fd, Dtree *dt, Node *n, size_t depth)
{
- char *s;
+ char *s;
- s = lblstr(dt->lbl);
- switch (n->lit.littype) {
- case Lchr: findentf(fd, depth, "%s: Lchr %c\n", s, n->lit.chrval); break;
- case Lbool: findentf(fd, depth, "%s: Lbool %s\n", s, n->lit.boolval ? "true" : "false"); break;
- case Lint: findentf(fd, depth, "%s: Lint %llu\n", s, n->lit.intval); break;
- case Lflt: findentf(fd, depth, "%s: Lflt %lf\n", s, n->lit.fltval); break;
- case Lstr: findentf(fd, depth, "%s: Lstr %.*s\n", s, (int)n->lit.strval.len, n->lit.strval.buf); break;
- case Llbl: findentf(fd, depth, "%s: Llbl %s\n", s, n->lit.lblval); break;
- case Lfunc: findentf(fd, depth, "%s: Lfunc\n"); break;
- }
+ s = lblstr(dt->lbl);
+ switch (n->lit.littype) {
+ case Lchr: findentf(fd, depth, "%s: Lchr %c\n", s, n->lit.chrval); break;
+ case Lbool: findentf(fd, depth, "%s: Lbool %s\n", s, n->lit.boolval ? "true" : "false"); break;
+ case Lint: findentf(fd, depth, "%s: Lint %llu\n", s, n->lit.intval); break;
+ case Lflt: findentf(fd, depth, "%s: Lflt %lf\n", s, n->lit.fltval); break;
+ case Lstr: findentf(fd, depth, "%s: Lstr %.*s\n", s, (int)n->lit.strval.len, n->lit.strval.buf); break;
+ case Llbl: findentf(fd, depth, "%s: Llbl %s\n", s, n->lit.lblval); break;
+ case Lfunc: findentf(fd, depth, "%s: Lfunc\n"); break;
+ }
}
void dtreedumpnode(FILE *fd, Dtree *dt, size_t depth)
{
- size_t i;
+ size_t i;
- if (dt->accept)
- findentf(fd, depth, "%s: accept\n", lblstr(dt->lbl));
+ if (dt->accept)
+ findentf(fd, depth, "%s: accept\n", lblstr(dt->lbl));
- for (i = 0; i < dt->nnext; i++) {
- dtreedumplit(fd, dt, dt->pat[i]->expr.args[0], depth);
- dtreedumpnode(fd, dt->next[i], depth + 1);
- }
- if (dt->any) {
- findentf(fd, depth, "%s: wildcard\n", lblstr(dt->lbl));
- dtreedumpnode(fd, dt->any, depth + 1);
- }
+ for (i = 0; i < dt->nnext; i++) {
+ dtreedumplit(fd, dt, dt->pat[i]->expr.args[0], depth);
+ dtreedumpnode(fd, dt->next[i], depth + 1);
+ }
+ if (dt->any) {
+ findentf(fd, depth, "%s: wildcard\n", lblstr(dt->lbl));
+ dtreedumpnode(fd, dt->any, depth + 1);
+ }
}
void dtreedump(FILE *fd, Dtree *dt)
{
- dtreedumpnode(fd, dt, 0);
+ dtreedumpnode(fd, dt, 0);
}
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -3,36 +3,36 @@
typedef struct Reaching Reaching;
struct Cfg {
- Node *fn;
- Bb **bb;
- Bb *start;
- Bb *end;
- size_t nbb;
+ Node *fn;
+ Bb **bb;
+ Bb *start;
+ Bb *end;
+ size_t nbb;
- /* for building bb */
- int nextbbid;
- Htab *lblmap; /* label => Bb mapping */
- Node **fixjmp;
- size_t nfixjmp;
- Bb **fixblk;
- size_t nfixblk;
+ /* for building bb */
+ int nextbbid;
+ Htab *lblmap; /* label => Bb mapping */
+ Node **fixjmp;
+ size_t nfixjmp;
+ Bb **fixblk;
+ size_t nfixblk;
};
struct Bb {
- int id;
- char **lbls;
- size_t nlbls;
- Node **nl;
- size_t nnl;
- Bitset *pred;
- Bitset *succ;
+ int id;
+ char **lbls;
+ size_t nlbls;
+ Node **nl;
+ size_t nnl;
+ Bitset *pred;
+ Bitset *succ;
};
struct Reaching {
- Bitset **in;
- Bitset **out;
- size_t **defs;
- size_t *ndefs;
+ Bitset **in;
+ Bitset **out;
+ size_t **defs;
+ size_t *ndefs;
};
/* expression folding */
--- a/mi/reaching.c
+++ b/mi/reaching.c
@@ -15,153 +15,138 @@
Node *assignee(Node *n)
{
- Node *a;
+ Node *a;
- switch (exprop(n)) {
- case Oundef: case Odef:
- case Oset:
- case Oasn: case Oaddeq:
- case Osubeq: case Omuleq:
- case Odiveq: case Omodeq:
- case Oboreq: case Obandeq:
- case Obxoreq: case Obsleq:
- case Obsreq:
- return n->expr.args[0];
- break;
- case Oblit:
- case Oclear:
- a = n->expr.args[0];
- if (exprop(a) != Oaddr)
- break;
- a = a->expr.args[0];
- if (exprop(a) != Ovar)
- break;
- return a;
- default:
- break;
- }
- return NULL;
+ switch (exprop(n)) {
+ case Oundef: case Odef:
+ case Oset:
+ case Oasn: case Oaddeq:
+ case Osubeq: case Omuleq:
+ case Odiveq: case Omodeq:
+ case Oboreq: case Obandeq:
+ case Obxoreq: case Obsleq:
+ case Obsreq:
+ return n->expr.args[0];
+ break;
+ case Oblit:
+ case Oclear:
+ a = n->expr.args[0];
+ if (exprop(a) != Oaddr)
+ break;
+ a = a->expr.args[0];
+ if (exprop(a) != Ovar)
+ break;
+ return a;
+ default:
+ break;
+ }
+ return NULL;
}
static void collectdefs(Cfg *cfg, size_t **defs, size_t *ndefs)
{
- size_t i, j, did;
- Node *n;
- Bb *bb;
+ size_t i, j, did;
+ Node *n;
+ Bb *bb;
- for (i = 0; i < cfg->nbb; i++) {
- bb = cfg->bb[i];
- if (!bb)
- continue;
- for (j = 0; j < bb->nnl; j++) {
- n = assignee(bb->nl[j]);
- if (n && exprop(n) == Ovar) {
- did = n->expr.did;
- ndefs[did]++;
- defs[did] = xrealloc(defs[did], ndefs[did] * sizeof(size_t));
- defs[did][ndefs[did] - 1] = bb->nl[j]->nid;
- }
- }
- }
+ for (i = 0; i < cfg->nbb; i++) {
+ bb = cfg->bb[i];
+ if (!bb)
+ continue;
+ for (j = 0; j < bb->nnl; j++) {
+ n = assignee(bb->nl[j]);
+ if (n && exprop(n) == Ovar) {
+ did = n->expr.did;
+ ndefs[did]++;
+ defs[did] = xrealloc(defs[did], ndefs[did] * sizeof(size_t));
+ defs[did][ndefs[did] - 1] = bb->nl[j]->nid;
+ }
+ }
+ }
}
static void genkill(Bb *bb, size_t **defs, size_t *ndefs, Bitset *gen, Bitset *kill)
{
- size_t i, j, did;
- Node *n;
+ size_t i, j, did;
+ Node *n;
- for (i = 0; i < bb->nnl; i++) {
- n = assignee(bb->nl[i]);
- if (!n)
- continue;
- did = n->expr.did;
- for (j = 0; j < ndefs[did]; j++) {
- bsput(kill, defs[did][j]);
- bsdel(gen, defs[did][j]);
- }
- bsput(gen, bb->nl[i]->nid);
- bsdel(kill, bb->nl[i]->nid);
- }
+ for (i = 0; i < bb->nnl; i++) {
+ n = assignee(bb->nl[i]);
+ if (!n)
+ continue;
+ did = n->expr.did;
+ for (j = 0; j < ndefs[did]; j++) {
+ bsput(kill, defs[did][j]);
+ bsdel(gen, defs[did][j]);
+ }
+ bsput(gen, bb->nl[i]->nid);
+ bsdel(kill, bb->nl[i]->nid);
+ }
}
void bsdump(Bitset *bs)
{
- size_t i;
- for (i = 0; bsiter(bs, &i); i++)
- printf("%zd ", i);
- printf("\n");
+ size_t i;
+ for (i = 0; bsiter(bs, &i); i++)
+ printf("%zd ", i);
+ printf("\n");
}
Reaching *reaching(Cfg *cfg)
{
- Bitset **in, **out;
- Bitset **gen, **kill;
- Bitset *bbin, *bbout;
- Reaching *reaching;
- size_t **defs; /* mapping from did => [def,list] */
- size_t *ndefs;
- size_t i, j;
- int changed;
+ Bitset **in, **out;
+ Bitset **gen, **kill;
+ Bitset *bbin, *bbout;
+ Reaching *reaching;
+ size_t **defs; /* mapping from did => [def,list] */
+ size_t *ndefs;
+ size_t i, j;
+ int changed;
- in = zalloc(cfg->nbb * sizeof(Bb*));
- out = zalloc(cfg->nbb * sizeof(Bb*));
- gen = zalloc(cfg->nbb * sizeof(Bb*));
- kill = zalloc(cfg->nbb * sizeof(Bb*));
- defs = zalloc(ndecls * sizeof(size_t*));
- ndefs = zalloc(ndecls * sizeof(size_t));
+ in = zalloc(cfg->nbb * sizeof(Bb*));
+ out = zalloc(cfg->nbb * sizeof(Bb*));
+ gen = zalloc(cfg->nbb * sizeof(Bb*));
+ kill = zalloc(cfg->nbb * sizeof(Bb*));
+ defs = zalloc(ndecls * sizeof(size_t*));
+ ndefs = zalloc(ndecls * sizeof(size_t));
- collectdefs(cfg, defs, ndefs);
- for (i = 0; i < cfg->nbb; i++) {
- in[i] = mkbs();
- out[i] = mkbs();
- gen[i] = mkbs();
- kill[i] = mkbs();
- if (cfg->bb[i])
- genkill(cfg->bb[i], defs, ndefs, gen[i], kill[i]);
- }
+ collectdefs(cfg, defs, ndefs);
+ for (i = 0; i < cfg->nbb; i++) {
+ in[i] = mkbs();
+ out[i] = mkbs();
+ gen[i] = mkbs();
+ kill[i] = mkbs();
+ if (cfg->bb[i])
+ genkill(cfg->bb[i], defs, ndefs, gen[i], kill[i]);
+ }
- do {
- changed = 0;
- for (i = 0; i < cfg->nbb; i++) {
- if (!cfg->bb[i])
- continue;
- bbin = mkbs();
- for (j = 0; bsiter(cfg->bb[i]->pred, &j); j++)
- bsunion(bbin, out[j]);
- bbout = bsdup(bbin);
- bsdiff(bbout, kill[i]);
- bsunion(bbout, gen[i]);
+ do {
+ changed = 0;
+ for (i = 0; i < cfg->nbb; i++) {
+ if (!cfg->bb[i])
+ continue;
+ bbin = mkbs();
+ for (j = 0; bsiter(cfg->bb[i]->pred, &j); j++)
+ bsunion(bbin, out[j]);
+ bbout = bsdup(bbin);
+ bsdiff(bbout, kill[i]);
+ bsunion(bbout, gen[i]);
- if (!bseq(out[i], bbout) || !bseq(in[i], bbin)) {
- changed = 1;
- bsfree(in[i]);
- bsfree(out[i]);
- in[i] = bbin;
- out[i] = bbout;
- }
- }
- } while (changed);
+ if (!bseq(out[i], bbout) || !bseq(in[i], bbin)) {
+ changed = 1;
+ bsfree(in[i]);
+ bsfree(out[i]);
+ in[i] = bbin;
+ out[i] = bbout;
+ }
+ }
+ } while (changed);
-// for (i = 0; i < ndecls; i++) {
-// if (defs[i])
-// printf("\t%zd: ", i);
-// for (j = 0; j < ndefs[i]; j++)
-// printf("%zd ", defs[i][j]);
-// if (defs[i])
-// printf("\n");
-// }
-// for (i = 0; i < cfg->nbb; i++) {
-// printf("bb %zd\n", i);
-// printf("\tin: ");
-// bsdump(in[i]);
-// printf("\tout: ");
-// bsdump(out[i]);
-// }
- reaching = xalloc(sizeof(Reaching));
- reaching->in = in;
- reaching->out = out;
- reaching->defs = defs;
- reaching->ndefs = ndefs;
- return reaching;
+ reaching = xalloc(sizeof(Reaching));
+ reaching->in = in;
+ reaching->out = out;
+ reaching->defs = defs;
+ reaching->ndefs = ndefs;
+ return reaching;
}
--- a/mk/lexyacc.mk
+++ b/mk/lexyacc.mk
@@ -3,7 +3,7 @@
%.h %.c: %.y
rm -f $*.h y.tab.h
yacc -d -o$*.c $<
- [ -f y.tab.h ] && mv y.tab.h $*.h
+ [ -f y.tab.h ] && mv y.tab.h $*.h || [ -f $*.h ]
%.c: %.l
flex -o$*.c $<
--- a/muse/muse.c
+++ b/muse/muse.c
@@ -26,87 +26,87 @@
static void usage(char *prog)
{
- printf("%s [-hIdos] [-o outfile] [-m] inputs\n", prog);
- printf("\t-h\tprint this help\n");
- printf("\t\tThe outfile must be the same name as each package merged.\n");
- printf("\t-I path\tAdd 'path' to use search path\n");
- printf("\t-d\tPrint debug dumps\n");
- printf("\t-o out\tOutput to outfile\n");
- printf("\t-s\tShow the contents of usefiles `inputs`\n");
+ printf("%s [-hIdos] [-o outfile] [-m] inputs\n", prog);
+ printf("\t-h\tprint this help\n");
+ printf("\t\tThe outfile must be the same name as each package merged.\n");
+ printf("\t-I path\tAdd 'path' to use search path\n");
+ printf("\t-d\tPrint debug dumps\n");
+ printf("\t-o out\tOutput to outfile\n");
+ printf("\t-s\tShow the contents of usefiles `inputs`\n");
}
static void mergeuse(char *path)
{
- FILE *f;
- Stab *st;
+ FILE *f;
+ Stab *st;
- st = file->file.globls;
- f = fopen(path, "r");
- if (!f)
- die("Couldn't open %s\n", path);
- loaduse(path, f, st, Visexport);
- fclose(f);
+ st = file->file.globls;
+ f = fopen(path, "r");
+ if (!f)
+ die("Couldn't open %s\n", path);
+ loaduse(path, f, st, Visexport);
+ fclose(f);
}
int main(int argc, char **argv)
{
- Optctx ctx;
- size_t i;
- FILE *f;
+ Optctx ctx;
+ size_t i;
+ FILE *f;
- optinit(&ctx, "d:hmo:I:l:", argv, argc);
- while (!optdone(&ctx)) {
- switch (optnext(&ctx)) {
- case 'h':
- usage(argv[0]);
- exit(0);
- break;
- case 'o':
- outfile = ctx.optarg;
- break;
- case 'd':
- while (ctx.optarg && *ctx.optarg)
- debugopt[*ctx.optarg++ & 0x7f] = 1;
- break;
- case 'I':
- lappend(&incpaths, &nincpaths, ctx.optarg);
- break;
- case 'l':
- lappend(&extralibs, &nextralibs, ctx.optarg);
- break;
- case 's':
- show = 1;
- break;
- default:
- usage(argv[0]);
- exit(0);
- break;
- }
- }
+ optinit(&ctx, "d:hmo:I:l:", argv, argc);
+ while (!optdone(&ctx)) {
+ switch (optnext(&ctx)) {
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ case 'o':
+ outfile = ctx.optarg;
+ break;
+ case 'd':
+ while (ctx.optarg && *ctx.optarg)
+ debugopt[*ctx.optarg++ & 0x7f] = 1;
+ break;
+ case 'I':
+ lappend(&incpaths, &nincpaths, ctx.optarg);
+ break;
+ case 'l':
+ lappend(&extralibs, &nextralibs, ctx.optarg);
+ break;
+ case 's':
+ show = 1;
+ break;
+ default:
+ usage(argv[0]);
+ exit(0);
+ break;
+ }
+ }
- lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
- if (!outfile) {
- fprintf(stderr, "output file needed when merging usefiles.\n");
- exit(1);
- }
+ lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
+ if (!outfile) {
+ fprintf(stderr, "output file needed when merging usefiles.\n");
+ exit(1);
+ }
- /* read and parse the file */
- file = mkfile("internal");
- file->file.globls = mkstab(0);
- updatens(file->file.globls, outfile);
- tyinit(file->file.globls);
- for (i = 0; i < ctx.nargs; i++)
- mergeuse(ctx.args[i]);
- infer(file);
- tagexports(file, 1);
- addextlibs(file, extralibs, nextralibs);
+ /* read and parse the file */
+ file = mkfile("internal");
+ file->file.globls = mkstab(0);
+ updatens(file->file.globls, outfile);
+ tyinit(file->file.globls);
+ for (i = 0; i < ctx.nargs; i++)
+ mergeuse(ctx.args[i]);
+ infer(file);
+ tagexports(file, 1);
+ addextlibs(file, extralibs, nextralibs);
- /* generate the usefile */
- f = fopen(outfile, "w");
- if (debugopt['s'] || show)
- dumpstab(file->file.globls, stdout);
- else
- writeuse(f, file);
- fclose(f);
- return 0;
+ /* generate the usefile */
+ f = fopen(outfile, "w");
+ if (debugopt['s'] || show)
+ dumpstab(file->file.globls, stdout);
+ else
+ writeuse(f, file);
+ fclose(f);
+ return 0;
}
--- a/parse/bitset.c
+++ b/parse/bitset.c
@@ -8,7 +8,7 @@
#include "parse.h"
-#define Sizetbits (CHAR_BIT*sizeof(size_t)) /* used in graph reprs */
+#define Sizetbits (CHAR_BIT * sizeof(size_t)) /* used in graph reprs */
/* Equalizes the size of a and b by
* growing the smaller to the size of the
@@ -19,91 +19,91 @@
*/
static void eqsz(Bitset *a, Bitset *b)
{
- size_t sz;
- size_t i;
- size_t *p;
+ size_t sz;
+ size_t i;
+ size_t *p;
- if (a->nchunks > b->nchunks)
- sz = a->nchunks;
- else
- sz = b->nchunks;
+ if (a->nchunks > b->nchunks)
+ sz = a->nchunks;
+ else
+ sz = b->nchunks;
- if (a->nchunks != sz) {
- p = zalloc(sz * sizeof(size_t));
- for (i = 0; i < a->nchunks; i++)
- p[i] = a->chunks[i];
- free(a->chunks);
- a->chunks = p;
- a->nchunks = sz;
- }
+ if (a->nchunks != sz) {
+ p = zalloc(sz * sizeof(size_t));
+ for (i = 0; i < a->nchunks; i++)
+ p[i] = a->chunks[i];
+ free(a->chunks);
+ a->chunks = p;
+ a->nchunks = sz;
+ }
- if (b->nchunks != sz) {
- p = zalloc(sz * sizeof(size_t));
- for (i = 0; i < b->nchunks; i++)
- p[i] = b->chunks[i];
- free(b->chunks);
- b->chunks = p;
- b->nchunks = sz;
- }
+ if (b->nchunks != sz) {
+ p = zalloc(sz * sizeof(size_t));
+ for (i = 0; i < b->nchunks; i++)
+ p[i] = b->chunks[i];
+ free(b->chunks);
+ b->chunks = p;
+ b->nchunks = sz;
+ }
}
/* Creates a new all-zero bit set */
Bitset *mkbs()
{
- Bitset *bs;
+ Bitset *bs;
- bs = xalloc(sizeof(Bitset));
- bs->nchunks = 1;
- bs->chunks = zalloc(1*sizeof(size_t));
- return bs;
+ bs = xalloc(sizeof(Bitset));
+ bs->nchunks = 1;
+ bs->chunks = zalloc(1 * sizeof(size_t));
+ return bs;
}
/* Frees a bitset. Safe to call on NULL. */
void bsfree(Bitset *bs)
{
- if (!bs)
- return;
- free(bs->chunks);
- free(bs);
+ if (!bs)
+ return;
+ free(bs->chunks);
+ free(bs);
}
/* Duplicates a bitset. NULL is duplicated to NULL. */
Bitset *bsdup(Bitset *a)
{
- Bitset *bs;
+ Bitset *bs;
- if (!a)
- return NULL;
- bs = xalloc(sizeof(Bitset));
- bs->nchunks = a->nchunks;
- bs->chunks = xalloc(a->nchunks*sizeof(size_t));
- memcpy(bs->chunks, a->chunks, a->nchunks*sizeof(size_t));
- return bs;
+ if (!a)
+ return NULL;
+ bs = xalloc(sizeof(Bitset));
+ bs->nchunks = a->nchunks;
+ bs->chunks = xalloc(a->nchunks * sizeof(size_t));
+ memcpy(bs->chunks, a->chunks, a->nchunks * sizeof(size_t));
+ return bs;
}
/* Zeroes all values in a bit set */
Bitset *bsclear(Bitset *bs)
{
- size_t i;
+ size_t i;
- if (!bs)
- return mkbs();
- for (i = 0; i < bs->nchunks; i++)
- bs->chunks[i] = 0;
- return bs;
+ if (!bs)
+ return mkbs();
+ for (i = 0; i < bs->nchunks; i++)
+ bs->chunks[i] = 0;
+ return bs;
}
/* Counts the number of values held in a bit set */
size_t bscount(Bitset *bs)
{
- size_t i, j, n;
+ size_t i, j, n;
- n = 0;
- for (i = 0; i < bs->nchunks; i++)
- for (j = 0; j < sizeof(size_t)*CHAR_BIT; j++)
- if (bs->chunks[i] & 1ULL << j)
- n++;
- return n;
+ n = 0;
+ for (i = 0; i < bs->nchunks; i++)
+ for (j = 0; j < sizeof(size_t) * CHAR_BIT; j++)
+ if (bs->chunks[i] & 1ULL << j)
+ n++;
+ return n;
}
/* A slightly tricky function to iterate over the contents
@@ -116,8 +116,8 @@
*
* Typical usage of this function:
*
- * for (i = 0; bsiter(set, &i); i++)
- * use(i);
+ * for (i = 0; bsiter(set, &i); i++)
+ * use(i);
*
* The increment of 'i' in the for loop is needed in order
* to prevent the function from returning the same value
@@ -125,105 +125,101 @@
*/
int bsiter(Bitset *bs, size_t *elt)
{
- size_t i;
+ size_t i;
- for (i = *elt; i < bsmax(bs); i++) {
- while (i < bsmax(bs) && !bs->chunks[i/Sizetbits])
- i = (i + Sizetbits) & ~(Sizetbits - 1);
- if (bshas(bs, i)) {
- *elt = i;
- return 1;
- }
- }
- return 0;
+ for (i = *elt; i < bsmax(bs); i++) {
+ while (i < bsmax(bs) && !bs->chunks[i / Sizetbits])
+ i = (i + Sizetbits) & ~(Sizetbits - 1);
+ if (bshas(bs, i)) {
+ *elt = i;
+ return 1;
+ }
+ }
+ return 0;
}
/* Returns the largest value that the bitset can possibly
* hold. It's conservative, but scanning the entire bitset
* is a bit slow. This is mostly an aid to iterate over it. */
-size_t bsmax(Bitset *bs)
-{
- return bs->nchunks*Sizetbits;
-}
+size_t bsmax(Bitset *bs) { return bs->nchunks * Sizetbits; }
void bsput(Bitset *bs, size_t elt)
{
- size_t sz;
- if (elt >= bs->nchunks*Sizetbits) {
- sz = (elt/Sizetbits)+1;
- bs->chunks = zrealloc(bs->chunks, bs->nchunks*sizeof(size_t), sz*sizeof(size_t));
- bs->nchunks = sz;
- }
- bs->chunks[elt/Sizetbits] |= 1ULL << (elt % Sizetbits);
+ size_t sz;
+ if (elt >= bs->nchunks * Sizetbits) {
+ sz = (elt / Sizetbits) + 1;
+ bs->chunks = zrealloc(bs->chunks, bs->nchunks * sizeof(size_t), sz * sizeof(size_t));
+ bs->nchunks = sz;
+ }
+ bs->chunks[elt / Sizetbits] |= 1ULL << (elt % Sizetbits);
}
void bsdel(Bitset *bs, size_t elt)
{
- if (elt < bs->nchunks*Sizetbits)
- bs->chunks[elt/Sizetbits] &= ~(1ULL << (elt % Sizetbits));
+ if (elt < bs->nchunks * Sizetbits)
+ bs->chunks[elt / Sizetbits] &= ~(1ULL << (elt % Sizetbits));
}
-
void bsunion(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] |= b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] |= b->chunks[i];
}
void bsintersect(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] &= b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] &= b->chunks[i];
}
void bsdiff(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] &= ~b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] &= ~b->chunks[i];
}
int bseq(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- if (!a || !b)
- return bsisempty(a) && bsisempty(b);
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++) {
- if (a->chunks[i] != b->chunks[i])
- return 0;
- }
- return 1;
+ if (!a || !b)
+ return bsisempty(a) && bsisempty(b);
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++) {
+ if (a->chunks[i] != b->chunks[i])
+ return 0;
+ }
+ return 1;
}
int bsissubset(Bitset *set, Bitset *sub)
{
- size_t i;
+ size_t i;
- eqsz(set, sub);
- for (i = 0; i < set->nchunks; i++)
- if ((sub->chunks[i] & set->chunks[i]) != set->chunks[i])
- return 0;
- return 1;
+ eqsz(set, sub);
+ for (i = 0; i < set->nchunks; i++)
+ if ((sub->chunks[i] & set->chunks[i]) != set->chunks[i])
+ return 0;
+ return 1;
}
int bsisempty(Bitset *set)
{
- size_t i;
+ size_t i;
- if (!set)
- return 1;
- for (i = 0; i < set->nchunks; i++)
- if (set->chunks[i])
- return 0;
- return 1;
+ if (!set)
+ return 1;
+ for (i = 0; i < set->nchunks; i++)
+ if (set->chunks[i])
+ return 0;
+ return 1;
}
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -15,9 +15,9 @@
/* outputs a fully qualified name */
static void outname(Node *n, FILE *fd)
{
- if (n->name.ns)
- fprintf(fd, "%s.", n->name.ns);
- fprintf(fd, "%s", n->name.name);
+ if (n->name.ns)
+ fprintf(fd, "%s.", n->name.ns);
+ fprintf(fd, "%s", n->name.name);
}
/* outputs a sym in a one-line short form (ie,
@@ -25,20 +25,17 @@
* expressed in indented tree. */
static void outsym(Node *s, FILE *fd, int depth)
{
- char buf[1024];
+ char buf[1024];
- if (s->decl.isconst)
- findentf(fd, depth, "const ");
- else
- findentf(fd, depth, "var ");
- outname(s->decl.name, fd);
- fprintf(fd, " : %s\n", tyfmt(buf, 1024, s->decl.type));
+ if (s->decl.isconst)
+ findentf(fd, depth, "const ");
+ else
+ findentf(fd, depth, "var ");
+ outname(s->decl.name, fd);
+ fprintf(fd, " : %s\n", tyfmt(buf, 1024, s->decl.type));
}
-void dumpsym(Node *s, FILE *fd)
-{
- outsym(s, fd, 0);
-}
+void dumpsym(Node *s, FILE *fd) { outsym(s, fd, 0); }
/* Outputs a symbol table, and it's sub-tables
* recursively, with a sigil describing the symbol
@@ -51,71 +48,68 @@
*/
static void outstab(Stab *st, FILE *fd, int depth)
{
- size_t i, n;
- char *name;
- void **k;
- char *ty;
- Type *t;
+ size_t i, n;
+ char *name;
+ void **k;
+ char *ty;
+ Type *t;
- name = "";
- if (st->name)
- name = st->name;
- findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, name);
- if (!st)
- return;
+ name = "";
+ if (st->name)
+ name = st->name;
+ findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, name);
+ if (!st)
+ return;
- /* print types */
- k = htkeys(st->ty, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "T ");
- /* already indented */
- outname(k[i], fd);
- t = gettype(st, k[i]);
- if (t->nsub)
- ty = tystr(t->sub[0]);
- else
- ty = strdup("none");
- fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
- free(ty);
- }
- free(k);
+ /* print types */
+ k = htkeys(st->ty, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "T ");
+ /* already indented */
+ outname(k[i], fd);
+ t = gettype(st, k[i]);
+ if (t->nsub)
+ ty = tystr(t->sub[0]);
+ else
+ ty = strdup("none");
+ fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
+ free(ty);
+ }
+ free(k);
- /* dump declarations */
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "S ");
- /* already indented */
- outsym(getdcl(st, k[i]), fd, 0);
- }
- free(k);
+ /* dump declarations */
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "S ");
+ /* already indented */
+ outsym(getdcl(st, k[i]), fd, 0);
+ }
+ free(k);
- /* dump closure */
- if (st->env) {
- k = htkeys(st->env, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "U ");
- /* already indented */
- outsym(getclosed(st, k[i]), fd, 0);
- }
- free(k);
- }
+ /* dump closure */
+ if (st->env) {
+ k = htkeys(st->env, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "U ");
+ /* already indented */
+ outsym(getclosed(st, k[i]), fd, 0);
+ }
+ free(k);
+ }
}
-void dumpstab(Stab *st, FILE *fd)
-{
- outstab(st, fd, 0);
-}
+void dumpstab(Stab *st, FILE *fd) { outstab(st, fd, 0); }
void dumpfilestabs(Node *file, int depth, FILE *fd)
{
- size_t nk, i;
- void **k;
+ size_t nk, i;
+ void **k;
- k = htkeys(file->file.ns, &nk);
- for (i = 0; i < nk; i++) {
- outstab(htget(file->file.ns, k[i]), fd, depth);
- }
- free(k);
+ k = htkeys(file->file.ns, &nk);
+ for (i = 0; i < nk; i++) {
+ outstab(htget(file->file.ns, k[i]), fd, depth);
+ }
+ free(k);
}
/* Outputs a node in indented tree form. This is
@@ -123,148 +117,142 @@
* understanding and debugging. */
static void outnode(Node *n, FILE *fd, int depth)
{
- size_t i;
- char *ty;
- char *tr;
- int tid;
- char buf[1024];
+ size_t i;
+ char *ty;
+ char *tr;
+ int tid;
+ char buf[1024];
- if (!n) {
- findentf(fd, depth, "Nil\n");
- return;
- }
- findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
- switch(n->type) {
- case Nfile:
- fprintf(fd, "(name = %s)\n", n->file.files[0]);
- dumpfilestabs(file, depth + 1, fd);
- for (i = 0; i < n->file.nuses; i++)
- outnode(n->file.uses[i], fd, depth + 1);
- for (i = 0; i < n->file.nstmts; i++)
- outnode(n->file.stmts[i], fd, depth + 1);
- break;
- case Ndecl:
- tr = "";
- if (n->decl.trait)
- tr = namestr(n->decl.trait->name);
- fprintf(fd, "(did = %zd, trait=%s, vis = %d)\n",
- n->decl.did, tr, n->decl.vis);
- findentf(fd, depth + 1, "isglobl=%d\n", n->decl.isglobl);
- findentf(fd, depth + 1, "isconst=%d\n", n->decl.isconst);
- findentf(fd, depth + 1, "isgeneric=%d\n", n->decl.isgeneric);
- findentf(fd, depth + 1, "isextern=%d\n", n->decl.isextern);
- findentf(fd, depth + 1, "ispkglocal=%d\n", n->decl.ispkglocal);
- findentf(fd, depth + 1, "ishidden=%d\n", n->decl.ishidden);
- findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
- findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
- findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
- findentf(fd, depth, ")\n");
- outsym(n, fd, depth + 1);
- outnode(n->decl.init, fd, depth + 1);
- break;
- case Nblock:
- fprintf(fd, "\n");
- outstab(n->block.scope, fd, depth + 1);
- for (i = 0; i < n->block.nstmts; i++)
- outnode(n->block.stmts[i], fd, depth+1);
- break;
- case Nifstmt:
- fprintf(fd, "\n");
- outnode(n->ifstmt.cond, fd, depth+1);
- outnode(n->ifstmt.iftrue, fd, depth+1);
- outnode(n->ifstmt.iffalse, fd, depth+1);
- break;
- case Nloopstmt:
- fprintf(fd, "\n");
- outnode(n->loopstmt.init, fd, depth+1);
- outnode(n->loopstmt.cond, fd, depth+1);
- outnode(n->loopstmt.step, fd, depth+1);
- outnode(n->loopstmt.body, fd, depth+1);
- break;
- case Niterstmt:
- fprintf(fd, "\n");
- outnode(n->iterstmt.elt, fd, depth+1);
- outnode(n->iterstmt.seq, fd, depth+1);
- outnode(n->iterstmt.body, fd, depth+1);
- break;
- case Nmatchstmt:
- fprintf(fd, "\n");
- outnode(n->matchstmt.val, fd, depth+1);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- outnode(n->matchstmt.matches[i], fd, depth+1);
- break;
- case Nmatch:
- fprintf(fd, "\n");
- outnode(n->match.pat, fd, depth+1);
- outnode(n->match.block, fd, depth+1);
- break;
- case Nuse:
- fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal);
- break;
- case Nexpr:
- if (exprop(n) == Ovar)
- assert(decls[n->expr.did]->decl.did == n->expr.did);
- ty = tystr(n->expr.type);
- if (n->expr.type)
- tid = n->expr.type->tid;
- else
- tid = -1;
- fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n",
- ty, tid, opstr[n->expr.op], n->expr.isconst, n->expr.did);
- free(ty);
- outnode(n->expr.idx, fd, depth + 1);
- for (i = 0; i < n->expr.nargs; i++)
- outnode(n->expr.args[i], fd, depth+1);
- break;
- case Nlit:
- switch (n->lit.littype) {
- case Lchr: fprintf(fd, " Lchr %c\n", n->lit.chrval); break;
- case Lbool: fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
- case Lint: fprintf(fd, " Lint %llu\n", n->lit.intval); break;
- case Lflt: fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
- case Lstr: fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf); break;
- case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
- case Lfunc:
- fprintf(fd, " Lfunc\n");
- outnode(n->lit.fnval, fd, depth+1);
- break;
- }
- break;
- case Nfunc:
- fprintf(fd, " (args =\n");
- for (i = 0; i < n->func.nargs; i++)
- outnode(n->func.args[i], fd, depth+1);
- findentf(fd, depth, ")\n");
- outstab(n->func.scope, fd, depth + 1);
- outnode(n->func.body, fd, depth+1);
- break;
- case Nname:
- fprintf(fd, "(");
- if (n->name.ns)
- fprintf(fd, "%s.", n->name.ns);
- fprintf(fd, "%s", n->name.name);
- fprintf(fd, ")\n");
- break;
- case Nimpl:
- fprintf(fd, "(name = %s, type = %s)\n", namestr(n->impl.traitname), tyfmt(buf, sizeof buf, n->impl.type));
- findentf(fd, depth, "");
- outnode(n->impl.traitname, fd, depth + 1);
- for (i = 0; i < n->impl.ndecls; i++)
- outnode(n->impl.decls[i], fd, depth+1);
- break;
- case Nnone:
- fprintf(stderr, "Nnone not a real node type!");
- fprintf(fd, "Nnone\n");
- break;
- }
+ if (!n) {
+ findentf(fd, depth, "Nil\n");
+ return;
+ }
+ findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
+ switch (n->type) {
+ case Nfile:
+ fprintf(fd, "(name = %s)\n", n->file.files[0]);
+ dumpfilestabs(file, depth + 1, fd);
+ for (i = 0; i < n->file.nuses; i++)
+ outnode(n->file.uses[i], fd, depth + 1);
+ for (i = 0; i < n->file.nstmts; i++)
+ outnode(n->file.stmts[i], fd, depth + 1);
+ break;
+ case Ndecl:
+ tr = "";
+ if (n->decl.trait)
+ tr = namestr(n->decl.trait->name);
+ fprintf(fd, "(did = %zd, trait=%s, vis = %d)\n", n->decl.did, tr, n->decl.vis);
+ findentf(fd, depth + 1, "isglobl=%d\n", n->decl.isglobl);
+ findentf(fd, depth + 1, "isconst=%d\n", n->decl.isconst);
+ findentf(fd, depth + 1, "isgeneric=%d\n", n->decl.isgeneric);
+ findentf(fd, depth + 1, "isextern=%d\n", n->decl.isextern);
+ findentf(fd, depth + 1, "ispkglocal=%d\n", n->decl.ispkglocal);
+ findentf(fd, depth + 1, "ishidden=%d\n", n->decl.ishidden);
+ findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
+ findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
+ findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
+ findentf(fd, depth, ")\n");
+ outsym(n, fd, depth + 1);
+ outnode(n->decl.init, fd, depth + 1);
+ break;
+ case Nblock:
+ fprintf(fd, "\n");
+ outstab(n->block.scope, fd, depth + 1);
+ for (i = 0; i < n->block.nstmts; i++)
+ outnode(n->block.stmts[i], fd, depth + 1);
+ break;
+ case Nifstmt:
+ fprintf(fd, "\n");
+ outnode(n->ifstmt.cond, fd, depth + 1);
+ outnode(n->ifstmt.iftrue, fd, depth + 1);
+ outnode(n->ifstmt.iffalse, fd, depth + 1);
+ break;
+ case Nloopstmt:
+ fprintf(fd, "\n");
+ outnode(n->loopstmt.init, fd, depth + 1);
+ outnode(n->loopstmt.cond, fd, depth + 1);
+ outnode(n->loopstmt.step, fd, depth + 1);
+ outnode(n->loopstmt.body, fd, depth + 1);
+ break;
+ case Niterstmt:
+ fprintf(fd, "\n");
+ outnode(n->iterstmt.elt, fd, depth + 1);
+ outnode(n->iterstmt.seq, fd, depth + 1);
+ outnode(n->iterstmt.body, fd, depth + 1);
+ break;
+ case Nmatchstmt:
+ fprintf(fd, "\n");
+ outnode(n->matchstmt.val, fd, depth + 1);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ outnode(n->matchstmt.matches[i], fd, depth + 1);
+ break;
+ case Nmatch:
+ fprintf(fd, "\n");
+ outnode(n->match.pat, fd, depth + 1);
+ outnode(n->match.block, fd, depth + 1);
+ break;
+ case Nuse: fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal); break;
+ case Nexpr:
+ if (exprop(n) == Ovar)
+ assert(decls[n->expr.did]->decl.did == n->expr.did);
+ ty = tystr(n->expr.type);
+ if (n->expr.type)
+ tid = n->expr.type->tid;
+ else
+ tid = -1;
+ fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n", ty, tid,
+ opstr[n->expr.op], n->expr.isconst, n->expr.did);
+ free(ty);
+ outnode(n->expr.idx, fd, depth + 1);
+ for (i = 0; i < n->expr.nargs; i++)
+ outnode(n->expr.args[i], fd, depth + 1);
+ break;
+ case Nlit:
+ switch (n->lit.littype) {
+ case Lchr: fprintf(fd, " Lchr %c\n", n->lit.chrval); break;
+ case Lbool: fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
+ case Lint: fprintf(fd, " Lint %llu\n", n->lit.intval); break;
+ case Lflt: fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
+ case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
+ case Lstr:
+ fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf);
+ break;
+ case Lfunc:
+ fprintf(fd, " lfunc\n");
+ outnode(n->lit.fnval, fd, depth + 1);
+ break;
+ }
+ break;
+ case Nfunc:
+ fprintf(fd, " (args =\n");
+ for (i = 0; i < n->func.nargs; i++)
+ outnode(n->func.args[i], fd, depth + 1);
+ findentf(fd, depth, ")\n");
+ outstab(n->func.scope, fd, depth + 1);
+ outnode(n->func.body, fd, depth + 1);
+ break;
+ case Nname:
+ fprintf(fd, "(");
+ if (n->name.ns)
+ fprintf(fd, "%s.", n->name.ns);
+ fprintf(fd, "%s", n->name.name);
+ fprintf(fd, ")\n");
+ break;
+ case Nimpl:
+ fprintf(fd, "(name = %s, type = %s)\n", namestr(n->impl.traitname),
+ tyfmt(buf, sizeof buf, n->impl.type));
+ findentf(fd, depth, "");
+ outnode(n->impl.traitname, fd, depth + 1);
+ for (i = 0; i < n->impl.ndecls; i++)
+ outnode(n->impl.decls[i], fd, depth + 1);
+ break;
+ case Nnone:
+ fprintf(stderr, "Nnone not a real node type!");
+ fprintf(fd, "Nnone\n");
+ break;
+ }
}
-void dump(Node *n, FILE *fd)
-{
- outnode(n, fd, 0);
-}
+void dump(Node *n, FILE *fd) { outnode(n, fd, 0); }
-void dumpn(Node *n)
-{
- dump(n, stdout);
-}
+void dumpn(Node *n) { dump(n, stdout); }
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -163,911 +163,910 @@
%type <uconlist> unionbody
%union {
- struct {
- Srcloc loc;
- Node **nl;
- size_t nn;
- } nodelist;
- struct {
- char **str;
- size_t nstr;
- } strlist;
- struct {
- Srcloc loc;
- Ucon **ucl;
- size_t nucl;
- } uconlist;
- struct {
- Srcloc loc;
- Type **types;
- size_t ntypes;
- } tylist;
- struct { /* FIXME: unused */
- Srcloc loc;
- char *name;
- Type *type;
- Type **params;
- size_t nparams;
- } tydef;
- Trait *trait;
- Node *node;
- Tok *tok;
- Type *ty;
- Ucon *ucon;
+ struct {
+ Srcloc loc;
+ Node **nl;
+ size_t nn;
+ } nodelist;
+ struct {
+ char **str;
+ size_t nstr;
+ } strlist;
+ struct {
+ Srcloc loc;
+ Ucon **ucl;
+ size_t nucl;
+ } uconlist;
+ struct {
+ Srcloc loc;
+ Type **types;
+ size_t ntypes;
+ } tylist;
+ struct { /* FIXME: unused */
+ Srcloc loc;
+ char *name;
+ Type *type;
+ Type **params;
+ size_t nparams;
+ } tydef;
+ Trait *trait;
+ Node *node;
+ Tok *tok;
+ Type *ty;
+ Ucon *ucon;
}
%%
file : toplev
- | file Tendln toplev
- ;
+ | file Tendln toplev
+ ;
-toplev : package
- | use {lappend(&file->file.uses, &file->file.nuses, $1);}
- | implstmt {
- lappend(&file->file.stmts, &file->file.nstmts, $1);
- }
- | traitdef {
- size_t i;
- puttrait(file->file.globls, $1->name, $1);
- for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.globls, $1->funcs[i]);
- }
- | tydef {
- puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.globls, $1.type);
- }
- | decl {
- size_t i;
- Node *n;
+toplev : package
+ | use {lappend(&file->file.uses, &file->file.nuses, $1);}
+ | implstmt {
+ lappend(&file->file.stmts, &file->file.nstmts, $1);
+ }
+ | traitdef {
+ size_t i;
+ puttrait(file->file.globls, $1->name, $1);
+ for (i = 0; i < $1->nfuncs; i++)
+ putdcl(file->file.globls, $1->funcs[i]);
+ }
+ | tydef {
+ puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);
+ }
+ | decl {
+ size_t i;
+ Node *n;
- for (i = 0; i < $1.nn; i++) {
- if (!strcmp(declname($1.nl[i]), "__init__"))
- setupinit($1.nl[i]);
- /* putdcl can merge, so we need to getdcl after */
- putdcl(file->file.globls, $1.nl[i]);
- n = getdcl(file->file.globls, $1.nl[i]->decl.name);
- lappend(&file->file.stmts, &file->file.nstmts, n);
- $1.nl[i]->decl.isglobl = 1;
- if ($1.nl[i]->decl.isinit)
- file->file.localinit = $1.nl[i];
- }
- }
- | /* empty */
- ;
+ for (i = 0; i < $1.nn; i++) {
+ if (!strcmp(declname($1.nl[i]), "__init__"))
+ setupinit($1.nl[i]);
+ /* putdcl can merge, so we need to getdcl after */
+ putdcl(file->file.globls, $1.nl[i]);
+ n = getdcl(file->file.globls, $1.nl[i]->decl.name);
+ lappend(&file->file.stmts, &file->file.nstmts, n);
+ $1.nl[i]->decl.isglobl = 1;
+ if ($1.nl[i]->decl.isinit)
+ file->file.localinit = $1.nl[i];
+ }
+ }
+ | /* empty */
+ ;
decl : attrs Tvar decllist {
- size_t i;
+ size_t i;
- for (i = 0; i < $3.nn; i++)
- setattrs($3.nl[i], $1.str, $1.nstr);
- $$ = $3;
- }
- | attrs Tconst decllist {
- size_t i;
- for (i = 0; i < $3.nn; i++) {
- setattrs($3.nl[i], $1.str, $1.nstr);
- $3.nl[i]->decl.isconst = 1;
- }
- $$ = $3;
- }
- | attrs Tgeneric decllist {
- size_t i;
+ for (i = 0; i < $3.nn; i++)
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $$ = $3;
+ }
+ | attrs Tconst decllist {
+ size_t i;
+ for (i = 0; i < $3.nn; i++) {
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $3.nl[i]->decl.isconst = 1;
+ }
+ $$ = $3;
+ }
+ | attrs Tgeneric decllist {
+ size_t i;
- for (i = 0; i < $3.nn; i++) {
- setattrs($3.nl[i], $1.str, $1.nstr);
- $3.nl[i]->decl.isconst = 1;
- $3.nl[i]->decl.isgeneric = 1;
- }
- $$ = $3;
- }
+ for (i = 0; i < $3.nn; i++) {
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $3.nl[i]->decl.isconst = 1;
+ $3.nl[i]->decl.isgeneric = 1;
+ }
+ $$ = $3;
+ }
attrs : /* empty */ {$$.nstr = 0; $$.str = NULL;}
- | Tattr attrs {
- $$ = $2;
- lappend(&$$.str, &$$.nstr, strdup($1->id));
- }
- ;
+ | Tattr attrs {
+ $$ = $2;
+ lappend(&$$.str, &$$.nstr, strdup($1->id));
+ }
+ ;
decllist: declbody {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | declbody Tcomma decllist {
- linsert(&$3.nl, &$3.nn, 0, $1);
- $$=$3;
- }
- ;
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | declbody Tcomma decllist {
+ linsert(&$3.nl, &$3.nn, 0, $1);
+ $$=$3;
+ }
+ ;
use : Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);}
- | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
- ;
+ | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
+ ;
optident: Tident {$$ = $1;}
- | /* empty */ {$$ = NULL;}
- ;
+ | /* empty */ {$$ = NULL;}
+ ;
package : Tpkg optident Tasn pkgbody Tendblk {
- if (file->file.globls->name)
- lfatal($1->loc, "Package already declared\n");
- if ($2) {
- updatens(file->file.globls, $2->id);
- }
- }
- ;
+ if (file->file.globls->name)
+ lfatal($1->loc, "Package already declared\n");
+ if ($2) {
+ updatens(file->file.globls, $2->id);
+ }
+ }
+ ;
pkgbody : pkgitem
- | pkgbody Tendln pkgitem
- ;
+ | pkgbody Tendln pkgitem
+ ;
pkgitem : decl {
- size_t i;
- for (i = 0; i < $1.nn; i++) {
- $1.nl[i]->decl.vis = Visexport;
- $1.nl[i]->decl.isglobl = 1;
- putdcl(file->file.globls, $1.nl[i]);
- if ($1.nl[i]->decl.init)
- lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
- }
- }
- | pkgtydef {
- /* the type may only be null in a package context, so we
- can set the type when merging in this case.
-
- FIXME: clean up the fucking special cases. */
- if ($1.type)
- $1.type->vis = Visexport;
- puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.globls, $1.type);
- }
- | traitdef {
- size_t i;
- $1->vis = Visexport;
- puttrait(file->file.globls, $1->name, $1);
- for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.globls, $1->funcs[i]);
- }
- | implstmt {
- $1->impl.vis = Visexport;
- lappend(&file->file.stmts, &file->file.nstmts, $1);
- }
- | /* empty */
- ;
-
+ size_t i;
+ for (i = 0; i < $1.nn; i++) {
+ $1.nl[i]->decl.vis = Visexport;
+ $1.nl[i]->decl.isglobl = 1;
+ putdcl(file->file.globls, $1.nl[i]);
+ if ($1.nl[i]->decl.init)
+ lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
+ }
+ }
+ | pkgtydef {
+ /* the type may only be null in a package context, so we
+ can set the type when merging in this case.
+
+ FIXME: clean up the fucking special cases. */
+ if ($1.type)
+ $1.type->vis = Visexport;
+ puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);
+ }
+ | traitdef {
+ size_t i;
+ $1->vis = Visexport;
+ puttrait(file->file.globls, $1->name, $1);
+ for (i = 0; i < $1->nfuncs; i++)
+ putdcl(file->file.globls, $1->funcs[i]);
+ }
+ | implstmt {
+ $1->impl.vis = Visexport;
+ lappend(&file->file.stmts, &file->file.nstmts, $1);
+ }
+ | /* empty */
+ ;
+
pkgtydef: attrs tydef {
- size_t i;
- $$ = $2;
- for (i = 0; i < $1.nstr; i++) {
- if (!strcmp($1.str[i], "pkglocal"))
- $$.type->ispkglocal = 1;
- else
- lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);
- }
- }
- ;
+ size_t i;
+ $$ = $2;
+ for (i = 0; i < $1.nstr; i++) {
+ if (!strcmp($1.str[i], "pkglocal"))
+ $$.type->ispkglocal = 1;
+ else
+ lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);
+ }
+ }
+ ;
declbody: declcore Tasn expr {$$ = $1; $1->decl.init = $3;}
- | declcore
- ;
+ | declcore
+ ;
declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));}
- | typedeclcore {$$ = $1;}
- ;
+ | typedeclcore {$$ = $1;}
+ ;
typedeclcore
- : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
- ;
+ : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
+ ;
name : Tident {$$ = mkname($1->loc, $1->id);}
- | Tident Tdot name {$$ = $3; setns($3, $1->id);}
- ;
+ | Tident Tdot name {$$ = $3; setns($3, $1->id);}
+ ;
implstmt: Timpl name type {
- $$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
- $$->impl.isproto = 1;
- }
- | Timpl name type Tasn Tendln implbody Tendblk {
- $$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
- }
- ;
+ $$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
+ $$->impl.isproto = 1;
+ }
+ | Timpl name type Tasn Tendln implbody Tendblk {
+ $$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
+ }
+ ;
implbody
- : optendlns {$$.nl = NULL; $$.nn = 0;}
- | implbody Tident Tasn exprln optendlns {
- Node *d;
- $$ = $1;
- d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
- d->decl.init = $4;
- d->decl.isconst = 1;
- d->decl.isglobl = 1;
- lappend(&$$.nl, &$$.nn, d);
- }
- ;
+ : optendlns {$$.nl = NULL; $$.nn = 0;}
+ | implbody Tident Tasn exprln optendlns {
+ Node *d;
+ $$ = $1;
+ d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
+ d->decl.init = $4;
+ d->decl.isconst = 1;
+ d->decl.isglobl = 1;
+ lappend(&$$.nl, &$$.nn, d);
+ }
+ ;
traitdef: Ttrait Tident generictype /* trait prototype */ {
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
- }
- | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
- size_t i;
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
- for (i = 0; i < $5.nn; i++) {
- $5.nl[i]->decl.trait = $$;
- $5.nl[i]->decl.isgeneric = 1;
- }
- }
- ;
+ $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
+ }
+ | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
+ size_t i;
+ $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
+ for (i = 0; i < $5.nn; i++) {
+ $5.nl[i]->decl.trait = $$;
+ $5.nl[i]->decl.isgeneric = 1;
+ }
+ }
+ ;
traitbody
- : optendlns {$$.nl = NULL; $$.nn = 0;}
- | traitbody Tident Tcolon type optendlns {
- Node *d;
- $$ = $1;
- d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
- d->decl.isgeneric = 1;
- d->decl.isconst = 1;
- lappend(&$$.nl, &$$.nn, d);
- }
- ;
+ : optendlns {$$.nl = NULL; $$.nn = 0;}
+ | traitbody Tident Tcolon type optendlns {
+ Node *d;
+ $$ = $1;
+ d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
+ d->decl.isgeneric = 1;
+ d->decl.isconst = 1;
+ lappend(&$$.nl, &$$.nn, d);
+ }
+ ;
tydef : Ttype typeid {$$ = $2;}
- | Ttype typeid Tasn type {
- $$ = $2;
- if ($$.nparams == 0) {
- $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
- } else {
- $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
- }
- }
- ;
+ | Ttype typeid Tasn type {
+ $$ = $2;
+ if ($$.nparams == 0) {
+ $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
+ } else {
+ $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
+ }
+ }
+ ;
typeid : Tident {
- $$.loc = $1->loc;
- $$.name = $1->id;
- $$.params = NULL;
- $$.type = NULL;
- }
- | Tident Toparen typarams Tcparen {
- $$.loc = $1->loc;
- $$.name = $1->id;
- $$.params = $3.types;
- $$.nparams = $3.ntypes;
- $$.type = NULL;
- }
- ;
+ $$.loc = $1->loc;
+ $$.name = $1->id;
+ $$.params = NULL;
+ $$.type = NULL;
+ }
+ | Tident Toparen typarams Tcparen {
+ $$.loc = $1->loc;
+ $$.name = $1->id;
+ $$.params = $3.types;
+ $$.nparams = $3.ntypes;
+ $$.type = NULL;
+ }
+ ;
typarams: generictype {
- $$.types = NULL; $$.ntypes = 0;
- lappend(&$$.types, &$$.ntypes, $1);
- }
- | typarams Tcomma generictype {lappend(&$$.types, &$$.ntypes, $3);}
- ;
+ $$.types = NULL; $$.ntypes = 0;
+ lappend(&$$.types, &$$.ntypes, $1);
+ }
+ | typarams Tcomma generictype {lappend(&$$.types, &$$.ntypes, $3);}
+ ;
type : structdef
- | tupledef
- | uniondef
- | compoundtype
- | generictype
- | Tellipsis {$$ = mktype($1->loc, Tyvalist);}
- ;
+ | tupledef
+ | uniondef
+ | compoundtype
+ | generictype
+ | Tellipsis {$$ = mktype($1->loc, Tyvalist);}
+ ;
generictype
- : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
- | Ttyparam Twith name {
- $$ = mktyparam($1->loc, $1->id);
- addtrait($$, $3->name.name);
- }
- | Ttyparam Twith Toparen typaramlist Tcparen {
- size_t i;
- $$ = mktyparam($1->loc, $1->id);
- for (i = 0; i < $4.nn; i++)
- addtrait($$, $4.nl[i]->name.name);
- }
- ;
+ : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
+ | Ttyparam Twith name {
+ $$ = mktyparam($1->loc, $1->id);
+ addtrait($$, $3->name.name);
+ }
+ | Ttyparam Twith Toparen typaramlist Tcparen {
+ size_t i;
+ $$ = mktyparam($1->loc, $1->id);
+ for (i = 0; i < $4.nn; i++)
+ addtrait($$, $4.nl[i]->name.name);
+ }
+ ;
typaramlist
- : name {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | typaramlist Tcomma name {lappend(&$$.nl, &$$.nn, $3);}
- ;
+ : name {
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | typaramlist Tcomma name {lappend(&$$.nl, &$$.nn, $3);}
+ ;
compoundtype
- : functype {$$ = $1;}
- | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
- | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
- | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
- | type Tderef {$$ = mktyptr($2->loc, $1);}
- | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
- | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
- | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
- ;
+ : functype {$$ = $1;}
+ | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
+ | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
+ | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
+ | type Tderef {$$ = mktyptr($2->loc, $1);}
+ | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
+ | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
+ | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
+ ;
functype: Toparen funcsig Tcparen {$$ = $2;}
- ;
+ ;
funcsig : argdefs Tret type
- {$$ = mktyfunc($2->loc, $1.nl, $1.nn, $3);}
- ;
+ {$$ = mktyfunc($2->loc, $1.nl, $1.nn, $3);}
+ ;
argdefs : typedeclcore {
- $$.loc = $1->loc;
- $$.nl = NULL;
- $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);
- }
- | argdefs Tcomma declcore {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */ {
- $$.loc.line = 0;
- $$.loc.file = 0;
- $$.nl = NULL;
- $$.nn = 0;
- }
- ;
+ $$.loc = $1->loc;
+ $$.nl = NULL;
+ $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);
+ }
+ | argdefs Tcomma declcore {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */ {
+ $$.loc.line = 0;
+ $$.loc.file = 0;
+ $$.nl = NULL;
+ $$.nn = 0;
+ }
+ ;
tupledef: Toparen typelist Tcparen
- {$$ = mktytuple($1->loc, $2.types, $2.ntypes);}
- ;
+ {$$ = mktytuple($1->loc, $2.types, $2.ntypes);}
+ ;
typelist: type {
- $$.types = NULL; $$.ntypes = 0;
- lappend(&$$.types, &$$.ntypes, $1);
- }
- | typelist Tcomma type
- {lappend(&$$.types, &$$.ntypes, $3);}
- ;
+ $$.types = NULL; $$.ntypes = 0;
+ lappend(&$$.types, &$$.ntypes, $1);
+ }
+ | typelist Tcomma type
+ {lappend(&$$.types, &$$.ntypes, $3);}
+ ;
structdef
- : Tstruct structbody Tendblk
- {$$ = mktystruct($1->loc, $2.nl, $2.nn);}
- ;
+ : Tstruct structbody Tendblk
+ {$$ = mktystruct($1->loc, $2.nl, $2.nn);}
+ ;
structbody
- : structent {
- if ($1) {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- }
- | structbody structent {
- if ($2)
- lappend(&$$.nl, &$$.nn, $2);
- }
- ;
+ : structent {
+ if ($1) {
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ }
+ | structbody structent {
+ if ($2)
+ lappend(&$$.nl, &$$.nn, $2);
+ }
+ ;
structent
- : declcore Tendln {$$ = $1;}
- | Tendln {$$ = NULL;}
- ;
+ : declcore Tendln {$$ = $1;}
+ | Tendln {$$ = NULL;}
+ ;
uniondef
- : Tunion unionbody Tendblk
- {$$ = mktyunion($1->loc, $2.ucl, $2.nucl);}
- ;
+ : Tunion unionbody Tendblk
+ {$$ = mktyunion($1->loc, $2.ucl, $2.nucl);}
+ ;
unionbody
- : unionelt {
- $$.ucl = NULL;
- $$.nucl = 0;
- if ($1)
- lappend(&$$.ucl, &$$.nucl, $1);
- }
- | unionbody unionelt {
- if ($2)
- lappend(&$$.ucl, &$$.nucl, $2);
- }
- ;
+ : unionelt {
+ $$.ucl = NULL;
+ $$.nucl = 0;
+ if ($1)
+ lappend(&$$.ucl, &$$.nucl, $1);
+ }
+ | unionbody unionelt {
+ if ($2)
+ lappend(&$$.ucl, &$$.nucl, $2);
+ }
+ ;
unionelt /* nb: the ucon union type gets filled in when we have context */
- : Ttick name type Tendln {$$ = mkucon($2->loc, $2, NULL, $3);}
- | Ttick name Tendln {$$ = mkucon($2->loc, $2, NULL, NULL);}
- | Tendln {$$ = NULL;}
- ;
+ : Ttick name type Tendln {$$ = mkucon($2->loc, $2, NULL, $3);}
+ | Ttick name Tendln {$$ = mkucon($2->loc, $2, NULL, NULL);}
+ | Tendln {$$ = NULL;}
+ ;
goto : Tgoto Tident {$$ = mkexpr($1->loc, Ojmp, mklbl($2->loc, $2->id), NULL);}
- ;
+ ;
retexpr : Tret expr {$$ = mkexpr($1->loc, Oret, $2, NULL);}
- | Tret {$$ = mkexpr($1->loc, Oret, NULL);}
- | expr
- ;
+ | Tret {$$ = mkexpr($1->loc, Oret, NULL);}
+ | expr
+ ;
optexpr : expr {$$ = $1;}
- | /* empty */ {$$ = NULL;}
- ;
+ | /* empty */ {$$ = NULL;}
+ ;
optexprln: exprln {$$ = $1;}
- | Tendln {$$ = NULL;}
- ;
+ | Tendln {$$ = NULL;}
+ ;
exprln : expr Tendln
- ;
+ ;
expr : asnexpr
- ;
+ ;
asnexpr : lorexpr asnop asnexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | lorexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | lorexpr
+ ;
asnop : Tasn
- | Taddeq /* += */
- | Tsubeq /* -= */
- | Tmuleq /* *= */
- | Tdiveq /* /= */
- | Tmodeq /* %= */
- | Tboreq /* |= */
- | Tbxoreq /* ^= */
- | Tbandeq /* &= */
- | Tbsleq /* <<= */
- | Tbsreq /* >>= */
- ;
+ | Taddeq /* += */
+ | Tsubeq /* -= */
+ | Tmuleq /* *= */
+ | Tdiveq /* /= */
+ | Tmodeq /* %= */
+ | Tboreq /* |= */
+ | Tbxoreq /* ^= */
+ | Tbandeq /* &= */
+ | Tbsleq /* <<= */
+ | Tbsreq /* >>= */
+ ;
lorexpr : lorexpr Tlor landexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | landexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | landexpr
+ ;
landexpr: landexpr Tland cmpexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | cmpexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | cmpexpr
+ ;
cmpexpr : cmpexpr cmpop castexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | unionexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | unionexpr
+ ;
cmpop : Teq | Tgt | Tlt | Tge | Tle | Tne ;
unionexpr
- : Ttick name unionexpr {$$ = mkexpr($1->loc, Oucon, $2, $3, NULL);}
- | Ttick name {$$ = mkexpr($1->loc, Oucon, $2, NULL);}
- | castexpr
- ;
+ : Ttick name unionexpr {$$ = mkexpr($1->loc, Oucon, $2, $3, NULL);}
+ | Ttick name {$$ = mkexpr($1->loc, Oucon, $2, NULL);}
+ | castexpr
+ ;
castexpr: castexpr Tcast Toparen type Tcparen {
- $$ = mkexpr($1->loc, Ocast, $1, NULL);
- $$->expr.type = $4;
- }
- | borexpr
- ;
+ $$ = mkexpr($1->loc, Ocast, $1, NULL);
+ $$->expr.type = $4;
+ }
+ | borexpr
+ ;
borexpr : borexpr Tbor bandexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | borexpr Tbxor bandexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | bandexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | borexpr Tbxor bandexpr
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | bandexpr
+ ;
bandexpr: bandexpr Tband addexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | addexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | addexpr
+ ;
addexpr : addexpr addop mulexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | mulexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | mulexpr
+ ;
addop : Tplus | Tminus ;
mulexpr : mulexpr mulop shiftexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | shiftexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | shiftexpr
+ ;
mulop : Tmul | Tdiv | Tmod
- ;
+ ;
shiftexpr
- : shiftexpr shiftop prefixexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | prefixexpr
- ;
+ : shiftexpr shiftop prefixexpr
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | prefixexpr
+ ;
shiftop : Tbsl | Tbsr;
prefixexpr
- : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
- | Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
- | Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
- | Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
- | Tbnot prefixexpr {$$ = mkexpr($1->loc, Obnot, $2, NULL);}
- | Tminus prefixexpr {$$ = mkexpr($1->loc, Oneg, $2, NULL);}
- | Tplus prefixexpr {$$ = $2;} /* positive is a nop */
- | postfixexpr
- ;
+ : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
+ | Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
+ | Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
+ | Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
+ | Tbnot prefixexpr {$$ = mkexpr($1->loc, Obnot, $2, NULL);}
+ | Tminus prefixexpr {$$ = mkexpr($1->loc, Oneg, $2, NULL);}
+ | Tplus prefixexpr {$$ = $2;} /* positive is a nop */
+ | postfixexpr
+ ;
postfixexpr
- : postfixexpr Tdot Tident
- {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
- | postfixexpr Tinc
- {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
- | postfixexpr Tdec
- {$$ = mkexpr($1->loc, Opostdec, $1, NULL);}
- | postfixexpr Tosqbrac expr Tcsqbrac
- {$$ = mkexpr($1->loc, Oidx, $1, $3, NULL);}
- | postfixexpr Tosqbrac optexpr Tcolon optexpr Tcsqbrac
- {$$ = mksliceexpr($1->loc, $1, $3, $5);}
- | postfixexpr Tderef
- {$$ = mkexpr($1->loc, Oderef, $1, NULL);}
- | postfixexpr Toparen arglist Tcparen
- {$$ = mkcall($1->loc, $1, $3.nl, $3.nn);}
- | atomicexpr
- ;
+ : postfixexpr Tdot Tident
+ {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
+ | postfixexpr Tinc
+ {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
+ | postfixexpr Tdec
+ {$$ = mkexpr($1->loc, Opostdec, $1, NULL);}
+ | postfixexpr Tosqbrac expr Tcsqbrac
+ {$$ = mkexpr($1->loc, Oidx, $1, $3, NULL);}
+ | postfixexpr Tosqbrac optexpr Tcolon optexpr Tcsqbrac
+ {$$ = mksliceexpr($1->loc, $1, $3, $5);}
+ | postfixexpr Tderef
+ {$$ = mkexpr($1->loc, Oderef, $1, NULL);}
+ | postfixexpr Toparen arglist Tcparen
+ {$$ = mkcall($1->loc, $1, $3.nl, $3.nn);}
+ | atomicexpr
+ ;
arglist : asnexpr
- {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
- | arglist Tcomma asnexpr
- {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */
- {$$.nl = NULL; $$.nn = 0;}
- ;
+ {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
+ | arglist Tcomma asnexpr
+ {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */
+ {$$.nl = NULL; $$.nn = 0;}
+ ;
atomicexpr
- : Tident
- {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
- | Tgap
- {$$ = mkexpr($1->loc, Ogap, NULL);}
- | Tidxlen
- {$$ = mkexpr($1->loc, Oidxlen, NULL);}
- | literal
- | Toparen expr Tcparen
- {$$ = $2;}
- | Tsizeof Toparen type Tcparen
- {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);}
- ;
+ : Tident
+ {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
+ | Tgap
+ {$$ = mkexpr($1->loc, Ogap, NULL);}
+ | Tidxlen
+ {$$ = mkexpr($1->loc, Oidxlen, NULL);}
+ | literal
+ | Toparen expr Tcparen
+ {$$ = $2;}
+ | Tsizeof Toparen type Tcparen
+ {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);}
+ ;
tupbody : tuphead tuprest
- {$$ = $2;
- linsert(&$$.nl, &$$.nn, 0, $1);}
- ;
+ {$$ = $2;
+ linsert(&$$.nl, &$$.nn, 0, $1);}
+ ;
tuphead : expr Tcomma {$$ = $1;}
- ;
+ ;
tuprest : /*empty */
- {$$.nl = NULL; $$.nn = 0;}
- | expr {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | tuprest Tcomma expr {lappend(&$$.nl, &$$.nn, $3);}
- ;
+ {$$.nl = NULL; $$.nn = 0;}
+ | expr {
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | tuprest Tcomma expr {lappend(&$$.nl, &$$.nn, $3);}
+ ;
literal : funclit {$$ = mkexpr($1->loc, Olit, $1, NULL);}
- | littok {$$ = mkexpr($1->loc, Olit, $1, NULL);}
- | seqlit {$$ = $1;}
- | tuplit {$$ = $1;}
- ;
+ | littok {$$ = mkexpr($1->loc, Olit, $1, NULL);}
+ | seqlit {$$ = $1;}
+ | tuplit {$$ = $1;}
+ ;
tuplit : Toparen tupbody Tcparen
- {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
+ {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
littok : Tstrlit {$$ = mkstr($1->loc, $1->strval);}
- | Tchrlit {$$ = mkchar($1->loc, $1->chrval);}
- | Tfloatlit {$$ = mkfloat($1->loc, $1->fltval);}
- | Tboollit {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
- | Tintlit {
- $$ = mkint($1->loc, $1->intval);
- if ($1->inttype)
- $$->lit.type = mktype($1->loc, $1->inttype);
- }
- ;
+ | Tchrlit {$$ = mkchar($1->loc, $1->chrval);}
+ | Tfloatlit {$$ = mkfloat($1->loc, $1->fltval);}
+ | Tboollit {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
+ | Tintlit {
+ $$ = mkint($1->loc, $1->intval);
+ if ($1->inttype)
+ $$->lit.type = mktype($1->loc, $1->inttype);
+ }
+ ;
funclit : Tobrace params Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
- | Tobrace params Tret type Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
- ;
+ {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
+ | Tobrace params Tret type Tendln blkbody Tcbrace
+ {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
+ ;
params : fnparam {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | params Tcomma fnparam {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */ {$$.nl = NULL; $$.nn = 0;}
- ;
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | params Tcomma fnparam {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */ {$$.nl = NULL; $$.nn = 0;}
+ ;
fnparam : declcore {$$ = $1;}
- | Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
- | Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
- ;
+ | Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
+ | Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
+ ;
seqlit : Tosqbrac arrayelts optcomma Tcsqbrac
- {$$ = mkexprl($1->loc, Oarr, $2.nl, $2.nn);}
- | Tosqbrac structelts optcomma Tcsqbrac
- {$$ = mkexprl($1->loc, Ostruct, $2.nl, $2.nn);}
- | Tosqbrac optendlns optcomma Tcsqbrac /* [] is the empty array. */
- {$$ = mkexprl($1->loc, Oarr, NULL, 0);}
- ;
+ {$$ = mkexprl($1->loc, Oarr, $2.nl, $2.nn);}
+ | Tosqbrac structelts optcomma Tcsqbrac
+ {$$ = mkexprl($1->loc, Ostruct, $2.nl, $2.nn);}
+ | Tosqbrac optendlns optcomma Tcsqbrac /* [] is the empty array. */
+ {$$ = mkexprl($1->loc, Oarr, NULL, 0);}
+ ;
optcomma: Tcomma optendlns
- | /* empty */
- ;
+ | /* empty */
+ ;
arrayelts
- : optendlns arrayelt {
- $$.nl = NULL;
- $$.nn = 0;
- if ($2->expr.idx)
- lappend(&$$.nl, &$$.nn, $2);
- else
- lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
- }
- | arrayelts Tcomma optendlns arrayelt {
- if ($4->expr.idx)
- lappend(&$$.nl, &$$.nn, $4);
- else
- lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
- }
- ;
+ : optendlns arrayelt {
+ $$.nl = NULL;
+ $$.nn = 0;
+ if ($2->expr.idx)
+ lappend(&$$.nl, &$$.nn, $2);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
+ }
+ | arrayelts Tcomma optendlns arrayelt {
+ if ($4->expr.idx)
+ lappend(&$$.nl, &$$.nn, $4);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
+ }
+ ;
arrayelt: expr optendlns {$$ = $1;}
- | expr Tcolon expr optendlns {
- $$ = mkidxinit($2->loc, $1, $3);
- }
- ;
+ | expr Tcolon expr optendlns {
+ $$ = mkidxinit($2->loc, $1, $3);
+ }
+ ;
structelts
- : optendlns structelt {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $2);
- }
- | structelts Tcomma optendlns structelt {
- lappend(&$$.nl, &$$.nn, $4);
- }
- ;
+ : optendlns structelt {
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $2);
+ }
+ | structelts Tcomma optendlns structelt {
+ lappend(&$$.nl, &$$.nn, $4);
+ }
+ ;
structelt: Tdot Tident Tasn expr optendlns {
- $$ = $4;
- mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
- }
- ;
+ $$ = $4;
+ mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
+ }
+ ;
optendlns : /* none */
- | optendlns Tendln
- ;
+ | optendlns Tendln
+ ;
stmt : goto
- | break
- | continue
- | retexpr
- | label
- | ifstmt
- | forstmt
- | whilestmt
- | matchstmt
- | /* empty */ {$$ = NULL;}
- ;
+ | break
+ | continue
+ | retexpr
+ | label
+ | ifstmt
+ | forstmt
+ | whilestmt
+ | matchstmt
+ | /* empty */ {$$ = NULL;}
+ ;
break : Tbreak
- {$$ = mkexpr($1->loc, Obreak, NULL);}
- ;
+ {$$ = mkexpr($1->loc, Obreak, NULL);}
+ ;
continue : Tcontinue
- {$$ = mkexpr($1->loc, Ocontinue, NULL);}
- ;
+ {$$ = mkexpr($1->loc, Ocontinue, NULL);}
+ ;
forstmt : Tfor optexprln optexprln optexprln block
- {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
- | Tfor expr Tin exprln block
- {$$ = mkiterstmt($1->loc, $2, $4, $5);}
- | Tfor decl Tendln optexprln optexprln block {
- //Node *init;
- if ($2.nn != 1)
- lfatal($1->loc, "only one declaration is allowed in for loop");
- $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
- putdcl($$->loopstmt.scope, $2.nl[0]);
- }
+ {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
+ | Tfor expr Tin exprln block
+ {$$ = mkiterstmt($1->loc, $2, $4, $5);}
+ | Tfor decl Tendln optexprln optexprln block {
+ //Node *init;
+ if ($2.nn != 1)
+ lfatal($1->loc, "only one declaration is allowed in for loop");
+ $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
+ putdcl($$->loopstmt.scope, $2.nl[0]);
+ }
- ;
+ ;
whilestmt
- : Twhile exprln block
- {$$ = mkloopstmt($1->loc, NULL, $2, NULL, $3);}
- ;
+ : Twhile exprln block
+ {$$ = mkloopstmt($1->loc, NULL, $2, NULL, $3);}
+ ;
ifstmt : Tif exprln blkbody elifs
- {$$ = mkifstmt($1->loc, $2, $3, $4);}
- ;
+ {$$ = mkifstmt($1->loc, $2, $3, $4);}
+ ;
elifs : Telif exprln blkbody elifs
- {$$ = mkifstmt($1->loc, $2, $3, $4);}
- | Telse block
- {$$ = $2;}
- | Tendblk
- {$$ = NULL;}
- ;
+ {$$ = mkifstmt($1->loc, $2, $3, $4);}
+ | Telse block
+ {$$ = $2;}
+ | Tendblk
+ {$$ = NULL;}
+ ;
matchstmt: Tmatch exprln optendlns Tbor matches Tendblk
- {$$ = mkmatchstmt($1->loc, $2, $5.nl, $5.nn);}
- ;
+ {$$ = mkmatchstmt($1->loc, $2, $5.nl, $5.nn);}
+ ;
matches : match {
- $$.nl = NULL;
- $$.nn = 0;
- if ($1)
- lappend(&$$.nl, &$$.nn, $1);
- }
- | matches Tbor match {
- if ($2)
- lappend(&$$.nl, &$$.nn, $3);
- }
- ;
+ $$.nl = NULL;
+ $$.nn = 0;
+ if ($1)
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | matches Tbor match {
+ if ($2)
+ lappend(&$$.nl, &$$.nn, $3);
+ }
+ ;
match : expr Tcolon blkbody Tendln {$$ = mkmatch($1->loc, $1, $3);}
- ;
+ ;
block : blkbody Tendblk
- ;
+ ;
blkbody : decl {
- size_t i;
- Node *n, *d, *u;
+ size_t i;
+ Node *n, *d, *u;
- $$ = mkblock($1.loc, mkstab(0));
- for (i = 0; i < $1.nn; i++) {
- d = $1.nl[i];
- putdcl($$->block.scope, d);
- if (!d->decl.init) {
- n = mkexpr(d->loc, Ovar, d->decl.name, NULL);
- u = mkexpr(n->loc, Oundef, n, NULL);
- n->expr.did = d->decl.did;
- lappend(&$$->block.stmts, &$$->block.nstmts, u);
- }
- lappend(&$$->block.stmts, &$$->block.nstmts, d);
- }
- }
- | stmt {
- $$ = mkblock(curloc, mkstab(0));
- if ($1)
- lappend(&$$->block.stmts, &$$->block.nstmts, $1);
- }
- | blkbody Tendln stmt {
- if ($3)
- lappend(&$1->block.stmts, &$1->block.nstmts, $3);
- $$ = $1;
- }
- | blkbody Tendln decl {
- size_t i;
- for (i = 0; i < $3.nn; i++){
- putdcl($$->block.scope, $3.nl[i]);
- lappend(&$1->block.stmts, &$1->block.nstmts, $3.nl[i]);
- }
- }
- ;
+ $$ = mkblock($1.loc, mkstab(0));
+ for (i = 0; i < $1.nn; i++) {
+ d = $1.nl[i];
+ putdcl($$->block.scope, d);
+ if (!d->decl.init) {
+ n = mkexpr(d->loc, Ovar, d->decl.name, NULL);
+ u = mkexpr(n->loc, Oundef, n, NULL);
+ n->expr.did = d->decl.did;
+ lappend(&$$->block.stmts, &$$->block.nstmts, u);
+ }
+ lappend(&$$->block.stmts, &$$->block.nstmts, d);
+ }
+ }
+ | stmt {
+ $$ = mkblock(curloc, mkstab(0));
+ if ($1)
+ lappend(&$$->block.stmts, &$$->block.nstmts, $1);
+ }
+ | blkbody Tendln stmt {
+ if ($3)
+ lappend(&$1->block.stmts, &$1->block.nstmts, $3);
+ $$ = $1;
+ }
+ | blkbody Tendln decl {
+ size_t i;
+ for (i = 0; i < $3.nn; i++){
+ putdcl($$->block.scope, $3.nl[i]);
+ lappend(&$1->block.stmts, &$1->block.nstmts, $3.nl[i]);
+ }
+ }
+ ;
-label : Tcolon Tident
- {$$ = mklbl($2->loc, $2->id);}
- ;
+label : Tcolon Tident {$$ = mklbl($2->loc, $2->id);}
+ ;
%%
static void setupinit(Node *n)
{
- char name[1024];
- char *p;
+ char name[1024];
+ char *p;
- bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
- p = name;
- while (*p) {
- if (!isalnum(*p) && *p != '_')
- *p = '$';
- p++;
- }
- n->decl.isinit = 1;
- n->decl.vis = Vishidden;
- n->decl.name->name.name = strdup(name);
+ bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
+ p = name;
+ while (*p) {
+ if (!isalnum(*p) && *p != '_')
+ *p = '$';
+ p++;
+ }
+ n->decl.isinit = 1;
+ n->decl.vis = Vishidden;
+ n->decl.name->name.name = strdup(name);
}
static void addtrait(Type *t, char *str)
{
- size_t i;
+ size_t i;
- for (i = 0; i < ntraittab; i++) {
- if (!strcmp(namestr(traittab[i]->name), str)) {
- settrait(t, traittab[i]);
- return;
- }
- }
- lfatal(t->loc, "Constraint %s does not exist", str);
+ for (i = 0; i < ntraittab; i++) {
+ if (!strcmp(namestr(traittab[i]->name), str)) {
+ settrait(t, traittab[i]);
+ return;
+ }
+ }
+ lfatal(t->loc, "Constraint %s does not exist", str);
}
static Node *mkpseudodecl(Srcloc l, Type *t)
{
- static int nextpseudoid;
- char buf[128];
+ static int nextpseudoid;
+ char buf[128];
- bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
- return mkdecl(l, mkname(l, buf), t);
+ bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
+ return mkdecl(l, mkname(l, buf), t);
}
static void setattrs(Node *dcl, char **attrs, size_t nattrs)
{
- size_t i;
+ size_t i;
- for (i = 0; i < nattrs; i++) {
- if (!strcmp(attrs[i], "extern"))
- dcl->decl.isextern = 1;
- else if (!strcmp(attrs[i], "$noret"))
- dcl->decl.isnoret = 1;
- else if (!strcmp(attrs[i], "pkglocal"))
- dcl->decl.ispkglocal = 1;
- }
+ for (i = 0; i < nattrs; i++) {
+ if (!strcmp(attrs[i], "extern"))
+ dcl->decl.isextern = 1;
+ else if (!strcmp(attrs[i], "$noret"))
+ dcl->decl.isnoret = 1;
+ else if (!strcmp(attrs[i], "pkglocal"))
+ dcl->decl.ispkglocal = 1;
+ }
}
static void installucons(Stab *st, Type *t)
{
- Type *b;
- size_t i;
+ Type *b;
+ size_t i;
- if (!t)
- return;
- b = tybase(t);
- switch (b->type) {
- case Tystruct:
- for (i = 0; i < b->nmemb; i++)
- installucons(st, b->sdecls[i]->decl.type);
- break;
- case Tyunion:
- for (i = 0; i < b->nmemb; i++) {
- b->udecls[i]->utype = b;
- b->udecls[i]->id = i;
- putucon(st, b->udecls[i]);
- }
- break;
- default:
- break;
- }
+ if (!t)
+ return;
+ b = tybase(t);
+ switch (b->type) {
+ case Tystruct:
+ for (i = 0; i < b->nmemb; i++)
+ installucons(st, b->sdecls[i]->decl.type);
+ break;
+ case Tyunion:
+ for (i = 0; i < b->nmemb; i++) {
+ b->udecls[i]->utype = b;
+ b->udecls[i]->id = i;
+ putucon(st, b->udecls[i]);
+ }
+ break;
+ default:
+ break;
+ }
}
static Op binop(int tt)
{
- Op o;
+ Op o;
- o = Obad;
- switch (tt) {
- case Tplus: o = Oadd; break;
- case Tminus: o = Osub; break;
- case Tmul: o = Omul; break;
- case Tdiv: o = Odiv; break;
- case Tmod: o = Omod; break;
- case Tasn: o = Oasn; break;
- case Taddeq: o = Oaddeq; break;
- case Tsubeq: o = Osubeq; break;
- case Tmuleq: o = Omuleq; break;
- case Tdiveq: o = Odiveq; break;
- case Tmodeq: o = Omodeq; break;
- case Tboreq: o = Oboreq; break;
- case Tbxoreq: o = Obxoreq; break;
- case Tbandeq: o = Obandeq; break;
- case Tbsleq: o = Obsleq; break;
- case Tbsreq: o = Obsreq; break;
- case Tbor: o = Obor; break;
- case Tbxor: o = Obxor; break;
- case Tband: o = Oband; break;
- case Tbsl: o = Obsl; break;
- case Tbsr: o = Obsr; break;
- case Teq: o = Oeq; break;
- case Tgt: o = Ogt; break;
- case Tlt: o = Olt; break;
- case Tge: o = Oge; break;
- case Tle: o = Ole; break;
- case Tne: o = One; break;
- case Tlor: o = Olor; break;
- case Tland: o = Oland; break;
- default:
- die("Unimplemented binop\n");
- break;
- }
- return o;
+ o = Obad;
+ switch (tt) {
+ case Tplus: o = Oadd; break;
+ case Tminus: o = Osub; break;
+ case Tmul: o = Omul; break;
+ case Tdiv: o = Odiv; break;
+ case Tmod: o = Omod; break;
+ case Tasn: o = Oasn; break;
+ case Taddeq: o = Oaddeq; break;
+ case Tsubeq: o = Osubeq; break;
+ case Tmuleq: o = Omuleq; break;
+ case Tdiveq: o = Odiveq; break;
+ case Tmodeq: o = Omodeq; break;
+ case Tboreq: o = Oboreq; break;
+ case Tbxoreq: o = Obxoreq; break;
+ case Tbandeq: o = Obandeq; break;
+ case Tbsleq: o = Obsleq; break;
+ case Tbsreq: o = Obsreq; break;
+ case Tbor: o = Obor; break;
+ case Tbxor: o = Obxor; break;
+ case Tband: o = Oband; break;
+ case Tbsl: o = Obsl; break;
+ case Tbsr: o = Obsr; break;
+ case Teq: o = Oeq; break;
+ case Tgt: o = Ogt; break;
+ case Tlt: o = Olt; break;
+ case Tge: o = Oge; break;
+ case Tle: o = Ole; break;
+ case Tne: o = One; break;
+ case Tlor: o = Olor; break;
+ case Tland: o = Oland; break;
+ default:
+ die("Unimplemented binop\n");
+ break;
+ }
+ return o;
}
--- a/parse/htab.c
+++ b/parse/htab.c
@@ -15,20 +15,20 @@
* hash collisions. */
Htab *mkht(ulong (*hash)(void *key), int (*cmp)(void *k1, void *k2))
{
- Htab *ht;
+ Htab *ht;
- ht = xalloc(sizeof(Htab));
- ht->nelt = 0;
- ht->ndead = 0;
- ht->sz = Initsz;
- ht->hash = hash;
- ht->cmp = cmp;
- ht->keys = zalloc(Initsz*sizeof(void*));
- ht->vals = zalloc(Initsz*sizeof(void*));
- ht->hashes = zalloc(Initsz*sizeof(void*));
- ht->dead = zalloc(Initsz*sizeof(char));
+ ht = xalloc(sizeof(Htab));
+ ht->nelt = 0;
+ ht->ndead = 0;
+ ht->sz = Initsz;
+ ht->hash = hash;
+ ht->cmp = cmp;
+ ht->keys = zalloc(Initsz * sizeof(void *));
+ ht->vals = zalloc(Initsz * sizeof(void *));
+ ht->hashes = zalloc(Initsz * sizeof(void *));
+ ht->dead = zalloc(Initsz * sizeof(char));
- return ht;
+ return ht;
}
/* Frees a hash table. Passing this function
@@ -35,13 +35,13 @@
* NULL is a no-op. */
void htfree(Htab *ht)
{
- if (!ht)
- return;
- free(ht->keys);
- free(ht->vals);
- free(ht->hashes);
- free(ht->dead);
- free(ht);
+ if (!ht)
+ return;
+ free(ht->keys);
+ free(ht->vals);
+ free(ht->hashes);
+ free(ht->dead);
+ free(ht);
}
/* Offsets the hash so that '0' can be
@@ -48,12 +48,12 @@
* used as a 'no valid value */
static ulong hash(Htab *ht, void *k)
{
- ulong h;
- h = ht->hash(k);
- if (h == 0)
- return 1;
- else
- return h;
+ ulong h;
+ h = ht->hash(k);
+ if (h == 0)
+ return 1;
+ else
+ return h;
}
/* Resizes the hash table by copying all
@@ -61,35 +61,35 @@
* new table. */
static void grow(Htab *ht, int sz)
{
- void **oldk;
- void **oldv;
- ulong *oldh;
- char *oldd;
- int oldsz;
- int i;
+ void **oldk;
+ void **oldv;
+ ulong *oldh;
+ char *oldd;
+ int oldsz;
+ int i;
- oldk = ht->keys;
- oldv = ht->vals;
- oldh = ht->hashes;
- oldd = ht->dead;
- oldsz = ht->sz;
+ oldk = ht->keys;
+ oldv = ht->vals;
+ oldh = ht->hashes;
+ oldd = ht->dead;
+ oldsz = ht->sz;
- ht->nelt = 0;
- ht->ndead = 0;
- ht->sz = sz;
- ht->keys = zalloc(sz*sizeof(void*));
- ht->vals = zalloc(sz*sizeof(void*));
- ht->hashes = zalloc(sz*sizeof(void*));
- ht->dead = zalloc(sz*sizeof(void*));
+ ht->nelt = 0;
+ ht->ndead = 0;
+ ht->sz = sz;
+ ht->keys = zalloc(sz * sizeof(void *));
+ ht->vals = zalloc(sz * sizeof(void *));
+ ht->hashes = zalloc(sz * sizeof(void *));
+ ht->dead = zalloc(sz * sizeof(void *));
- for (i = 0; i < oldsz; i++)
- if (oldh[i] && !oldd[i])
- htput(ht, oldk[i], oldv[i]);
+ for (i = 0; i < oldsz; i++)
+ if (oldh[i] && !oldd[i])
+ htput(ht, oldk[i], oldv[i]);
- free(oldh);
- free(oldk);
- free(oldv);
- free(oldd);
+ free(oldh);
+ free(oldk);
+ free(oldv);
+ free(oldd);
}
/* Inserts 'k' into the hash table, possibly
@@ -97,39 +97,39 @@
* as equal. */
int htput(Htab *ht, void *k, void *v)
{
- int i;
- ulong h;
- int di;
+ int i;
+ ulong h;
+ int di;
- di = 0;
- h = hash(ht, k);
- i = h & (ht->sz - 1);
- while (ht->hashes[i] && !ht->dead[i]) {
- /* second insertion overwrites first. nb, we shouldn't touch the
- * keys for dead values */
- if (ht->hashes[i] == h) {
- if (ht->dead[i])
- break;
- else if (ht->cmp(ht->keys[i], k))
- goto conflicted;
- }
- di++;
- i = (h + di) & (ht->sz - 1);
- }
- ht->nelt++;
+ di = 0;
+ h = hash(ht, k);
+ i = h & (ht->sz - 1);
+ while (ht->hashes[i] && !ht->dead[i]) {
+ /* second insertion overwrites first. nb, we shouldn't touch the
+ * keys for dead values */
+ if (ht->hashes[i] == h) {
+ if (ht->dead[i])
+ break;
+ else if (ht->cmp(ht->keys[i], k))
+ goto conflicted;
+ }
+ di++;
+ i = (h + di) & (ht->sz - 1);
+ }
+ ht->nelt++;
conflicted:
- if (ht->dead[i])
- ht->ndead--;
- ht->hashes[i] = h;
- ht->keys[i] = k;
- ht->vals[i] = v;
- ht->dead[i] = 0;
+ if (ht->dead[i])
+ ht->ndead--;
+ ht->hashes[i] = h;
+ ht->keys[i] = k;
+ ht->vals[i] = v;
+ ht->dead[i] = 0;
- if (ht->sz < ht->nelt * 2)
- grow(ht, ht->sz * 2);
- if (ht->sz < ht->ndead * 4)
- grow(ht, ht->sz);
- return 1;
+ if (ht->sz < ht->nelt * 2)
+ grow(ht, ht->sz * 2);
+ if (ht->sz < ht->ndead * 4)
+ grow(ht, ht->sz);
+ return 1;
}
/* Finds the index that we would insert
@@ -136,23 +136,23 @@
* the key into */
static ssize_t htidx(Htab *ht, void *k)
{
- ssize_t i;
- ulong h;
- int di;
+ ssize_t i;
+ ulong h;
+ int di;
- di = 0;
- h = hash(ht, k);
- i = h & (ht->sz - 1);
- while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) {
+ di = 0;
+ h = hash(ht, k);
+ i = h & (ht->sz - 1);
+ while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) {
searchmore:
- di++;
- i = (h + di) & (ht->sz - 1);
- }
- if (!ht->hashes[i])
- return -1;
- if ((ht->hashes[i] == h && ht->dead[i]) || !ht->cmp(ht->keys[i], k))
- goto searchmore; /* collision */
- return i;
+ di++;
+ i = (h + di) & (ht->sz - 1);
+ }
+ if (!ht->hashes[i])
+ return -1;
+ if ((ht->hashes[i] == h && ht->dead[i]) || !ht->cmp(ht->keys[i], k))
+ goto searchmore; /* collision */
+ return i;
}
/* Looks up a key, returning NULL if
@@ -162,35 +162,31 @@
* not there */
void *htget(Htab *ht, void *k)
{
- ssize_t i;
+ ssize_t i;
- i = htidx(ht, k);
- if (i < 0)
- return NULL;
- else
- return ht->vals[i];
+ i = htidx(ht, k);
+ if (i < 0)
+ return NULL;
+ else
+ return ht->vals[i];
}
void htdel(Htab *ht, void *k)
{
- ssize_t i;
+ ssize_t i;
- i = htidx(ht, k);
- if (i < 0)
- return;
- assert(!ht->dead[i]);
- assert(ht->hashes[i]);
- ht->dead[i] = 1;
- ht->nelt--;
- ht->ndead++;
+ i = htidx(ht, k);
+ if (i < 0)
+ return;
+ assert(!ht->dead[i]);
+ assert(ht->hashes[i]);
+ ht->dead[i] = 1;
+ ht->nelt--;
+ ht->ndead++;
}
-
/* Tests for 'k's presence in 'ht' */
-int hthas(Htab *ht, void *k)
-{
- return htidx(ht, k) >= 0;
-}
+int hthas(Htab *ht, void *k) { return htidx(ht, k) >= 0; }
/* Returns a list of all keys in the hash
* table, storing the size of the returned
@@ -199,103 +195,94 @@
* job of the caller to free it */
void **htkeys(Htab *ht, size_t *nkeys)
{
- void **k;
- size_t i, j;
+ void **k;
+ size_t i, j;
- j = 0;
- k = xalloc(sizeof(void*)*ht->nelt);
- for (i = 0; i < ht->sz; i++)
- if (ht->hashes[i] && !ht->dead[i])
- k[j++] = ht->keys[i];
- *nkeys = ht->nelt;
- return k;
+ j = 0;
+ k = xalloc(sizeof(void *) * ht->nelt);
+ for (i = 0; i < ht->sz; i++)
+ if (ht->hashes[i] && !ht->dead[i])
+ k[j++] = ht->keys[i];
+ *nkeys = ht->nelt;
+ return k;
}
ulong strhash(void *_s)
{
- char *s;
- ulong h;
- ulong g;
+ char *s;
+ ulong h;
+ ulong g;
- s = _s;
- h = 0;
- while (s && *s) {
- h = ((h << 4) + *s++);
+ s = _s;
+ h = 0;
+ while (s && *s) {
+ h = ((h << 4) + *s++);
- if ((g = (h & 0xF0000000)))
- h ^= (g >> 24);
+ if ((g = (h & 0xF0000000)))
+ h ^= (g >> 24);
- h &= ~g;
- }
- return h;
+ h &= ~g;
+ }
+ return h;
}
int streq(void *a, void *b)
{
- if (a == b)
- return 1;
- if (a == NULL || b == NULL)
- return 0;
- return !strcmp(a, b);
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ return !strcmp(a, b);
}
ulong strlithash(void *_s)
{
- Str *s;
- ulong h, g, i;
+ Str *s;
+ ulong h, g, i;
- s = _s;
- h = 0;
- for (i = 0; i < s->len; i++) {
- h = ((h << 4) + s->buf[i]);
+ s = _s;
+ h = 0;
+ for (i = 0; i < s->len; i++) {
+ h = ((h << 4) + s->buf[i]);
- if ((g = (h & 0xF0000000)))
- h ^= (g >> 24);
+ if ((g = (h & 0xF0000000)))
+ h ^= (g >> 24);
- h &= ~g;
- }
- return h;
+ h &= ~g;
+ }
+ return h;
}
int strliteq(void *_a, void *_b)
{
- Str *a, *b;
+ Str *a, *b;
- a = _a;
- b = _b;
- if (a == b)
- return 1;
- if (a == NULL || b == NULL)
- return 0;
- if (a->len != b->len)
- return 0;
- return !memcmp(a, b, a->len);
+ a = _a;
+ b = _b;
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ if (a->len != b->len)
+ return 0;
+ return !memcmp(a, b, a->len);
}
-ulong ptrhash(void *key)
-{
- return inthash((uintptr_t)key);
-}
+ulong ptrhash(void *key) { return inthash((uintptr_t)key); }
ulong inthash(uint64_t key)
{
- uintptr_t h;
+ uintptr_t h;
- h = (uintptr_t) key;
- h *= 357913941;
- h ^= h << 24;
- h += ~357913941;
- h ^= h >> 31;
- h ^= h << 31;
- return h;
+ h = (uintptr_t)key;
+ h *= 357913941;
+ h ^= h << 24;
+ h += ~357913941;
+ h ^= h >> 31;
+ h ^= h << 31;
+ return h;
}
-int inteq(uint64_t a, uint64_t b)
-{
- return a == b;
-}
+int inteq(uint64_t a, uint64_t b) { return a == b; }
-int ptreq(void *a, void *b)
-{
- return a == b;
-}
+int ptreq(void *a, void *b) { return a == b; }
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -16,36 +16,36 @@
typedef struct Inferstate Inferstate;
struct Inferstate {
- int ingeneric;
- int inaggr;
- int innamed;
- int sawret;
- int indentdepth;
- Type *ret;
+ int ingeneric;
+ int inaggr;
+ int innamed;
+ int sawret;
+ int indentdepth;
+ Type *ret;
- /* bound by patterns turn into decls in the action block */
- Node **binds;
- size_t nbinds;
- /* nodes that need post-inference checking/unification */
- Node **postcheck;
- size_t npostcheck;
- Stab **postcheckscope;
- size_t npostcheckscope;
- /* the type params bound at the current point */
- Htab **tybindings;
- size_t ntybindings;
- /* generic declarations to be specialized */
- Node **genericdecls;
- size_t ngenericdecls;
- /* delayed unification -- we fall back to these types in a post pass if we
- * haven't unifed to something more specific */
- Htab *delayed;
- /* the nodes that we've specialized them to, and the scopes they
- * appear in */
- Node **specializations;
- size_t nspecializations;
- Stab **specializationscope;
- size_t nspecializationscope;
+ /* bound by patterns turn into decls in the action block */
+ Node **binds;
+ size_t nbinds;
+ /* nodes that need post-inference checking/unification */
+ Node **postcheck;
+ size_t npostcheck;
+ Stab **postcheckscope;
+ size_t npostcheckscope;
+ /* the type params bound at the current point */
+ Htab **tybindings;
+ size_t ntybindings;
+ /* generic declarations to be specialized */
+ Node **genericdecls;
+ size_t ngenericdecls;
+ /* delayed unification -- we fall back to these types in a post pass if we
+ * haven't unifed to something more specific */
+ Htab *delayed;
+ /* the nodes that we've specialized them to, and the scopes they
+ * appear in */
+ Node **specializations;
+ size_t nspecializations;
+ Stab **specializationscope;
+ size_t nspecializationscope;
};
static void infernode(Inferstate *st, Node **np, Type *ret, int *sawret);
@@ -62,57 +62,57 @@
static void ctxstrcall(char *buf, size_t sz, Inferstate *st, Node *n)
{
- char *p, *end, *sep, *t;
- size_t nargs, i;
- Node **args;
- Type *et;
+ char *p, *end, *sep, *t;
+ size_t nargs, i;
+ Node **args;
+ Type *et;
- args = n->expr.args;
- nargs = n->expr.nargs;
- p = buf;
- end = buf + sz;
- sep = "";
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ p = buf;
+ end = buf + sz;
+ sep = "";
- if (exprop(args[0]) == Ovar)
- p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
- else
- p += bprintf(p, end - p, "<e>(");
- for (i = 1; i < nargs; i++) {
- et = tyfix(st, NULL, exprtype(args[i]), 1);
- if (et != NULL)
- t = tystr(et);
- else
- t = strdup("?");
+ if (exprop(args[0]) == Ovar)
+ p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
+ else
+ p += bprintf(p, end - p, "<e>(");
+ for (i = 1; i < nargs; i++) {
+ et = tyfix(st, NULL, exprtype(args[i]), 1);
+ if (et != NULL)
+ t = tystr(et);
+ else
+ t = strdup("?");
- if (exprop(args[i]) == Ovar)
- p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
- else
- p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
- sep = ", ";
- free(t);
- }
- if (exprtype(args[0])->nsub)
- t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
- else
- t = strdup("unknown");
- p += bprintf(p, end - p, "): %s", t);
- free(t);
+ if (exprop(args[i]) == Ovar)
+ p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
+ else
+ p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
+ sep = ", ";
+ free(t);
+ }
+ if (exprtype(args[0])->nsub)
+ t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
+ else
+ t = strdup("unknown");
+ p += bprintf(p, end - p, "): %s", t);
+ free(t);
}
static char *nodetystr(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- t = NULL;
- if (n->type == Nexpr && exprtype(n) != NULL)
- t = tyfix(st, NULL, exprtype(n), 1);
- else if (n->type == Ndecl && decltype(n) != NULL)
- t = tyfix(st, NULL, decltype(n), 1);
+ t = NULL;
+ if (n->type == Nexpr && exprtype(n) != NULL)
+ t = tyfix(st, NULL, exprtype(n), 1);
+ else if (n->type == Ndecl && decltype(n) != NULL)
+ t = tyfix(st, NULL, decltype(n), 1);
- if (t && tybase(t)->type != Tyvar)
- return tystr(t);
- else
- return strdup("unknown");
+ if (t && tybase(t)->type != Tyvar)
+ return tystr(t);
+ else
+ return strdup("unknown");
}
/* Tries to give a good string describing the context
@@ -119,141 +119,125 @@
* for the sake of error messages. */
static char *ctxstr(Inferstate *st, Node *n)
{
- char *t, *t1, *t2, *t3;
- char *s, *d;
- size_t nargs;
- Node **args;
- char buf[512];
+ char *t, *t1, *t2, *t3;
+ char *s, *d;
+ size_t nargs;
+ Node **args;
+ char buf[512];
- switch (n->type) {
- default:
- s = strdup(nodestr[n->type]);
- break;
- case Ndecl:
- d = declname(n);
- t = nodetystr(st, n);
- bprintf(buf, sizeof buf, "%s:%s", d, t);
- s = strdup(buf);
- free(t);
- break;
- case Nname:
- s = strdup(namestr(n));
- break;
- case Nexpr:
- args = n->expr.args;
- nargs = n->expr.nargs;
- t1 = NULL;
- t2 = NULL;
- t3 = NULL;
- if (exprop(n) == Ovar)
- d = namestr(args[0]);
- else
- d = opstr[exprop(n)];
- t = nodetystr(st, n);
- if (nargs >= 1)
- t1 = nodetystr(st, args[0]);
- if (nargs >= 2)
- t2 = nodetystr(st, args[1]);
- if (nargs >= 3)
- t3 = nodetystr(st, args[2]);
- switch (opclass[exprop(n)]) {
- case OTbin:
- bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
- break;
- case OTpre:
- bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]);
- break;
- case OTpost:
- bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]);
- break;
- case OTzarg:
- bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]);
- break;
- case OTmisc:
- switch (exprop(n)) {
- case Ovar:
- bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t);
- break;
- case Ocall:
- ctxstrcall(buf, sizeof buf, st, n);
- break;
- case Oidx:
- if (exprop(args[0]) == Ovar)
- bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
- else
- bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
- break;
- case Oslice:
- if (exprop(args[0]) == Ovar)
- bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
- else
- bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
- break;
- case Omemb:
- bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
- break;
- default:
- bprintf(buf, sizeof buf, "%s:%s", d, t);
- break;
- }
- break;
- default:
- bprintf(buf, sizeof buf, "%s", d);
- break;
- }
- free(t);
- free(t1);
- free(t2);
- free(t3);
- s = strdup(buf);
- break;
- }
- return s;
+ switch (n->type) {
+ default: s = strdup(nodestr[n->type]); break;
+ case Ndecl:
+ d = declname(n);
+ t = nodetystr(st, n);
+ bprintf(buf, sizeof buf, "%s:%s", d, t);
+ s = strdup(buf);
+ free(t);
+ break;
+ case Nname: s = strdup(namestr(n)); break;
+ case Nexpr:
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ t1 = NULL;
+ t2 = NULL;
+ t3 = NULL;
+ if (exprop(n) == Ovar)
+ d = namestr(args[0]);
+ else
+ d = opstr[exprop(n)];
+ t = nodetystr(st, n);
+ if (nargs >= 1)
+ t1 = nodetystr(st, args[0]);
+ if (nargs >= 2)
+ t2 = nodetystr(st, args[1]);
+ if (nargs >= 3)
+ t3 = nodetystr(st, args[2]);
+
+ switch (opclass[exprop(n)]) {
+ case OTpre: bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]); break;
+ case OTpost: bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]); break;
+ case OTzarg: bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]); break;
+ case OTmisc:
+ case OTbin:
+ bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
+ break;
+ switch (exprop(n)) {
+ case Ovar: bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t); break;
+ case Ocall: ctxstrcall(buf, sizeof buf, st, n); break;
+ case Oidx:
+ if (exprop(args[0]) == Ovar)
+ bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
+ else
+ bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
+ break;
+ case Oslice:
+ if (exprop(args[0]) == Ovar)
+ bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
+ else
+ bprintf( buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
+ break;
+ case Omemb:
+ bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
+ break;
+ default:
+ bprintf(buf, sizeof buf, "%s:%s", d, t);
+ break;
+ }
+ break;
+ default: bprintf(buf, sizeof buf, "%s", d); break;
+ }
+ free(t);
+ free(t1);
+ free(t2);
+ free(t3);
+ s = strdup(buf);
+ break;
+ }
+ return s;
}
static void addspecialization(Inferstate *st, Node *n, Stab *stab)
{
- Node *dcl;
+ Node *dcl;
- dcl = decls[n->expr.did];
- lappend(&st->specializationscope, &st->nspecializationscope, stab);
- lappend(&st->specializations, &st->nspecializations, n);
- lappend(&st->genericdecls, &st->ngenericdecls, dcl);
+ dcl = decls[n->expr.did];
+ lappend(&st->specializationscope, &st->nspecializationscope, stab);
+ lappend(&st->specializations, &st->nspecializations, n);
+ lappend(&st->genericdecls, &st->ngenericdecls, dcl);
}
static void delayedcheck(Inferstate *st, Node *n, Stab *s)
{
- lappend(&st->postcheck, &st->npostcheck, n);
- lappend(&st->postcheckscope, &st->npostcheckscope, s);
+ lappend(&st->postcheck, &st->npostcheck, n);
+ lappend(&st->postcheckscope, &st->npostcheckscope, s);
}
static void typeerror(Inferstate *st, Type *a, Type *b, Node *ctx, char *msg)
{
- char *t1, *t2, *c;
+ char *t1, *t2, *c;
- t1 = tystr(tyfix(st, NULL, a, 1));
- t2 = tystr(tyfix(st, NULL, b, 1));
- c = ctxstr(st, ctx);
- if (msg)
- fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
- else
- fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
- free(t1);
- free(t2);
- free(c);
+ t1 = tystr(tyfix(st, NULL, a, 1));
+ t2 = tystr(tyfix(st, NULL, b, 1));
+ c = ctxstr(st, ctx);
+ if (msg)
+ fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
+ else
+ fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
+ free(t1);
+ free(t2);
+ free(c);
}
-
/* Set a scope's enclosing scope up correctly.
* We don't do this in the parser for some reason. */
static void setsuper(Stab *st, Stab *super)
{
- Stab *s;
+ Stab *s;
- /* verify that we don't accidentally create loops */
- for (s = super; s; s = s->super)
- assert(s->super != st);
- st->super = super;
+ /* verify that we don't accidentally create loops */
+ for (s = super; s; s = s->super)
+ assert(s->super != st);
+ st->super = super;
}
/* If the current environment binds a type,
@@ -260,13 +244,13 @@
* we return true */
static int isbound(Inferstate *st, Type *t)
{
- ssize_t i;
+ ssize_t i;
- for (i = st->ntybindings - 1; i >= 0; i--) {
- if (htget(st->tybindings[i], t->pname))
- return 1;
- }
- return 0;
+ for (i = st->ntybindings - 1; i >= 0; i--) {
+ if (htget(st->tybindings[i], t->pname))
+ return 1;
+ }
+ return 0;
}
/* Checks if a type that directly contains itself.
@@ -275,222 +259,225 @@
* would lead to a value of infinite size */
static int tyinfinite(Inferstate *st, Type *t, Type *sub)
{
- size_t i;
+ size_t i;
- assert(t != NULL);
- if (t == sub) /* FIXME: is this actually right? */
- return 1;
- /* if we're on the first iteration, the subtype is the type
- * itself. The assignment must come after the equality check
- * for obvious reasons. */
- if (!sub)
- sub = t;
+ assert(t != NULL);
+ if (t == sub) /* FIXME: is this actually right? */
+ return 1;
+ /* if we're on the first iteration, the subtype is the type
+ * itself. The assignment must come after the equality check
+ * for obvious reasons. */
+ if (!sub)
+ sub = t;
- switch (sub->type) {
- case Tystruct:
- for (i = 0; i < sub->nmemb; i++)
- if (tyinfinite(st, t, decltype(sub->sdecls[i])))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < sub->nmemb; i++) {
- if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
- return 1;
- }
- break;
-
- case Typtr:
- case Tyslice:
- return 0;
- default:
- for (i = 0; i < sub->nsub; i++)
- if (tyinfinite(st, t, sub->sub[i]))
- return 1;
- break;
- }
- return 0;
+ switch (sub->type) {
+ case Tystruct:
+ for (i = 0; i < sub->nmemb; i++)
+ if (tyinfinite(st, t, decltype(sub->sdecls[i])))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < sub->nmemb; i++) {
+ if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
+ return 1;
+ }
+ break;
+ case Typtr:
+ case Tyslice: return 0;
+ default:
+ for (i = 0; i < sub->nsub; i++)
+ if (tyinfinite(st, t, sub->sub[i]))
+ return 1;
+ break;
+ }
+ return 0;
}
-
static int needfreshenrec(Inferstate *st, Type *t, Bitset *visited)
{
- size_t i;
+ size_t i;
- if (bshas(visited, t->tid))
- return 0;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram: return 1;
- case Tygeneric: return 1;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- if (needfreshenrec(st, t->arg[i], visited))
- return 1;
- return needfreshenrec(st, t->sub[0], visited);
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- if (needfreshenrec(st, decltype(t->sdecls[i]), visited))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype && needfreshenrec(st, t->udecls[i]->etype, visited))
- return 1;
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- if (needfreshenrec(st, t->sub[i], visited))
- return 1;
- break;
- }
- return 0;
+ if (bshas(visited, t->tid))
+ return 0;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram: return 1;
+ case Tygeneric: return 1;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ if (needfreshenrec(st, t->arg[i], visited))
+ return 1;
+ return needfreshenrec(st, t->sub[0], visited);
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ if (needfreshenrec(st, decltype(t->sdecls[i]), visited))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype && needfreshenrec(st, t->udecls[i]->etype, visited))
+ return 1;
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ if (needfreshenrec(st, t->sub[i], visited))
+ return 1;
+ break;
+ }
+ return 0;
}
static int needfreshen(Inferstate *st, Type *t)
{
- Bitset *visited;
- int ret;
+ Bitset *visited;
+ int ret;
- visited = mkbs();
- ret = needfreshenrec(st, t, visited);
- bsfree(visited);
- return ret;
+ visited = mkbs();
+ ret = needfreshenrec(st, t, visited);
+ bsfree(visited);
+ return ret;
}
/* Freshens the type of a declaration. */
static Type *tyfreshen(Inferstate *st, Htab *subst, Type *t)
{
- char *from, *to;
+ char *from, *to;
- if (!needfreshen(st, t)) {
- if (debugopt['u'])
- indentf(st->indentdepth, "%s isn't generic: skipping freshen\n", tystr(t));
- return t;
- }
+ if (!needfreshen(st, t)) {
+ if (debugopt['u'])
+ indentf(st->indentdepth, "%s isn't generic: skipping freshen\n", tystr(t));
+ return t;
+ }
- from = tystr(t);
- tybind(st, t);
- if (!subst) {
- subst = mkht(tyhash, tyeq);
- t = tyspecialize(t, subst, st->delayed);
- htfree(subst);
- } else {
- t = tyspecialize(t, subst, st->delayed);
- }
- tyunbind(st, t);
- if (debugopt['u']) {
- to = tystr(t);
- indentf(st->indentdepth, "Freshen %s => %s\n", from, to);
- free(from);
- free(to);
- }
+ from = tystr(t);
+ tybind(st, t);
+ if (!subst) {
+ subst = mkht(tyhash, tyeq);
+ t = tyspecialize(t, subst, st->delayed);
+ htfree(subst);
+ }
+ else {
+ t = tyspecialize(t, subst, st->delayed);
+ }
+ tyunbind(st, t);
+ if (debugopt['u']) {
+ to = tystr(t);
+ indentf(st->indentdepth, "Freshen %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
- return t;
+ return t;
}
/* Resolves a type and all it's subtypes recursively.*/
static void tyresolve(Inferstate *st, Type *t)
{
- size_t i;
- Type *base;
+ size_t i;
+ Type *base;
- if (t->resolved)
- return;
- /* type resolution should never throw errors about non-generics
- * showing up within a generic type, so we push and pop a generic
- * around resolution */
- st->ingeneric++;
- t->resolved = 1;
- /* Walk through aggregate type members */
- if (t->type == Tystruct) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++)
- infernode(st, &t->sdecls[i], NULL, NULL);
- st->inaggr--;
- } else if (t->type == Tyunion) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++) {
- t->udecls[i]->utype = t;
- t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
- if (t->udecls[i]->etype) {
- tyresolve(st, t->udecls[i]->etype);
- t->udecls[i]->etype = tf(st, t->udecls[i]->etype);
- }
- }
- st->inaggr--;
- } else if (t->type == Tyarray) {
- if (!st->inaggr && !t->asize)
- lfatal(t->loc, "unsized array type outside of struct");
- infernode(st, &t->asize, NULL, NULL);
- } else if (t->type == Typaram && st->innamed) {
- if (!isbound(st, t))
- lfatal(t->loc, "type parameter %s is undefined in generic context", tystr(t));
- }
+ if (t->resolved)
+ return;
+ /* type resolution should never throw errors about non-generics
+ * showing up within a generic type, so we push and pop a generic
+ * around resolution */
+ st->ingeneric++;
+ t->resolved = 1;
+ /* Walk through aggregate type members */
+ if (t->type == Tystruct) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++)
+ infernode(st, &t->sdecls[i], NULL, NULL);
+ st->inaggr--;
+ }
+ else if (t->type == Tyunion) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++) {
+ t->udecls[i]->utype = t;
+ t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
+ if (t->udecls[i]->etype) {
+ tyresolve(st, t->udecls[i]->etype);
+ t->udecls[i]->etype = tf(st, t->udecls[i]->etype);
+ }
+ }
+ st->inaggr--;
+ }
+ else if (t->type == Tyarray) {
+ if (!st->inaggr && !t->asize)
+ lfatal(t->loc, "unsized array type outside of struct");
+ infernode(st, &t->asize, NULL, NULL);
+ }
+ else if (t->type == Typaram && st->innamed) {
+ if (!isbound(st, t))
+ lfatal(
+ t->loc, "type parameter %s is undefined in generic context", tystr(t));
+ }
- if (t->type == Tyname || t->type == Tygeneric) {
- tybind(st, t);
- st->innamed++;
- }
- for (i = 0; i < t->nsub; i++)
- t->sub[i] = tf(st, t->sub[i]);
- base = tybase(t);
- /* no-ops if base == t */
- if (t->traits)
- bsunion(t->traits, base->traits);
- else
- t->traits = bsdup(base->traits);
- if (tyinfinite(st, t, NULL))
- lfatal(t->loc, "type %s includes itself", tystr(t));
- st->ingeneric--;
- if (t->type == Tyname || t->type == Tygeneric) {
- tyunbind(st, t);
- st->innamed--;
- }
+ if (t->type == Tyname || t->type == Tygeneric) {
+ tybind(st, t);
+ st->innamed++;
+ }
+ for (i = 0; i < t->nsub; i++)
+ t->sub[i] = tf(st, t->sub[i]);
+ base = tybase(t);
+ /* no-ops if base == t */
+ if (t->traits)
+ bsunion(t->traits, base->traits);
+ else
+ t->traits = bsdup(base->traits);
+ if (tyinfinite(st, t, NULL))
+ lfatal(t->loc, "type %s includes itself", tystr(t));
+ st->ingeneric--;
+ if (t->type == Tyname || t->type == Tygeneric) {
+ tyunbind(st, t);
+ st->innamed--;
+ }
}
/* Look up the best type to date in the unification table, returning it */
Type *tysearch(Type *t)
{
- Type *lu;
- Stab *ns;
+ Type *lu;
+ Stab *ns;
- assert(t != NULL);
- lu = NULL;
- while (1) {
- if (!tytab[t->tid] && t->type == Tyunres) {
- ns = curstab();
- if (t->name->name.ns) {
- ns = getns(file, t->name->name.ns);
- }
- if (!ns)
- fatal(t->name, "could not resolve namespace \"%s\"", t->name->name.ns);
- if (!(lu = gettype(ns, t->name)))
- fatal(t->name, "could not resolve type %s", tystr(t));
- tytab[t->tid] = lu;
- }
+ assert(t != NULL);
+ lu = NULL;
+ while (1) {
+ if (!tytab[t->tid] && t->type == Tyunres) {
+ ns = curstab();
+ if (t->name->name.ns) {
+ ns = getns(file, t->name->name.ns);
+ }
+ if (!ns)
+ fatal(t->name, "could not resolve namespace \"%s\"",
+ t->name->name.ns);
+ if (!(lu = gettype(ns, t->name)))
+ fatal(t->name, "could not resolve type %s", tystr(t));
+ tytab[t->tid] = lu;
+ }
- if (!tytab[t->tid])
- break;
- /* compress paths: shift the link up one level */
- if (tytab[tytab[t->tid]->tid])
- tytab[t->tid] = tytab[tytab[t->tid]->tid];
- t = tytab[t->tid];
- }
- return t;
+ if (!tytab[t->tid])
+ break;
+ /* compress paths: shift the link up one level */
+ if (tytab[tytab[t->tid]->tid])
+ tytab[t->tid] = tytab[tytab[t->tid]->tid];
+ t = tytab[t->tid];
+ }
+ return t;
}
static Type *tysubst(Inferstate *st, Type *t, Type *orig)
{
- Htab *subst;
- size_t i;
+ Htab *subst;
+ size_t i;
- subst = mkht(tyhash, tyeq);
- for (i = 0; i < t->ngparam; i++) {
- htput(subst, t->gparam[i], tf(st, orig->arg[i]));
- }
- t = tyfreshen(st, subst, t);
- htfree(subst);
- return t;
+ subst = mkht(tyhash, tyeq);
+ for (i = 0; i < t->ngparam; i++) {
+ htput(subst, t->gparam[i], tf(st, orig->arg[i]));
+ }
+ t = tyfreshen(st, subst, t);
+ htfree(subst);
+ return t;
}
/* fixd the most accurate type mapping we have (ie,
@@ -497,162 +484,160 @@
* the end of the unification chain */
static Type *tf(Inferstate *st, Type *orig)
{
- int isgeneric;
- Type *t;
+ int isgeneric;
+ Type *t;
- assert(orig != NULL);
- t = tysearch(orig);
- isgeneric = t->type == Tygeneric;
- st->ingeneric += isgeneric;
- tyresolve(st, t);
- /* If this is an instantiation of a generic type, we want the params to
- * match the instantiation */
- if (orig->type == Tyunres && t->type == Tygeneric) {
- if (t->ngparam != orig->narg) {
- lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
- tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
- }
- t = tysubst(st, t, orig);
- }
- st->ingeneric -= isgeneric;
- return t;
+ assert(orig != NULL);
+ t = tysearch(orig);
+ isgeneric = t->type == Tygeneric;
+ st->ingeneric += isgeneric;
+ tyresolve(st, t);
+ /* If this is an instantiation of a generic type, we want the params to
+ * match the instantiation */
+ if (orig->type == Tyunres && t->type == Tygeneric) {
+ if (t->ngparam != orig->narg) {
+ lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
+ tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
+ }
+ t = tysubst(st, t, orig);
+ }
+ st->ingeneric -= isgeneric;
+ return t;
}
/* set the type of any typable node */
static void settype(Inferstate *st, Node *n, Type *t)
{
- t = tf(st, t);
- switch (n->type) {
- case Nexpr: n->expr.type = t; break;
- case Ndecl: n->decl.type = t; break;
- case Nlit: n->lit.type = t; break;
- case Nfunc: n->func.type = t; break;
- default:
- die("untypable node %s", nodestr[n->type]);
- break;
- }
+ t = tf(st, t);
+ switch (n->type) {
+ case Nexpr: n->expr.type = t; break;
+ case Ndecl: n->decl.type = t; break;
+ case Nlit: n->lit.type = t; break;
+ case Nfunc: n->func.type = t; break;
+ default: die("untypable node %s", nodestr[n->type]); break;
+ }
}
/* Gets the type of a literal value */
static Type *littype(Node *n)
{
- Type *t;
+ Type *t;
- t = NULL;
- if (!n->lit.type) {
- switch (n->lit.littype) {
- case Lchr: t = mktype(n->loc, Tychar); break;
- case Lbool: t = mktype(n->loc, Tybool); break;
- case Lint: t = mktylike(n->loc, Tyint); break;
- case Lflt: t = mktylike(n->loc, Tyflt64); break;
- case Lstr: t = mktyslice(n->loc, mktype(n->loc, Tybyte)); break;
- case Llbl: t = mktyptr(n->loc, mktype(n->loc, Tyvoid)); break;
- case Lfunc: t = n->lit.fnval->func.type; break;
- }
- n->lit.type = t;
- }
- return n->lit.type;
+ t = NULL;
+ if (!n->lit.type) {
+ switch (n->lit.littype) {
+ case Lchr: t = mktype(n->loc, Tychar); break;
+ case Lbool: t = mktype(n->loc, Tybool); break;
+ case Lint: t = mktylike(n->loc, Tyint); break;
+ case Lflt: t = mktylike(n->loc, Tyflt64); break;
+ case Lstr: t = mktyslice(n->loc, mktype(n->loc, Tybyte)); break;
+ case Llbl: t = mktyptr(n->loc, mktype(n->loc, Tyvoid)); break;
+ case Lfunc: t = n->lit.fnval->func.type; break;
+ }
+ n->lit.type = t;
+ }
+ return n->lit.type;
}
static Type *delayeducon(Inferstate *st, Type *fallback)
{
- Type *t;
- char *from, *to;
+ Type *t;
+ char *from, *to;
- if (fallback->type != Tyunion)
- return fallback;
- t = mktylike(fallback->loc, fallback->type);
- htput(st->delayed, t, fallback);
- if (debugopt['u']) {
- from = tystr(t);
- to = tystr(fallback);
- indentf(st->indentdepth, "Delay %s -> %s\n", from, to);
- free(from);
- free(to);
- }
- return t;
+ if (fallback->type != Tyunion)
+ return fallback;
+ t = mktylike(fallback->loc, fallback->type);
+ htput(st->delayed, t, fallback);
+ if (debugopt['u']) {
+ from = tystr(t);
+ to = tystr(fallback);
+ indentf(st->indentdepth, "Delay %s -> %s\n", from, to);
+ free(from);
+ free(to);
+ }
+ return t;
}
/* Finds the type of any typable node */
static Type *type(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- switch (n->type) {
- case Nlit: t = littype(n); break;
- case Nexpr: t = n->expr.type; break;
- case Ndecl: t = decltype(n); break;
- case Nfunc: t = n->func.type; break;
- default:
- t = NULL;
- die("untypeable node %s", nodestr[n->type]);
- break;
- };
- return tf(st, t);
+ switch (n->type) {
+ case Nlit: t = littype(n); break;
+ case Nexpr: t = n->expr.type; break;
+ case Ndecl: t = decltype(n); break;
+ case Nfunc: t = n->func.type; break;
+ default:
+ t = NULL;
+ die("untypeable node %s", nodestr[n->type]);
+ break;
+ };
+ return tf(st, t);
}
static Ucon *uconresolve(Inferstate *st, Node *n)
{
- Ucon *uc;
- Node **args;
- Stab *ns;
+ Ucon *uc;
+ Node **args;
+ Stab *ns;
- args = n->expr.args;
- ns = curstab();
- if (args[0]->name.ns)
- ns = getns(file, args[0]->name.ns);
- if (!ns)
- fatal(n, "no namespace %s\n", args[0]->name.ns);
- uc = getucon(ns, args[0]);
- if (!uc)
- fatal(n, "no union constructor `%s", ctxstr(st, args[0]));
- if (!uc->etype && n->expr.nargs > 1)
- fatal(n, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
- else if (uc->etype && n->expr.nargs != 2)
- fatal(n, "union constructor `%s needs arg ", ctxstr(st, args[0]));
- return uc;
+ args = n->expr.args;
+ ns = curstab();
+ if (args[0]->name.ns)
+ ns = getns(file, args[0]->name.ns);
+ if (!ns)
+ fatal(n, "no namespace %s\n", args[0]->name.ns);
+ uc = getucon(ns, args[0]);
+ if (!uc)
+ fatal(n, "no union constructor `%s", ctxstr(st, args[0]));
+ if (!uc->etype && n->expr.nargs > 1)
+ fatal(n, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
+ else if (uc->etype && n->expr.nargs != 2)
+ fatal(n, "union constructor `%s needs arg ", ctxstr(st, args[0]));
+ return uc;
}
static void putbindingsrec(Inferstate *st, Htab *bt, Type *t, Bitset *visited)
{
- size_t i;
+ size_t i;
- if (bshas(visited, t->tid))
- return;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram:
- if (hthas(bt, t->pname))
- unify(st, NULL, htget(bt, t->pname), t);
- else if (!isbound(st, t))
- htput(bt, t->pname, t);
- break;
- case Tygeneric:
- for (i = 0; i < t->ngparam; i++)
- putbindingsrec(st, bt, t->gparam[i], visited);
- break;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- putbindingsrec(st, bt, t->arg[i], visited);
- break;
- case Tyunres:
- for (i = 0; i < t->narg; i++)
- putbindingsrec(st, bt, t->arg[i], visited);
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- putbindingsrec(st, bt, t->sdecls[i]->decl.type, visited);
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- putbindingsrec(st, bt, t->udecls[i]->etype, visited);
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- putbindingsrec(st, bt, t->sub[i], visited);
- break;
- }
+ if (bshas(visited, t->tid))
+ return;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram:
+ if (hthas(bt, t->pname))
+ unify(st, NULL, htget(bt, t->pname), t);
+ else if (!isbound(st, t))
+ htput(bt, t->pname, t);
+ break;
+ case Tygeneric:
+ for (i = 0; i < t->ngparam; i++)
+ putbindingsrec(st, bt, t->gparam[i], visited);
+ break;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ putbindingsrec(st, bt, t->arg[i], visited);
+ break;
+ case Tyunres:
+ for (i = 0; i < t->narg; i++)
+ putbindingsrec(st, bt, t->arg[i], visited);
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ putbindingsrec(st, bt, t->sdecls[i]->decl.type, visited);
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ putbindingsrec(st, bt, t->udecls[i]->etype, visited);
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ putbindingsrec(st, bt, t->sub[i], visited);
+ break;
+ }
}
/* Binds the type parameters present in the
@@ -659,28 +644,28 @@
* current type into the type environment */
static void putbindings(Inferstate *st, Htab *bt, Type *t)
{
- Bitset *visited;
+ Bitset *visited;
- if (!t)
- return;
- visited = mkbs();
- putbindingsrec(st, bt, t, visited);
- bsfree(visited);
+ if (!t)
+ return;
+ visited = mkbs();
+ putbindingsrec(st, bt, t, visited);
+ bsfree(visited);
}
static void tybind(Inferstate *st, Type *t)
{
- Htab *bt;
- char *s;
+ Htab *bt;
+ char *s;
- if (debugopt['u']) {
- s = tystr(t);
- indentf(st->indentdepth, "Binding %s\n", s);
- free(s);
- }
- bt = mkht(strhash, streq);
- lappend(&st->tybindings, &st->ntybindings, bt);
- putbindings(st, bt, t);
+ if (debugopt['u']) {
+ s = tystr(t);
+ indentf(st->indentdepth, "Binding %s\n", s);
+ free(s);
+ }
+ bt = mkht(strhash, streq);
+ lappend(&st->tybindings, &st->ntybindings, bt);
+ putbindings(st, bt, t);
}
/* Binds the type parameters in the
@@ -687,20 +672,20 @@
* declaration into the type environment */
static void bind(Inferstate *st, Node *n)
{
- Htab *bt;
+ Htab *bt;
- assert(n->type == Ndecl);
- if (!n->decl.isgeneric)
- return;
- if (!n->decl.init)
- fatal(n, "generic %s has no initializer", n->decl);
+ assert(n->type == Ndecl);
+ if (!n->decl.isgeneric)
+ return;
+ if (!n->decl.init)
+ fatal(n, "generic %s has no initializer", n->decl);
- st->ingeneric++;
- bt = mkht(strhash, streq);
- lappend(&st->tybindings, &st->ntybindings, bt);
+ st->ingeneric++;
+ bt = mkht(strhash, streq);
+ lappend(&st->tybindings, &st->ntybindings, bt);
- putbindings(st, bt, n->decl.type);
- putbindings(st, bt, n->decl.init->expr.type);
+ putbindings(st, bt, n->decl.type);
+ putbindings(st, bt, n->decl.init->expr.type);
}
/* Rolls back the binding of type parameters in
@@ -707,19 +692,19 @@
* the type environment */
static void unbind(Inferstate *st, Node *n)
{
- if (!n->decl.isgeneric)
- return;
- htfree(st->tybindings[st->ntybindings - 1]);
- lpop(&st->tybindings, &st->ntybindings);
- st->ingeneric--;
+ if (!n->decl.isgeneric)
+ return;
+ htfree(st->tybindings[st->ntybindings - 1]);
+ lpop(&st->tybindings, &st->ntybindings);
+ st->ingeneric--;
}
static void tyunbind(Inferstate *st, Type *t)
{
- if (t->type != Tygeneric)
- return;
- htfree(st->tybindings[st->ntybindings - 1]);
- lpop(&st->tybindings, &st->ntybindings);
+ if (t->type != Tygeneric)
+ return;
+ htfree(st->tybindings[st->ntybindings - 1]);
+ lpop(&st->tybindings, &st->ntybindings);
}
/* Constrains a type to implement the required constraints. On
@@ -728,73 +713,77 @@
* if it has the required constraint */
static void constrain(Inferstate *st, Node *ctx, Type *a, Trait *c)
{
- if (a->type == Tyvar) {
- if (!a->traits)
- a->traits = mkbs();
- settrait(a, c);
- } else if (!a->traits || !bshas(a->traits, c->uid)) {
- fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(st, ctx));
- }
+ if (a->type == Tyvar) {
+ if (!a->traits)
+ a->traits = mkbs();
+ settrait(a, c);
+ }
+ else if (!a->traits || !bshas(a->traits, c->uid)) {
+ fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(st, ctx));
+ }
}
/* does b satisfy all the constraints of a? */
static int checktraits(Type *a, Type *b)
{
- /* a has no traits to satisfy */
- if (!a->traits)
- return 1;
- /* b satisfies no traits; only valid if a requires none */
- if (!b->traits)
- return bscount(a->traits) == 0;
- /* if a->traits is a subset of b->traits, all of
- * a's constraints are satisfied by b. */
- return bsissubset(a->traits, b->traits);
+ /* a has no traits to satisfy */
+ if (!a->traits)
+ return 1;
+ /* b satisfies no traits; only valid if a requires none */
+ if (!b->traits)
+ return bscount(a->traits) == 0;
+ /* if a->traits is a subset of b->traits, all of
+ * a's constraints are satisfied by b. */
+ return bsissubset(a->traits, b->traits);
}
static void verifytraits(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- size_t i, n;
- char *sep;
- char traitbuf[1024], abuf[1024], bbuf[1024];
+ size_t i, n;
+ char *sep;
+ char traitbuf[1024], abuf[1024], bbuf[1024];
- if (!checktraits(a, b)) {
- sep = "";
- n = 0;
- for (i = 0; bsiter(a->traits, &i); i++) {
- if (!b->traits || !bshas(b->traits, i))
- n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep, namestr(traittab[i]->name));
- sep = ",";
- }
- tyfmt(abuf, sizeof abuf, a);
- tyfmt(bbuf, sizeof bbuf, b);
- fatal(ctx, "%s missing traits %s for %s near %s", bbuf, traitbuf, abuf, ctxstr(st, ctx));
- }
+ if (!checktraits(a, b)) {
+ sep = "";
+ n = 0;
+ for (i = 0; bsiter(a->traits, &i); i++) {
+ if (!b->traits || !bshas(b->traits, i))
+ n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep,
+ namestr(traittab[i]->name));
+ sep = ",";
+ }
+ tyfmt(abuf, sizeof abuf, a);
+ tyfmt(bbuf, sizeof bbuf, b);
+ fatal(ctx, "%s missing traits %s for %s near %s", bbuf, traitbuf, abuf,
+ ctxstr(st, ctx));
+ }
}
/* Merges the constraints on types */
static void mergetraits(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- if (b->type == Tyvar) {
- /* make sure that if a = b, both have same traits */
- if (a->traits && b->traits)
- bsunion(b->traits, a->traits);
- else if (a->traits)
- b->traits = bsdup(a->traits);
- else if (b->traits)
- a->traits = bsdup(b->traits);
- } else {
- verifytraits(st, ctx, a, b);
- }
+ if (b->type == Tyvar) {
+ /* make sure that if a = b, both have same traits */
+ if (a->traits && b->traits)
+ bsunion(b->traits, a->traits);
+ else if (a->traits)
+ b->traits = bsdup(a->traits);
+ else if (b->traits)
+ a->traits = bsdup(b->traits);
+ }
+ else {
+ verifytraits(st, ctx, a, b);
+ }
}
/* Tells us if we have an index hack on the type */
static int idxhacked(Type *a, Type *b)
{
- if (a->type == Tyvar && a->nsub > 0)
- return 1;
- if (a->type == Tyarray || a->type == Tyslice)
- return a->type == b->type;
- return 0;
+ if (a->type == Tyvar && a->nsub > 0)
+ return 1;
+ if (a->type == Tyarray || a->type == Tyslice)
+ return a->type == b->type;
+ return 0;
}
/* prevents types that contain themselves in the unification;
@@ -801,14 +790,14 @@
* eg @a U (@a -> foo) */
static int occurs(Type *a, Type *b)
{
- size_t i;
+ size_t i;
- if (a == b)
- return 1;
- for (i = 0; i < b->nsub; i++)
- if (occurs(a, b->sub[i]))
- return 1;
- return 0;
+ if (a == b)
+ return 1;
+ for (i = 0; i < b->nsub; i++)
+ if (occurs(a, b->sub[i]))
+ return 1;
+ return 0;
}
/* Computes the 'rank' of the type; ie, in which
@@ -817,173 +806,177 @@
* specific) type. */
static int tyrank(Type *t)
{
- /* plain tyvar */
- if (t->type == Tyvar && t->nsub == 0)
- return 0;
- /* parameterized tyvar */
- if (t->type == Tyvar && t->nsub > 0)
- return 1;
- /* concrete type */
- return 2;
+ /* plain tyvar */
+ if (t->type == Tyvar && t->nsub == 0)
+ return 0;
+ /* parameterized tyvar */
+ if (t->type == Tyvar && t->nsub > 0)
+ return 1;
+ /* concrete type */
+ return 2;
}
-static int hasparam(Type *t)
-{
- return t->type == Tyname && t->narg > 0;
-}
+static int hasparam(Type *t) { return t->type == Tyname && t->narg > 0; }
static void unionunify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- size_t i, j;
- int found;
+ size_t i, j;
+ int found;
- if (u->nmemb != v->nmemb)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
+ if (u->nmemb != v->nmemb)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- for (i = 0; i < u->nmemb; i++) {
- found = 0;
- for (j = 0; j < v->nmemb; j++) {
- if (strcmp(namestr(u->udecls[i]->name), namestr(v->udecls[i]->name)) != 0)
- continue;
- found = 1;
- if (u->udecls[i]->etype == NULL && v->udecls[i]->etype == NULL)
- continue;
- else if (u->udecls[i]->etype && v->udecls[i]->etype)
- unify(st, ctx, u->udecls[i]->etype, v->udecls[i]->etype);
- else
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
- if (!found)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
+ for (i = 0; i < u->nmemb; i++) {
+ found = 0;
+ for (j = 0; j < v->nmemb; j++) {
+ if (strcmp(namestr(u->udecls[i]->name), namestr(v->udecls[i]->name)) != 0)
+ continue;
+ found = 1;
+ if (u->udecls[i]->etype == NULL && v->udecls[i]->etype == NULL)
+ continue;
+ else if (u->udecls[i]->etype && v->udecls[i]->etype)
+ unify(st, ctx, u->udecls[i]->etype, v->udecls[i]->etype);
+ else
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
+ if (!found)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
}
static void structunify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- size_t i, j;
- int found;
+ size_t i, j;
+ int found;
- if (u->nmemb != v->nmemb)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
+ if (u->nmemb != v->nmemb)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- for (i = 0; i < u->nmemb; i++) {
- found = 0;
- for (j = 0; j < v->nmemb; j++) {
- if (strcmp(namestr(u->sdecls[i]->decl.name), namestr(v->sdecls[i]->decl.name)) != 0)
- continue;
- found = 1;
- unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
- }
- if (!found)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
+ for (i = 0; i < u->nmemb; i++) {
+ found = 0;
+ for (j = 0; j < v->nmemb; j++) {
+ if (strcmp(namestr(u->sdecls[i]->decl.name),
+ namestr(v->sdecls[i]->decl.name)) != 0)
+ continue;
+ found = 1;
+ unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
+ }
+ if (!found)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
}
-static void membunify(Inferstate *st, Node *ctx, Type *u, Type *v) {
- if (hthas(st->delayed, u))
- u = htget(st->delayed, u);
- u = tybase(u);
- if (hthas(st->delayed, v))
- v = htget(st->delayed, v);
- v = tybase(v);
- if (u->type == Tyunion && v->type == Tyunion && u != v)
- unionunify(st, ctx, u, v);
- else if (u->type == Tystruct && v->type == Tystruct && u != v)
- structunify(st, ctx, u, v);
+static void membunify(Inferstate *st, Node *ctx, Type *u, Type *v)
+{
+ if (hthas(st->delayed, u))
+ u = htget(st->delayed, u);
+ u = tybase(u);
+ if (hthas(st->delayed, v))
+ v = htget(st->delayed, v);
+ v = tybase(v);
+ if (u->type == Tyunion && v->type == Tyunion && u != v)
+ unionunify(st, ctx, u, v);
+ else if (u->type == Tystruct && v->type == Tystruct && u != v)
+ structunify(st, ctx, u, v);
}
/* Unifies two types, or errors if the types are not unifiable. */
static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- Type *t, *r;
- Type *a, *b;
- char *from, *to;
- size_t i;
+ Type *t, *r;
+ Type *a, *b;
+ char *from, *to;
+ size_t i;
- /* a ==> b */
- a = tf(st, u);
- b = tf(st, v);
- if (a == b)
- return a;
+ /* a ==> b */
+ a = tf(st, u);
+ b = tf(st, v);
+ if (a == b)
+ return a;
- /* we unify from lower to higher ranked types */
- if (tyrank(b) < tyrank(a)) {
- t = a;
- a = b;
- b = t;
- }
+ /* we unify from lower to higher ranked types */
+ if (tyrank(b) < tyrank(a)) {
+ t = a;
+ a = b;
+ b = t;
+ }
- if (debugopt['u']) {
- from = tystr(a);
- to = tystr(b);
- indentf(st->indentdepth, "Unify %s => %s\n", from, to);
- free(from);
- free(to);
- }
+ if (debugopt['u']) {
+ from = tystr(a);
+ to = tystr(b);
+ indentf(st->indentdepth, "Unify %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
- r = NULL;
- if (a->type == Tyvar) {
- tytab[a->tid] = b;
- r = b;
- }
+ r = NULL;
+ if (a->type == Tyvar) {
+ tytab[a->tid] = b;
+ r = b;
+ }
- /* Disallow recursive types */
- if (a->type == Tyvar && b->type != Tyvar) {
- if (occurs(a, b))
- typeerror(st, a, b, ctx, "Infinite type\n");
- }
+ /* Disallow recursive types */
+ if (a->type == Tyvar && b->type != Tyvar) {
+ if (occurs(a, b))
+ typeerror(st, a, b, ctx, "Infinite type\n");
+ }
- /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
- * Otherwise, match up subtypes. */
- if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
- if (hasparam(a) && hasparam(b)) {
- /* Only Tygeneric and Tyname should be able to unify. And they
- * should have the same names for this to be true. */
- if (!nameeq(a->name, b->name))
- typeerror(st, a, b, ctx, NULL);
- if (a->narg != b->narg)
- typeerror(st, a, b, ctx, "Incompatible parameter lists");
- for (i = 0; i < a->narg; i++)
- unify(st, ctx, a->arg[i], b->arg[i]);
- r = b;
- }
- if (a->nsub != b->nsub) {
- verifytraits(st, ctx, a, b);
- if (tybase(a)->type == Tyfunc)
- typeerror(st, a, b, ctx, "function arity mismatch");
- else
- typeerror(st, a, b, ctx, "subtype counts incompatible");
- }
- for (i = 0; i < b->nsub; i++)
- unify(st, ctx, a->sub[i], b->sub[i]);
- r = b;
- } else if (a->type != Tyvar) {
- typeerror(st, a, b, ctx, NULL);
- }
- mergetraits(st, ctx, a, b);
- if (a->isreflect || b->isreflect)
- r->isreflect = a->isreflect = b->isreflect = 1;
- membunify(st, ctx, a, b);
+ /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
+ * Otherwise, match up subtypes. */
+ if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
+ if (hasparam(a) && hasparam(b)) {
+ /* Only Tygeneric and Tyname should be able to unify. And they
+ * should have the same names for this to be true. */
+ if (!nameeq(a->name, b->name))
+ typeerror(st, a, b, ctx, NULL);
+ if (a->narg != b->narg)
+ typeerror(st, a, b, ctx, "Incompatible parameter lists");
+ for (i = 0; i < a->narg; i++)
+ unify(st, ctx, a->arg[i], b->arg[i]);
+ r = b;
+ }
+ if (a->nsub != b->nsub) {
+ verifytraits(st, ctx, a, b);
+ if (tybase(a)->type == Tyfunc)
+ typeerror(st, a, b, ctx, "function arity mismatch");
+ else
+ typeerror(st, a, b, ctx, "subtype counts incompatible");
+ }
+ for (i = 0; i < b->nsub; i++)
+ unify(st, ctx, a->sub[i], b->sub[i]);
+ r = b;
+ }
+ else if (a->type != Tyvar) {
+ typeerror(st, a, b, ctx, NULL);
+ }
+ mergetraits(st, ctx, a, b);
+ if (a->isreflect || b->isreflect)
+ r->isreflect = a->isreflect = b->isreflect = 1;
+ membunify(st, ctx, a, b);
- /* if we have delayed types for a tyvar, transfer it over. */
- if (a->type == Tyvar && b->type == Tyvar) {
- if (hthas(st->delayed, a) && !hthas(st->delayed, b))
- htput(st->delayed, b, htget(st->delayed, a));
- else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
- htput(st->delayed, a, htget(st->delayed, b));
- } else if (hthas(st->delayed, a)) {
- unify(st, ctx, htget(st->delayed, a), tybase(b));
- }
+ /* if we have delayed types for a tyvar, transfer it over. */
+ if (a->type == Tyvar && b->type == Tyvar) {
+ if (hthas(st->delayed, a) && !hthas(st->delayed, b))
+ htput(st->delayed, b, htget(st->delayed, a));
+ else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
+ htput(st->delayed, a, htget(st->delayed, b));
+ }
+ else if (hthas(st->delayed, a)) {
+ unify(st, ctx, htget(st->delayed, a), tybase(b));
+ }
- return r;
+ return r;
}
static void markvatypes(Type **types, size_t ntypes)
{
- size_t i;
+ size_t i;
- for (i = 0; i < ntypes; i++)
- types[i]->isreflect = 1;
+ for (i = 0; i < ntypes; i++)
+ types[i]->isreflect = 1;
}
/* Applies unifications to function calls.
@@ -991,103 +984,107 @@
* different approach to unification. */
static void unifycall(Inferstate *st, Node *n)
{
- size_t i;
- Type *ft;
- char *ret, *ctx;
+ size_t i;
+ Type *ft;
+ char *ret, *ctx;
- ft = type(st, n->expr.args[0]);
+ ft = type(st, n->expr.args[0]);
- if (ft->type == Tyvar) {
- /* the first arg is the function itself, so it shouldn't be counted */
- ft = mktyfunc(n->loc, &n->expr.args[1], n->expr.nargs - 1, mktyvar(n->loc));
- unify(st, n, ft, type(st, n->expr.args[0]));
- } else if (tybase(ft)->type != Tyfunc) {
- fatal(n, "calling uncallable type %s", tystr(ft));
- }
- /* first arg: function itself */
- for (i = 1; i < n->expr.nargs; i++)
- if (exprtype(n->expr.args[i])->type == Tyvoid)
- fatal(n, "void passed where value expected, near %s", ctxstr(st, n));
- for (i = 1; i < n->expr.nargs; i++) {
- if (i == ft->nsub)
- fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
- ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
+ if (ft->type == Tyvar) {
+ /* the first arg is the function itself, so it shouldn't be counted */
+ ft = mktyfunc(n->loc, &n->expr.args[1], n->expr.nargs - 1, mktyvar(n->loc));
+ unify(st, n, ft, type(st, n->expr.args[0]));
+ }
+ else if (tybase(ft)->type != Tyfunc) {
+ fatal(n, "calling uncallable type %s", tystr(ft));
+ }
+ /* first arg: function itself */
+ for (i = 1; i < n->expr.nargs; i++)
+ if (exprtype(n->expr.args[i])->type == Tyvoid)
+ fatal(n, "void passed where value expected, near %s", ctxstr(st, n));
+ for (i = 1; i < n->expr.nargs; i++) {
+ if (i == ft->nsub)
+ fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
+ ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
- if (ft->sub[i]->type == Tyvalist) {
- markvatypes(&ft->sub[i], ft->nsub - i);
- break;
- }
- inferexpr(st, &n->expr.args[i], NULL, NULL);
- unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
- }
- if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
- fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
- ctxstr(st, n->expr.args[0]), ft->nsub - 1, i - 1);
- if (debugopt['u']) {
- ret = tystr(ft->sub[0]);
- ctx = ctxstr(st, n->expr.args[0]);
- indentf(st->indentdepth, "Call of %s returns %s\n", ctx, ret);
- free(ctx);
- free(ret);
- }
+ if (ft->sub[i]->type == Tyvalist) {
+ markvatypes(&ft->sub[i], ft->nsub - i);
+ break;
+ }
+ inferexpr(st, &n->expr.args[i], NULL, NULL);
+ unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
+ }
+ if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
+ fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
+ ctxstr(st, n->expr.args[0]), ft->nsub - 1, i - 1);
+ if (debugopt['u']) {
+ ret = tystr(ft->sub[0]);
+ ctx = ctxstr(st, n->expr.args[0]);
+ indentf(st->indentdepth, "Call of %s returns %s\n", ctx, ret);
+ free(ctx);
+ free(ret);
+ }
- settype(st, n, ft->sub[0]);
+ settype(st, n, ft->sub[0]);
}
static void unifyparams(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- size_t i;
+ size_t i;
- /* The only types with unifiable params are Tyunres and Tyname.
- * Tygeneric should always be freshened, and no other types have
- * parameters attached.
- *
- * FIXME: Is it possible to have parameterized typarams? */
- if (a->type != Tyunres && a->type != Tyname)
- return;
- if (b->type != Tyunres && b->type != Tyname)
- return;
+ /* The only types with unifiable params are Tyunres and Tyname.
+ * Tygeneric should always be freshened, and no other types have
+ * parameters attached.
+ *
+ * FIXME: Is it possible to have parameterized typarams? */
+ if (a->type != Tyunres && a->type != Tyname)
+ return;
+ if (b->type != Tyunres && b->type != Tyname)
+ return;
- if (a->narg != b->narg)
- fatal(ctx, "mismatched arg list sizes: %s with %s near %s", tystr(a), tystr(b), ctxstr(st, ctx));
- for (i = 0; i < a->narg; i++)
- unify(st, ctx, a->arg[i], b->arg[i]);
+ if (a->narg != b->narg)
+ fatal(ctx, "mismatched arg list sizes: %s with %s near %s", tystr(a), tystr(b),
+ ctxstr(st, ctx));
+ for (i = 0; i < a->narg; i++)
+ unify(st, ctx, a->arg[i], b->arg[i]);
}
static void loaduses(Node *n)
{
- size_t i;
+ size_t i;
- /* uses only allowed at top level. Do we want to keep it this way? */
- for (i = 0; i < n->file.nuses; i++)
- readuse(n->file.uses[i], n->file.globls, Visintern);
+ /* uses only allowed at top level. Do we want to keep it this way? */
+ for (i = 0; i < n->file.nuses; i++)
+ readuse(n->file.uses[i], n->file.globls, Visintern);
}
static Type *initvar(Inferstate *st, Node *n, Node *s)
{
- Type *t;
+ Type *t;
- if (s->decl.ishidden)
- fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
- if (s->decl.isgeneric)
- t = tysubst(st, tf(st, s->decl.type), s->decl.type);
- else
- t = s->decl.type;
- n->expr.did = s->decl.did;
- n->expr.isconst = s->decl.isconst;
- if (s->decl.isgeneric && !st->ingeneric) {
- t = tyfreshen(st, NULL, t);
- addspecialization(st, n, curstab());
- if (t->type == Tyvar) {
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
- } else {
- settype(st, n, t);
- }
- } else {
- settype(st, n, t);
- }
- return t;
+ if (s->decl.ishidden)
+ fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
+ if (s->decl.isgeneric)
+ t = tysubst(st, tf(st, s->decl.type), s->decl.type);
+ else
+ t = s->decl.type;
+ n->expr.did = s->decl.did;
+ n->expr.isconst = s->decl.isconst;
+ if (s->decl.isgeneric && !st->ingeneric) {
+ t = tyfreshen(st, NULL, t);
+ addspecialization(st, n, curstab());
+ if (t->type == Tyvar) {
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
+ }
+ else {
+ settype(st, n, t);
+ }
+ }
+ else {
+ settype(st, n, t);
+ }
+ return t;
}
/* Finds out if the member reference is actually
@@ -1097,675 +1094,696 @@
* that we do have */
static Node *checkns(Inferstate *st, Node *n, Node **ret)
{
- Node *var, *name, *nsname;
- Node **args;
- Stab *stab;
- Node *s;
+ Node *var, *name, *nsname;
+ Node **args;
+ Stab *stab;
+ Node *s;
- /* check that this is a namespaced declaration */
- if (n->type != Nexpr)
- return n;
- if (exprop(n) != Omemb)
- return n;
- if (!n->expr.nargs)
- return n;
- args = n->expr.args;
- if (args[0]->type != Nexpr || exprop(args[0]) != Ovar)
- return n;
- name = args[0]->expr.args[0];
- stab = getns(file, namestr(name));
- if (!stab)
- return n;
+ /* check that this is a namespaced declaration */
+ if (n->type != Nexpr)
+ return n;
+ if (exprop(n) != Omemb)
+ return n;
+ if (!n->expr.nargs)
+ return n;
+ args = n->expr.args;
+ if (args[0]->type != Nexpr || exprop(args[0]) != Ovar)
+ return n;
+ name = args[0]->expr.args[0];
+ stab = getns(file, namestr(name));
+ if (!stab)
+ return n;
- /* substitute the namespaced name */
- nsname = mknsname(n->loc, namestr(name), namestr(args[1]));
- s = getdcl(stab, args[1]);
- if (!s)
- fatal(n, "undeclared var %s.%s", nsname->name.ns, nsname->name.name);
- var = mkexpr(n->loc, Ovar, nsname, NULL);
- var->expr.idx = n->expr.idx;
- initvar(st, var, s);
- *ret = var;
- return var;
+ /* substitute the namespaced name */
+ nsname = mknsname(n->loc, namestr(name), namestr(args[1]));
+ s = getdcl(stab, args[1]);
+ if (!s)
+ fatal(n, "undeclared var %s.%s", nsname->name.ns, nsname->name.name);
+ var = mkexpr(n->loc, Ovar, nsname, NULL);
+ var->expr.idx = n->expr.idx;
+ initvar(st, var, s);
+ *ret = var;
+ return var;
}
static void inferstruct(Inferstate *st, Node *n, int *isconst)
{
- size_t i;
+ size_t i;
- *isconst = 1;
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- if (!n->expr.args[i]->expr.isconst)
- *isconst = 0;
- }
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
+ *isconst = 1;
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ if (!n->expr.args[i]->expr.isconst)
+ *isconst = 0;
+ }
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
}
static void inferarray(Inferstate *st, Node *n, int *isconst)
{
- size_t i;
- Type *t;
- Node *len;
+ size_t i;
+ Type *t;
+ Node *len;
- *isconst = 1;
- len = mkintlit(n->loc, n->expr.nargs);
- t = mktyarray(n->loc, mktyvar(n->loc), len);
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- unify(st, n, t->sub[0], type(st, n->expr.args[i]));
- if (!n->expr.args[i]->expr.isconst)
- *isconst = 0;
- }
- settype(st, n, t);
+ *isconst = 1;
+ len = mkintlit(n->loc, n->expr.nargs);
+ t = mktyarray(n->loc, mktyvar(n->loc), len);
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ unify(st, n, t->sub[0], type(st, n->expr.args[i]));
+ if (!n->expr.args[i]->expr.isconst)
+ *isconst = 0;
+ }
+ settype(st, n, t);
}
static void infertuple(Inferstate *st, Node *n, int *isconst)
{
- Type **types;
- size_t i;
+ Type **types;
+ size_t i;
- *isconst = 1;
- types = xalloc(sizeof(Type *)*n->expr.nargs);
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
- types[i] = type(st, n->expr.args[i]);
- }
- *isconst = n->expr.isconst;
- settype(st, n, mktytuple(n->loc, types, n->expr.nargs));
+ *isconst = 1;
+ types = xalloc(sizeof(Type *) * n->expr.nargs);
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
+ types[i] = type(st, n->expr.args[i]);
+ }
+ *isconst = n->expr.isconst;
+ settype(st, n, mktytuple(n->loc, types, n->expr.nargs));
}
static void inferucon(Inferstate *st, Node *n, int *isconst)
{
- Ucon *uc;
- Type *t;
+ Ucon *uc;
+ Type *t;
- *isconst = 1;
- uc = uconresolve(st, n);
- t = tysubst(st, tf(st, uc->utype), uc->utype);
- uc = tybase(t)->udecls[uc->id];
- if (uc->etype) {
- inferexpr(st, &n->expr.args[1], NULL, NULL);
- unify(st, n, uc->etype, type(st, n->expr.args[1]));
- *isconst = n->expr.args[1]->expr.isconst;
- }
- settype(st, n, delayeducon(st, t));
+ *isconst = 1;
+ uc = uconresolve(st, n);
+ t = tysubst(st, tf(st, uc->utype), uc->utype);
+ uc = tybase(t)->udecls[uc->id];
+ if (uc->etype) {
+ inferexpr(st, &n->expr.args[1], NULL, NULL);
+ unify(st, n, uc->etype, type(st, n->expr.args[1]));
+ *isconst = n->expr.args[1]->expr.isconst;
+ }
+ settype(st, n, delayeducon(st, t));
}
static void inferpat(Inferstate *st, Node **np, Node *val, Node ***bind, size_t *nbind)
{
- size_t i;
- Node **args;
- Node *s, *n;
- Stab *ns;
- Type *t;
+ size_t i;
+ Node **args;
+ Node *s, *n;
+ Stab *ns;
+ Type *t;
- n = *np;
- n = checkns(st, n, np);
- args = n->expr.args;
- for (i = 0; i < n->expr.nargs; i++)
- if (args[i]->type == Nexpr)
- inferpat(st, &args[i], val, bind, nbind);
- switch (exprop(n)) {
- case Otup:
- case Ostruct:
- case Oarr:
- case Olit:
- case Omemb:
- infernode(st, np, NULL, NULL);
- break;
- /* arithmetic expressions just need to be constant */
- case Oneg:
- case Oadd:
- case Osub:
- case Omul:
- case Odiv:
- case Obsl:
- case Obsr:
- case Oband:
- case Obor:
- case Obxor:
- case Obnot:
- infernode(st, np, NULL, NULL);
- if (!n->expr.isconst)
- fatal(n, "matching against non-constant expression near %s", ctxstr(st, n));
- break;
- case Oucon: inferucon(st, n, &n->expr.isconst); break;
- case Ovar:
- ns = curstab();
- if (args[0]->name.ns)
- ns = getns(file, args[0]->name.ns);
- s = getdcl(ns, args[0]);
- if (s && !s->decl.ishidden) {
- if (s->decl.isgeneric)
- t = tysubst(st, s->decl.type, s->decl.type);
- else if (s->decl.isconst)
- t = s->decl.type;
- else
- fatal(n, "pattern shadows variable declared on %s:%d near %s", fname(s->loc), lnum(s->loc), ctxstr(st, s));
- } else {
- t = mktyvar(n->loc);
- s = mkdecl(n->loc, n->expr.args[0], t);
- s->decl.init = val;
- settype(st, n, t);
- lappend(bind, nbind, s);
- }
- settype(st, n, t);
- n->expr.did = s->decl.did;
- break;
- case Ogap:
- infernode(st, np, NULL, NULL);
- break;
- default:
- fatal(n, "invalid pattern");
- break;
- }
+ n = *np;
+ n = checkns(st, n, np);
+ args = n->expr.args;
+ for (i = 0; i < n->expr.nargs; i++)
+ if (args[i]->type == Nexpr)
+ inferpat(st, &args[i], val, bind, nbind);
+ switch (exprop(n)) {
+ case Otup:
+ case Ostruct:
+ case Oarr:
+ case Olit:
+ case Omemb:
+ infernode(st, np, NULL, NULL);
+ break;
+ /* arithmetic expressions just need to be constant */
+ case Oneg:
+ case Oadd:
+ case Osub:
+ case Omul:
+ case Odiv:
+ case Obsl:
+ case Obsr:
+ case Oband:
+ case Obor:
+ case Obxor:
+ case Obnot:
+ infernode(st, np, NULL, NULL);
+ if (!n->expr.isconst)
+ fatal(n, "matching against non-constant expression near %s", ctxstr(st, n));
+ break;
+ case Oucon:
+ inferucon(st, n, &n->expr.isconst);
+ break;
+ case Ovar:
+ ns = curstab();
+ if (args[0]->name.ns)
+ ns = getns(file, args[0]->name.ns);
+ s = getdcl(ns, args[0]);
+ if (s && !s->decl.ishidden) {
+ if (s->decl.isgeneric)
+ t = tysubst(st, s->decl.type, s->decl.type);
+ else if (s->decl.isconst)
+ t = s->decl.type;
+ else
+ fatal(n, "pattern shadows variable declared on %s:%d near %s",
+ fname(s->loc), lnum(s->loc), ctxstr(st, s));
+ }
+ else {
+ t = mktyvar(n->loc);
+ s = mkdecl(n->loc, n->expr.args[0], t);
+ s->decl.init = val;
+ settype(st, n, t);
+ lappend(bind, nbind, s);
+ }
+ settype(st, n, t);
+ n->expr.did = s->decl.did;
+ break;
+ case Ogap: infernode(st, np, NULL, NULL); break;
+ default: fatal(n, "invalid pattern"); break;
+ }
}
void addbindings(Inferstate *st, Node *n, Node **bind, size_t nbind)
{
- size_t i;
+ size_t i;
- /* order of binding shouldn't matter, so push them into the block
- * in reverse order. */
- for (i = 0; i < nbind; i++) {
- putdcl(n->block.scope, bind[i]);
- linsert(&n->block.stmts, &n->block.nstmts, 0, bind[i]);
- }
+ /* order of binding shouldn't matter, so push them into the block
+ * in reverse order. */
+ for (i = 0; i < nbind; i++) {
+ putdcl(n->block.scope, bind[i]);
+ linsert(&n->block.stmts, &n->block.nstmts, 0, bind[i]);
+ }
}
static void infersub(Inferstate *st, Node *n, Type *ret, int *sawret, int *exprconst)
{
- Node **args;
- size_t i, nargs;
- int isconst;
+ Node **args;
+ size_t i, nargs;
+ int isconst;
- args = n->expr.args;
- nargs = n->expr.nargs;
- isconst = 1;
- for (i = 0; i < nargs; i++) {
- /* Nlit, Nvar, etc should not be inferred as exprs */
- if (args[i]->type == Nexpr) {
- /* Omemb can sometimes resolve to a namespace. We have to check
- * this. Icky. */
- checkns(st, args[i], &args[i]);
- inferexpr(st, &args[i], ret, sawret);
- isconst = isconst && args[i]->expr.isconst;
- }
- }
- if (exprop(n) == Ovar)
- n->expr.isconst = decls[n->expr.did]->decl.isconst;
- else if (opispure[exprop(n)])
- n->expr.isconst = isconst;
- *exprconst = n->expr.isconst;
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ isconst = 1;
+ for (i = 0; i < nargs; i++) {
+ /* Nlit, Nvar, etc should not be inferred as exprs */
+ if (args[i]->type == Nexpr) {
+ /* Omemb can sometimes resolve to a namespace. We have to check
+ * this. Icky. */
+ checkns(st, args[i], &args[i]);
+ inferexpr(st, &args[i], ret, sawret);
+ isconst = isconst && args[i]->expr.isconst;
+ }
+ }
+ if (exprop(n) == Ovar)
+ n->expr.isconst = decls[n->expr.did]->decl.isconst;
+ else if (opispure[exprop(n)])
+ n->expr.isconst = isconst;
+ *exprconst = n->expr.isconst;
}
static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret)
{
- Node **args;
- size_t i, nargs;
- Node *s, *n;
- Type *t;
- int isconst;
+ Node **args;
+ size_t i, nargs;
+ Node *s, *n;
+ Type *t;
+ int isconst;
- n = *np;
- assert(n->type == Nexpr);
- args = n->expr.args;
- nargs = n->expr.nargs;
- infernode(st, &n->expr.idx, NULL, NULL);
- n = checkns(st, n, np);
- switch (exprop(n)) {
- /* all operands are same type */
- case Oadd: /* @a + @a -> @a */
- case Osub: /* @a - @a -> @a */
- case Omul: /* @a * @a -> @a */
- case Odiv: /* @a / @a -> @a */
- case Oneg: /* -@a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- constrain(st, n, type(st, args[0]), traittab[Tcnum]);
- isconst = args[0]->expr.isconst;
- for (i = 1; i < nargs; i++) {
- isconst = isconst && args[i]->expr.isconst;
- t = unify(st, n, t, type(st, args[i]));
- }
- n->expr.isconst = isconst;
- settype(st, n, t);
- break;
- case Omod: /* @a % @a -> @a */
- case Obor: /* @a | @a -> @a */
- case Oband: /* @a & @a -> @a */
- case Obxor: /* @a ^ @a -> @a */
- case Obsl: /* @a << @a -> @a */
- case Obsr: /* @a >> @a -> @a */
- case Obnot: /* ~@a -> @a */
- case Opreinc: /* ++@a -> @a */
- case Opredec: /* --@a -> @a */
- case Opostinc: /* @a++ -> @a */
- case Opostdec: /* @a-- -> @a */
- case Oaddeq: /* @a += @a -> @a */
- case Osubeq: /* @a -= @a -> @a */
- case Omuleq: /* @a *= @a -> @a */
- case Odiveq: /* @a /= @a -> @a */
- case Omodeq: /* @a %= @a -> @a */
- case Oboreq: /* @a |= @a -> @a */
- case Obandeq: /* @a &= @a -> @a */
- case Obxoreq: /* @a ^= @a -> @a */
- case Obsleq: /* @a <<= @a -> @a */
- case Obsreq: /* @a >>= @a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- constrain(st, n, type(st, args[0]), traittab[Tcnum]);
- constrain(st, n, type(st, args[0]), traittab[Tcint]);
- isconst = args[0]->expr.isconst;
- for (i = 1; i < nargs; i++) {
- isconst = isconst && args[i]->expr.isconst;
- t = unify(st, n, t, type(st, args[i]));
- }
- n->expr.isconst = isconst;
- settype(st, n, t);
- break;
- case Oasn: /* @a = @a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- for (i = 1; i < nargs; i++)
- t = unify(st, n, t, type(st, args[i]));
- settype(st, n, t);
- if (args[0]->expr.isconst)
- fatal(n, "attempting to assign constant \"%s\"", ctxstr(st, args[0]));
- break;
+ n = *np;
+ assert(n->type == Nexpr);
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ infernode(st, &n->expr.idx, NULL, NULL);
+ n = checkns(st, n, np);
+ switch (exprop(n)) {
+ /* all operands are same type */
+ case Oadd: /* @a + @a -> @a */
+ case Osub: /* @a - @a -> @a */
+ case Omul: /* @a * @a -> @a */
+ case Odiv: /* @a / @a -> @a */
+ case Oneg: /* -@a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ constrain(st, n, type(st, args[0]), traittab[Tcnum]);
+ isconst = args[0]->expr.isconst;
+ for (i = 1; i < nargs; i++) {
+ isconst = isconst && args[i]->expr.isconst;
+ t = unify(st, n, t, type(st, args[i]));
+ }
+ n->expr.isconst = isconst;
+ settype(st, n, t);
+ break;
+ case Omod: /* @a % @a -> @a */
+ case Obor: /* @a | @a -> @a */
+ case Oband: /* @a & @a -> @a */
+ case Obxor: /* @a ^ @a -> @a */
+ case Obsl: /* @a << @a -> @a */
+ case Obsr: /* @a >> @a -> @a */
+ case Obnot: /* ~@a -> @a */
+ case Opreinc: /* ++@a -> @a */
+ case Opredec: /* --@a -> @a */
+ case Opostinc: /* @a++ -> @a */
+ case Opostdec: /* @a-- -> @a */
+ case Oaddeq: /* @a += @a -> @a */
+ case Osubeq: /* @a -= @a -> @a */
+ case Omuleq: /* @a *= @a -> @a */
+ case Odiveq: /* @a /= @a -> @a */
+ case Omodeq: /* @a %= @a -> @a */
+ case Oboreq: /* @a |= @a -> @a */
+ case Obandeq: /* @a &= @a -> @a */
+ case Obxoreq: /* @a ^= @a -> @a */
+ case Obsleq: /* @a <<= @a -> @a */
+ case Obsreq: /* @a >>= @a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ constrain(st, n, type(st, args[0]), traittab[Tcnum]);
+ constrain(st, n, type(st, args[0]), traittab[Tcint]);
+ isconst = args[0]->expr.isconst;
+ for (i = 1; i < nargs; i++) {
+ isconst = isconst && args[i]->expr.isconst;
+ t = unify(st, n, t, type(st, args[i]));
+ }
+ n->expr.isconst = isconst;
+ settype(st, n, t);
+ break;
+ case Oasn: /* @a = @a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ for (i = 1; i < nargs; i++)
+ t = unify(st, n, t, type(st, args[i]));
+ settype(st, n, t);
+ if (args[0]->expr.isconst)
+ fatal(n, "attempting to assign constant \"%s\"", ctxstr(st, args[0]));
+ break;
- /* operands same type, returning bool */
- case Olor: /* @a || @b -> bool */
- case Oland: /* @a && @b -> bool */
- case Oeq: /* @a == @a -> bool */
- case One: /* @a != @a -> bool */
- case Ogt: /* @a > @a -> bool */
- case Oge: /* @a >= @a -> bool */
- case Olt: /* @a < @a -> bool */
- case Ole: /* @a <= @b -> bool */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- for (i = 1; i < nargs; i++)
- unify(st, n, t, type(st, args[i]));
- settype(st, n, mktype(Zloc, Tybool));
- break;
+ /* operands same type, returning bool */
+ case Olor: /* @a || @b -> bool */
+ case Oland: /* @a && @b -> bool */
+ case Oeq: /* @a == @a -> bool */
+ case One: /* @a != @a -> bool */
+ case Ogt: /* @a > @a -> bool */
+ case Oge: /* @a >= @a -> bool */
+ case Olt: /* @a < @a -> bool */
+ case Ole: /* @a <= @b -> bool */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ for (i = 1; i < nargs; i++)
+ unify(st, n, t, type(st, args[i]));
+ settype(st, n, mktype(Zloc, Tybool));
+ break;
- case Olnot: /* !bool -> bool */
- infersub(st, n, ret, sawret, &isconst);
- t = unify(st, n, type(st, args[0]), mktype(Zloc, Tybool));
- settype(st, n, t);
- break;
+ case Olnot: /* !bool -> bool */
+ infersub(st, n, ret, sawret, &isconst);
+ t = unify(st, n, type(st, args[0]), mktype(Zloc, Tybool));
+ settype(st, n, t);
+ break;
- /* reach into a type and pull out subtypes */
- case Oaddr: /* &@a -> @a* */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktyptr(n->loc, type(st, args[0])));
- break;
- case Oderef: /* *@a* -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = unify(st, n, type(st, args[0]), mktyptr(n->loc, mktyvar(n->loc)));
- settype(st, n, t->sub[0]);
- break;
- case Oidx: /* @a[@b::tcint] -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = mktyidxhack(n->loc, mktyvar(n->loc));
- unify(st, n, type(st, args[0]), t);
- constrain(st, n, type(st, args[0]), traittab[Tcidx]);
- constrain(st, n, type(st, args[1]), traittab[Tcint]);
- settype(st, n, t->sub[0]);
- break;
- case Oslice: /* @a[@b::tcint,@b::tcint] -> @a[,] */
- infersub(st, n, ret, sawret, &isconst);
- t = mktyidxhack(n->loc, mktyvar(n->loc));
- unify(st, n, type(st, args[0]), t);
- constrain(st, n, type(st, args[1]), traittab[Tcint]);
- constrain(st, n, type(st, args[2]), traittab[Tcint]);
- settype(st, n, mktyslice(n->loc, t->sub[0]));
- break;
+ /* reach into a type and pull out subtypes */
+ case Oaddr: /* &@a -> @a* */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktyptr(n->loc, type(st, args[0])));
+ break;
+ case Oderef: /* *@a* -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = unify(st, n, type(st, args[0]), mktyptr(n->loc, mktyvar(n->loc)));
+ settype(st, n, t->sub[0]);
+ break;
+ case Oidx: /* @a[@b::tcint] -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = mktyidxhack(n->loc, mktyvar(n->loc));
+ unify(st, n, type(st, args[0]), t);
+ constrain(st, n, type(st, args[0]), traittab[Tcidx]);
+ constrain(st, n, type(st, args[1]), traittab[Tcint]);
+ settype(st, n, t->sub[0]);
+ break;
+ case Oslice: /* @a[@b::tcint,@b::tcint] -> @a[,] */
+ infersub(st, n, ret, sawret, &isconst);
+ t = mktyidxhack(n->loc, mktyvar(n->loc));
+ unify(st, n, type(st, args[0]), t);
+ constrain(st, n, type(st, args[1]), traittab[Tcint]);
+ constrain(st, n, type(st, args[2]), traittab[Tcint]);
+ settype(st, n, mktyslice(n->loc, t->sub[0]));
+ break;
- /* special cases */
- case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
- break;
- case Osize: /* sizeof @a -> size */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktylike(n->loc, Tyuint));
- break;
- case Ocall: /* (@a, @b, @c, ... -> @r)(@a,@b,@c, ... -> @r) -> @r */
- infersub(st, n, ret, sawret, &isconst);
- unifycall(st, n);
- break;
- case Ocast: /* cast(@a, @b) -> @b */
- infersub(st, n, ret, sawret, &isconst);
- delayedcheck(st, n, curstab());
- break;
- case Oret: /* -> @a -> void */
- infersub(st, n, ret, sawret, &isconst);
- if (sawret)
- *sawret = 1;
- if (!ret)
- fatal(n, "returns are not valid near %s", ctxstr(st, n));
- if (nargs)
- t = unify(st, n, ret, type(st, args[0]));
- else
- t = unify(st, n, mktype(Zloc, Tyvoid), ret);
- settype(st, n, t);
- break;
- case Obreak:
- case Ocontinue:
- /* nullary: nothing to infer. */
- settype(st, n, mktype(Zloc, Tyvoid));
- break;
- case Ojmp: /* goto void* -> void */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktype(Zloc, Tyvoid));
- break;
- case Ovar: /* a:@a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- /* if we created this from a namespaced var, the type should be
- * set, and the normal lookup is expected to fail. Since we're
- * already done with this node, we can just return. */
- if (n->expr.type)
- return;
- s = getdcl(curstab(), args[0]);
- if (!s)
- fatal(n, "undeclared var %s", ctxstr(st, args[0]));
- initvar(st, n, s);
- break;
- case Ogap: /* _ -> @a */
- if (n->expr.type)
- return;
- n->expr.type = mktyvar(n->loc);
- break;
- case Oucon:
- inferucon(st, n, &n->expr.isconst);
- break;
- case Otup:
- infertuple(st, n, &n->expr.isconst);
- break;
- case Ostruct:
- inferstruct(st, n, &n->expr.isconst);
- break;
- case Oarr:
- inferarray(st, n, &n->expr.isconst);
- break;
- case Olit: /* <lit>:@a::tyclass -> @a */
- infersub(st, n, ret, sawret, &isconst);
- switch (args[0]->lit.littype) {
- case Lfunc:
- infernode(st, &args[0]->lit.fnval, NULL, NULL);
- /* FIXME: env capture means this is non-const */
- n->expr.isconst = 1;
- break;
- default:
- n->expr.isconst = 1;
- break;
- }
- settype(st, n, type(st, args[0]));
- break;
- case Oundef:
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktype(n->loc, Tyvoid));
- break;
- case Oidxlen:
- t = mktyvar(n->loc);
- constrain(st, n, t, traittab[Tcnum]);
- constrain(st, n, t, traittab[Tcint]);
- settype(st, n, t);
- break;
- case Odef:
- case Odead:
- n->expr.type = mktype(n->loc, Tyvoid);
- break;
- case Obad: case Ocjmp: case Ovjmp: case Oset:
- case Oslbase: case Osllen: case Outag: case Ocallind:
- case Oblit: case Oclear: case Oudata:
- case Otrunc: case Oswiden: case Ozwiden:
- case Oint2flt: case Oflt2int: case Oflt2flt:
- case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg:
- case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
- case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
- case Otupget:
- case Numops:
- die("Should not see %s in fe", opstr[exprop(n)]);
- break;
- }
+ /* special cases */
+ case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
+ break;
+ case Osize: /* sizeof @a -> size */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktylike(n->loc, Tyuint));
+ break;
+ case Ocall: /* (@a, @b, @c, ... -> @r)(@a,@b,@c, ... -> @r) -> @r */
+ infersub(st, n, ret, sawret, &isconst);
+ unifycall(st, n);
+ break;
+ case Ocast: /* cast(@a, @b) -> @b */
+ infersub(st, n, ret, sawret, &isconst);
+ delayedcheck(st, n, curstab());
+ break;
+ case Oret: /* -> @a -> void */
+ infersub(st, n, ret, sawret, &isconst);
+ if (sawret)
+ *sawret = 1;
+ if (!ret)
+ fatal(n, "returns are not valid near %s", ctxstr(st, n));
+ if (nargs)
+ t = unify(st, n, ret, type(st, args[0]));
+ else
+ t = unify(st, n, mktype(Zloc, Tyvoid), ret);
+ settype(st, n, t);
+ break;
+ case Obreak:
+ case Ocontinue:
+ /* nullary: nothing to infer. */
+ settype(st, n, mktype(Zloc, Tyvoid));
+ break;
+ case Ojmp: /* goto void* -> void */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktype(Zloc, Tyvoid));
+ break;
+ case Ovar: /* a:@a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ /* if we created this from a namespaced var, the type should be
+ * set, and the normal lookup is expected to fail. Since we're
+ * already done with this node, we can just return. */
+ if (n->expr.type)
+ return;
+ s = getdcl(curstab(), args[0]);
+ if (!s)
+ fatal(n, "undeclared var %s", ctxstr(st, args[0]));
+ initvar(st, n, s);
+ break;
+ case Ogap: /* _ -> @a */
+ if (n->expr.type)
+ return;
+ n->expr.type = mktyvar(n->loc);
+ break;
+ case Oucon: inferucon(st, n, &n->expr.isconst); break;
+ case Otup: infertuple(st, n, &n->expr.isconst); break;
+ case Ostruct: inferstruct(st, n, &n->expr.isconst); break;
+ case Oarr: inferarray(st, n, &n->expr.isconst); break;
+ case Olit: /* <lit>:@a::tyclass -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ switch (args[0]->lit.littype) {
+ case Lfunc:
+ infernode(st, &args[0]->lit.fnval, NULL, NULL);
+ /* FIXME: env capture means this is non-const */
+ n->expr.isconst = 1;
+ break;
+ default: n->expr.isconst = 1; break;
+ }
+ settype(st, n, type(st, args[0]));
+ break;
+ case Oundef:
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktype(n->loc, Tyvoid));
+ break;
+ case Oidxlen:
+ t = mktyvar(n->loc);
+ constrain(st, n, t, traittab[Tcnum]);
+ constrain(st, n, t, traittab[Tcint]);
+ settype(st, n, t);
+ break;
+ case Odef:
+ case Odead: n->expr.type = mktype(n->loc, Tyvoid); break;
+ case Obad:
+ case Ocjmp:
+ case Ovjmp:
+ case Oset:
+ case Oslbase:
+ case Osllen:
+ case Outag:
+ case Ocallind:
+ case Oblit:
+ case Oclear:
+ case Oudata:
+ case Otrunc:
+ case Oswiden:
+ case Ozwiden:
+ case Oint2flt:
+ case Oflt2int:
+ case Oflt2flt:
+ case Ofadd:
+ case Ofsub:
+ case Ofmul:
+ case Ofdiv:
+ case Ofneg:
+ case Ofeq:
+ case Ofne:
+ case Ofgt:
+ case Ofge:
+ case Oflt:
+ case Ofle:
+ case Oueq:
+ case Oune:
+ case Ougt:
+ case Ouge:
+ case Oult:
+ case Oule:
+ case Otupget:
+ case Numops: die("Should not see %s in fe", opstr[exprop(n)]); break;
+ }
}
static void inferfunc(Inferstate *st, Node *n)
{
- size_t i;
- int sawret;
+ size_t i;
+ int sawret;
- sawret = 0;
- for (i = 0; i < n->func.nargs; i++)
- infernode(st, &n->func.args[i], NULL, NULL);
- infernode(st, &n->func.body, n->func.type->sub[0], &sawret);
- /* if there's no return stmt in the function, assume void ret */
- if (!sawret)
- unify(st, n, type(st, n)->sub[0], mktype(Zloc, Tyvoid));
+ sawret = 0;
+ for (i = 0; i < n->func.nargs; i++)
+ infernode(st, &n->func.args[i], NULL, NULL);
+ infernode(st, &n->func.body, n->func.type->sub[0], &sawret);
+ /* if there's no return stmt in the function, assume void ret */
+ if (!sawret)
+ unify(st, n, type(st, n)->sub[0], mktype(Zloc, Tyvoid));
}
static void specializeimpl(Inferstate *st, Node *n)
{
- Node *dcl, *proto, *name;
- Type *ty;
- Htab *ht;
- Trait *t;
- size_t i, j;
+ Node *dcl, *proto, *name;
+ Type *ty;
+ Htab *ht;
+ Trait *t;
+ size_t i, j;
- t = gettrait(curstab(), n->impl.traitname);
- if (!t)
- fatal(n, "no trait %s\n", namestr(n->impl.traitname));
- n->impl.trait = t;
+ t = gettrait(curstab(), n->impl.traitname);
+ if (!t)
+ fatal(n, "no trait %s\n", namestr(n->impl.traitname));
+ n->impl.trait = t;
- dcl = NULL;
- proto = NULL;
- n->impl.type = tf(st, n->impl.type);
- for (i = 0; i < n->impl.ndecls; i++) {
- /* look up the prototype */
- proto = NULL;
- dcl = n->impl.decls[i];
+ dcl = NULL;
+ proto = NULL;
+ n->impl.type = tf(st, n->impl.type);
+ for (i = 0; i < n->impl.ndecls; i++) {
+ /* look up the prototype */
+ proto = NULL;
+ dcl = n->impl.decls[i];
- /*
- since the decls in an impl are not installed in a namespace, their names
- are not updated when we call updatens() on the symbol table. Because we need
- to do namespace dependent comparisons for specializing, we need to set the
- namespace here.
- */
- if (file->file.globls->name)
- setns(dcl->decl.name, file->file.globls->name);
- for (j = 0; j < t->nfuncs; j++) {
- if (nameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
- proto = t->funcs[j];
- break;
- }
- }
- if (!proto)
- fatal(n, "declaration %s missing in %s, near %s",
- namestr(dcl->decl.name), namestr(t->name), ctxstr(st, n));
+ /*
+ since the decls in an impl are not installed in a namespace, their names
+ are not updated when we call updatens() on the symbol table. Because we
+ need
+ to do namespace dependent comparisons for specializing, we need to set
+ the
+ namespace here.
+ */
+ if (file->file.globls->name)
+ setns(dcl->decl.name, file->file.globls->name);
+ for (j = 0; j < t->nfuncs; j++) {
+ if (nameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
+ proto = t->funcs[j];
+ break;
+ }
+ }
+ if (!proto)
+ fatal(n, "declaration %s missing in %s, near %s", namestr(dcl->decl.name),
+ namestr(t->name), ctxstr(st, n));
- /* infer and unify types */
- if (n->impl.type->type == Tygeneric || n->impl.type->type == Typaram)
- fatal(n, "trait specialization requires concrete type, got %s", tystr(n->impl.type));
- verifytraits(st, n, t->param, n->impl.type);
- ht = mkht(tyhash, tyeq);
- htput(ht, t->param, n->impl.type);
- ty = tyspecialize(type(st, proto), ht, st->delayed);
- htfree(ht);
+ /* infer and unify types */
+ if (n->impl.type->type == Tygeneric || n->impl.type->type == Typaram)
+ fatal(n, "trait specialization requires concrete type, got %s",
+ tystr(n->impl.type));
+ verifytraits(st, n, t->param, n->impl.type);
+ ht = mkht(tyhash, tyeq);
+ htput(ht, t->param, n->impl.type);
+ ty = tyspecialize(type(st, proto), ht, st->delayed);
+ htfree(ht);
- inferdecl(st, dcl);
- unify(st, n, type(st, dcl), ty);
+ inferdecl(st, dcl);
+ unify(st, n, type(st, dcl), ty);
- /* and put the specialization into the global stab */
- name = genericname(proto, ty);
- dcl->decl.name = name;
- putdcl(file->file.globls, dcl);
- if (debugopt['S'])
- printf("specializing trait [%d]%s:%s => %s:%s\n",
- n->loc.line, namestr(proto->decl.name), tystr(type(st, proto)), namestr(name), tystr(ty));
- dcl->decl.vis = t->vis;
- lappend(&file->file.stmts, &file->file.nstmts, dcl);
- }
+ /* and put the specialization into the global stab */
+ name = genericname(proto, ty);
+ dcl->decl.name = name;
+ putdcl(file->file.globls, dcl);
+ if (debugopt['S'])
+ printf("specializing trait [%d]%s:%s => %s:%s\n", n->loc.line,
+ namestr(proto->decl.name), tystr(type(st, proto)), namestr(name),
+ tystr(ty));
+ dcl->decl.vis = t->vis;
+ lappend(&file->file.stmts, &file->file.nstmts, dcl);
+ }
}
static void inferdecl(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- t = tf(st, decltype(n));
- if (t->type == Tygeneric && !n->decl.isgeneric) {
- t = tyfreshen(st, NULL, t);
- unifyparams(st, n, t, decltype(n));
- }
- settype(st, n, t);
- if (n->decl.init) {
- inferexpr(st, &n->decl.init, NULL, NULL);
- unify(st, n, type(st, n), type(st, n->decl.init));
- if (n->decl.isconst && !n->decl.init->expr.isconst)
- fatal(n, "non-const initializer for \"%s\"", ctxstr(st, n));
- } else {
- if ((n->decl.isconst || n->decl.isgeneric) && !n->decl.isextern)
- fatal(n, "non-extern \"%s\" has no initializer", ctxstr(st, n));
- }
+ t = tf(st, decltype(n));
+ if (t->type == Tygeneric && !n->decl.isgeneric) {
+ t = tyfreshen(st, NULL, t);
+ unifyparams(st, n, t, decltype(n));
+ }
+ settype(st, n, t);
+ if (n->decl.init) {
+ inferexpr(st, &n->decl.init, NULL, NULL);
+ unify(st, n, type(st, n), type(st, n->decl.init));
+ if (n->decl.isconst && !n->decl.init->expr.isconst)
+ fatal(n, "non-const initializer for \"%s\"", ctxstr(st, n));
+ }
+ else {
+ if ((n->decl.isconst || n->decl.isgeneric) && !n->decl.isextern)
+ fatal(n, "non-extern \"%s\" has no initializer", ctxstr(st, n));
+ }
}
static void inferstab(Inferstate *st, Stab *s)
{
- void **k;
- size_t n, i;
- Type *t;
+ void **k;
+ size_t n, i;
+ Type *t;
- k = htkeys(s->ty, &n);
- for (i = 0; i < n; i++) {
- t = gettype(s, k[i]);
- if (!t)
- fatal(k[i], "undefined type %s", namestr(k[i]));
- t = tysearch(t);
- tybind(st, t);
- tyresolve(st, t);
- tyunbind(st, t);
- updatetype(s, k[i], t);
- }
- free(k);
+ k = htkeys(s->ty, &n);
+ for (i = 0; i < n; i++) {
+ t = gettype(s, k[i]);
+ if (!t)
+ fatal(k[i], "undefined type %s", namestr(k[i]));
+ t = tysearch(t);
+ tybind(st, t);
+ tyresolve(st, t);
+ tyunbind(st, t);
+ updatetype(s, k[i], t);
+ }
+ free(k);
}
static void infernode(Inferstate *st, Node **np, Type *ret, int *sawret)
{
- size_t i, nbound;
- Node **bound, *n, *pat;
- Type *t;
+ size_t i, nbound;
+ Node **bound, *n, *pat;
+ Type *t;
- n = *np;
- if (!n)
- return;
- switch (n->type) {
- case Nfile:
- pushstab(n->file.globls);
- inferstab(st, n->file.globls);
- for (i = 0; i < n->file.nstmts; i++)
- infernode(st, &n->file.stmts[i], NULL, sawret);
- popstab();
- break;
- case Ndecl:
- if (debugopt['u'])
- indentf(st->indentdepth, "--- infer %s ---\n", declname(n));
- st->indentdepth++;
- bind(st, n);
- inferdecl(st, n);
- if (type(st, n)->type == Typaram && !st->ingeneric)
- fatal(n, "generic type %s in non-generic near %s", tystr(type(st, n)), ctxstr(st, n));
- unbind(st, n);
- st->indentdepth--;
- if (debugopt['u'])
- indentf(st->indentdepth, "--- done ---\n");
- break;
- case Nblock:
- setsuper(n->block.scope, curstab());
- pushstab(n->block.scope);
- inferstab(st, n->block.scope);
- for (i = 0; i < n->block.nstmts; i++) {
- infernode(st, &n->block.stmts[i], ret, sawret);
- }
- popstab();
- break;
- case Nifstmt:
- infernode(st, &n->ifstmt.cond, NULL, sawret);
- infernode(st, &n->ifstmt.iftrue, ret, sawret);
- infernode(st, &n->ifstmt.iffalse, ret, sawret);
- unify(st, n, type(st, n->ifstmt.cond), mktype(n->loc, Tybool));
- break;
- case Nloopstmt:
- setsuper(n->loopstmt.scope, curstab());
- pushstab(n->loopstmt.scope);
- infernode(st, &n->loopstmt.init, ret, sawret);
- infernode(st, &n->loopstmt.cond, NULL, sawret);
- infernode(st, &n->loopstmt.step, ret, sawret);
- infernode(st, &n->loopstmt.body, ret, sawret);
- unify(st, n, type(st, n->loopstmt.cond), mktype(n->loc, Tybool));
- popstab();
- break;
- case Niterstmt:
- bound = NULL;
- nbound = 0;
+ n = *np;
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nfile:
+ pushstab(n->file.globls);
+ inferstab(st, n->file.globls);
+ for (i = 0; i < n->file.nstmts; i++)
+ infernode(st, &n->file.stmts[i], NULL, sawret);
+ popstab();
+ break;
+ case Ndecl:
+ if (debugopt['u'])
+ indentf(st->indentdepth, "--- infer %s ---\n", declname(n));
+ st->indentdepth++;
+ bind(st, n);
+ inferdecl(st, n);
+ if (type(st, n)->type == Typaram && !st->ingeneric)
+ fatal(n, "generic type %s in non-generic near %s", tystr(type(st, n)),
+ ctxstr(st, n));
+ unbind(st, n);
+ st->indentdepth--;
+ if (debugopt['u'])
+ indentf(st->indentdepth, "--- done ---\n");
+ break;
+ case Nblock:
+ setsuper(n->block.scope, curstab());
+ pushstab(n->block.scope);
+ inferstab(st, n->block.scope);
+ for (i = 0; i < n->block.nstmts; i++) {
+ infernode(st, &n->block.stmts[i], ret, sawret);
+ }
+ popstab();
+ break;
+ case Nifstmt:
+ infernode(st, &n->ifstmt.cond, NULL, sawret);
+ infernode(st, &n->ifstmt.iftrue, ret, sawret);
+ infernode(st, &n->ifstmt.iffalse, ret, sawret);
+ unify(st, n, type(st, n->ifstmt.cond), mktype(n->loc, Tybool));
+ break;
+ case Nloopstmt:
+ setsuper(n->loopstmt.scope, curstab());
+ pushstab(n->loopstmt.scope);
+ infernode(st, &n->loopstmt.init, ret, sawret);
+ infernode(st, &n->loopstmt.cond, NULL, sawret);
+ infernode(st, &n->loopstmt.step, ret, sawret);
+ infernode(st, &n->loopstmt.body, ret, sawret);
+ unify(st, n, type(st, n->loopstmt.cond), mktype(n->loc, Tybool));
+ popstab();
+ break;
+ case Niterstmt:
+ bound = NULL;
+ nbound = 0;
- inferpat(st, &n->iterstmt.elt, NULL, &bound, &nbound);
- addbindings(st, n->iterstmt.body, bound, nbound);
+ inferpat(st, &n->iterstmt.elt, NULL, &bound, &nbound);
+ addbindings(st, n->iterstmt.body, bound, nbound);
- infernode(st, &n->iterstmt.seq, NULL, sawret);
- infernode(st, &n->iterstmt.body, ret, sawret);
+ infernode(st, &n->iterstmt.seq, NULL, sawret);
+ infernode(st, &n->iterstmt.body, ret, sawret);
- t = mktyidxhack(n->loc, mktyvar(n->loc));
- constrain(st, n, type(st, n->iterstmt.seq), traittab[Tcidx]);
- unify(st, n, type(st, n->iterstmt.seq), t);
- unify(st, n, type(st, n->iterstmt.elt), t->sub[0]);
- break;
- case Nmatchstmt:
- infernode(st, &n->matchstmt.val, NULL, sawret);
- if (tybase(type(st, n->matchstmt.val))->type == Tyvoid)
- fatal(n, "can't match against a void type near %s", ctxstr(st, n->matchstmt.val));
- for (i = 0; i < n->matchstmt.nmatches; i++) {
- infernode(st, &n->matchstmt.matches[i], ret, sawret);
- pat = n->matchstmt.matches[i]->match.pat;
- unify(st, pat, type(st, n->matchstmt.val), type(st, n->matchstmt.matches[i]->match.pat));
- }
- break;
- case Nmatch:
- bound = NULL;
- nbound = 0;
- inferpat(st, &n->match.pat, NULL, &bound, &nbound);
- addbindings(st, n->match.block, bound, nbound);
- infernode(st, &n->match.block, ret, sawret);
- break;
- case Nexpr:
- inferexpr(st, np, ret, sawret);
- break;
- case Nfunc:
- setsuper(n->func.scope, curstab());
- if (st->ntybindings > 0)
- for (i = 0; i < n->func.nargs; i++)
- putbindings(st, st->tybindings[st->ntybindings - 1], n->func.args[i]->decl.type);
- pushstab(n->func.scope);
- inferstab(st, n->func.scope);
- inferfunc(st, n);
- popstab();
- break;
- case Nimpl:
- specializeimpl(st, n);
- break;
- case Nname:
- case Nlit:
- case Nuse:
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
+ t = mktyidxhack(n->loc, mktyvar(n->loc));
+ constrain(st, n, type(st, n->iterstmt.seq), traittab[Tcidx]);
+ unify(st, n, type(st, n->iterstmt.seq), t);
+ unify(st, n, type(st, n->iterstmt.elt), t->sub[0]);
+ break;
+ case Nmatchstmt:
+ infernode(st, &n->matchstmt.val, NULL, sawret);
+ if (tybase(type(st, n->matchstmt.val))->type == Tyvoid)
+ fatal(n, "can't match against a void type near %s",
+ ctxstr(st, n->matchstmt.val));
+ for (i = 0; i < n->matchstmt.nmatches; i++) {
+ infernode(st, &n->matchstmt.matches[i], ret, sawret);
+ pat = n->matchstmt.matches[i]->match.pat;
+ unify(st, pat, type(st, n->matchstmt.val),
+ type(st, n->matchstmt.matches[i]->match.pat));
+ }
+ break;
+ case Nmatch:
+ bound = NULL;
+ nbound = 0;
+ inferpat(st, &n->match.pat, NULL, &bound, &nbound);
+ addbindings(st, n->match.block, bound, nbound);
+ infernode(st, &n->match.block, ret, sawret);
+ break;
+ case Nexpr:
+ inferexpr(st, np, ret, sawret);
+ break;
+ case Nfunc:
+ setsuper(n->func.scope, curstab());
+ if (st->ntybindings > 0)
+ for (i = 0; i < n->func.nargs; i++)
+ putbindings(st, st->tybindings[st->ntybindings - 1],
+ n->func.args[i]->decl.type);
+ pushstab(n->func.scope);
+ inferstab(st, n->func.scope);
+ inferfunc(st, n);
+ popstab();
+ break;
+ case Nimpl:
+ specializeimpl(st, n);
+ break;
+ case Nname:
+ case Nlit:
+ case Nuse:
+ break;
+ case Nnone:
+ die("Nnone should not be seen as node type!");
+ break;
+ }
}
/* returns the final type for t, after all unifications
@@ -1772,194 +1790,204 @@
* and default constraint selections */
static Type *tyfix(Inferstate *st, Node *ctx, Type *orig, int noerr)
{
- static Type *tyint, *tyflt;
- Type *t, *delayed;
- char *from, *to;
- size_t i;
- char buf[1024];
+ static Type *tyint, *tyflt;
+ Type *t, *delayed;
+ char *from, *to;
+ size_t i;
+ char buf[1024];
- if (!tyint)
- tyint = mktype(Zloc, Tyint);
- if (!tyflt)
- tyflt = mktype(Zloc, Tyflt64);
+ if (!tyint)
+ tyint = mktype(Zloc, Tyint);
+ if (!tyflt)
+ tyflt = mktype(Zloc, Tyflt64);
- t = tysearch(orig);
- if (orig->type == Tyvar && hthas(st->delayed, orig)) {
- delayed = htget(st->delayed, orig);
- if (t->type == Tyvar)
- t = delayed;
- else if (tybase(t)->type != delayed->type && !noerr)
- fatal(ctx, "type %s not compatible with %s near %s\n", tystr(t), tystr(delayed), ctxstr(st, ctx));
- }
- if (t->type == Tyvar) {
- if (hastrait(t, traittab[Tcint]) && checktraits(t, tyint))
- t = tyint;
- if (hastrait(t, traittab[Tcfloat]) && checktraits(t, tyflt))
- t = tyflt;
- } else if (!t->fixed) {
- t->fixed = 1;
- if (t->type == Tyarray) {
- typesub(st, t->asize, noerr);
- } else if (t->type == Tystruct) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++)
- typesub(st, t->sdecls[i], noerr);
- st->inaggr--;
- } else if (t->type == Tyunion) {
- for (i = 0; i < t->nmemb; i++) {
- if (t->udecls[i]->etype) {
- tyresolve(st, t->udecls[i]->etype);
- t->udecls[i]->etype = tyfix(st, ctx, t->udecls[i]->etype, noerr);
- }
- }
- } else if (t->type == Tyname) {
- for (i = 0; i < t->narg; i++)
- t->arg[i] = tyfix(st, ctx, t->arg[i], noerr);
- }
- for (i = 0; i < t->nsub; i++)
- t->sub[i] = tyfix(st, ctx, t->sub[i], noerr);
- }
+ t = tysearch(orig);
+ if (orig->type == Tyvar && hthas(st->delayed, orig)) {
+ delayed = htget(st->delayed, orig);
+ if (t->type == Tyvar)
+ t = delayed;
+ else if (tybase(t)->type != delayed->type && !noerr)
+ fatal(ctx, "type %s not compatible with %s near %s\n", tystr(t),
+ tystr(delayed), ctxstr(st, ctx));
+ }
+ if (t->type == Tyvar) {
+ if (hastrait(t, traittab[Tcint]) && checktraits(t, tyint))
+ t = tyint;
+ if (hastrait(t, traittab[Tcfloat]) && checktraits(t, tyflt))
+ t = tyflt;
+ }
+ else if (!t->fixed) {
+ t->fixed = 1;
+ if (t->type == Tyarray) {
+ typesub(st, t->asize, noerr);
+ }
+ else if (t->type == Tystruct) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++)
+ typesub(st, t->sdecls[i], noerr);
+ st->inaggr--;
+ }
+ else if (t->type == Tyunion) {
+ for (i = 0; i < t->nmemb; i++) {
+ if (t->udecls[i]->etype) {
+ tyresolve(st, t->udecls[i]->etype);
+ t->udecls[i]->etype =
+ tyfix(st, ctx, t->udecls[i]->etype, noerr);
+ }
+ }
+ }
+ else if (t->type == Tyname) {
+ for (i = 0; i < t->narg; i++)
+ t->arg[i] = tyfix(st, ctx, t->arg[i], noerr);
+ }
+ for (i = 0; i < t->nsub; i++)
+ t->sub[i] = tyfix(st, ctx, t->sub[i], noerr);
+ }
- if (t->type == Tyvar && !noerr) {
- if (debugopt['T'])
- dump(file, stdout);
- fatal(ctx, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(st, ctx));
- }
+ if (t->type == Tyvar && !noerr) {
+ if (debugopt['T'])
+ dump(file, stdout);
+ fatal(
+ ctx, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(st, ctx));
+ }
- if (debugopt['u'] && !tyeq(orig, t)) {
- from = tystr(orig);
- to = tystr(t);
- indentf(st->indentdepth, "subst %s => %s\n", from, to);
- free(from);
- free(to);
- }
+ if (debugopt['u'] && !tyeq(orig, t)) {
+ from = tystr(orig);
+ to = tystr(t);
+ indentf(st->indentdepth, "subst %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
- return t;
+ return t;
}
static void checkcast(Inferstate *st, Node *n)
{
- /* FIXME: actually verify the casts. Right now, it's ok to leave this
- * unimplemented because bad casts get caught by the backend. */
+ /* FIXME: actually verify the casts. Right now, it's ok to leave this
+ * unimplemented because bad casts get caught by the backend. */
}
static void infercompn(Inferstate *st, Node *n)
{
- Node *aggr;
- Node *memb;
- Node **nl;
- Type *t;
- size_t i;
- int found;
+ Node *aggr;
+ Node *memb;
+ Node **nl;
+ Type *t;
+ size_t i;
+ int found;
- aggr = n->expr.args[0];
- memb = n->expr.args[1];
+ aggr = n->expr.args[0];
+ memb = n->expr.args[1];
- found = 0;
- t = tybase(tf(st, type(st, aggr)));
- /* all array-like types have a fake "len" member that we emulate */
- if (t->type == Tyslice || t->type == Tyarray) {
- if (!strcmp(namestr(memb), "len")) {
- constrain(st, n, type(st, n), traittab[Tcnum]);
- constrain(st, n, type(st, n), traittab[Tcint]);
- found = 1;
- }
- /* otherwise, we search aggregate types for the member, and unify
- * the expression with the member type; ie:
- *
- * x: aggrtype y : memb in aggrtype
- * ---------------------------------------
- * x.y : membtype
- */
- } else {
- if (tybase(t)->type == Typtr)
- t = tybase(tf(st, t->sub[0]));
- if (tybase(t)->type != Tystruct) {
- if (tybase(t)->type == Tyvar)
- fatal(n, "underspecified type defined on %s:%d used near %s", fname(t->loc), lnum(t->loc), ctxstr(st, n));
- else
- fatal(n, "type %s does not support member operators near %s", tystr(t), ctxstr(st, n));
- }
- nl = t->sdecls;
- for (i = 0; i < t->nmemb; i++) {
- if (!strcmp(namestr(memb), declname(nl[i]))) {
- unify(st, n, type(st, n), decltype(nl[i]));
- found = 1;
- break;
- }
- }
- }
- if (!found)
- fatal(aggr, "type %s has no member \"%s\" near %s",
- tystr(type(st, aggr)), ctxstr(st, memb), ctxstr(st, aggr));
+ found = 0;
+ t = tybase(tf(st, type(st, aggr)));
+ /* all array-like types have a fake "len" member that we emulate */
+ if (t->type == Tyslice || t->type == Tyarray) {
+ if (!strcmp(namestr(memb), "len")) {
+ constrain(st, n, type(st, n), traittab[Tcnum]);
+ constrain(st, n, type(st, n), traittab[Tcint]);
+ found = 1;
+ }
+ /* otherwise, we search aggregate types for the member, and unify
+ * the expression with the member type; ie:
+ *
+ * x: aggrtype y : memb in aggrtype
+ * ---------------------------------------
+ * x.y : membtype
+ */
+ }
+ else {
+ if (tybase(t)->type == Typtr)
+ t = tybase(tf(st, t->sub[0]));
+ if (tybase(t)->type != Tystruct) {
+ if (tybase(t)->type == Tyvar)
+ fatal(n, "underspecified type defined on %s:%d used near %s",
+ fname(t->loc), lnum(t->loc), ctxstr(st, n));
+ else
+ fatal(n, "type %s does not support member operators near %s",
+ tystr(t), ctxstr(st, n));
+ }
+ nl = t->sdecls;
+ for (i = 0; i < t->nmemb; i++) {
+ if (!strcmp(namestr(memb), declname(nl[i]))) {
+ unify(st, n, type(st, n), decltype(nl[i]));
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!found)
+ fatal(aggr, "type %s has no member \"%s\" near %s", tystr(type(st, aggr)),
+ ctxstr(st, memb), ctxstr(st, aggr));
}
static void checkstruct(Inferstate *st, Node *n)
{
- Type *t, *et;
- Node *val, *name;
- size_t i, j;
+ Type *t, *et;
+ Node *val, *name;
+ size_t i, j;
- t = tybase(tf(st, n->lit.type));
- if (t->type != Tystruct) {
- /*
- * If we haven't inferred the type, and it's inside another struct,
- * we'll eventually get to it.
- *
- * If, on the other hand, it is genuinely underspecified, we'll give
- * a better error on it later.
- */
- return;
- }
+ t = tybase(tf(st, n->lit.type));
+ if (t->type != Tystruct) {
+ /*
+ * If we haven't inferred the type, and it's inside another struct,
+ * we'll eventually get to it.
+ *
+ * If, on the other hand, it is genuinely underspecified, we'll give
+ * a better error on it later.
+ */
+ return;
+ }
- for (i = 0; i < n->expr.nargs; i++) {
- val = n->expr.args[i];
- name = val->expr.idx;
+ for (i = 0; i < n->expr.nargs; i++) {
+ val = n->expr.args[i];
+ name = val->expr.idx;
- et = NULL;
- for (j = 0; j < t->nmemb; j++) {
- if (!strcmp(namestr(t->sdecls[j]->decl.name), namestr(name))) {
- et = type(st, t->sdecls[j]);
- break;
- }
- }
+ et = NULL;
+ for (j = 0; j < t->nmemb; j++) {
+ if (!strcmp(namestr(t->sdecls[j]->decl.name), namestr(name))) {
+ et = type(st, t->sdecls[j]);
+ break;
+ }
+ }
- if (!et)
- fatal(n, "could not find member %s in struct %s, near %s",
- namestr(name), tystr(t), ctxstr(st, n));
+ if (!et)
+ fatal(n, "could not find member %s in struct %s, near %s", namestr(name),
+ tystr(t), ctxstr(st, n));
- unify(st, val, et, type(st, val));
- }
+ unify(st, val, et, type(st, val));
+ }
}
static void checkvar(Inferstate *st, Node *n)
{
- Node *dcl;
+ Node *dcl;
- dcl = decls[n->expr.did];
- unify(st, n, type(st, n), tyfreshen(st, NULL, type(st, dcl)));
+ dcl = decls[n->expr.did];
+ unify(st, n, type(st, n), tyfreshen(st, NULL, type(st, dcl)));
}
static void postcheck(Inferstate *st, Node *file)
{
- size_t i;
- Node *n;
+ size_t i;
+ Node *n;
- for (i = 0; i < st->npostcheck; i++) {
- n = st->postcheck[i];
- pushstab(st->postcheckscope[i]);
- if (n->type == Nexpr && exprop(n) == Omemb)
- infercompn(st, n);
- else if (n->type == Nexpr && exprop(n) == Ocast)
- checkcast(st, n);
- else if (n->type == Nexpr && exprop(n) == Ostruct)
- checkstruct(st, n);
- else if (n->type == Nexpr && exprop(n) == Ovar)
- checkvar(st, n);
- else
- die("Thing we shouldn't be checking in postcheck\n");
- popstab();
- }
+ for (i = 0; i < st->npostcheck; i++) {
+ n = st->postcheck[i];
+ pushstab(st->postcheckscope[i]);
+ if (n->type == Nexpr && exprop(n) == Omemb)
+ infercompn(st, n);
+ else if (n->type == Nexpr && exprop(n) == Ocast)
+ checkcast(st, n);
+ else if (n->type == Nexpr && exprop(n) == Ostruct)
+ checkstruct(st, n);
+ else if (n->type == Nexpr && exprop(n) == Ovar)
+ checkvar(st, n);
+ else
+ die("Thing we shouldn't be checking in postcheck\n");
+ popstab();
+ }
}
/* After inference, replace all
@@ -1967,93 +1995,91 @@
* the final computed types */
static void stabsub(Inferstate *st, Stab *s)
{
- void **k;
- size_t n, i;
- Type *t;
- Node *d;
+ void **k;
+ size_t n, i;
+ Type *t;
+ Node *d;
- k = htkeys(s->ty, &n);
- for (i = 0; i < n; i++) {
- t = tysearch(gettype(s, k[i]));
- updatetype(s, k[i], t);
- tyfix(st, k[i], t, 0);
- }
- free(k);
+ k = htkeys(s->ty, &n);
+ for (i = 0; i < n; i++) {
+ t = tysearch(gettype(s, k[i]));
+ updatetype(s, k[i], t);
+ tyfix(st, k[i], t, 0);
+ }
+ free(k);
- k = htkeys(s->dcl, &n);
- for (i = 0; i < n; i++) {
- d = getdcl(s, k[i]);
- if (d)
- d->decl.type = tyfix(st, d, d->decl.type, 0);
- }
- free(k);
+ k = htkeys(s->dcl, &n);
+ for (i = 0; i < n; i++) {
+ d = getdcl(s, k[i]);
+ if (d)
+ d->decl.type = tyfix(st, d, d->decl.type, 0);
+ }
+ free(k);
}
static void checkrange(Inferstate *st, Node *n)
{
- Type *t;
- int64_t sval;
- uint64_t uval;
- static const int64_t svranges[][2] = {
- /* signed ints */
- [Tyint8] = {-128LL, 127LL},
- [Tyint16] = {-32768LL, 32767LL},
- [Tyint32] = {-2147483648LL, 2*2147483647LL}, /* FIXME: this has been doubled allow for uints... */
- [Tyint] = {-2147483648LL, 2*2147483647LL},
- [Tyint64] = {-9223372036854775808ULL, 9223372036854775807LL},
- };
+ Type *t;
+ int64_t sval;
+ uint64_t uval;
+ static const int64_t svranges[][2] = {
+ /* signed ints */
+ [Tyint8] = {-128LL, 127LL}, [Tyint16] = {-32768LL, 32767LL},
+ /* FIXME: this has been doubled allow for uints... */
+ [Tyint32] = {-2147483648LL, 2 * 2147483647LL},
+ [Tyint] = {-2147483648LL, 2 * 2147483647LL},
+ [Tyint64] = {-9223372036854775808ULL, 9223372036854775807LL},
+ };
- static const uint64_t uvranges[][2] = {
- [Tybyte] = {0, 255ULL},
- [Tyuint8] = {0, 255ULL},
- [Tyuint16] = {0, 65535ULL},
- [Tyuint32] = {0, 4294967295ULL},
- [Tyuint64] = {0, 18446744073709551615ULL},
- [Tychar] = {0, 4294967295ULL},
- };
+ static const uint64_t uvranges[][2] = {
+ [Tybyte] = {0, 255ULL}, [Tyuint8] = {0, 255ULL}, [Tyuint16] = {0, 65535ULL},
+ [Tyuint32] = {0, 4294967295ULL}, [Tyuint64] = {0, 18446744073709551615ULL},
+ [Tychar] = {0, 4294967295ULL},
+ };
- /* signed types */
- t = type(st, n);
- if (t->type >= Tyint8 && t->type <= Tyint64) {
- sval = n->lit.intval;
- if (sval < svranges[t->type][0] || sval > svranges[t->type][1])
- fatal(n, "literal value %lld out of range for type \"%s\"", sval, tystr(t));
- } else if ((t->type >= Tybyte && t->type <= Tyint64) || t->type == Tychar) {
- uval = n->lit.intval;
- if (uval < uvranges[t->type][0] || uval > uvranges[t->type][1])
- fatal(n, "literal value %llu out of range for type \"%s\"", uval, tystr(t));
- }
+ /* signed types */
+ t = type(st, n);
+ if (t->type >= Tyint8 && t->type <= Tyint64) {
+ sval = n->lit.intval;
+ if (sval < svranges[t->type][0] || sval > svranges[t->type][1])
+ fatal(n, "literal value %lld out of range for type \"%s\"", sval, tystr(t));
+ }
+ else if ((t->type >= Tybyte && t->type <= Tyint64) || t->type == Tychar) {
+ uval = n->lit.intval;
+ if (uval < uvranges[t->type][0] || uval > uvranges[t->type][1])
+ fatal(n, "literal value %llu out of range for type \"%s\"", uval, tystr(t));
+ }
}
static int initcompatible(Type *t)
{
- if (t->type != Tyfunc)
- return 0;
- if (t->nsub != 1)
- return 0;
- if (tybase(t->sub[0])->type != Tyvoid)
- return 0;
- return 1;
+ if (t->type != Tyfunc)
+ return 0;
+ if (t->nsub != 1)
+ return 0;
+ if (tybase(t->sub[0])->type != Tyvoid)
+ return 0;
+ return 1;
}
static int maincompatible(Type *t)
{
- if (t->nsub > 2)
- return 0;
- if (tybase(t->sub[0])->type != Tyvoid)
- return 0;
- if (t->nsub == 2) {
- t = tybase(t->sub[1]);
- if (t->type != Tyslice)
- return 0;
- t = tybase(t->sub[0]);
- if (t->type != Tyslice)
- return 0;
- t = tybase(t->sub[0]);
- if (t->type != Tybyte)
- return 0;
- }
- return 1;
+ if (t->nsub > 2)
+ return 0;
+ if (tybase(t->sub[0])->type != Tyvoid)
+ return 0;
+ if (t->nsub == 2) {
+ t = tybase(t->sub[1]);
+ if (t->type != Tyslice)
+ return 0;
+ t = tybase(t->sub[0]);
+ if (t->type != Tyslice)
+ return 0;
+ t = tybase(t->sub[0]);
+ if (t->type != Tybyte)
+ return 0;
+ }
+ return 1;
}
/* After type inference, replace all types
@@ -2060,297 +2086,293 @@
* with the final computed type */
static void typesub(Inferstate *st, Node *n, int noerr)
{
- size_t i;
+ size_t i;
- if (!n)
- return;
- switch (n->type) {
- case Nfile:
- pushstab(n->file.globls);
- stabsub(st, n->file.globls);
- for (i = 0; i < n->file.nstmts; i++)
- typesub(st, n->file.stmts[i], noerr);
- popstab();
- break;
- case Ndecl:
- settype(st, n, tyfix(st, n, type(st, n), noerr));
- if (n->decl.init)
- typesub(st, n->decl.init, noerr);
- if (streq(declname(n), "main"))
- if (!maincompatible(tybase(decltype(n))))
- fatal(n, "main must be (->void) or (byte[:][:] -> void), got %s", tystr(decltype(n)));
- if (streq(declname(n), "__init__"))
- if (!initcompatible(tybase(decltype(n))))
- fatal(n, "__init__ must be (->void), got %s", tystr(decltype(n)));
- break;
- case Nblock:
- pushstab(n->block.scope);
- for (i = 0; i < n->block.nstmts; i++)
- typesub(st, n->block.stmts[i], noerr);
- popstab();
- break;
- case Nifstmt:
- typesub(st, n->ifstmt.cond, noerr);
- typesub(st, n->ifstmt.iftrue, noerr);
- typesub(st, n->ifstmt.iffalse, noerr);
- break;
- case Nloopstmt:
- typesub(st, n->loopstmt.cond, noerr);
- typesub(st, n->loopstmt.init, noerr);
- typesub(st, n->loopstmt.step, noerr);
- typesub(st, n->loopstmt.body, noerr);
- break;
- case Niterstmt:
- typesub(st, n->iterstmt.elt, noerr);
- typesub(st, n->iterstmt.seq, noerr);
- typesub(st, n->iterstmt.body, noerr);
- break;
- case Nmatchstmt:
- typesub(st, n->matchstmt.val, noerr);
- for (i = 0; i < n->matchstmt.nmatches; i++) {
- typesub(st, n->matchstmt.matches[i], noerr);
- }
- break;
- case Nmatch:
- typesub(st, n->match.pat, noerr);
- typesub(st, n->match.block, noerr);
- break;
- case Nexpr:
- settype(st, n, tyfix(st, n, type(st, n), 0));
- typesub(st, n->expr.idx, noerr);
- if (exprop(n) == Ocast && exprop(n->expr.args[0]) == Olit && n->expr.args[0]->expr.args[0]->lit.littype == Lint) {
- settype(st, n->expr.args[0], exprtype(n));
- settype(st, n->expr.args[0]->expr.args[0], exprtype(n));
- }
- for (i = 0; i < n->expr.nargs; i++)
- typesub(st, n->expr.args[i], noerr);
- break;
- case Nfunc:
- pushstab(n->func.scope);
- settype(st, n, tyfix(st, n, n->func.type, 0));
- for (i = 0; i < n->func.nargs; i++)
- typesub(st, n->func.args[i], noerr);
- typesub(st, n->func.body, noerr);
- popstab();
- break;
- case Nlit:
- settype(st, n, tyfix(st, n, type(st, n), 0));
- switch (n->lit.littype) {
- case Lfunc:
- typesub(st, n->lit.fnval, noerr); break;
- case Lint:
- checkrange(st, n);
- default: break;
- }
- break;
- case Nimpl:
- putimpl(curstab(), n);
- break;
- case Nname:
- case Nuse:
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nfile:
+ pushstab(n->file.globls);
+ stabsub(st, n->file.globls);
+ for (i = 0; i < n->file.nstmts; i++)
+ typesub(st, n->file.stmts[i], noerr);
+ popstab();
+ break;
+ case Ndecl:
+ settype(st, n, tyfix(st, n, type(st, n), noerr));
+ if (n->decl.init)
+ typesub(st, n->decl.init, noerr);
+ if (streq(declname(n), "main"))
+ if (!maincompatible(tybase(decltype(n))))
+ fatal(n, "main must be (->void) or (byte[:][:] -> void), got %s",
+ tystr(decltype(n)));
+ if (streq(declname(n), "__init__"))
+ if (!initcompatible(tybase(decltype(n))))
+ fatal(n, "__init__ must be (->void), got %s", tystr(decltype(n)));
+ break;
+ case Nblock:
+ pushstab(n->block.scope);
+ for (i = 0; i < n->block.nstmts; i++)
+ typesub(st, n->block.stmts[i], noerr);
+ popstab();
+ break;
+ case Nifstmt:
+ typesub(st, n->ifstmt.cond, noerr);
+ typesub(st, n->ifstmt.iftrue, noerr);
+ typesub(st, n->ifstmt.iffalse, noerr);
+ break;
+ case Nloopstmt:
+ typesub(st, n->loopstmt.cond, noerr);
+ typesub(st, n->loopstmt.init, noerr);
+ typesub(st, n->loopstmt.step, noerr);
+ typesub(st, n->loopstmt.body, noerr);
+ break;
+ case Niterstmt:
+ typesub(st, n->iterstmt.elt, noerr);
+ typesub(st, n->iterstmt.seq, noerr);
+ typesub(st, n->iterstmt.body, noerr);
+ break;
+ case Nmatchstmt:
+ typesub(st, n->matchstmt.val, noerr);
+ for (i = 0; i < n->matchstmt.nmatches; i++) {
+ typesub(st, n->matchstmt.matches[i], noerr);
+ }
+ break;
+ case Nmatch:
+ typesub(st, n->match.pat, noerr);
+ typesub(st, n->match.block, noerr);
+ break;
+ case Nexpr:
+ settype(st, n, tyfix(st, n, type(st, n), 0));
+ typesub(st, n->expr.idx, noerr);
+ if (exprop(n) == Ocast && exprop(n->expr.args[0]) == Olit &&
+ n->expr.args[0]->expr.args[0]->lit.littype == Lint) {
+ settype(st, n->expr.args[0], exprtype(n));
+ settype(st, n->expr.args[0]->expr.args[0], exprtype(n));
+ }
+ for (i = 0; i < n->expr.nargs; i++)
+ typesub(st, n->expr.args[i], noerr);
+ break;
+ case Nfunc:
+ pushstab(n->func.scope);
+ settype(st, n, tyfix(st, n, n->func.type, 0));
+ for (i = 0; i < n->func.nargs; i++)
+ typesub(st, n->func.args[i], noerr);
+ typesub(st, n->func.body, noerr);
+ popstab();
+ break;
+ case Nlit:
+ settype(st, n, tyfix(st, n, type(st, n), 0));
+ switch (n->lit.littype) {
+ case Lfunc: typesub(st, n->lit.fnval, noerr); break;
+ case Lint: checkrange(st, n);
+ default: break;
+ }
+ break;
+ case Nimpl: putimpl(curstab(), n); break;
+ case Nname:
+ case Nuse: break;
+ case Nnone: die("Nnone should not be seen as node type!"); break;
+ }
}
static void taghidden(Type *t)
{
- size_t i;
+ size_t i;
- if (t->vis != Visintern)
- return;
- t->vis = Vishidden;
- for (i = 0; i < t->nsub; i++)
- taghidden(t->sub[i]);
- switch (t->type) {
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- taghidden(decltype(t->sdecls[i]));
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- taghidden(t->udecls[i]->etype);
- break;
- case Tyname:
- t->isreflect = 1;
- for (i = 0; i < t->narg; i++)
- taghidden(t->arg[i]);
- case Tygeneric:
- for (i = 0; i < t->ngparam; i++)
- taghidden(t->gparam[i]);
- break;
- default:
- break;
- }
+ if (t->vis != Visintern)
+ return;
+ t->vis = Vishidden;
+ for (i = 0; i < t->nsub; i++)
+ taghidden(t->sub[i]);
+ switch (t->type) {
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ taghidden(decltype(t->sdecls[i]));
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ taghidden(t->udecls[i]->etype);
+ break;
+ case Tyname:
+ t->isreflect = 1;
+ for (i = 0; i < t->narg; i++)
+ taghidden(t->arg[i]);
+ case Tygeneric:
+ for (i = 0; i < t->ngparam; i++)
+ taghidden(t->gparam[i]);
+ break;
+ default: break;
+ }
}
int isexportinit(Node *n)
{
- if (n->decl.isgeneric && !n->decl.trait)
- return 1;
- /* we want to inline small values, which means we need to export them */
- if (istyprimitive(n->decl.type))
- return 1;
- return 0;
+ if (n->decl.isgeneric && !n->decl.trait)
+ return 1;
+ /* we want to inline small values, which means we need to export them */
+ if (istyprimitive(n->decl.type))
+ return 1;
+ return 0;
}
static void nodetag(Stab *st, Node *n, int ingeneric, int hidelocal)
{
- size_t i;
- Node *d;
+ size_t i;
+ Node *d;
- if (!n)
- return;
- switch (n->type) {
- case Nblock:
- for (i = 0; i < n->block.nstmts; i++)
- nodetag(st, n->block.stmts[i], ingeneric, hidelocal);
- break;
- case Nifstmt:
- nodetag(st, n->ifstmt.cond, ingeneric, hidelocal);
- nodetag(st, n->ifstmt.iftrue, ingeneric, hidelocal);
- nodetag(st, n->ifstmt.iffalse, ingeneric, hidelocal);
- break;
- case Nloopstmt:
- nodetag(st, n->loopstmt.init, ingeneric, hidelocal);
- nodetag(st, n->loopstmt.cond, ingeneric, hidelocal);
- nodetag(st, n->loopstmt.step, ingeneric, hidelocal);
- nodetag(st, n->loopstmt.body, ingeneric, hidelocal);
- break;
- case Niterstmt:
- nodetag(st, n->iterstmt.elt, ingeneric, hidelocal);
- nodetag(st, n->iterstmt.seq, ingeneric, hidelocal);
- nodetag(st, n->iterstmt.body, ingeneric, hidelocal);
- break;
- case Nmatchstmt:
- nodetag(st, n->matchstmt.val, ingeneric, hidelocal);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- nodetag(st, n->matchstmt.matches[i], ingeneric, hidelocal);
- break;
- case Nmatch:
- nodetag(st, n->match.pat, ingeneric, hidelocal);
- nodetag(st, n->match.block, ingeneric, hidelocal);
- break;
- case Nexpr:
- nodetag(st, n->expr.idx, ingeneric, hidelocal);
- taghidden(n->expr.type);
- for (i = 0; i < n->expr.nargs; i++)
- nodetag(st, n->expr.args[i], ingeneric, hidelocal);
- /* generics need to have the decls they refer to exported. */
- if (ingeneric && exprop(n) == Ovar) {
- d = decls[n->expr.did];
- if (d->decl.isglobl && d->decl.vis == Visintern) {
- d->decl.vis = Vishidden;
- nodetag(st, d, ingeneric, hidelocal);
- }
- }
- break;
- case Nlit:
- taghidden(n->lit.type);
- if (n->lit.littype == Lfunc)
- nodetag(st, n->lit.fnval, ingeneric, hidelocal);
- break;
- case Ndecl:
- taghidden(n->decl.type);
- if (hidelocal && n->decl.ispkglocal)
- n->decl.vis = Vishidden;
- n->decl.isexportinit = isexportinit(n);
- if (n->decl.isexportinit)
- nodetag(st, n->decl.init, n->decl.isgeneric, hidelocal);
- break;
- case Nfunc:
- taghidden(n->func.type);
- for (i = 0; i < n->func.nargs; i++)
- nodetag(st, n->func.args[i], ingeneric, hidelocal);
- nodetag(st, n->func.body, ingeneric, hidelocal);
- break;
- case Nimpl:
- for (i = 0; i < n->impl.ndecls; i++) {
- n->impl.decls[i]->decl.vis = Vishidden;
- nodetag(st, n->impl.decls[i], 0, hidelocal);
- }
- break;
- case Nuse: case Nname:
- break;
- case Nfile: case Nnone:
- die("Invalid node for type export\n");
- break;
- }
-}
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nblock:
+ for (i = 0; i < n->block.nstmts; i++)
+ nodetag(st, n->block.stmts[i], ingeneric, hidelocal);
+ break;
+ case Nifstmt:
+ nodetag(st, n->ifstmt.cond, ingeneric, hidelocal);
+ nodetag(st, n->ifstmt.iftrue, ingeneric, hidelocal);
+ nodetag(st, n->ifstmt.iffalse, ingeneric, hidelocal);
+ break;
+ case Nloopstmt:
+ nodetag(st, n->loopstmt.init, ingeneric, hidelocal);
+ nodetag(st, n->loopstmt.cond, ingeneric, hidelocal);
+ nodetag(st, n->loopstmt.step, ingeneric, hidelocal);
+ nodetag(st, n->loopstmt.body, ingeneric, hidelocal);
+ break;
+ case Niterstmt:
+ nodetag(st, n->iterstmt.elt, ingeneric, hidelocal);
+ nodetag(st, n->iterstmt.seq, ingeneric, hidelocal);
+ nodetag(st, n->iterstmt.body, ingeneric, hidelocal);
+ break;
+ case Nmatchstmt:
+ nodetag(st, n->matchstmt.val, ingeneric, hidelocal);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ nodetag(st, n->matchstmt.matches[i], ingeneric, hidelocal);
+ break;
+ case Nmatch:
+ nodetag(st, n->match.pat, ingeneric, hidelocal);
+ nodetag(st, n->match.block, ingeneric, hidelocal);
+ break;
+ case Nexpr:
+ nodetag(st, n->expr.idx, ingeneric, hidelocal);
+ taghidden(n->expr.type);
+ for (i = 0; i < n->expr.nargs; i++)
+ nodetag(st, n->expr.args[i], ingeneric, hidelocal);
+ /* generics need to have the decls they refer to exported. */
+ if (ingeneric && exprop(n) == Ovar) {
+ d = decls[n->expr.did];
+ if (d->decl.isglobl && d->decl.vis == Visintern) {
+ d->decl.vis = Vishidden;
+ nodetag(st, d, ingeneric, hidelocal);
+ }
+ }
+ break;
+ case Nlit:
+ taghidden(n->lit.type);
+ if (n->lit.littype == Lfunc)
+ nodetag(st, n->lit.fnval, ingeneric, hidelocal);
+ break;
+ case Ndecl:
+ taghidden(n->decl.type);
+ if (hidelocal && n->decl.ispkglocal)
+ n->decl.vis = Vishidden;
+ n->decl.isexportinit = isexportinit(n);
+ if (n->decl.isexportinit)
+ nodetag(st, n->decl.init, n->decl.isgeneric, hidelocal);
+ break;
+ case Nfunc:
+ taghidden(n->func.type);
+ for (i = 0; i < n->func.nargs; i++)
+ nodetag(st, n->func.args[i], ingeneric, hidelocal);
+ nodetag(st, n->func.body, ingeneric, hidelocal);
+ break;
+ case Nimpl:
+ for (i = 0; i < n->impl.ndecls; i++) {
+ n->impl.decls[i]->decl.vis = Vishidden;
+ nodetag(st, n->impl.decls[i], 0, hidelocal);
+ }
+ break;
+ case Nuse:
+ case Nname:
+ break;
+ case Nfile:
+ case Nnone:
+ die("Invalid node for type export\n");
+ break;
+ }
+}
void tagexports(Node *file, int hidelocal)
{
- size_t i, j, n;
- Trait *tr;
- Stab *st;
- void **k;
- Node *s;
- Type *t;
+ size_t i, j, n;
+ Trait *tr;
+ Stab *st;
+ void **k;
+ Node *s;
+ Type *t;
- st = file->file.globls;
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- s = getdcl(st, k[i]);
- if (s->decl.vis == Visexport)
- nodetag(st, s, 0, hidelocal);
- }
- free(k);
+ st = file->file.globls;
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ s = getdcl(st, k[i]);
+ if (s->decl.vis == Visexport)
+ nodetag(st, s, 0, hidelocal);
+ }
+ free(k);
- k = htkeys(st->impl, &n);
- for (i = 0; i < n; i++) {
- s = getimpl(st, k[i]);
- if (s->impl.vis == Visexport)
- nodetag(st, s, 0, hidelocal);
- }
- free(k);
+ k = htkeys(st->impl, &n);
+ for (i = 0; i < n; i++) {
+ s = getimpl(st, k[i]);
+ if (s->impl.vis == Visexport)
+ nodetag(st, s, 0, hidelocal);
+ }
+ free(k);
- for (i = 0; i < file->file.ninit; i++)
- nodetag(st, file->file.init[i], 0, hidelocal);
- if (file->file.localinit)
- nodetag(st, file->file.localinit, 0, hidelocal);
+ for (i = 0; i < file->file.ninit; i++)
+ nodetag(st, file->file.init[i], 0, hidelocal);
+ if (file->file.localinit)
+ nodetag(st, file->file.localinit, 0, hidelocal);
- k = htkeys(st->tr, &n);
- for (i = 0; i < n; i++) {
- tr = gettrait(st, k[i]);
- if (tr->vis == Visexport) {
- tr->param->vis = Visexport;
- for (i = 0; i < tr->nmemb; i++) {
- tr->memb[i]->decl.vis = Visexport;
- nodetag(st, tr->memb[i], 0, hidelocal);
- }
- for (i = 0; i < tr->nfuncs; i++) {
- tr->funcs[i]->decl.vis = Visexport;
- nodetag(st, tr->funcs[i], 0, hidelocal);
- }
- }
- }
- free(k);
+ k = htkeys(st->tr, &n);
+ for (i = 0; i < n; i++) {
+ tr = gettrait(st, k[i]);
+ if (tr->vis == Visexport) {
+ tr->param->vis = Visexport;
+ for (i = 0; i < tr->nmemb; i++) {
+ tr->memb[i]->decl.vis = Visexport;
+ nodetag(st, tr->memb[i], 0, hidelocal);
+ }
+ for (i = 0; i < tr->nfuncs; i++) {
+ tr->funcs[i]->decl.vis = Visexport;
+ nodetag(st, tr->funcs[i], 0, hidelocal);
+ }
+ }
+ }
+ free(k);
- /* get the explicitly exported symbols */
- k = htkeys(st->ty, &n);
- for (i = 0; i < n; i++) {
- t = gettype(st, k[i]);
- if (!t->isreflect && t->vis != Visexport)
- continue;
- if (hidelocal && t->ispkglocal)
- t->vis = Vishidden;
- taghidden(t);
- for (j = 0; j < t->nsub; j++)
- taghidden(t->sub[j]);
- if (t->type == Tyname) {
- t->isreflect = 1;
- for (j = 0; j < t->narg; j++)
- taghidden(t->arg[j]);
- } else if (t->type == Tygeneric) {
- for (j = 0; j < t->ngparam; j++)
- taghidden(t->gparam[j]);
- }
- }
- free(k);
-
+ /* get the explicitly exported symbols */
+ k = htkeys(st->ty, &n);
+ for (i = 0; i < n; i++) {
+ t = gettype(st, k[i]);
+ if (!t->isreflect && t->vis != Visexport)
+ continue;
+ if (hidelocal && t->ispkglocal)
+ t->vis = Vishidden;
+ taghidden(t);
+ for (j = 0; j < t->nsub; j++)
+ taghidden(t->sub[j]);
+ if (t->type == Tyname) {
+ t->isreflect = 1;
+ for (j = 0; j < t->narg; j++)
+ taghidden(t->arg[j]);
+ }
+ else if (t->type == Tygeneric) {
+ for (j = 0; j < t->ngparam; j++)
+ taghidden(t->gparam[j]);
+ }
+ }
+ free(k);
}
/* Take generics and build new versions of them
@@ -2358,80 +2380,82 @@
* specialized types */
static void specialize(Inferstate *st, Node *f)
{
- Node *d, *name;
- size_t i;
+ Node *d, *name;
+ size_t i;
- for (i = 0; i < st->nspecializations; i++) {
- pushstab(st->specializationscope[i]);
- d = specializedcl(st->genericdecls[i], st->specializations[i]->expr.type, &name);
- st->specializations[i]->expr.args[0] = name;
- st->specializations[i]->expr.did = d->decl.did;
+ for (i = 0; i < st->nspecializations; i++) {
+ pushstab(st->specializationscope[i]);
+ d = specializedcl(st->genericdecls[i], st->specializations[i]->expr.type, &name);
+ st->specializations[i]->expr.args[0] = name;
+ st->specializations[i]->expr.did = d->decl.did;
- /* we need to sub in default types in the specialization, so call
- * typesub on the specialized function */
- typesub(st, d, 0);
- popstab();
- }
+ /* we need to sub in default types in the specialization, so call
+ * typesub on the specialized function */
+ typesub(st, d, 0);
+ popstab();
+ }
}
void applytraits(Inferstate *st, Node *f)
{
- size_t i;
- Node *n;
- Trait *trait;
- Type *ty;
+ size_t i;
+ Node *n;
+ Trait *trait;
+ Type *ty;
- pushstab(f->file.globls);
- /* for now, traits can only be declared globally */
- for (i = 0; i < f->file.nstmts; i++) {
- if (f->file.stmts[i]->type == Nimpl) {
- n = f->file.stmts[i];
- trait = gettrait(f->file.globls, n->impl.traitname);
- if (!trait)
- fatal(n, "trait %s does not exist near %s", namestr(n->impl.traitname), ctxstr(st, n));
- ty = tf(st, n->impl.type);
- settrait(ty, trait);
- }
- }
- popstab();
+ pushstab(f->file.globls);
+ /* for now, traits can only be declared globally */
+ for (i = 0; i < f->file.nstmts; i++) {
+ if (f->file.stmts[i]->type == Nimpl) {
+ n = f->file.stmts[i];
+ trait = gettrait(f->file.globls, n->impl.traitname);
+ if (!trait)
+ fatal(n, "trait %s does not exist near %s",
+ namestr(n->impl.traitname), ctxstr(st, n));
+ ty = tf(st, n->impl.type);
+ settrait(ty, trait);
+ }
+ }
+ popstab();
}
void verify(Inferstate *st, Node *f)
{
- Node *n;
- size_t i;
+ Node *n;
+ size_t i;
- pushstab(f->file.globls);
- /* for now, traits can only be declared globally */
- for (i = 0; i < f->file.nstmts; i++) {
- if (f->file.stmts[i]->type == Nimpl) {
- n = f->file.stmts[i];
- /* we merge, so we need to get it back again when error checking */
- if (n->impl.isproto)
- fatal(n, "missing implementation for prototype '%s %s'",
- namestr(n->impl.traitname), tystr(n->impl.type));
- }
- }
+ pushstab(f->file.globls);
+ /* for now, traits can only be declared globally */
+ for (i = 0; i < f->file.nstmts; i++) {
+ if (f->file.stmts[i]->type == Nimpl) {
+ n = f->file.stmts[i];
+ /* we merge, so we need to get it back again when error checking */
+ if (n->impl.isproto)
+ fatal(n, "missing implementation for prototype '%s %s'",
+ namestr(n->impl.traitname), tystr(n->impl.type));
+ }
+ }
}
void infer(Node *file)
{
- Inferstate st = {0,};
+ Inferstate st = {
+ 0,
+ };
- assert(file->type == Nfile);
- st.delayed = mkht(tyhash, tyeq);
- /* set up the symtabs */
- loaduses(file);
- //mergeexports(&st, file);
+ assert(file->type == Nfile);
+ st.delayed = mkht(tyhash, tyeq);
+ /* set up the symtabs */
+ loaduses(file);
+ // mergeexports(&st, file);
- /* do the inference */
- applytraits(&st, file);
- infernode(&st, &file, NULL, NULL);
- postcheck(&st, file);
+ /* do the inference */
+ applytraits(&st, file);
+ infernode(&st, &file, NULL, NULL);
+ postcheck(&st, file);
- /* and replace type vars with actual types */
- typesub(&st, file, 0);
- specialize(&st, file);
- verify(&st, file);
+ /* and replace type vars with actual types */
+ typesub(&st, file, 0);
+ specialize(&st, file);
+ verify(&st, file);
}
-
--- a/parse/names.c
+++ b/parse/names.c
@@ -12,19 +12,18 @@
#include "parse.h"
-char *opstr[] = {
+char *opstr[] = {
#define O(op, pure, class, pretty) #op,
#include "ops.def"
#undef O
};
-char * oppretty[] = {
+char *oppretty[] = {
#define O(op, pure, class, pretty) pretty,
#include "ops.def"
#undef O
};
-
int opispure[] = {
#define O(op, pure, class, pretty) pure,
#include "ops.def"
@@ -37,19 +36,19 @@
#undef O
};
-char *nodestr[] = {
+char *nodestr[] = {
#define N(nt) #nt,
#include "nodes.def"
#undef N
};
-char *litstr[] = {
+char *litstr[] = {
#define L(lt) #lt,
#include "lits.def"
#undef L
};
-char *tidstr[] = {
+char *tidstr[] = {
#define Ty(t, n, stk) n,
#include "types.def"
#undef Ty
--- a/parse/node.c
+++ b/parse/node.c
@@ -17,15 +17,9 @@
Node **decls;
size_t ndecls;
-char *fname(Srcloc l)
-{
- return file->file.files[l.file];
-}
+char *fname(Srcloc l) { return file->file.files[l.file]; }
-int lnum(Srcloc l)
-{
- return l.line;
-}
+int lnum(Srcloc l) { return l.line; }
/*
* Bah, this is going to need to know how to fold things.
@@ -33,487 +27,473 @@
*/
uint64_t arraysz(Node *sz)
{
- Node *n;
+ Node *n;
- n = sz;
- if (exprop(n) != Olit)
- fatal(sz, "too many layers of indirection when finding intializer. (initialization loop?)");
+ n = sz;
+ if (exprop(n) != Olit)
+ fatal(sz, "too much indirection when finding intializer. (initialization loop?)");
- n = n->expr.args[0];
- if (n->lit.littype != Lint)
- fatal(sz, "initializer is not an integer");
- return n->lit.intval;
+ n = n->expr.args[0];
+ if (n->lit.littype != Lint)
+ fatal(sz, "initializer is not an integer");
+ return n->lit.intval;
}
Node *mknode(Srcloc loc, Ntype nt)
{
- Node *n;
+ Node *n;
- n = zalloc(sizeof(Node));
- n->nid = nnodes;
- n->type = nt;
- n->loc = loc;
- lappend(&nodes, &nnodes, n);
- return n;
+ n = zalloc(sizeof(Node));
+ n->nid = nnodes;
+ n->type = nt;
+ n->loc = loc;
+ lappend(&nodes, &nnodes, n);
+ return n;
}
Node *mkfile(char *name)
{
- Node *n;
+ Node *n;
- n = mknode(Zloc, Nfile);
- n->file.ns = mkht(strhash, streq);
- lappend(&n->file.files, &n->file.nfiles, strdup(name));
- return n;
+ n = mknode(Zloc, Nfile);
+ n->file.ns = mkht(strhash, streq);
+ lappend(&n->file.files, &n->file.nfiles, strdup(name));
+ return n;
}
Node *mkuse(Srcloc loc, char *use, int islocal)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nuse);
- n->use.name = strdup(use);
- n->use.islocal = islocal;
+ n = mknode(loc, Nuse);
+ n->use.name = strdup(use);
+ n->use.islocal = islocal;
- return n;
+ return n;
}
Node *mksliceexpr(Srcloc loc, Node *sl, Node *base, Node *off)
{
- if (!base)
- base = mkintlit(loc, 0);
- if (!off)
- off = mkexpr(loc, Omemb, sl, mkname(loc, "len"), NULL);
- return mkexpr(loc, Oslice, sl, base, off, NULL);
+ if (!base)
+ base = mkintlit(loc, 0);
+ if (!off)
+ off = mkexpr(loc, Omemb, sl, mkname(loc, "len"), NULL);
+ return mkexpr(loc, Oslice, sl, base, off, NULL);
}
Node *mkexprl(Srcloc loc, Op op, Node **args, size_t nargs)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nexpr);
- n->expr.op = op;
- n->expr.args = args;
- n->expr.nargs = nargs;
- return n;
+ n = mknode(loc, Nexpr);
+ n->expr.op = op;
+ n->expr.args = args;
+ n->expr.nargs = nargs;
+ return n;
}
Node *mkexpr(Srcloc loc, Op op, ...)
{
- Node *n;
- va_list ap;
- Node *arg;
+ Node *n;
+ va_list ap;
+ Node *arg;
- n = mknode(loc, Nexpr);
- n->expr.op = op;
- va_start(ap, op);
- while ((arg = va_arg(ap, Node*)) != NULL)
- lappend(&n->expr.args, &n->expr.nargs, arg);
- va_end(ap);
+ n = mknode(loc, Nexpr);
+ n->expr.op = op;
+ va_start(ap, op);
+ while ((arg = va_arg(ap, Node *)) != NULL)
+ lappend(&n->expr.args, &n->expr.nargs, arg);
+ va_end(ap);
- return n;
+ return n;
}
-Node *mkcall(Srcloc loc, Node *fn, Node **args, size_t nargs)
+Node *mkcall(Srcloc loc, Node *fn, Node **args, size_t nargs)
{
- Node *n;
- size_t i;
+ Node *n;
+ size_t i;
- n = mkexpr(loc, Ocall, fn, NULL);
- for (i = 0; i < nargs; i++)
- lappend(&n->expr.args, &n->expr.nargs, args[i]);
- return n;
+ n = mkexpr(loc, Ocall, fn, NULL);
+ for (i = 0; i < nargs; i++)
+ lappend(&n->expr.args, &n->expr.nargs, args[i]);
+ return n;
}
Node *mkifstmt(Srcloc loc, Node *cond, Node *iftrue, Node *iffalse)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nifstmt);
- n->ifstmt.cond = cond;
- n->ifstmt.iftrue = iftrue;
- n->ifstmt.iffalse = iffalse;
+ n = mknode(loc, Nifstmt);
+ n->ifstmt.cond = cond;
+ n->ifstmt.iftrue = iftrue;
+ n->ifstmt.iffalse = iffalse;
- return n;
+ return n;
}
Node *mkloopstmt(Srcloc loc, Node *init, Node *cond, Node *incr, Node *body)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nloopstmt);
- n->loopstmt.init = init;
- n->loopstmt.cond = cond;
- n->loopstmt.step = incr;
- n->loopstmt.body = body;
- n->loopstmt.scope = mkstab(0);
+ n = mknode(loc, Nloopstmt);
+ n->loopstmt.init = init;
+ n->loopstmt.cond = cond;
+ n->loopstmt.step = incr;
+ n->loopstmt.body = body;
+ n->loopstmt.scope = mkstab(0);
- return n;
+ return n;
}
Node *mkiterstmt(Srcloc loc, Node *elt, Node *seq, Node *body)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Niterstmt);
- n->iterstmt.elt = elt;
- n->iterstmt.seq = seq;
- n->iterstmt.body = body;
+ n = mknode(loc, Niterstmt);
+ n->iterstmt.elt = elt;
+ n->iterstmt.seq = seq;
+ n->iterstmt.body = body;
- return n;
+ return n;
}
Node *mkmatchstmt(Srcloc loc, Node *val, Node **matches, size_t nmatches)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nmatchstmt);
- n->matchstmt.val = val;
- n->matchstmt.matches = matches;
- n->matchstmt.nmatches = nmatches;
- return n;
+ n = mknode(loc, Nmatchstmt);
+ n->matchstmt.val = val;
+ n->matchstmt.matches = matches;
+ n->matchstmt.nmatches = nmatches;
+ return n;
}
Node *mkmatch(Srcloc loc, Node *pat, Node *body)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nmatch);
- n->match.pat = pat;
- n->match.block = body;
- return n;
+ n = mknode(loc, Nmatch);
+ n->match.pat = pat;
+ n->match.block = body;
+ return n;
}
Node *mkfunc(Srcloc loc, Node **args, size_t nargs, Type *ret, Node *body)
{
- Node *n;
- Node *f;
- size_t i;
+ Node *n;
+ Node *f;
+ size_t i;
- f = mknode(loc, Nfunc);
- f->func.args = args;
- f->func.nargs = nargs;
- f->func.body = body;
- f->func.scope = mkstab(1);
- f->func.type = mktyfunc(loc, args, nargs, ret);
+ f = mknode(loc, Nfunc);
+ f->func.args = args;
+ f->func.nargs = nargs;
+ f->func.body = body;
+ f->func.scope = mkstab(1);
+ f->func.type = mktyfunc(loc, args, nargs, ret);
- for (i = 0; i < nargs; i++)
- putdcl(f->func.scope, args[i]);
+ for (i = 0; i < nargs; i++)
+ putdcl(f->func.scope, args[i]);
- n = mknode(loc, Nlit);
- n->lit.littype = Lfunc;
- n->lit.fnval = f;
- return n;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lfunc;
+ n->lit.fnval = f;
+ return n;
}
Node *mkblock(Srcloc loc, Stab *scope)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nblock);
- n->block.scope = scope;
- return n;
+ n = mknode(loc, Nblock);
+ n->block.scope = scope;
+ return n;
}
-
Node *mkimplstmt(Srcloc loc, Node *name, Type *t, Node **decls, size_t ndecls)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nimpl);
- n->impl.traitname = name;
- n->impl.type = t;
- n->impl.decls = decls;
- n->impl.ndecls = ndecls;
- return n;
+ n = mknode(loc, Nimpl);
+ n->impl.traitname = name;
+ n->impl.type = t;
+ n->impl.decls = decls;
+ n->impl.ndecls = ndecls;
+ return n;
}
+Node *mkintlit(Srcloc loc, uvlong val) { return mkexpr(loc, Olit, mkint(loc, val), NULL); }
-Node *mkintlit(Srcloc loc, uvlong val)
-{
- return mkexpr(loc, Olit, mkint(loc, val), NULL);
-}
-
Node *mklbl(Srcloc loc, char *lbl)
{
- Node *n;
+ Node *n;
- assert(lbl != NULL);
- n = mknode(loc, Nlit);
- n->lit.littype = Llbl;
- n->lit.lblval = strdup(lbl);
- return mkexpr(loc, Olit, n, NULL);
+ assert(lbl != NULL);
+ n = mknode(loc, Nlit);
+ n->lit.littype = Llbl;
+ n->lit.lblval = strdup(lbl);
+ return mkexpr(loc, Olit, n, NULL);
}
char *genlblstr(char *buf, size_t sz, char *suffix)
{
- static int nextlbl;
- bprintf(buf, 128, ".L%d%s", nextlbl++, suffix);
- return buf;
+ static int nextlbl;
+ bprintf(buf, 128, ".L%d%s", nextlbl++, suffix);
+ return buf;
}
Node *genlbl(Srcloc loc)
{
- char buf[128];
+ char buf[128];
- genlblstr(buf, 128, "");
- return mklbl(loc, buf);
+ genlblstr(buf, 128, "");
+ return mklbl(loc, buf);
}
Node *mkstr(Srcloc loc, Str val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lstr;
- n->lit.strval.len = val.len;
- n->lit.strval.buf = malloc(val.len);
- memcpy(n->lit.strval.buf, val.buf, val.len);
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lstr;
+ n->lit.strval.len = val.len;
+ n->lit.strval.buf = malloc(val.len);
+ memcpy(n->lit.strval.buf, val.buf, val.len);
- return n;
+ return n;
}
Node *mkint(Srcloc loc, uint64_t val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lint;
- n->lit.intval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lint;
+ n->lit.intval = val;
- return n;
+ return n;
}
Node *mkchar(Srcloc loc, uint32_t val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lchr;
- n->lit.chrval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lchr;
+ n->lit.chrval = val;
- return n;
+ return n;
}
Node *mkfloat(Srcloc loc, double val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lflt;
- n->lit.fltval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lflt;
+ n->lit.fltval = val;
- return n;
+ return n;
}
Node *mkidxinit(Srcloc loc, Node *idx, Node *init)
{
- init->expr.idx = idx;
- return init;
+ init->expr.idx = idx;
+ return init;
}
Node *mkname(Srcloc loc, char *name)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nname);
- n->name.name = strdup(name);
+ n = mknode(loc, Nname);
+ n->name.name = strdup(name);
- return n;
+ return n;
}
Node *mknsname(Srcloc loc, char *ns, char *name)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nname);
- n->name.ns = strdup(ns);
- n->name.name = strdup(name);
+ n = mknode(loc, Nname);
+ n->name.ns = strdup(ns);
+ n->name.name = strdup(name);
- return n;
+ return n;
}
Node *mkdecl(Srcloc loc, Node *name, Type *ty)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Ndecl);
- n->decl.did = ndecls;
- n->decl.name = name;
- n->decl.type = ty;
- lappend(&decls, &ndecls, n);
- return n;
+ n = mknode(loc, Ndecl);
+ n->decl.did = ndecls;
+ n->decl.name = name;
+ n->decl.type = ty;
+ lappend(&decls, &ndecls, n);
+ return n;
}
Node *gentemp(Srcloc loc, Type *ty, Node **dcl)
{
- char buf[128];
- static int nexttmp;
- Node *t, *r, *n;
+ char buf[128];
+ static int nexttmp;
+ Node *t, *r, *n;
- bprintf(buf, 128, ".t%d", nexttmp++);
- n = mkname(loc, buf);
- t = mkdecl(loc, n, ty);
- r = mkexpr(loc, Ovar, n, NULL);
- r->expr.type = t->decl.type;
- r->expr.did = t->decl.did;
- if (dcl)
- *dcl = t;
- return r;
+ bprintf(buf, 128, ".t%d", nexttmp++);
+ n = mkname(loc, buf);
+ t = mkdecl(loc, n, ty);
+ r = mkexpr(loc, Ovar, n, NULL);
+ r->expr.type = t->decl.type;
+ r->expr.did = t->decl.did;
+ if (dcl)
+ *dcl = t;
+ return r;
}
Ucon *mkucon(Srcloc loc, Node *name, Type *ut, Type *et)
{
- Ucon *uc;
+ Ucon *uc;
- uc = zalloc(sizeof(Ucon));
- uc->loc = loc;
- uc->name = name;
- uc->utype = ut;
- uc->etype = et;
- return uc;
+ uc = zalloc(sizeof(Ucon));
+ uc->loc = loc;
+ uc->name = name;
+ uc->utype = ut;
+ uc->etype = et;
+ return uc;
}
Node *mkbool(Srcloc loc, int val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lbool;
- n->lit.boolval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lbool;
+ n->lit.boolval = val;
- return n;
+ return n;
}
char *declname(Node *n)
{
- Node *name;
- assert(n->type == Ndecl);
- name = n->decl.name;
- return name->name.name;
+ Node *name;
+ assert(n->type == Ndecl);
+ name = n->decl.name;
+ return name->name.name;
}
-Type *decltype(Node *n)
+Type *decltype(Node * n)
{
- assert(n->type == Ndecl);
- return nodetype(n);
+ assert(n->type == Ndecl);
+ return nodetype(n);
}
Type *exprtype(Node *n)
{
- assert(n->type == Nexpr);
- return nodetype(n);
+ assert(n->type == Nexpr);
+ return nodetype(n);
}
Type *nodetype(Node *n)
{
- switch (n->type) {
- case Ndecl: return n->decl.type; break;
- case Nexpr: return n->expr.type; break;
- case Nlit: return n->lit.type; break;
- default: die("Node %s has no type", nodestr[n->type]); break;
- }
- return NULL;
+ switch (n->type) {
+ case Ndecl: return n->decl.type; break;
+ case Nexpr: return n->expr.type; break;
+ case Nlit: return n->lit.type; break;
+ default: die("Node %s has no type", nodestr[n->type]); break;
+ }
+ return NULL;
}
int liteq(Node *a, Node *b)
{
- assert(a->type == Nlit && b->type == Nlit);
- if (a->lit.littype != b->lit.littype)
- return 0;
- if (!tyeq(a->lit.type, b->lit.type))
- return 0;
- switch (a->lit.littype) {
- case Lchr:
- return a->lit.chrval == b->lit.chrval;
- case Lbool:
- return a->lit.boolval == b->lit.boolval;
- case Lint:
- return a->lit.intval == b->lit.intval;
- case Lflt:
- return a->lit.fltval == b->lit.fltval;
- case Lstr:
- return a->lit.strval.len == b->lit.strval.len &&
- !memcmp(a->lit.strval.buf, b->lit.strval.buf, a->lit.strval.len);
- case Lfunc:
- return a->lit.fnval == b->lit.fnval;
- case Llbl:
- return !strcmp(a->lit.lblval, b->lit.lblval);
- break;
- }
- return 0;
+ assert(a->type == Nlit && b->type == Nlit);
+ if (a->lit.littype != b->lit.littype)
+ return 0;
+ if (!tyeq(a->lit.type, b->lit.type))
+ return 0;
+ switch (a->lit.littype) {
+ case Lchr: return a->lit.chrval == b->lit.chrval;
+ case Lbool: return a->lit.boolval == b->lit.boolval;
+ case Lint: return a->lit.intval == b->lit.intval;
+ case Lflt: return a->lit.fltval == b->lit.fltval;
+ case Lstr:
+ return a->lit.strval.len == b->lit.strval.len &&
+ !memcmp(a->lit.strval.buf, b->lit.strval.buf, a->lit.strval.len);
+ case Lfunc: return a->lit.fnval == b->lit.fnval;
+ case Llbl: return !strcmp(a->lit.lblval, b->lit.lblval); break;
+ }
+ return 0;
}
/* name hashing */
ulong namehash(void *p)
{
- Node *n;
+ Node *n;
- n = p;
- return strhash(namestr(n)) ^ strhash(n->name.ns);
+ n = p;
+ return strhash(namestr(n)) ^ strhash(n->name.ns);
}
int nameeq(void *p1, void *p2)
{
- Node *a, *b;
- a = p1;
- b = p2;
- if (a == b)
- return 1;
+ Node *a, *b;
+ a = p1;
+ b = p2;
+ if (a == b)
+ return 1;
- return streq(namestr(a), namestr(b)) && streq(a->name.ns, b->name.ns);
+ return streq(namestr(a), namestr(b)) && streq(a->name.ns, b->name.ns);
}
void setns(Node *n, char *ns)
{
- assert(!n->name.ns || !strcmp(n->name.ns, ns));
- n->name.ns = strdup(ns);
+ assert(!n->name.ns || !strcmp(n->name.ns, ns));
+ n->name.ns = strdup(ns);
}
Op exprop(Node *e)
{
- assert(e->type == Nexpr);
- return e->expr.op;
+ assert(e->type == Nexpr);
+ return e->expr.op;
}
char *namestr(Node *name)
{
- if (!name)
- return "";
- assert(name->type == Nname);
- return name->name.name;
+ if (!name)
+ return "";
+ assert(name->type == Nname);
+ return name->name.name;
}
char *lblstr(Node *n)
{
- assert(exprop(n) == Olit);
- assert(n->expr.args[0]->type == Nlit);
- assert(n->expr.args[0]->lit.littype == Llbl);
- return n->expr.args[0]->lit.lblval;
+ assert(exprop(n) == Olit);
+ assert(n->expr.args[0]->type == Nlit);
+ assert(n->expr.args[0]->lit.littype == Llbl);
+ return n->expr.args[0]->lit.lblval;
}
static size_t did(Node *n)
{
- if (n->type == Ndecl) {
- return n->decl.did;
- } else if (n->type == Nexpr) {
- assert(exprop(n) == Ovar);
- return n->expr.did;
- }
- dump(n, stderr);
- die("Can't get did");
- return 0;
+ if (n->type == Ndecl) {
+ return n->decl.did;
+ }
+ else if (n->type == Nexpr) {
+ assert(exprop(n) == Ovar);
+ return n->expr.did;
+ }
+ dump(n, stderr);
+ die("Can't get did");
+ return 0;
}
/* Hashes a Ovar expr or an Ndecl */
ulong varhash(void *dcl)
{
- /* large-prime hash. meh. */
- return did(dcl) * 366787;
+ /* large-prime hash. meh. */
+ return did(dcl) * 366787;
}
/* Checks if the did of two vars are equal */
-int vareq(void *a, void *b)
-{
- return did(a) == did(b);
-}
+int vareq(void *a, void *b) { return did(a) == did(b); }
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -1,15 +1,15 @@
#ifdef __GNUC__
-# define FATAL __attribute__((noreturn))
+#define FATAL __attribute__((noreturn))
#else
-# define FATAL
+#define FATAL
#endif
#define Abiversion 8
-typedef uint8_t byte;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-typedef long long vlong;
+typedef uint8_t byte;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef long long vlong;
typedef unsigned long long uvlong;
typedef struct Srcloc Srcloc;
@@ -28,17 +28,17 @@
typedef struct Trait Trait;
typedef enum {
- OTmisc,
- OTpre,
- OTpost,
- OTbin,
- OTzarg,
+ OTmisc,
+ OTpre,
+ OTpost,
+ OTbin,
+ OTzarg,
} Optype;
typedef enum {
#define O(op, pure, type, pretty) op,
#include "ops.def"
- Numops,
+ Numops,
#undef O
} Op;
@@ -58,7 +58,7 @@
#define Ty(t, n, stk) t,
#include "types.def"
#undef Ty
- Ntypes
+ Ntypes
} Ty;
typedef enum {
@@ -65,335 +65,337 @@
#define Tc(c, n) c,
#include "trait.def"
#undef Tc
- Ntraits
+ Ntraits
} Tc;
#define Zloc ((Srcloc){-1, 0})
struct Strbuf {
- char *buf;
- size_t sz;
- size_t len;
+ char *buf;
+ size_t sz;
+ size_t len;
};
struct Srcloc {
- int line;
- int file;
+ int line;
+ int file;
};
struct Str {
- size_t len;
- char *buf;
+ size_t len;
+ char *buf;
};
typedef enum {
- Visintern,
- Visexport,
- Vishidden,
- Visbuiltin,
+ Visintern,
+ Visexport,
+ Vishidden,
+ Visbuiltin,
} Vis;
typedef enum {
- Dclconst = 1 << 0,
- Dclextern = 1 << 1,
+ Dclconst = 1 << 0,
+ Dclextern = 1 << 1,
} Dclflags;
struct Bitset {
- size_t nchunks;
- size_t *chunks;
+ size_t nchunks;
+ size_t *chunks;
};
struct Htab {
- size_t nelt;
- size_t ndead;
- size_t sz;
- ulong (*hash)(void *k);
- int (*cmp)(void *a, void *b);
- void **keys;
- void **vals;
- ulong *hashes;
- char *dead;
+ size_t nelt;
+ size_t ndead;
+ size_t sz;
+ ulong (*hash)(void *k);
+ int (*cmp)(void *a, void *b);
+ void **keys;
+ void **vals;
+ ulong *hashes;
+ char *dead;
};
struct Tok {
- int type;
- Srcloc loc;
- char *id;
+ int type;
+ Srcloc loc;
+ char *id;
- /* values parsed out */
- vlong intval;
- Ty inttype; /* for explicitly specified suffixes */
- double fltval;
- uint32_t chrval;
- Str strval;
+ /* values parsed out */
+ vlong intval;
+ Ty inttype; /* for explicitly specified suffixes */
+ double fltval;
+ uint32_t chrval;
+ Str strval;
};
struct Stab {
- Stab *super;
- char *name;
- char isfunc;
+ Stab *super;
+ char *name;
+ char isfunc;
- /* Contents of stab.
- * types and values are in separate namespaces. */
- Htab *dcl;
- Htab *env; /* the syms we close over, if we're a function */
- Htab *ty; /* types */
- Htab *tr; /* traits */
- Htab *uc; /* union constructors */
- Htab *impl; /* trait implementations: really a set of implemented traits. */
+ /* Contents of stab.
+ * types and values are in separate namespaces. */
+ Htab *dcl;
+ Htab *env; /* the syms we close over, if we're a function */
+ Htab *ty; /* types */
+ Htab *tr; /* traits */
+ Htab *uc; /* union constructors */
+ Htab *impl; /* trait implementations: really a set of implemented traits. */
};
struct Type {
- Ty type;
- int tid;
- Srcloc loc;
- Vis vis;
+ Ty type;
+ int tid;
+ Srcloc loc;
+ Vis vis;
- int resolved; /* Have we resolved the subtypes? Prevents infinite recursion. */
- int fixed; /* Have we fixed the subtypes? Prevents infinite recursion. */
+ int resolved; /* Have we resolved the subtypes? Prevents infinite recursion. */
+ int fixed; /* Have we fixed the subtypes? Prevents infinite recursion. */
- Bitset *traits; /* the type constraints matched on this type */
- Node **traitlist; /* The names of the constraints on the type. Used to fill the bitset */
- size_t ntraitlist; /* The length of the constraint list above */
+ Bitset *traits; /* the type constraints matched on this type */
+ Node **traitlist; /* The names of the constraints on the type. Used to fill the bitset */
+ size_t ntraitlist; /* The length of the constraint list above */
- Type **gparam; /* Tygeneric: type parameters that match the type args */
- size_t ngparam; /* Tygeneric: count of type parameters */
- Type **arg; /* Tyname: type arguments instantiated */
- size_t narg; /* Tyname: count of type arguments */
- Type **inst; /* Tyname: instances created */
- size_t ninst; /* Tyname: count of instances created */
+ Type **gparam; /* Tygeneric: type parameters that match the type args */
+ size_t ngparam; /* Tygeneric: count of type parameters */
+ Type **arg; /* Tyname: type arguments instantiated */
+ size_t narg; /* Tyname: count of type arguments */
+ Type **inst; /* Tyname: instances created */
+ size_t ninst; /* Tyname: count of instances created */
- Type **sub; /* sub-types; shared by all composite types */
- size_t nsub; /* For compound types */
- size_t nmemb; /* for aggregate types (struct, union) */
- union {
- Node *name; /* Tyname: unresolved name. Tyalias: alias name */
- Node *asize; /* array size */
- char *pname; /* Typaram: name of type parameter */
- Node **sdecls; /* Tystruct: decls in struct */
- Ucon **udecls; /* Tyunion: decls in union */
- };
+ Type **sub; /* sub-types; shared by all composite types */
+ size_t nsub; /* For compound types */
+ size_t nmemb; /* for aggregate types (struct, union) */
+ union {
+ Node *name; /* Tyname: unresolved name. Tyalias: alias name */
+ Node *asize; /* array size */
+ char *pname; /* Typaram: name of type parameter */
+ Node **sdecls; /* Tystruct: decls in struct */
+ Ucon **udecls; /* Tyunion: decls in union */
+ };
- char issynth; /* Tyname: whether this is synthesized or not */
- char ishidden; /* Tyname: whether this is hidden or not */
- char ispkglocal; /* Tyname: whether this is package local or not */
- char isimport; /* Tyname: whether tyis type was imported. */
- char isreflect; /* Tyname: whether this type has reflection info */
+ char issynth; /* Tyname: whether this is synthesized or not */
+ char ishidden; /* Tyname: whether this is hidden or not */
+ char ispkglocal; /* Tyname: whether this is package local or not */
+ char isimport; /* Tyname: whether tyis type was imported. */
+ char isreflect; /* Tyname: whether this type has reflection info */
};
struct Ucon {
- Srcloc loc;
- size_t id; /* unique id */
- int synth; /* is it generated? */
- Node *name; /* ucon name */
- Type *utype; /* type of the union this is an element of */
- Type *etype; /* type for the element */
+ Srcloc loc;
+ size_t id; /* unique id */
+ int synth; /* is it generated? */
+ Node *name; /* ucon name */
+ Type *utype; /* type of the union this is an element of */
+ Type *etype; /* type for the element */
};
struct Trait {
- int uid; /* unique id */
- Srcloc loc;
- Vis vis;
+ int uid; /* unique id */
+ Srcloc loc;
+ Vis vis;
- Node *name; /* the name of the trait */
- Type *param; /* the type parameter */
- Node **memb; /* type must have these members */
- size_t nmemb;
- Node **funcs; /* and declare these funcs */
- size_t nfuncs;
+ Node *name; /* the name of the trait */
+ Type *param; /* the type parameter */
+ Node **memb; /* type must have these members */
+ size_t nmemb;
+ Node **funcs; /* and declare these funcs */
+ size_t nfuncs;
- char isproto; /* is it a prototype (for exporting purposes) */
- char ishidden; /* should user code be able to use this? */
+ char isproto; /* is it a prototype (for exporting purposes) */
+ char ishidden; /* should user code be able to use this? */
};
struct Node {
- Srcloc loc;
- Ntype type;
- int nid;
- union {
- struct {
- size_t nfiles; /* file names for location mapping */
- char **files;
- Node **uses; /* use files that we loaded */
- size_t nuses;
- char **libdeps; /* library dependencies */
- size_t nlibdeps;
- char **extlibs; /* non-myrddin libraries */
- size_t nextlibs;
- Node **stmts; /* all top level statements */
- size_t nstmts;
- Node **init; /* a list of all __init__ function names of our deps. NB, this is a Nname, not an Ndecl */
- size_t ninit;
- Node *localinit; /* and the local one, if any */
- Stab *globls; /* global symtab */
- Htab *ns; /* namespaces */
- } file;
+ Srcloc loc;
+ Ntype type;
+ int nid;
+ union {
+ struct {
+ size_t nfiles; /* file names for location mapping */
+ char **files;
+ Node **uses; /* use files that we loaded */
+ size_t nuses;
+ char **libdeps; /* library dependencies */
+ size_t nlibdeps;
+ char **extlibs; /* non-myrddin libraries */
+ size_t nextlibs;
+ Node **stmts; /* all top level statements */
+ size_t nstmts;
+ Node
+ **init; /* a list of all __init__ function names of our deps. NB, this
+ is a Nname, not an Ndecl */
+ size_t ninit;
+ Node *localinit; /* and the local one, if any */
+ Stab *globls; /* global symtab */
+ Htab *ns; /* namespaces */
+ } file;
- struct {
- Op op;
- Type *type;
- int isconst;
- size_t did; /* for Ovar, we want a mapping to the decl id */
- size_t nargs;
- Node *idx; /* used when this is in an indexed initializer */
- Node **args;
- } expr;
+ struct {
+ Op op;
+ Type *type;
+ int isconst;
+ size_t did; /* for Ovar, we want a mapping to the decl id */
+ size_t nargs;
+ Node *idx; /* used when this is in an indexed initializer */
+ Node **args;
+ } expr;
- struct {
- char *ns;
- char *name;
- } name;
+ struct {
+ char *ns;
+ char *name;
+ } name;
- struct {
- int islocal;
- char *name;
- } use;
+ struct {
+ int islocal;
+ char *name;
+ } use;
- struct {
- Littype littype;
- Type *type;
- size_t nelt;
- union {
- uvlong intval;
- double fltval;
- uint32_t chrval;
- Str strval;
- char *lblval;
- int boolval;
- Node *fnval;
- };
- } lit;
+ struct {
+ Littype littype;
+ Type *type;
+ size_t nelt;
+ union {
+ uvlong intval;
+ double fltval;
+ uint32_t chrval;
+ Str strval;
+ char *lblval;
+ int boolval;
+ Node *fnval;
+ };
+ } lit;
- struct {
- Node *init;
- Node *cond;
- Node *step;
- Node *body;
- Stab *scope;
- } loopstmt;
+ struct {
+ Node *init;
+ Node *cond;
+ Node *step;
+ Node *body;
+ Stab *scope;
+ } loopstmt;
- struct {
- Node *elt;
- Node *seq;
- Node *body;
- } iterstmt;
+ struct {
+ Node *elt;
+ Node *seq;
+ Node *body;
+ } iterstmt;
- struct {
- Node *cond;
- Node *iftrue;
- Node *iffalse;
- } ifstmt;
+ struct {
+ Node *cond;
+ Node *iftrue;
+ Node *iffalse;
+ } ifstmt;
- struct {
- Node *val;
- size_t nmatches;
- Node **matches;
- } matchstmt;
+ struct {
+ Node *val;
+ size_t nmatches;
+ Node **matches;
+ } matchstmt;
- struct {
- Node *pat;
- Node *block;
- } match;
+ struct {
+ Node *pat;
+ Node *block;
+ } match;
- struct {
- Stab *scope;
- size_t nstmts;
- Node **stmts;
- } block;
+ struct {
+ Stab *scope;
+ size_t nstmts;
+ Node **stmts;
+ } block;
- struct {
- size_t did;
- Node *name;
- Type *type;
- Node *init;
- /*
- If we have a link to a trait, we should only look it up
- when specializing, but we should not create a new decl
- node for it. That will be done when specializing the
- impl.
- */
- Trait *trait;
- char vis;
+ struct {
+ size_t did;
+ Node *name;
+ Type *type;
+ Node *init;
+ /*
+ If we have a link to a trait, we should only look it up
+ when specializing, but we should not create a new decl
+ node for it. That will be done when specializing the
+ impl.
+ */
+ Trait *trait;
+ char vis;
- /* flags */
- char isglobl;
- char isconst;
- char isgeneric;
- char isextern;
- char ispkglocal;
- char ishidden;
- char isimport;
- char isnoret;
- char isexportinit;
- char isinit;
- } decl;
+ /* flags */
+ char isglobl;
+ char isconst;
+ char isgeneric;
+ char isextern;
+ char ispkglocal;
+ char ishidden;
+ char isimport;
+ char isnoret;
+ char isexportinit;
+ char isinit;
+ } decl;
- struct {
- long uid;
- Node *name;
- Type *elt;
- Type *alt;
- } uelt;
+ struct {
+ long uid;
+ Node *name;
+ Type *elt;
+ Type *alt;
+ } uelt;
- struct {
- Stab *scope;
- Type *type;
- size_t nargs;
- Node **args;
- Node *body;
- } func;
+ struct {
+ Stab *scope;
+ Type *type;
+ size_t nargs;
+ Node **args;
+ Node *body;
+ } func;
- struct {
- Node *name;
- size_t traitid;
+ struct {
+ Node *name;
+ size_t traitid;
- Node **funcs;
- size_t nfuncs;
- Node **membs;
- size_t nmembs;
- } trait;
+ Node **funcs;
+ size_t nfuncs;
+ Node **membs;
+ size_t nmembs;
+ } trait;
- struct {
- Node *traitname;
- Trait *trait;
- Type *type;
- Node **decls;
- size_t ndecls;
- Vis vis;
- char isproto;
- } impl;
- };
+ struct {
+ Node *traitname;
+ Trait *trait;
+ Type *type;
+ Node **decls;
+ size_t ndecls;
+ Vis vis;
+ char isproto;
+ } impl;
+ };
};
struct Optctx {
- /* public exports */
- char *optarg;
- char **args;
- size_t nargs;
+ /* public exports */
+ char *optarg;
+ char **args;
+ size_t nargs;
- /* internal state */
- char *optstr;
- char **optargs;
- size_t noptargs;
- size_t argidx;
- int optdone; /* seen -- */
- int finished;
- char *curarg;
+ /* internal state */
+ char *optstr;
+ char **optargs;
+ size_t noptargs;
+ size_t argidx;
+ int optdone; /* seen -- */
+ int finished;
+ char *curarg;
};
/* globals */
extern Srcloc curloc;
extern char *filename;
-extern Tok *curtok; /* the last token we tokenized */
-extern Node *file; /* the current file we're compiling */
-extern Type **tytab; /* type -> type map used by inference. size maintained by type creation code */
+extern Tok *curtok; /* the last token we tokenized */
+extern Node *file; /* the current file we're compiling */
+extern Type **tytab; /* type -> type map used by inference. size maintained by type creation code */
extern Type **types;
extern size_t ntypes;
-extern Trait **traittab; /* int -> trait map */
+extern Trait **traittab; /* int -> trait map */
extern size_t ntraittab;
-extern Node **decls; /* decl id -> decl map */
+extern Node **decls; /* decl id -> decl map */
extern size_t nnodes;
-extern Node **nodes; /* node id -> node map */
+extern Node **nodes; /* node id -> node map */
extern size_t ndecls;
extern Node **exportimpls;
extern size_t nexportimpls;
@@ -409,7 +411,7 @@
/* data structures */
Bitset *mkbs(void);
-void bsfree(Bitset *bs);
+void bsfree(Bitset *bs);
Bitset *bsdup(Bitset *bs);
Bitset *bsclear(Bitset *bs);
void delbs(Bitset *bs);
@@ -418,18 +420,19 @@
void bsunion(Bitset *a, Bitset *b);
void bsintersect(Bitset *a, Bitset *b);
void bsdiff(Bitset *a, Bitset *b);
-int bseq(Bitset *a, Bitset *b);
-int bsissubset(Bitset *set, Bitset *sub);
-int bsisempty(Bitset *set);
-int bsiter(Bitset *bs, size_t *elt);
+int bseq(Bitset *a, Bitset *b);
+int bsissubset(Bitset *set, Bitset *sub);
+int bsisempty(Bitset *set);
+int bsiter(Bitset *bs, size_t *elt);
size_t bsmax(Bitset *bs);
size_t bscount(Bitset *bs);
/* inline for speed */
static inline int bshas(Bitset *bs, size_t elt)
{
- if (elt >= bs->nchunks*8*sizeof(size_t))
- return 0;
- return (bs->chunks[elt/(8*sizeof(size_t))] & (1ULL << (elt % (8*sizeof(size_t))))) != 0;
+ if (elt >= bs->nchunks * 8 * sizeof(size_t))
+ return 0;
+ return (bs->chunks[elt / (8 * sizeof(size_t))] & (1ULL << (elt % (8 * sizeof(size_t))))) !=
+ 0;
}
Htab *mkht(ulong (*hash)(void *key), int (*cmp)(void *k1, void *k2));
@@ -519,15 +522,16 @@
Type *mktyfunc(Srcloc l, Node **args, size_t nargs, Type *ret);
Type *mktystruct(Srcloc l, Node **decls, size_t ndecls);
Type *mktyunion(Srcloc l, Ucon **decls, size_t ndecls);
-Trait *mktrait(Srcloc l, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto);
+Trait *mktrait(Srcloc l, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs,
+ size_t nfuncs, int isproto);
Type *mktylike(Srcloc l, Ty ty); /* constrains tyvar t like it was builtin ty */
Ucon *finducon(Type *t, Node *name);
-int isstacktype(Type *t);
-int istysigned(Type *t);
-int istyunsigned(Type *t);
-int istyfloat(Type *t);
-int istyprimitive(Type *t);
-int hasparams(Type *t);
+int isstacktype(Type *t);
+int istysigned(Type *t);
+int istyunsigned(Type *t);
+int istyfloat(Type *t);
+int istyprimitive(Type *t);
+int hasparams(Type *t);
/* type manipulation */
Type *tybase(Type *t);
@@ -580,7 +584,7 @@
char *namestr(Node *name);
char *lblstr(Node *n);
char *declname(Node *n);
-Type *decltype(Node *n);
+Type *decltype(Node * n);
Type *exprtype(Node *n);
Type *nodetype(Node *n);
void addstmt(Node *file, Node *stmt);
@@ -597,7 +601,7 @@
void geninit(Node *file);
/* usefiles */
-int loaduse(char *path, FILE *f, Stab *into, Vis vis);
+int loaduse(char *path, FILE *f, Stab *into, Vis vis);
void readuse(Node *use, Stab *into, Vis vis);
void writeuse(FILE *fd, Node *file);
void tagexports(Node *file, int hidelocal);
@@ -618,7 +622,8 @@
int optdone(Optctx *c);
/* convenience funcs */
-void lappend(void *l, size_t *len, void *n); /* hack; nl is void* b/c void*** is incompatible with T*** */
+/* hack; nl is void* b/c void*** is incompatible with T*** */
+void lappend( void *l, size_t *len, void *n);
void lcat(void *dst, size_t *ndst, void *src, size_t nsrc);
void linsert(void *l, size_t *len, size_t idx, void *n);
void *lpop(void *l, size_t *len);
@@ -630,8 +635,8 @@
vlong host64(byte buf[8]);
void be32(long v, byte buf[4]);
long host32(byte buf[4]);
-static inline intptr_t ptoi(void *p) {return (intptr_t)p;}
-static inline void* itop(intptr_t i) {return (void*)i;}
+static inline intptr_t ptoi(void *p) { return (intptr_t)p; }
+static inline void *itop(intptr_t i) { return (void *)i; }
void wrbuf(FILE *fd, void *buf, size_t sz);
void rdbuf(FILE *fd, void *buf, size_t sz);
@@ -665,7 +670,7 @@
/* indented printf */
void indentf(int depth, char *fmt, ...);
void findentf(FILE *fd, int depth, char *fmt, ...);
-void vfindentf(FILE *fd, int depth, char *fmt, va_list ap);
+void vfindentf(FILE *fd, int depth, char *fmt, va_list ap);
/* Options to control the compilation */
extern char debugopt[128];
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -16,11 +16,11 @@
void addtraits(Type *t, Bitset *traits)
{
- size_t b;
+ size_t b;
- if (traits)
- for (b = 0; bsiter(traits, &b); b++)
- settrait(t, traittab[b]);
+ if (traits)
+ for (b = 0; bsiter(traits, &b); b++)
+ settrait(t, traittab[b]);
}
/*
@@ -34,78 +34,80 @@
* against */
Type *tyspecialize(Type *t, Htab *tsmap, Htab *delayed)
{
- Type *ret, *tmp, **arg;
- size_t i, narg;
+ Type *ret, *tmp, **arg;
+ size_t i, narg;
- t = tysearch(t);
- if (hthas(tsmap, t))
- return htget(tsmap, t);
- arg = NULL;
- narg = 0;
- switch (t->type) {
- case Typaram:
- ret = mktyvar(t->loc);
- addtraits(ret, t->traits);
- htput(tsmap, t, ret);
- break;
- case Tygeneric:
- ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
- ret->issynth = 1;
- htput(tsmap, t, ret);
- for (i = 0; i < t->ngparam; i++)
- lappend(&ret->arg, &ret->narg, tyspecialize(t->gparam[i], tsmap, delayed));
- break;
- case Tyname:
- if (!hasparams(t))
- return t;
- for (i = 0; i < t->narg; i++)
- lappend(&arg, &narg, tyspecialize(t->arg[i], tsmap, delayed));
- ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
- ret->arg = arg;
- ret->narg = narg;
- break;
- case Tystruct:
- ret = tydup(t);
- htput(tsmap, t, ret);
- pushstab(NULL);
- for (i = 0; i < t->nmemb; i++)
- ret->sdecls[i] = specializenode(t->sdecls[i], tsmap);
- popstab();
- break;
- case Tyunion:
- ret = tydup(t);
- htput(tsmap, t, ret);
- for (i = 0; i < t->nmemb; i++) {
- tmp = NULL;
- if (ret->udecls[i]->etype)
- tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
- ret->udecls[i] = mkucon(t->loc, t->udecls[i]->name, ret, tmp);
- ret->udecls[i]->utype = ret;
- ret->udecls[i]->id = i;
- ret->udecls[i]->synth = 1;
- }
- break;
- case Tyvar:
- if (delayed && hthas(delayed, t)) {
- ret = tydup(t);
- tmp = htget(delayed, t);
- htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
- } else {
- ret = t;
- }
- break;
- default:
- if (t->nsub > 0) {
- ret = tydup(t);
- htput(tsmap, t, ret);
- for (i = 0; i < t->nsub; i++)
- ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
- } else {
- ret = t;
- }
- break;
- }
- return ret;
+ t = tysearch(t);
+ if (hthas(tsmap, t))
+ return htget(tsmap, t);
+ arg = NULL;
+ narg = 0;
+ switch (t->type) {
+ case Typaram:
+ ret = mktyvar(t->loc);
+ addtraits(ret, t->traits);
+ htput(tsmap, t, ret);
+ break;
+ case Tygeneric:
+ ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
+ ret->issynth = 1;
+ htput(tsmap, t, ret);
+ for (i = 0; i < t->ngparam; i++)
+ lappend(&ret->arg, &ret->narg, tyspecialize(t->gparam[i], tsmap, delayed));
+ break;
+ case Tyname:
+ if (!hasparams(t))
+ return t;
+ for (i = 0; i < t->narg; i++)
+ lappend(&arg, &narg, tyspecialize(t->arg[i], tsmap, delayed));
+ ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
+ ret->arg = arg;
+ ret->narg = narg;
+ break;
+ case Tystruct:
+ ret = tydup(t);
+ htput(tsmap, t, ret);
+ pushstab(NULL);
+ for (i = 0; i < t->nmemb; i++)
+ ret->sdecls[i] = specializenode(t->sdecls[i], tsmap);
+ popstab();
+ break;
+ case Tyunion:
+ ret = tydup(t);
+ htput(tsmap, t, ret);
+ for (i = 0; i < t->nmemb; i++) {
+ tmp = NULL;
+ if (ret->udecls[i]->etype)
+ tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
+ ret->udecls[i] = mkucon(t->loc, t->udecls[i]->name, ret, tmp);
+ ret->udecls[i]->utype = ret;
+ ret->udecls[i]->id = i;
+ ret->udecls[i]->synth = 1;
+ }
+ break;
+ case Tyvar:
+ if (delayed && hthas(delayed, t)) {
+ ret = tydup(t);
+ tmp = htget(delayed, t);
+ htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
+ }
+ else {
+ ret = t;
+ }
+ break;
+ default:
+ if (t->nsub > 0) {
+ ret = tydup(t);
+ htput(tsmap, t, ret);
+ for (i = 0; i < t->nsub; i++)
+ ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
+ }
+ else {
+ ret = t;
+ }
+ break;
+ }
+ return ret;
}
/* Checks if the type 't' is generic, and if it is
@@ -113,33 +115,33 @@
* so we don't gratuitously duplicate types */
static Type *tysubst(Type *t, Htab *tsmap)
{
- if (hasparams(t))
- return tyspecialize(t, tsmap, NULL);
- else
- return t;
+ if (hasparams(t))
+ return tyspecialize(t, tsmap, NULL);
+ else
+ return t;
}
-/*
+/*
* Fills the substitution map with a mapping from
* the type parameter 'from' to it's substititon 'to'
*/
static void fillsubst(Htab *tsmap, Type *to, Type *from)
{
- size_t i;
+ size_t i;
- if (from->type == Typaram) {
- if (debugopt['S'])
- printf("mapping %s => %s\n", tystr(from), tystr(to));
- htput(tsmap, from, to);
- return;
- }
- assert(to->nsub == from->nsub);
- for (i = 0; i < to->nsub; i++)
- fillsubst(tsmap, to->sub[i], from->sub[i]);
- if (to->type == Tyname && to->narg > 0) {
- for (i = 0; i < to->narg; i++)
- fillsubst(tsmap, to->arg[i], from->arg[i]);
- }
+ if (from->type == Typaram) {
+ if (debugopt['S'])
+ printf("mapping %s => %s\n", tystr(from), tystr(to));
+ htput(tsmap, from, to);
+ return;
+ }
+ assert(to->nsub == from->nsub);
+ for (i = 0; i < to->nsub; i++)
+ fillsubst(tsmap, to->sub[i], from->sub[i]);
+ if (to->type == Tyname && to->narg > 0) {
+ for (i = 0; i < to->narg; i++)
+ fillsubst(tsmap, to->arg[i], from->arg[i]);
+ }
}
/*
@@ -148,98 +150,94 @@
*/
static void fixup(Node *n)
{
- size_t i;
- Node *d;
- Stab *ns;
+ size_t i;
+ Node *d;
+ Stab *ns;
- if (!n)
- return;
- switch (n->type) {
- case Nfile:
- case Nuse:
- die("Node %s not allowed here\n", nodestr[n->type]);
- break;
- case Nexpr:
- fixup(n->expr.idx);
- for (i = 0; i < n->expr.nargs; i++)
- fixup(n->expr.args[i]);
- if (n->expr.op == Ovar) {
- ns = curstab();
- if (n->expr.args[0]->name.ns)
- ns = getns(file, n->expr.args[0]->name.ns);
- if (!ns)
- fatal(n, "No namespace %s\n", n->expr.args[0]->name.ns);
- d = getdcl(ns, n->expr.args[0]);
- if (!d)
- die("Missing decl %s", namestr(n->expr.args[0]));
- if (d->decl.isgeneric)
- d = specializedcl(d, n->expr.type, &n->expr.args[0]);
- n->expr.did = d->decl.did;
- }
- break;
- case Nlit:
- switch (n->lit.littype) {
- case Lfunc: fixup(n->lit.fnval); break;
- case Lchr: case Lint: case Lflt:
- case Lstr: case Llbl: case Lbool:
- break;
- }
- break;
- case Nifstmt:
- fixup(n->ifstmt.cond);
- fixup(n->ifstmt.iftrue);
- fixup(n->ifstmt.iffalse);
- break;
- case Nloopstmt:
- pushstab(n->loopstmt.scope);
- fixup(n->loopstmt.init);
- fixup(n->loopstmt.cond);
- fixup(n->loopstmt.step);
- fixup(n->loopstmt.body);
- popstab();
- break;
- case Niterstmt:
- pushstab(n->iterstmt.body->block.scope);
- fixup(n->iterstmt.elt);
- popstab();
- fixup(n->iterstmt.seq);
- fixup(n->iterstmt.body);
- break;
- case Nmatchstmt:
- fixup(n->matchstmt.val);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- fixup(n->matchstmt.matches[i]);
- break;
- case Nmatch:
- /* patterns are evaluated in their block's scope */
- pushstab(n->match.block->block.scope);
- fixup(n->match.pat);
- popstab();
- fixup(n->match.block);
- break;
- case Nblock:
- pushstab(n->block.scope);
- for (i = 0; i < n->block.nstmts; i++)
- fixup(n->block.stmts[i]);
- popstab();
- break;
- case Ndecl:
- fixup(n->decl.init);
- break;
- case Nfunc:
- pushstab(n->func.scope);
- fixup(n->func.body);
- popstab();
- break;
- case Nnone: case Nname:
- break;
- case Nimpl:
- die("trait/impl not implemented");
- break;
- }
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nfile:
+ case Nuse: die("Node %s not allowed here\n", nodestr[n->type]); break;
+ case Nexpr:
+ fixup(n->expr.idx);
+ for (i = 0; i < n->expr.nargs; i++)
+ fixup(n->expr.args[i]);
+ if (n->expr.op == Ovar) {
+ ns = curstab();
+ if (n->expr.args[0]->name.ns)
+ ns = getns(file, n->expr.args[0]->name.ns);
+ if (!ns)
+ fatal(n, "No namespace %s\n", n->expr.args[0]->name.ns);
+ d = getdcl(ns, n->expr.args[0]);
+ if (!d)
+ die("Missing decl %s", namestr(n->expr.args[0]));
+ if (d->decl.isgeneric)
+ d = specializedcl(d, n->expr.type, &n->expr.args[0]);
+ n->expr.did = d->decl.did;
+ }
+ break;
+ case Nlit:
+ switch (n->lit.littype) {
+ case Lfunc: fixup(n->lit.fnval); break;
+ case Lchr:
+ case Lint:
+ case Lflt:
+ case Lstr:
+ case Llbl:
+ case Lbool: break;
+ }
+ break;
+ case Nifstmt:
+ fixup(n->ifstmt.cond);
+ fixup(n->ifstmt.iftrue);
+ fixup(n->ifstmt.iffalse);
+ break;
+ case Nloopstmt:
+ pushstab(n->loopstmt.scope);
+ fixup(n->loopstmt.init);
+ fixup(n->loopstmt.cond);
+ fixup(n->loopstmt.step);
+ fixup(n->loopstmt.body);
+ popstab();
+ break;
+ case Niterstmt:
+ pushstab(n->iterstmt.body->block.scope);
+ fixup(n->iterstmt.elt);
+ popstab();
+ fixup(n->iterstmt.seq);
+ fixup(n->iterstmt.body);
+ break;
+ case Nmatchstmt:
+ fixup(n->matchstmt.val);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ fixup(n->matchstmt.matches[i]);
+ break;
+ case Nmatch:
+ /* patterns are evaluated in their block's scope */
+ pushstab(n->match.block->block.scope);
+ fixup(n->match.pat);
+ popstab();
+ fixup(n->match.block);
+ break;
+ case Nblock:
+ pushstab(n->block.scope);
+ for (i = 0; i < n->block.nstmts; i++)
+ fixup(n->block.stmts[i]);
+ popstab();
+ break;
+ case Ndecl: fixup(n->decl.init); break;
+ case Nfunc:
+ pushstab(n->func.scope);
+ fixup(n->func.body);
+ popstab();
+ break;
+ case Nnone:
+ case Nname: break;
+ case Nimpl: die("trait/impl not implemented"); break;
+ }
}
-
/*
* Duplicates a node, replacing all things that
* need to be specialized to make it concrete
@@ -247,142 +245,141 @@
*/
static Node *specializenode(Node *n, Htab *tsmap)
{
- Node *r;
- size_t i;
+ Node *r;
+ size_t i;
- if (!n)
- return NULL;
- r = mknode(n->loc, n->type);
- switch (n->type) {
- case Nfile:
- case Nuse:
- die("Node %s not allowed here\n", nodestr[n->type]);
- break;
- case Nexpr:
- r->expr.op = n->expr.op;
- r->expr.type = tysubst(n->expr.type, tsmap);
- r->expr.isconst = n->expr.isconst;
- r->expr.nargs = n->expr.nargs;
- r->expr.idx = specializenode(n->expr.idx, tsmap);
- r->expr.args = xalloc(n->expr.nargs * sizeof(Node*));
- for (i = 0; i < n->expr.nargs; i++)
- r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
- break;
- case Nname:
- if (n->name.ns)
- r->name.ns = strdup(n->name.ns);
- r->name.name = strdup(n->name.name);
- break;
- case Nlit:
- r->lit.littype = n->lit.littype;
- r->lit.type = tysubst(n->expr.type, tsmap);
- switch (n->lit.littype) {
- case Lchr: r->lit.chrval = n->lit.chrval; break;
- case Lint: r->lit.intval = n->lit.intval; break;
- case Lflt: r->lit.fltval = n->lit.fltval; break;
- case Lstr: r->lit.strval = n->lit.strval; break;
- case Llbl: r->lit.lblval = n->lit.lblval; break;
- case Lbool: r->lit.boolval = n->lit.boolval; break;
- case Lfunc: r->lit.fnval = specializenode(n->lit.fnval, tsmap); break;
- }
- break;
- case Nifstmt:
- r->ifstmt.cond = specializenode(n->ifstmt.cond, tsmap);
- r->ifstmt.iftrue = specializenode(n->ifstmt.iftrue, tsmap);
- r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
- break;
- case Nloopstmt:
- r->loopstmt.scope = mkstab(0);
- r->loopstmt.scope->super = curstab();
- pushstab(r->loopstmt.scope);
- r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
- r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
- r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
- r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
- popstab();
- break;
- case Niterstmt:
- r->iterstmt.elt = specializenode(n->iterstmt.elt, tsmap);
- r->iterstmt.seq = specializenode(n->iterstmt.seq, tsmap);
- r->iterstmt.body = specializenode(n->iterstmt.body, tsmap);
- break;
- case Nmatchstmt:
- r->matchstmt.val = specializenode(n->matchstmt.val, tsmap);
- r->matchstmt.nmatches = n->matchstmt.nmatches;
- r->matchstmt.matches = xalloc(n->matchstmt.nmatches * sizeof(Node*));
- for (i = 0; i < n->matchstmt.nmatches; i++)
- r->matchstmt.matches[i] = specializenode(n->matchstmt.matches[i], tsmap);
- break;
- case Nmatch:
- r->match.pat = specializenode(n->match.pat, tsmap);
- r->match.block = specializenode(n->match.block, tsmap);
- break;
- case Nblock:
- r->block.scope = mkstab(0);
- r->block.scope->super = curstab();
- pushstab(r->block.scope);
- r->block.nstmts = n->block.nstmts;
- r->block.stmts = xalloc(sizeof(Node *)*n->block.nstmts);
- for (i = 0; i < n->block.nstmts; i++)
- r->block.stmts[i] = specializenode(n->block.stmts[i], tsmap);
- popstab();
- break;
- case Ndecl:
- r->decl.did = ndecls;
- /* sym */
- r->decl.name = specializenode(n->decl.name, tsmap);
- r->decl.type = tysubst(n->decl.type, tsmap);
+ if (!n)
+ return NULL;
+ r = mknode(n->loc, n->type);
+ switch (n->type) {
+ case Nfile:
+ case Nuse: die("Node %s not allowed here\n", nodestr[n->type]); break;
+ case Nexpr:
+ r->expr.op = n->expr.op;
+ r->expr.type = tysubst(n->expr.type, tsmap);
+ r->expr.isconst = n->expr.isconst;
+ r->expr.nargs = n->expr.nargs;
+ r->expr.idx = specializenode(n->expr.idx, tsmap);
+ r->expr.args = xalloc(n->expr.nargs * sizeof(Node *));
+ for (i = 0; i < n->expr.nargs; i++)
+ r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
+ break;
+ case Nname:
+ if (n->name.ns)
+ r->name.ns = strdup(n->name.ns);
+ r->name.name = strdup(n->name.name);
+ break;
+ case Nlit:
+ r->lit.littype = n->lit.littype;
+ r->lit.type = tysubst(n->expr.type, tsmap);
+ switch (n->lit.littype) {
+ case Lchr: r->lit.chrval = n->lit.chrval; break;
+ case Lint: r->lit.intval = n->lit.intval; break;
+ case Lflt: r->lit.fltval = n->lit.fltval; break;
+ case Lstr: r->lit.strval = n->lit.strval; break;
+ case Llbl: r->lit.lblval = n->lit.lblval; break;
+ case Lbool: r->lit.boolval = n->lit.boolval; break;
+ case Lfunc: r->lit.fnval = specializenode(n->lit.fnval, tsmap); break;
+ }
+ break;
+ case Nifstmt:
+ r->ifstmt.cond = specializenode(n->ifstmt.cond, tsmap);
+ r->ifstmt.iftrue = specializenode(n->ifstmt.iftrue, tsmap);
+ r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
+ break;
+ case Nloopstmt:
+ r->loopstmt.scope = mkstab(0);
+ r->loopstmt.scope->super = curstab();
+ pushstab(r->loopstmt.scope);
+ r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
+ r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
+ r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
+ r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
+ popstab();
+ break;
+ case Niterstmt:
+ r->iterstmt.elt = specializenode(n->iterstmt.elt, tsmap);
+ r->iterstmt.seq = specializenode(n->iterstmt.seq, tsmap);
+ r->iterstmt.body = specializenode(n->iterstmt.body, tsmap);
+ break;
+ case Nmatchstmt:
+ r->matchstmt.val = specializenode(n->matchstmt.val, tsmap);
+ r->matchstmt.nmatches = n->matchstmt.nmatches;
+ r->matchstmt.matches = xalloc(n->matchstmt.nmatches * sizeof(Node *));
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ r->matchstmt.matches[i] = specializenode(n->matchstmt.matches[i], tsmap);
+ break;
+ case Nmatch:
+ r->match.pat = specializenode(n->match.pat, tsmap);
+ r->match.block = specializenode(n->match.block, tsmap);
+ break;
+ case Nblock:
+ r->block.scope = mkstab(0);
+ r->block.scope->super = curstab();
+ pushstab(r->block.scope);
+ r->block.nstmts = n->block.nstmts;
+ r->block.stmts = xalloc(sizeof(Node *) * n->block.nstmts);
+ for (i = 0; i < n->block.nstmts; i++)
+ r->block.stmts[i] = specializenode(n->block.stmts[i], tsmap);
+ popstab();
+ break;
+ case Ndecl:
+ r->decl.did = ndecls;
+ /* sym */
+ r->decl.name = specializenode(n->decl.name, tsmap);
+ r->decl.type = tysubst(n->decl.type, tsmap);
+
+ /* symflags */
+ r->decl.isconst = n->decl.isconst;
+ r->decl.isgeneric = n->decl.isgeneric;
+ r->decl.isextern = n->decl.isextern;
+ r->decl.isglobl = n->decl.isglobl;
+ if (curstab())
+ putdcl(curstab(), r);
- /* symflags */
- r->decl.isconst = n->decl.isconst;
- r->decl.isgeneric = n->decl.isgeneric;
- r->decl.isextern = n->decl.isextern;
- r->decl.isglobl = n->decl.isglobl;
- if (curstab())
- putdcl(curstab(), r);
-
- /* init */
- r->decl.init = specializenode(n->decl.init, tsmap);
- lappend(&decls, &ndecls, r);
- break;
- case Nfunc:
- r->func.scope = mkstab(0);
- r->func.scope->super = curstab();
- pushstab(r->func.scope);
- r->func.type = tysubst(n->func.type, tsmap);
- r->func.nargs = n->func.nargs;
- r->func.args = xalloc(sizeof(Node *)*n->func.nargs);
- for (i = 0; i < n->func.nargs; i++)
- r->func.args[i] = specializenode(n->func.args[i], tsmap);
- r->func.body = specializenode(n->func.body, tsmap);
- popstab();
- break;
- case Nimpl:
- die("trait/impl not implemented");
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
- return r;
+ /* init */
+ r->decl.init = specializenode(n->decl.init, tsmap);
+ lappend(&decls, &ndecls, r);
+ break;
+ case Nfunc:
+ r->func.scope = mkstab(0);
+ r->func.scope->super = curstab();
+ pushstab(r->func.scope);
+ r->func.type = tysubst(n->func.type, tsmap);
+ r->func.nargs = n->func.nargs;
+ r->func.args = xalloc(sizeof(Node *) * n->func.nargs);
+ for (i = 0; i < n->func.nargs; i++)
+ r->func.args[i] = specializenode(n->func.args[i], tsmap);
+ r->func.body = specializenode(n->func.body, tsmap);
+ popstab();
+ break;
+ case Nimpl:
+ die("trait/impl not implemented");
+ break;
+ case Nnone:
+ die("Nnone should not be seen as node type!");
+ break;
+ }
+ return r;
}
Node *genericname(Node *n, Type *t)
{
- char buf[1024];
- char *p;
- char *end;
- Node *name;
+ char buf[1024];
+ char *p;
+ char *end;
+ Node *name;
- if (!n->decl.isgeneric)
- return n->decl.name;
- p = buf;
- end = buf + sizeof buf;
- p += bprintf(p, end - p, "%s", n->decl.name->name.name);
- p += bprintf(p, end - p, "$");
- p += tyidfmt(p, end - p, t);
- name = mkname(n->loc, buf);
- if (n->decl.name->name.ns)
- setns(name, n->decl.name->name.ns);
- return name;
+ if (!n->decl.isgeneric)
+ return n->decl.name;
+ p = buf;
+ end = buf + sizeof buf;
+ p += bprintf(p, end - p, "%s", n->decl.name->name.name);
+ p += bprintf(p, end - p, "$");
+ p += tyidfmt(p, end - p, t);
+ name = mkname(n->loc, buf);
+ if (n->decl.name->name.ns)
+ setns(name, n->decl.name->name.ns);
+ return name;
}
/*
@@ -392,53 +389,54 @@
*/
Node *specializedcl(Node *g, Type *to, Node **name)
{
- extern int stabstkoff;
- Node *d, *n;
- Htab *tsmap;
- Stab *st;
+ extern int stabstkoff;
+ Node *d, *n;
+ Htab *tsmap;
+ Stab *st;
- assert(g->type == Ndecl);
- assert(g->decl.isgeneric);
-
- n = genericname(g, to);
- *name = n;
- if (n->name.ns)
- st = getns(file, n->name.ns);
- else
- st = file->file.globls;
- if (!st)
- fatal(n, "Can't find symbol table for %s.%s", n->name.ns, n->name.name);
- d = getdcl(st, n);
- if (debugopt['S'])
- printf("depth[%d] specializing [%d]%s => %s\n", stabstkoff, g->loc.line, namestr(g->decl.name), namestr(n));
- if (d)
- return d;
- if (g->decl.trait) {
- printf("%s\n", namestr(n));
- fatal(g, "No trait implemented for for %s:%s", namestr(g->decl.name), tystr(to));
- }
- /* namespaced names need to be looked up in their correct
- * context. */
- if (n->name.ns)
- pushstab(st);
+ assert(g->type == Ndecl);
+ assert(g->decl.isgeneric);
- /* specialize */
- tsmap = mkht(tyhash, tyeq);
- fillsubst(tsmap, to, g->decl.type);
+ n = genericname(g, to);
+ *name = n;
+ if (n->name.ns)
+ st = getns(file, n->name.ns);
+ else
+ st = file->file.globls;
+ if (!st)
+ fatal(n, "Can't find symbol table for %s.%s", n->name.ns, n->name.name);
+ d = getdcl(st, n);
+ if (debugopt['S'])
+ printf("depth[%d] specializing [%d]%s => %s\n", stabstkoff, g->loc.line,
+ namestr(g->decl.name), namestr(n));
+ if (d)
+ return d;
+ if (g->decl.trait) {
+ printf("%s\n", namestr(n));
+ fatal(g, "No trait implemented for for %s:%s", namestr(g->decl.name), tystr(to));
+ }
+ /* namespaced names need to be looked up in their correct
+ * context. */
+ if (n->name.ns)
+ pushstab(st);
- d = mkdecl(g->loc, n, tysubst(g->decl.type, tsmap));
- d->decl.isconst = g->decl.isconst;
- d->decl.isextern = g->decl.isextern;
- d->decl.isglobl = g->decl.isglobl;
- d->decl.init = specializenode(g->decl.init, tsmap);
- putdcl(st, d);
+ /* specialize */
+ tsmap = mkht(tyhash, tyeq);
+ fillsubst(tsmap, to, g->decl.type);
- fixup(d);
+ d = mkdecl(g->loc, n, tysubst(g->decl.type, tsmap));
+ d->decl.isconst = g->decl.isconst;
+ d->decl.isextern = g->decl.isextern;
+ d->decl.isglobl = g->decl.isglobl;
+ d->decl.init = specializenode(g->decl.init, tsmap);
+ putdcl(st, d);
- lappend(&file->file.stmts, &file->file.nstmts, d);
- if (d->decl.name->name.ns)
- popstab();
- return d;
+ fixup(d);
+
+ lappend(&file->file.stmts, &file->file.nstmts, d);
+ if (d->decl.name->name.ns)
+ popstab();
+ return d;
}
/*
@@ -455,65 +453,65 @@
*/
static Node *initdecl(Node *file, Node *name, Type *tyvoidfn)
{
- Node *dcl;
+ Node *dcl;
- dcl = getdcl(file->file.globls, name);
- if (!dcl) {
- dcl = mkdecl(Zloc, name, tyvoidfn);
- dcl->decl.isconst = 1;
- dcl->decl.isglobl = 1;
- dcl->decl.isinit = 1;
- dcl->decl.isextern = 1;
- dcl->decl.ishidden = 1;
- putdcl(file->file.globls, dcl);
- }
- return dcl;
+ dcl = getdcl(file->file.globls, name);
+ if (!dcl) {
+ dcl = mkdecl(Zloc, name, tyvoidfn);
+ dcl->decl.isconst = 1;
+ dcl->decl.isglobl = 1;
+ dcl->decl.isinit = 1;
+ dcl->decl.isextern = 1;
+ dcl->decl.ishidden = 1;
+ putdcl(file->file.globls, dcl);
+ }
+ return dcl;
}
static void callinit(Node *block, Node *init, Type *tyvoid, Type *tyvoidfn)
{
- Node *call, *var;
+ Node *call, *var;
- var = mkexpr(Zloc, Ovar, init->decl.name, NULL);
- call = mkexpr(Zloc, Ocall, var, NULL);
+ var = mkexpr(Zloc, Ovar, init->decl.name, NULL);
+ call = mkexpr(Zloc, Ocall, var, NULL);
- var->expr.type = tyvoidfn;
- call->expr.type = tyvoid;
- var->expr.did = init->decl.did;
- var->expr.isconst = 1;
- lappend(&block->block.stmts, &block->block.nstmts, call);
+ var->expr.type = tyvoidfn;
+ call->expr.type = tyvoid;
+ var->expr.did = init->decl.did;
+ var->expr.isconst = 1;
+ lappend(&block->block.stmts, &block->block.nstmts, call);
}
void geninit(Node *file)
{
- Node *name, *decl, *func, *block, *init;
- Type *tyvoid, *tyvoidfn;
- size_t i;
+ Node *name, *decl, *func, *block, *init;
+ Type *tyvoid, *tyvoidfn;
+ size_t i;
- name = mkname(Zloc, "__init__");
- decl = mkdecl(Zloc, name, mktyvar(Zloc));
- block = mkblock(Zloc, mkstab(0));
- block->block.scope->super = file->file.globls;
- tyvoid = mktype(Zloc, Tyvoid);
- tyvoidfn = mktyfunc(Zloc, NULL, 0, tyvoid);
+ name = mkname(Zloc, "__init__");
+ decl = mkdecl(Zloc, name, mktyvar(Zloc));
+ block = mkblock(Zloc, mkstab(0));
+ block->block.scope->super = file->file.globls;
+ tyvoid = mktype(Zloc, Tyvoid);
+ tyvoidfn = mktyfunc(Zloc, NULL, 0, tyvoid);
- for (i = 0; i < file->file.ninit; i++) {
- init = initdecl(file, file->file.init[i], tyvoidfn);
- callinit(block, init, tyvoid, tyvoidfn);
- }
- if (file->file.localinit)
- callinit(block, file->file.localinit, tyvoid, tyvoidfn);
+ for (i = 0; i < file->file.ninit; i++) {
+ init = initdecl(file, file->file.init[i], tyvoidfn);
+ callinit(block, init, tyvoid, tyvoidfn);
+ }
+ if (file->file.localinit)
+ callinit(block, file->file.localinit, tyvoid, tyvoidfn);
- func = mkfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid), block);
- func->expr.type = tyvoidfn;
- init = mkexpr(Zloc, Olit, func, NULL);
- init->expr.type = tyvoidfn;
+ func = mkfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid), block);
+ func->expr.type = tyvoidfn;
+ init = mkexpr(Zloc, Olit, func, NULL);
+ init->expr.type = tyvoidfn;
- decl->decl.init = init;
- decl->decl.isconst = 1;
- decl->decl.isglobl = 1;
- decl->decl.type = tyvoidfn;
- decl->decl.vis = Vishidden;
+ decl->decl.init = init;
+ decl->decl.isconst = 1;
+ decl->decl.isglobl = 1;
+ decl->decl.type = tyvoidfn;
+ decl->decl.vis = Vishidden;
- lappend(&file->file.stmts, &file->file.nstmts, decl);
+ lappend(&file->file.stmts, &file->file.nstmts, decl);
}
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -16,15 +16,15 @@
typedef struct Tydefn Tydefn;
typedef struct Traitdefn Traitdefn;
struct Tydefn {
- Srcloc loc;
- Node *name;
- Type *type;
+ Srcloc loc;
+ Node *name;
+ Type *type;
};
struct Traitdefn {
- Srcloc loc;
- Node *name;
- Trait *trait;
+ Srcloc loc;
+ Node *name;
+ Trait *trait;
};
#define Maxstabdepth 128
@@ -34,105 +34,99 @@
/* scope management */
Stab *curstab()
{
- assert(stabstkoff > 0);
- return stabstk[stabstkoff - 1];
+ assert(stabstkoff > 0);
+ return stabstk[stabstkoff - 1];
}
void pushstab(Stab *st)
{
- assert(stabstkoff < Maxstabdepth);
- stabstk[stabstkoff++] = st;
+ assert(stabstkoff < Maxstabdepth);
+ stabstk[stabstkoff++] = st;
}
void popstab(void)
{
- assert(stabstkoff > 0);
- stabstkoff--;
+ assert(stabstkoff > 0);
+ stabstkoff--;
}
/* name hashing: we want namespaced lookups to find the
* name even if we haven't set the namespace up, since
* we can update it after the fact. */
-static ulong nsnamehash(void *n)
-{
- return strhash(namestr(n));
-}
+static ulong nsnamehash(void *n) { return strhash(namestr(n)); }
-static int nsnameeq(void *a, void *b)
-{
- return a == b || !strcmp(namestr(a), namestr(b));
-}
+static int nsnameeq(void *a, void *b) { return a == b || !strcmp(namestr(a), namestr(b)); }
static ulong implhash(void *p)
{
- Node *n;
- ulong h;
+ Node *n;
+ ulong h;
- n = p;
- h = nsnamehash(n->impl.traitname);
- h *= tyhash(n->impl.type);
- return h;
+ n = p;
+ h = nsnamehash(n->impl.traitname);
+ h *= tyhash(n->impl.type);
+ return h;
}
static int impleq(void *pa, void *pb)
{
- Node *a, *b;
+ Node *a, *b;
- a = pa;
- b = pb;
- if (nsnameeq(a->impl.traitname, b->impl.traitname))
- return tyeq(a->impl.type, b->impl.type);
- return 0;
+ a = pa;
+ b = pb;
+ if (nsnameeq(a->impl.traitname, b->impl.traitname))
+ return tyeq(a->impl.type, b->impl.type);
+ return 0;
}
Stab *mkstab(int isfunc)
{
- Stab *st;
+ Stab *st;
- st = zalloc(sizeof(Stab));
- st->dcl = mkht(nsnamehash, nsnameeq);
- st->ty = mkht(nsnamehash, nsnameeq);
- st->tr = mkht(nsnamehash, nsnameeq);
- st->uc = mkht(nsnamehash, nsnameeq);
- if (isfunc)
- st->env = mkht(nsnamehash, nsnameeq);
- st->impl = mkht(implhash, impleq);
- return st;
+ st = zalloc(sizeof(Stab));
+ st->dcl = mkht(nsnamehash, nsnameeq);
+ st->ty = mkht(nsnamehash, nsnameeq);
+ st->tr = mkht(nsnamehash, nsnameeq);
+ st->uc = mkht(nsnamehash, nsnameeq);
+ if (isfunc)
+ st->env = mkht(nsnamehash, nsnameeq);
+ st->impl = mkht(implhash, impleq);
+ return st;
}
Node *getclosed(Stab *st, Node *n)
{
- while (st && !st->env)
- st = st->super;
- if (st)
- return htget(st->env, n);
- return NULL;
+ while (st && !st->env)
+ st = st->super;
+ if (st)
+ return htget(st->env, n);
+ return NULL;
}
Node **getclosure(Stab *st, size_t *n)
{
- size_t nkeys, i;
- void **keys;
- Node **vals;
+ size_t nkeys, i;
+ void **keys;
+ Node **vals;
- while (st && !st->env)
- st = st->super;
+ while (st && !st->env)
+ st = st->super;
- if (!st) {
- *n = 0;
- return NULL;
- }
+ if (!st) {
+ *n = 0;
+ return NULL;
+ }
- vals = NULL;
- *n = 0;
- keys = htkeys(st->env, &nkeys);
- for (i = 0; i < nkeys; i++)
- lappend(&vals, n, htget(st->env, keys[i]));
- free(keys);
- return vals;
+ vals = NULL;
+ *n = 0;
+ keys = htkeys(st->env, &nkeys);
+ for (i = 0; i < nkeys; i++)
+ lappend(&vals, n, htget(st->env, keys[i]));
+ free(keys);
+ return vals;
}
-/*
+/*
* Searches for declarations from current
* scope, and all enclosing scopes. Does
* not resolve namespaces -- that is the job
@@ -144,312 +138,322 @@
*/
Node *getdcl(Stab *st, Node *n)
{
- Node *s;
- Stab *fn;
+ Node *s;
+ Stab *fn;
- fn = NULL;
- do {
- s = htget(st->dcl, n);
- if (s) {
- /* record that this is in the closure of this scope */
- if (fn && !s->decl.isglobl)
- htput(fn->env, s->decl.name, s);
- return s;
- }
- if (!fn && st->env)
- fn = st;
- st = st->super;
- } while (st);
- return NULL;
+ fn = NULL;
+ do {
+ s = htget(st->dcl, n);
+ if (s) {
+ /* record that this is in the closure of this scope */
+ if (fn && !s->decl.isglobl)
+ htput(fn->env, s->decl.name, s);
+ return s;
+ }
+ if (!fn && st->env)
+ fn = st;
+ st = st->super;
+ } while (st);
+ return NULL;
}
Type *gettype_l(Stab *st, Node *n)
{
- Tydefn *t;
+ Tydefn *t;
- if ((t = htget(st->ty, n)))
- return t->type;
- return NULL;
+ if ((t = htget(st->ty, n)))
+ return t->type;
+ return NULL;
}
-
Type *gettype(Stab *st, Node *n)
{
- Tydefn *t;
+ Tydefn *t;
- do {
- if ((t = htget(st->ty, n)))
- return t->type;
- st = st->super;
- } while (st);
- return NULL;
+ do {
+ if ((t = htget(st->ty, n)))
+ return t->type;
+ st = st->super;
+ } while (st);
+ return NULL;
}
int hastype(Stab *st, Node *n)
{
- do {
- if (hthas(st->ty, n))
- return 1;
- st = st->super;
- } while(st);
- return 0;
+ do {
+ if (hthas(st->ty, n))
+ return 1;
+ st = st->super;
+ } while (st);
+ return 0;
}
Ucon *getucon(Stab *st, Node *n)
{
- Ucon *uc;
+ Ucon *uc;
- do {
- if ((uc = htget(st->uc, n)))
- return uc;
- st = st->super;
- } while (st);
- return NULL;
+ do {
+ if ((uc = htget(st->uc, n)))
+ return uc;
+ st = st->super;
+ } while (st);
+ return NULL;
}
Trait *gettrait(Stab *st, Node *n)
{
- Traitdefn *c;
+ Traitdefn *c;
- do {
- if ((c = htget(st->tr, n)))
- return c->trait;
- st = st->super;
- } while (st);
- return NULL;
+ do {
+ if ((c = htget(st->tr, n)))
+ return c->trait;
+ st = st->super;
+ } while (st);
+ return NULL;
}
-Stab *getns(Node *file, char *name)
-{
- return htget(file->file.ns, name);
-}
+Stab *getns(Node *file, char *name) { return htget(file->file.ns, name); }
static int mergedecl(Node *old, Node *new)
{
- Node *e, *g;
+ Node *e, *g;
- if (old->decl.ishidden || new->decl.ishidden) {
- old->decl.ishidden = old->decl.ishidden && new->decl.ishidden;
- return 1;
- }
- if (old->decl.isextern || new->decl.isextern) {
- old->decl.isextern = old->decl.isextern && new->decl.isextern;
- return 1;
- }
- if (old->decl.vis == Visexport && new->decl.vis != Visexport) {
- e = old;
- g = new;
- } else if (new->decl.vis == Visexport && old->decl.vis != Visexport) {
- e = new;
- g = old;
- } else {
- return 0;
- }
- old->decl.vis = Visexport;
+ if (old->decl.ishidden || new->decl.ishidden) {
+ old->decl.ishidden = old->decl.ishidden && new->decl.ishidden;
+ return 1;
+ }
+ if (old->decl.isextern || new->decl.isextern) {
+ old->decl.isextern = old->decl.isextern && new->decl.isextern;
+ return 1;
+ }
+ if (old->decl.vis == Visexport && new->decl.vis != Visexport) {
+ e = old;
+ g = new;
+ }
+ else if (new->decl.vis == Visexport && old->decl.vis != Visexport) {
+ e = new;
+ g = old;
+ }
+ else {
+ return 0;
+ }
+ old->decl.vis = Visexport;
- if (e->decl.init && g->decl.init)
- fatal(e, "export %s double initialized on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
- if (e->decl.isgeneric != g->decl.isgeneric)
- fatal(e, "export %s declared with different genericness on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
- if (e->decl.isconst != g->decl.isconst)
- fatal(e, "export %s declared with different constness on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
- if (e->decl.isconst != g->decl.isconst)
- fatal(e, "export %s declared with different externness on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
+ if (e->decl.init && g->decl.init)
+ fatal(e, "export %s double initialized on %s:%d", declname(e), fname(g->loc),
+ lnum(g->loc));
+ if (e->decl.isgeneric != g->decl.isgeneric)
+ fatal(e, "export %s declared with different genericness on %s:%d", declname(e),
+ fname(g->loc), lnum(g->loc));
+ if (e->decl.isconst != g->decl.isconst)
+ fatal(e, "export %s declared with different constness on %s:%d", declname(e),
+ fname(g->loc), lnum(g->loc));
+ if (e->decl.isconst != g->decl.isconst)
+ fatal(e, "export %s declared with different externness on %s:%d", declname(e),
+ fname(g->loc), lnum(g->loc));
- if (new->decl.name->name.ns)
- setns(old->decl.name, new->decl.name->name.ns);
- if (e->decl.type->type == Tyvar)
- e->decl.type = g->decl.type;
- else if (g->decl.type->type == Tyvar)
- g->decl.type = e->decl.type;
+ if (new->decl.name->name.ns)
+ setns(old->decl.name, new->decl.name->name.ns);
+ if (e->decl.type->type == Tyvar)
+ e->decl.type = g->decl.type;
+ else if (g->decl.type->type == Tyvar)
+ g->decl.type = e->decl.type;
- if (!e->decl.init)
- e->decl.init = g->decl.init;
- else if (!g->decl.init)
- g->decl.init = e->decl.init;
+ if (!e->decl.init)
+ e->decl.init = g->decl.init;
+ else if (!g->decl.init)
+ g->decl.init = e->decl.init;
- /* FIXME: check compatible typing */
- old->decl.ishidden = e->decl.ishidden || g->decl.ishidden;
- old->decl.isimport = e->decl.isimport || g->decl.isimport;
- old->decl.isnoret = e->decl.isnoret || g->decl.isnoret;
- old->decl.isexportinit = e->decl.isexportinit || g->decl.isexportinit;
- old->decl.isglobl = e->decl.isglobl || g->decl.isglobl;
- old->decl.ispkglocal = e->decl.ispkglocal || g->decl.ispkglocal;
- old->decl.isextern = e->decl.isextern || g->decl.isextern;
- return 1;
+ /* FIXME: check compatible typing */
+ old->decl.ishidden = e->decl.ishidden || g->decl.ishidden;
+ old->decl.isimport = e->decl.isimport || g->decl.isimport;
+ old->decl.isnoret = e->decl.isnoret || g->decl.isnoret;
+ old->decl.isexportinit = e->decl.isexportinit || g->decl.isexportinit;
+ old->decl.isglobl = e->decl.isglobl || g->decl.isglobl;
+ old->decl.ispkglocal = e->decl.ispkglocal || g->decl.ispkglocal;
+ old->decl.isextern = e->decl.isextern || g->decl.isextern;
+ return 1;
}
-void forcedcl (Stab *st, Node *s) {
- if (st->name)
- setns(s->decl.name, st->name);
- htput(st->dcl, s->decl.name, s);
- assert(htget(st->dcl, s->decl.name) != NULL);
+void forcedcl(Stab *st, Node *s)
+{
+ if (st->name)
+ setns(s->decl.name, st->name);
+ htput(st->dcl, s->decl.name, s);
+ assert(htget(st->dcl, s->decl.name) != NULL);
}
void putdcl(Stab *st, Node *s)
{
- Node *name, *old;
- Stab *ns;
+ Node *name, *old;
+ Stab *ns;
- name = s->decl.name;
- if (name->name.ns) {
- ns = getns(file, name->name.ns);
- if (!ns) {
- ns = mkstab(0);
- updatens(ns, name->name.ns);
- }
- st = ns;
- }
- old = htget(st->dcl, s->decl.name);
- if (!old)
- forcedcl(st, s);
- else if (!mergedecl(old, s))
- fatal(old, "%s already declared on %s:%d", namestr(s->decl.name), fname(s->loc), lnum(s->loc));
+ name = s->decl.name;
+ if (name->name.ns) {
+ ns = getns(file, name->name.ns);
+ if (!ns) {
+ ns = mkstab(0);
+ updatens(ns, name->name.ns);
+ }
+ st = ns;
+ }
+ old = htget(st->dcl, s->decl.name);
+ if (!old)
+ forcedcl(st, s);
+ else if (!mergedecl(old, s))
+ fatal(old, "%s already declared on %s:%d", namestr(s->decl.name), fname(s->loc),
+ lnum(s->loc));
}
void updatetype(Stab *st, Node *n, Type *t)
{
- Tydefn *td;
+ Tydefn *td;
- td = htget(st->ty, n);
- if (!td)
- die("No type %s to update", namestr(n));
- td->type = t;
+ td = htget(st->ty, n);
+ if (!td)
+ die("No type %s to update", namestr(n));
+ td->type = t;
}
int mergetype(Type *old, Type *new)
{
- if (!new) {
- lfatal(new->loc, "double prototyping of %s", tystr(new));
- } else if (old->vis == Visexport && new->vis != Visexport) {
- if (!old->sub && new->sub) {
- old->sub = new->sub;
- old->nsub = new->nsub;
- return 1;
- }
- } else if (new->vis == Visexport && old->vis != Visexport) {
- if (!new->sub && old->sub) {
- new->sub = old->sub;
- new->nsub = old->nsub;
- return 1;
- }
- }
- return 0;
+ if (!new) {
+ lfatal(new->loc, "double prototyping of %s", tystr(new));
+ }
+ else if (old->vis == Visexport && new->vis != Visexport) {
+ if (!old->sub && new->sub) {
+ old->sub = new->sub;
+ old->nsub = new->nsub;
+ return 1;
+ }
+ }
+ else if (new->vis == Visexport && old->vis != Visexport) {
+ if (!new->sub && old->sub) {
+ new->sub = old->sub;
+ new->nsub = old->nsub;
+ return 1;
+ }
+ }
+ return 0;
}
void puttype(Stab *st, Node *n, Type *t)
{
- Tydefn *td;
- Type *ty;
+ Tydefn *td;
+ Type *ty;
- if (st->name)
- setns(n, st->name);
- if (st->name && t && t->name)
- setns(t->name, st->name);
+ if (st->name)
+ setns(n, st->name);
+ if (st->name && t && t->name)
+ setns(t->name, st->name);
- ty = gettype(st, n);
- if (!ty) {
- if (t && hastype(st, n)) {
- t->vis = Visexport;
- updatetype(st, n, t);
- } else {
- td = xalloc(sizeof(Tydefn));
- td->loc = n->loc;
- td->name = n;
- td->type = t;
- htput(st->ty, td->name, td);
- }
- } else if (!mergetype(ty, t)) {
- fatal(n, "Type %s already declared on %s:%d", tystr(ty), fname(ty->loc), lnum(ty->loc));
- }
+ ty = gettype(st, n);
+ if (!ty) {
+ if (t && hastype(st, n)) {
+ t->vis = Visexport;
+ updatetype(st, n, t);
+ }
+ else {
+ td = xalloc(sizeof(Tydefn));
+ td->loc = n->loc;
+ td->name = n;
+ td->type = t;
+ htput(st->ty, td->name, td);
+ }
+ }
+ else if (!mergetype(ty, t)) {
+ fatal(n, "Type %s already declared on %s:%d", tystr(ty), fname(ty->loc),
+ lnum(ty->loc));
+ }
}
void putucon(Stab *st, Ucon *uc)
{
- Ucon *old;
+ Ucon *old;
-
- old = getucon(st, uc->name);
- if (old)
- lfatal(old->loc, "`%s already defined on %s:%d", namestr(uc->name), fname(uc->loc), lnum(uc->loc));
- htput(st->uc, uc->name, uc);
+ old = getucon(st, uc->name);
+ if (old)
+ lfatal(old->loc, "`%s already defined on %s:%d", namestr(uc->name), fname(uc->loc),
+ lnum(uc->loc));
+ htput(st->uc, uc->name, uc);
}
static int mergetrait(Trait *old, Trait *new)
{
- if (old->isproto && !new->isproto)
- *old = *new;
- else if (new->isproto && !old->isproto)
- *new = *old;
- else
- return 0;
- return 1;
+ if (old->isproto && !new->isproto)
+ *old = *new;
+ else if (new->isproto && !old->isproto)
+ *new = *old;
+ else
+ return 0;
+ return 1;
}
void puttrait(Stab *st, Node *n, Trait *c)
{
- Traitdefn *td;
- Trait *t;
- Type *ty;
+ Traitdefn *td;
+ Trait *t;
+ Type *ty;
- t = gettrait(st, n);
- if (t && !mergetrait(t, c))
- fatal(n, "Trait %s already defined on %s:%d", namestr(n), fname(t->loc), lnum(t->loc));
- ty = gettype(st, n);
- if (ty)
- fatal(n, "Trait %s defined as a type on %s:%d", namestr(n), fname(ty->loc), lnum(ty->loc));
- td = xalloc(sizeof(Traitdefn));
- td->loc = n->loc;
- td->name = n;
- td->trait = c;
- htput(st->tr, td->name, td);
+ t = gettrait(st, n);
+ if (t && !mergetrait(t, c))
+ fatal(n, "Trait %s already defined on %s:%d", namestr(n), fname(t->loc),
+ lnum(t->loc));
+ ty = gettype(st, n);
+ if (ty)
+ fatal(n, "Trait %s defined as a type on %s:%d", namestr(n), fname(ty->loc),
+ lnum(ty->loc));
+ td = xalloc(sizeof(Traitdefn));
+ td->loc = n->loc;
+ td->name = n;
+ td->trait = c;
+ htput(st->tr, td->name, td);
}
static int mergeimpl(Node *old, Node *new)
{
- if (old->impl.isproto && !new->impl.isproto)
- *old = *new;
- else if (new->impl.isproto && !old->impl.isproto)
- *new = *old;
- else
- return 0;
- return 1;
+ if (old->impl.isproto && !new->impl.isproto)
+ *old = *new;
+ else if (new->impl.isproto && !old->impl.isproto)
+ *new = *old;
+ else
+ return 0;
+ return 1;
}
void putimpl(Stab *st, Node *n)
{
- Node *impl;
+ Node *impl;
- impl = getimpl(st, n);
- if (impl && !mergeimpl(impl, n))
- fatal(n, "Trait %s already implemented over %s at %s:%d",
- namestr(n->impl.traitname), tystr(n->impl.type),
- fname(n->loc), lnum(n->loc));
- if (st->name)
- setns(n->impl.traitname, st->name);
- htput(st->impl, n, n);
+ impl = getimpl(st, n);
+ if (impl && !mergeimpl(impl, n))
+ fatal(n, "Trait %s already implemented over %s at %s:%d",
+ namestr(n->impl.traitname), tystr(n->impl.type), fname(n->loc), lnum(n->loc));
+ if (st->name)
+ setns(n->impl.traitname, st->name);
+ htput(st->impl, n, n);
}
Node *getimpl(Stab *st, Node *n)
{
- Node *imp;
-
- do {
- if ((imp = htget(st->impl, n)))
- return imp;
- st = st->super;
- } while (st);
- return NULL;
+ Node *imp;
+
+ do {
+ if ((imp = htget(st->impl, n)))
+ return imp;
+ st = st->super;
+ } while (st);
+ return NULL;
}
void putns(Node *file, Stab *scope)
{
- Stab *s;
+ Stab *s;
- s = getns(file, scope->name);
- if (s)
- lfatal(Zloc, "Namespace %s already defined", scope->name);
- htput(file->file.ns, scope->name, scope);
+ s = getns(file, scope->name);
+ if (s)
+ lfatal(Zloc, "Namespace %s already defined", scope->name);
+ htput(file->file.ns, scope->name, scope);
}
/*
@@ -459,25 +463,25 @@
*/
void updatens(Stab *st, char *name)
{
- void **k;
- size_t i, nk;
- Tydefn *td;
+ void **k;
+ size_t i, nk;
+ Tydefn *td;
- if (st->name)
- die("Stab %s already has namespace; Can't set to %s", st->name, name);
- st->name = strdup(name);
- htput(file->file.ns, st->name, st);
- k = htkeys(st->dcl, &nk);
- for (i = 0; i < nk; i++)
- setns(k[i], name);
- free(k);
- k = htkeys(st->ty, &nk);
- for (i = 0; i < nk; i++)
- setns(k[i], name);
- for (i = 0; i < nk; i++) {
- td = htget(st->ty, k[i]);
- if (td->type && (td->type->type == Tyname || td->type->type == Tygeneric))
- setns(td->type->name, name);
- }
- free(k);
+ if (st->name)
+ die("Stab %s already has namespace; Can't set to %s", st->name, name);
+ st->name = strdup(name);
+ htput(file->file.ns, st->name, st);
+ k = htkeys(st->dcl, &nk);
+ for (i = 0; i < nk; i++)
+ setns(k[i], name);
+ free(k);
+ k = htkeys(st->ty, &nk);
+ for (i = 0; i < nk; i++)
+ setns(k[i], name);
+ for (i = 0; i < nk; i++) {
+ td = htget(st->ty, k[i]);
+ if (td->type && (td->type->type == Tyname || td->type->type == Tygeneric))
+ setns(td->type->name, name);
+ }
+ free(k);
}
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -22,36 +22,33 @@
Tok *curtok;
/* the file contents are stored globally */
-static int fidx;
-static int fbufsz;
+static int fidx;
+static int fbufsz;
static char *fbuf;
static int peekn(int n)
{
- if (fidx + n >= fbufsz)
- return End;
- else
- return fbuf[fidx + n];
+ if (fidx + n >= fbufsz)
+ return End;
+ else
+ return fbuf[fidx + n];
}
-static int peek(void)
-{
- return peekn(0);
-}
+static int peek(void) { return peekn(0); }
static int next(void)
{
- int c;
+ int c;
- c = peek();
- fidx++;
- return c;
+ c = peek();
+ fidx++;
+ return c;
}
static void unget(void)
{
- fidx--;
- assert(fidx >= 0);
+ fidx--;
+ assert(fidx >= 0);
}
/*
@@ -62,61 +59,57 @@
*/
static int match(char c)
{
- if (peek() == c) {
- next();
- return 1;
- } else {
- return 0;
- }
+ if (peek() == c) {
+ next();
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
static Tok *mktok(int tt)
{
- Tok *t;
+ Tok *t;
- t = zalloc(sizeof(Tok));
- t->type = tt;
- t->loc = curloc;
- return t;
+ t = zalloc(sizeof(Tok));
+ t->type = tt;
+ t->loc = curloc;
+ return t;
}
-static int identchar(int c)
-{
- return isalnum(c) || c == '_' || c == '$';
-}
+static int identchar(int c) { return isalnum(c) || c == '_' || c == '$'; }
static void eatcomment(void)
{
- int depth;
- int startln;
- int c;
+ int depth;
+ int startln;
+ int c;
- depth = 0;
- startln = curloc.line;
- while (1) {
- c = next();
- switch (c) {
- /* enter level of nesting */
- case '/':
- if (match('*'))
- depth++;
- break;
- /* leave level of nesting */
- case '*':
- if (match('/'))
- depth--;
- break;
- /* have to keep line numbers synced */
- case '\n':
- curloc.line++;
- break;
- case End:
- lfatal(curloc, "File ended within comment starting at line %d", startln);
- break;
- }
- if (depth == 0)
- break;
- }
+ depth = 0;
+ startln = curloc.line;
+ while (1) {
+ c = next();
+ switch (c) {
+ /* enter level of nesting */
+ case '/':
+ if (match('*'))
+ depth++;
+ break;
+ /* leave level of nesting */
+ case '*':
+ if (match('/'))
+ depth--;
+ break;
+ /* have to keep line numbers synced */
+ case '\n': curloc.line++; break;
+ case End:
+ lfatal(curloc, "File ended within comment starting at line %d", startln);
+ break;
+ }
+ if (depth == 0)
+ break;
+ }
}
/*
@@ -128,29 +121,34 @@
*/
static void eatspace(void)
{
- int c;
- int ignorenl;
+ int c;
+ int ignorenl;
- ignorenl = 0;
- while (1) {
- c = peek();
- if (!ignorenl && c == '\n') {
- break;
- } else if (c == '\\') {
- ignorenl = 1;
- next();
- } else if (ignorenl && c == '\n') {
- next();
- curloc.line++;
- ignorenl = 0;
- } else if (isspace(c)) {
- next();
- } else if (c == '/' && peekn(1) == '*') {
- eatcomment();
- } else {
- break;
- }
- }
+ ignorenl = 0;
+ while (1) {
+ c = peek();
+ if (!ignorenl && c == '\n') {
+ break;
+ }
+ else if (c == '\\') {
+ ignorenl = 1;
+ next();
+ }
+ else if (ignorenl && c == '\n') {
+ next();
+ curloc.line++;
+ ignorenl = 0;
+ }
+ else if (isspace(c)) {
+ next();
+ }
+ else if (c == '/' && peekn(1) == '*') {
+ eatcomment();
+ }
+ else {
+ break;
+ }
+ }
}
/*
@@ -161,116 +159,93 @@
*/
static int kwd(char *s)
{
- static const struct {char* kw; int tt;} kwmap[] = {
- {"$", Tidxlen},
- {"$noret", Tattr},
- {"_", Tgap},
- {"break", Tbreak},
- {"castto", Tcast},
- {"const", Tconst},
- {"continue", Tcontinue},
- {"elif", Telif},
- {"else", Telse},
- {"export", Texport},
- {"extern", Tattr},
- {"false", Tboollit},
- {"for", Tfor},
- {"generic", Tgeneric},
- {"goto", Tgoto},
- {"if", Tif},
- {"impl", Timpl},
- {"in", Tin},
- {"match", Tmatch},
- {"pkg", Tpkg},
- {"pkglocal", Tattr},
- {"protect", Tprotect},
- {"sizeof", Tsizeof},
- {"struct", Tstruct},
- {"trait", Ttrait},
- {"true", Tboollit},
- {"type", Ttype},
- {"union", Tunion},
- {"use", Tuse},
- {"var", Tvar},
- {"while", Twhile},
- };
+ static const struct {
+ char *kw;
+ int tt;
+ } kwmap[] = {
+ {"$", Tidxlen}, {"$noret", Tattr}, {"_", Tgap}, {"break", Tbreak}, {"castto", Tcast},
+ {"const", Tconst}, {"continue", Tcontinue}, {"elif", Telif}, {"else", Telse},
+ {"export", Texport}, {"extern", Tattr}, {"false", Tboollit}, {"for", Tfor},
+ {"generic", Tgeneric}, {"goto", Tgoto}, {"if", Tif}, {"impl", Timpl}, {"in", Tin},
+ {"match", Tmatch}, {"pkg", Tpkg}, {"pkglocal", Tattr}, {"protect", Tprotect},
+ {"sizeof", Tsizeof}, {"struct", Tstruct}, {"trait", Ttrait}, {"true", Tboollit},
+ {"type", Ttype}, {"union", Tunion}, {"use", Tuse}, {"var", Tvar}, {"while", Twhile},
+ };
- size_t min, max, mid;
- int cmp;
+ size_t min, max, mid;
+ int cmp;
-
- min = 0;
- max = sizeof(kwmap)/sizeof(kwmap[0]);
- while (max > min) {
- mid = (max + min) / 2;
- cmp = strcmp(s, kwmap[mid].kw);
- if (cmp == 0)
- return kwmap[mid].tt;
- else if (cmp > 0)
- min = mid + 1;
- else if (cmp < 0)
- max = mid;
- }
- return Tident;
+ min = 0;
+ max = sizeof(kwmap) / sizeof(kwmap[0]);
+ while (max > min) {
+ mid = (max + min) / 2;
+ cmp = strcmp(s, kwmap[mid].kw);
+ if (cmp == 0)
+ return kwmap[mid].tt;
+ else if (cmp > 0)
+ min = mid + 1;
+ else if (cmp < 0)
+ max = mid;
+ }
+ return Tident;
}
static int identstr(char *buf, size_t sz)
{
- size_t i;
- char c;
+ size_t i;
+ char c;
- i = 0;
- for (c = peek(); i < sz && identchar(c); c = peek()) {
- next();
- buf[i++] = c;
- }
- buf[i] = '\0';
- return i;
+ i = 0;
+ for (c = peek(); i < sz && identchar(c); c = peek()) {
+ next();
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+ return i;
}
static Tok *kwident(void)
{
- char buf[1024];
- Tok *t;
+ char buf[1024];
+ Tok *t;
- if (!identstr(buf, sizeof buf))
- return NULL;
- t = mktok(kwd(buf));
- t->id = strdup(buf);
- return t;
+ if (!identstr(buf, sizeof buf))
+ return NULL;
+ t = mktok(kwd(buf));
+ t->id = strdup(buf);
+ return t;
}
static void append(char **buf, size_t *len, size_t *sz, int c)
{
- if (!*sz) {
- *sz = 16;
- *buf = malloc(*sz);
- }
- if (*len == *sz - 1) {
- *sz = *sz * 2;
- *buf = realloc(*buf, *sz);
- }
+ if (!*sz) {
+ *sz = 16;
+ *buf = malloc(*sz);
+ }
+ if (*len == *sz - 1) {
+ *sz = *sz * 2;
+ *buf = realloc(*buf, *sz);
+ }
- buf[0][*len] = c;
- (*len)++;
+ buf[0][*len] = c;
+ (*len)++;
}
-
static void encode(char *buf, size_t len, uint32_t c)
{
- int mark;
- size_t i;
+ int mark;
+ size_t i;
- assert(len > 0 && len < 5);
- if (len == 1)
- mark = 0;
- else
- mark = (((1 << (8 - len)) - 1) ^ 0xff);
- for (i = len - 1; i > 0; i--) {
- buf[i] = (c & 0x3f) | 0x80;
- c >>= 6;
- }
- buf[0] = (c | mark);
+ assert(len > 0 && len < 5);
+ if (len == 1)
+ mark = 0;
+ else
+ mark = (((1 << (8 - len)) - 1) ^ 0xff);
+ for (i = len - 1; i > 0; i--) {
+ buf[i] = (c & 0x3f) | 0x80;
+ c >>= 6;
+ }
+ buf[0] = (c | mark);
}
/*
@@ -279,34 +254,34 @@
*/
static void appendc(char **buf, size_t *len, size_t *sz, uint32_t c)
{
- size_t i, charlen;
- char charbuf[5] = {0};
+ size_t i, charlen;
+ char charbuf[5] = {0};
- if (c < 0x80)
- charlen = 1;
- else if (c < 0x800)
- charlen = 2;
- else if (c < 0x10000)
- charlen = 3;
- else if (c < 0x200000)
- charlen = 4;
- else
- lfatal(curloc, "invalid utf character '\\u{%x}'", c);
+ if (c < 0x80)
+ charlen = 1;
+ else if (c < 0x800)
+ charlen = 2;
+ else if (c < 0x10000)
+ charlen = 3;
+ else if (c < 0x200000)
+ charlen = 4;
+ else
+ lfatal(curloc, "invalid utf character '\\u{%x}'", c);
- encode(charbuf, charlen, c);
- for (i = 0; i < charlen; i++)
- append(buf, len, sz, charbuf[i]);
+ encode(charbuf, charlen, c);
+ for (i = 0; i < charlen; i++)
+ append(buf, len, sz, charbuf[i]);
}
static int ishexval(char c)
{
- if (c >= 'a' && c <= 'f')
- return 1;
- else if (c >= 'A' && c <= 'F')
- return 1;
- else if (c >= '0' && c <= '9')
- return 1;
- return 0;
+ if (c >= 'a' && c <= 'f')
+ return 1;
+ else if (c >= 'A' && c <= 'F')
+ return 1;
+ else if (c >= '0' && c <= '9')
+ return 1;
+ return 0;
}
/*
@@ -314,35 +289,35 @@
*/
static int hexval(char c)
{
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- else if (c >= '0' && c <= '9')
- return c - '0';
- lfatal(curloc, "passed non-hex value '%c' to where hex was expected", c);
- return -1;
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= '0' && c <= '9')
+ return c - '0';
+ lfatal(curloc, "passed non-hex value '%c' to where hex was expected", c);
+ return -1;
}
/* \u{abc} */
static int32_t unichar(void)
{
- uint32_t v;
- int c;
+ uint32_t v;
+ int c;
- /* we've already seen the \u */
- if (next() != '{')
- lfatal(curloc, "\\u escape sequence without initial '{'");
- v = 0;
- while (ishexval(peek())) {
- c = next();
- v = 16*v + hexval(c);
- if (v > 0x10FFFF)
- lfatal(curloc, "invalid codepoint for \\u escape sequence");
- }
- if (next() != '}')
- lfatal(curloc, "\\u escape sequence without ending '}'");
- return v;
+ /* we've already seen the \u */
+ if (next() != '{')
+ lfatal(curloc, "\\u escape sequence without initial '{'");
+ v = 0;
+ while (ishexval(peek())) {
+ c = next();
+ v = 16 * v + hexval(c);
+ if (v > 0x10FFFF)
+ lfatal(curloc, "invalid codepoint for \\u escape sequence");
+ }
+ if (next() != '}')
+ lfatal(curloc, "\\u escape sequence without ending '}'");
+ return v;
}
/*
@@ -352,492 +327,507 @@
*/
static int decode(char **buf, size_t *len, size_t *sz)
{
- char c, c1, c2;
- int32_t v;
+ char c, c1, c2;
+ int32_t v;
- c = next();
- /* we've already seen the '\' */
- switch (c) {
- case 'u':
- v = unichar();
- appendc(buf, len, sz, v);
- return v;
- case 'x': /* arbitrary hex */
- c1 = next();
- if (!isxdigit(c1))
- lfatal(curloc, "expected hex digit, got %c", c1);
- c2 = next();
- if (!isxdigit(c2))
- lfatal(curloc, "expected hex digit, got %c", c1);
- v = 16*hexval(c1) + hexval(c2);
- break;
- case 'n': v = '\n'; break;
- case 'r': v = '\r'; break;
- case 't': v = '\t'; break;
- case 'b': v = '\b'; break;
- case '"': v = '\"'; break;
- case '\'': v = '\''; break;
- case 'v': v = '\v'; break;
- case '\\': v = '\\'; break;
- case '0': v = '\0'; break;
- default: lfatal(curloc, "unknown escape code \\%c", c);
- }
- append(buf, len, sz, v);
- return v;
+ c = next();
+ /* we've already seen the '\' */
+ switch (c) {
+ case 'u':
+ v = unichar();
+ appendc(buf, len, sz, v);
+ return v;
+ case 'x': /* arbitrary hex */
+ c1 = next();
+ if (!isxdigit(c1))
+ lfatal(curloc, "expected hex digit, got %c", c1);
+ c2 = next();
+ if (!isxdigit(c2))
+ lfatal(curloc, "expected hex digit, got %c", c1);
+ v = 16 * hexval(c1) + hexval(c2);
+ break;
+ case 'n': v = '\n'; break;
+ case 'r': v = '\r'; break;
+ case 't': v = '\t'; break;
+ case 'b': v = '\b'; break;
+ case '"': v = '\"'; break;
+ case '\'': v = '\''; break;
+ case 'v': v = '\v'; break;
+ case '\\': v = '\\'; break;
+ case '0': v = '\0'; break;
+ default: lfatal(curloc, "unknown escape code \\%c", c);
+ }
+ append(buf, len, sz, v);
+ return v;
}
static Tok *strlit(void)
{
- Tok *t;
- int c;
- size_t len, sz;
- char *buf;
+ Tok *t;
+ int c;
+ size_t len, sz;
+ char *buf;
- assert(next() == '"');
+ assert(next() == '"');
- buf = NULL;
- len = 0;
- sz = 0;
- while (1) {
- c = next();
- /* we don't unescape here, but on output */
- if (c == '"')
- break;
- else if (c == End)
- lfatal(curloc, "Unexpected EOF within string");
- else if (c == '\n')
- lfatal(curloc, "Newlines not allowed in strings");
- else if (c == '\\')
- decode(&buf, &len, &sz);
- else
- append(&buf, &len, &sz, c);
- };
- t = mktok(Tstrlit);
- t->strval.len = len;
+ buf = NULL;
+ len = 0;
+ sz = 0;
+ while (1) {
+ c = next();
+ /* we don't unescape here, but on output */
+ if (c == '"')
+ break;
+ else if (c == End)
+ lfatal(curloc, "Unexpected EOF within string");
+ else if (c == '\n')
+ lfatal(curloc, "Newlines not allowed in strings");
+ else if (c == '\\')
+ decode(&buf, &len, &sz);
+ else
+ append(&buf, &len, &sz, c);
+ };
+ t = mktok(Tstrlit);
+ t->strval.len = len;
- /* null terminator should not count towards length */
- append(&buf, &len, &sz, '\0');
- t->strval.buf = buf;
- t->id = buf;
- return t;
+ /* null terminator should not count towards length */
+ append(&buf, &len, &sz, '\0');
+ t->strval.buf = buf;
+ t->id = buf;
+ return t;
}
-static uint32_t readutf(char c, char **buf, size_t *buflen, size_t *sz) {
- size_t i, len;
- uint32_t val;
+static uint32_t readutf(char c, char **buf, size_t *buflen, size_t *sz)
+{
+ size_t i, len;
+ uint32_t val;
- if ((c & 0x80) == 0)
- len = 1;
- else if ((c & 0xe0) == 0xc0)
- len = 2;
- else if ((c & 0xf0) == 0xe0)
- len = 3;
- else if ((c & 0xf8) == 0xf0)
- len = 4;
- else
- lfatal(curloc, "Invalid utf8 encoded character constant");
+ if ((c & 0x80) == 0)
+ len = 1;
+ else if ((c & 0xe0) == 0xc0)
+ len = 2;
+ else if ((c & 0xf0) == 0xe0)
+ len = 3;
+ else if ((c & 0xf8) == 0xf0)
+ len = 4;
+ else
+ lfatal(curloc, "Invalid utf8 encoded character constant");
- val = c & ((1 << (8 - len)) - 1);
- append(buf, buflen, sz, c);
- for (i = 1; i < len; i++) {
- c = next();
- if ((c & 0xc0) != 0x80)
- lfatal(curloc, "Invalid utf8 codepoint in character literal");
- val = (val << 6) | (c & 0x3f);
- append(buf, buflen, sz, c);
- }
- return val;
+ val = c & ((1 << (8 - len)) - 1);
+ append(buf, buflen, sz, c);
+ for (i = 1; i < len; i++) {
+ c = next();
+ if ((c & 0xc0) != 0x80)
+ lfatal(curloc, "Invalid utf8 codepoint in character literal");
+ val = (val << 6) | (c & 0x3f);
+ append(buf, buflen, sz, c);
+ }
+ return val;
}
static Tok *charlit(void)
{
- Tok *t;
- int c;
- uint32_t val;
- size_t len, sz;
- char *buf;
+ Tok *t;
+ int c;
+ uint32_t val;
+ size_t len, sz;
+ char *buf;
+ assert(next() == '\'');
- assert(next() == '\'');
+ buf = NULL;
+ len = 0;
+ sz = 0;
+ val = 0;
+ c = next();
+ if (c == End)
+ lfatal(curloc, "Unexpected EOF within char lit");
+ else if (c == '\n')
+ lfatal(curloc, "Newlines not allowed in char lit");
+ else if (c == '\\')
+ val = decode(&buf, &len, &sz);
+ else
+ val = readutf(c, &buf, &len, &sz);
+ append(&buf, &len, &sz, '\0');
+ if (next() != '\'')
+ lfatal(curloc, "Character constant with multiple characters");
- buf = NULL;
- len = 0;
- sz = 0;
- val = 0;
- c = next();
- if (c == End)
- lfatal(curloc, "Unexpected EOF within char lit");
- else if (c == '\n')
- lfatal(curloc, "Newlines not allowed in char lit");
- else if (c == '\\')
- val = decode(&buf, &len, &sz);
- else
- val = readutf(c, &buf, &len, &sz);
- append(&buf, &len, &sz, '\0');
- if (next() != '\'')
- lfatal(curloc, "Character constant with multiple characters");
-
- t = mktok(Tchrlit);
- t->chrval = val;
- t->id = buf;
- return t;
+ t = mktok(Tchrlit);
+ t->chrval = val;
+ t->id = buf;
+ return t;
}
static Tok *oper(void)
{
- int tt;
- char c;
+ int tt;
+ char c;
- c = next();
- switch (c) {
- case '{': tt = Tobrace; break;
- case '}': tt = Tcbrace; break;
- case '(': tt = Toparen; break;
- case ')': tt = Tcparen; break;
- case '[': tt = Tosqbrac; break;
- case ']': tt = Tcsqbrac; break;
- case ',': tt = Tcomma; break;
- case '`': tt = Ttick; break;
- case '#': tt = Tderef; break;
- case ':':
- if (match(':'))
- tt = Twith;
- else
- tt = Tcolon;
- break;
- case '~': tt = Tbnot; break;
- case ';':
- if (match(';'))
- tt = Tendblk;
- else
- tt = Tendln;
- break;
- case '.':
- if (match('.')) {
- if (match('.')) {
- tt = Tellipsis;
- } else {
- unget();
- tt = Tdot;
- }
- } else {
- tt = Tdot;
- }
- break;
- case '+':
- if (match('='))
- tt = Taddeq;
- else if (match('+'))
- tt = Tinc;
- else
- tt = Tplus;
- break;
- case '-':
- if (match('='))
- tt = Tsubeq;
- else if (match('-'))
- tt = Tdec;
- else if (match('>'))
- tt = Tret;
- else
- tt = Tminus;
- break;
- case '*':
- if (match('='))
- tt = Tmuleq;
- else
- tt = Tmul;
- break;
- case '/':
- if (match('='))
- tt = Tdiveq;
- else
- tt = Tdiv;
- break;
- case '%':
- if (match('='))
- tt = Tmodeq;
- else
- tt = Tmod;
- break;
- case '=':
- if (match('='))
- tt = Teq;
- else
- tt = Tasn;
- break;
- case '|':
- if (match('='))
- tt = Tboreq;
- else if (match('|'))
- tt = Tlor;
- else
- tt = Tbor;
- break;
- case '&':
- if (match('='))
- tt = Tbandeq;
- else if (match('&'))
- tt = Tland;
- else
- tt = Tband;
- break;
- case '^':
- if (match('='))
- tt = Tbxoreq;
- else
- tt = Tbxor;
- break;
- case '<':
- if (match('=')) {
- tt = Tle;
- } else if (match('<')) {
- if (match('='))
- tt = Tbsleq;
- else
- tt = Tbsl;
- } else {
- tt = Tlt;
- }
- break;
- case '>':
- if (match('=')) {
- tt = Tge;
- } else if (match('>')) {
- if (match('='))
- tt = Tbsreq;
- else
- tt = Tbsr;
- } else {
- tt = Tgt;
- }
- break;
+ c = next();
+ switch (c) {
+ case '{': tt = Tobrace; break;
+ case '}': tt = Tcbrace; break;
+ case '(': tt = Toparen; break;
+ case ')': tt = Tcparen; break;
+ case '[': tt = Tosqbrac; break;
+ case ']': tt = Tcsqbrac; break;
+ case ',': tt = Tcomma; break;
+ case '`': tt = Ttick; break;
+ case '#': tt = Tderef; break;
+ case ':':
+ if (match(':'))
+ tt = Twith;
+ else
+ tt = Tcolon;
+ break;
+ case '~': tt = Tbnot; break;
+ case ';':
+ if (match(';'))
+ tt = Tendblk;
+ else
+ tt = Tendln;
+ break;
+ case '.':
+ if (match('.')) {
+ if (match('.')) {
+ tt = Tellipsis;
+ }
+ else {
+ unget();
+ tt = Tdot;
+ }
+ }
+ else {
+ tt = Tdot;
+ }
+ break;
+ case '+':
+ if (match('='))
+ tt = Taddeq;
+ else if (match('+'))
+ tt = Tinc;
+ else
+ tt = Tplus;
+ break;
+ case '-':
+ if (match('='))
+ tt = Tsubeq;
+ else if (match('-'))
+ tt = Tdec;
+ else if (match('>'))
+ tt = Tret;
+ else
+ tt = Tminus;
+ break;
+ case '*':
+ if (match('='))
+ tt = Tmuleq;
+ else
+ tt = Tmul;
+ break;
+ case '/':
+ if (match('='))
+ tt = Tdiveq;
+ else
+ tt = Tdiv;
+ break;
+ case '%':
+ if (match('='))
+ tt = Tmodeq;
+ else
+ tt = Tmod;
+ break;
+ case '=':
+ if (match('='))
+ tt = Teq;
+ else
+ tt = Tasn;
+ break;
+ case '|':
+ if (match('='))
+ tt = Tboreq;
+ else if (match('|'))
+ tt = Tlor;
+ else
+ tt = Tbor;
+ break;
+ case '&':
+ if (match('='))
+ tt = Tbandeq;
+ else if (match('&'))
+ tt = Tland;
+ else
+ tt = Tband;
+ break;
+ case '^':
+ if (match('='))
+ tt = Tbxoreq;
+ else
+ tt = Tbxor;
+ break;
+ case '<':
+ if (match('=')) {
+ tt = Tle;
+ }
+ else if (match('<')) {
+ if (match('='))
+ tt = Tbsleq;
+ else
+ tt = Tbsl;
+ }
+ else {
+ tt = Tlt;
+ }
+ break;
+ case '>':
+ if (match('=')) {
+ tt = Tge;
+ }
+ else if (match('>')) {
+ if (match('='))
+ tt = Tbsreq;
+ else
+ tt = Tbsr;
+ }
+ else {
+ tt = Tgt;
+ }
+ break;
- case '!':
- if (match('='))
- tt = Tne;
- else
- tt = Tlnot;
- break;
- default:
- tt = Terror;
- lfatal(curloc, "Junk character %c", c);
- break;
- }
- return mktok(tt);
+ case '!':
+ if (match('='))
+ tt = Tne;
+ else
+ tt = Tlnot;
+ break;
+ default:
+ tt = Terror;
+ lfatal(curloc, "Junk character %c", c);
+ break;
+ }
+ return mktok(tt);
}
static Tok *number(int base)
{
- Tok *t;
- int start;
- int c;
- int isfloat;
- int unsignedval;
- /* because we allow '_' in numbers, and strtod/stroull don't, we
- * need a buffer that holds the number without '_'.
- */
- char buf[2048];
- size_t nbuf;
+ Tok *t;
+ int start;
+ int c;
+ int isfloat;
+ int unsignedval;
+ /* because we allow '_' in numbers, and strtod/stroull don't, we
+ * need a buffer that holds the number without '_'.
+ */
+ char buf[2048];
+ size_t nbuf;
- t = NULL;
- isfloat = 0;
- start = fidx;
- nbuf = 0;
- for (c = peek(); isxdigit(c) || c == '.' || c == '_'; c = peek()) {
- next();
- if (c == '_')
- continue;
- if (c == '.')
- isfloat = 1;
- else if (hexval(c) < 0 || hexval(c) > base)
- lfatal(curloc, "Integer digit '%c' outside of base %d", c, base);
- if (nbuf >= sizeof buf - 1) {
- buf[nbuf-1] = '\0';
- lfatal(curloc, "number %s... too long to represent", buf);
- }
- buf[nbuf++] = c;
- }
- buf[nbuf] = '\0';
+ t = NULL;
+ isfloat = 0;
+ start = fidx;
+ nbuf = 0;
+ for (c = peek(); isxdigit(c) || c == '.' || c == '_'; c = peek()) {
+ next();
+ if (c == '_')
+ continue;
+ if (c == '.')
+ isfloat = 1;
+ else if (hexval(c) < 0 || hexval(c) > base)
+ lfatal(curloc, "Integer digit '%c' outside of base %d", c, base);
+ if (nbuf >= sizeof buf - 1) {
+ buf[nbuf - 1] = '\0';
+ lfatal(curloc, "number %s... too long to represent", buf);
+ }
+ buf[nbuf++] = c;
+ }
+ buf[nbuf] = '\0';
- /* we only support base 10 floats */
- if (isfloat && base == 10) {
- t = mktok(Tfloatlit);
- t->id = strdupn(&fbuf[start], fidx - start);
- t->fltval = strtod(buf, NULL);
- } else {
- t = mktok(Tintlit);
- t->id = strdupn(&fbuf[start], fidx - start);
- t->intval = strtoull(buf, NULL, base);
- /* check suffixes:
- * u -> unsigned
- * l -> 64 bit
- * i -> 32 bit
- * w -> 16 bit
- * b -> 8 bit
- */
- unsignedval = 0;
+ /* we only support base 10 floats */
+ if (isfloat && base == 10) {
+ t = mktok(Tfloatlit);
+ t->id = strdupn(&fbuf[start], fidx - start);
+ t->fltval = strtod(buf, NULL);
+ }
+ else {
+ t = mktok(Tintlit);
+ t->id = strdupn(&fbuf[start], fidx - start);
+ t->intval = strtoull(buf, NULL, base);
+ /* check suffixes:
+ * u -> unsigned
+ * l -> 64 bit
+ * i -> 32 bit
+ * w -> 16 bit
+ * b -> 8 bit
+ */
+ unsignedval = 0;
nextsuffix:
- switch (peek()) {
- case 'u':
- if (unsignedval == 1)
- lfatal(curloc, "Duplicate 'u' integer specifier");
- next();
- unsignedval = 1;
- goto nextsuffix;
- case 'l':
- next();
- if (unsignedval)
- t->inttype = Tyuint64;
- else
- t->inttype = Tyint64;
- break;
- case 'i':
- next();
- if (unsignedval)
- t->inttype = Tyuint32;
- else
- t->inttype = Tyint32;
- break;
- case 's':
- next();
- if (unsignedval)
- t->inttype = Tyuint16;
- else
- t->inttype = Tyint16;
- break;
- case 'b':
- next();
- if (unsignedval)
- t->inttype = Tyuint8;
- else
- t->inttype = Tyint8;
- break;
- default:
- if (unsignedval)
- lfatal(curloc, "Unrecognized character int type specifier after 'u'");
- break;
- }
- }
+ switch (peek()) {
+ case 'u':
+ if (unsignedval == 1)
+ lfatal(curloc, "Duplicate 'u' integer specifier");
+ next();
+ unsignedval = 1;
+ goto nextsuffix;
+ case 'l':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint64;
+ else
+ t->inttype = Tyint64;
+ break;
+ case 'i':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint32;
+ else
+ t->inttype = Tyint32;
+ break;
+ case 's':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint16;
+ else
+ t->inttype = Tyint16;
+ break;
+ case 'b':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint8;
+ else
+ t->inttype = Tyint8;
+ break;
+ default:
+ if (unsignedval)
+ lfatal(
+ curloc, "Unrecognized character int type specifier after 'u'");
+ break;
+ }
+ }
- return t;
+ return t;
}
static Tok *numlit(void)
{
- Tok *t;
+ Tok *t;
- /* check for 0x or 0b prefix */
- if (match('0')) {
- if (match('x'))
- t = number(16);
- else if (match('b'))
- t = number(2);
- else if (match('o'))
- t = number(8);
- else
- t = number(10);
- } else {
- t = number(10);
- }
+ /* check for 0x or 0b prefix */
+ if (match('0')) {
+ if (match('x'))
+ t = number(16);
+ else if (match('b'))
+ t = number(2);
+ else if (match('o'))
+ t = number(8);
+ else
+ t = number(10);
+ }
+ else {
+ t = number(10);
+ }
- return t;
+ return t;
}
static Tok *typaram(void)
{
- Tok *t;
- char buf[1024];
+ Tok *t;
+ char buf[1024];
- t = NULL;
- if (!match('@'))
- return NULL;
- if (!identstr(buf, 1024))
- return NULL;
- t = mktok(Ttyparam);
- t->id = strdup(buf);
- return t;
+ t = NULL;
+ if (!match('@'))
+ return NULL;
+ if (!identstr(buf, 1024))
+ return NULL;
+ t = mktok(Ttyparam);
+ t->id = strdup(buf);
+ return t;
}
static Tok *toknext()
{
- Tok *t;
- int c;
+ Tok *t;
+ int c;
- eatspace();
- c = peek();
- if (c == End) {
- t = mktok(0);
- } else if (c == '\n') {
- curloc.line++;
- next();
- t = mktok(Tendln);
- } else if (isalpha(c) || c == '_' || c == '$') {
- t = kwident();
- } else if (c == '"') {
- t = strlit();
- } else if (c == '\'') {
- t = charlit();
- } else if (isdigit(c)) {
- t = numlit();
- } else if (c == '@') {
- t = typaram();
- } else {
- t = oper();
- }
+ eatspace();
+ c = peek();
+ if (c == End) {
+ t = mktok(0);
+ }
+ else if (c == '\n') {
+ curloc.line++;
+ next();
+ t = mktok(Tendln);
+ }
+ else if (isalpha(c) || c == '_' || c == '$') {
+ t = kwident();
+ }
+ else if (c == '"') {
+ t = strlit();
+ }
+ else if (c == '\'') {
+ t = charlit();
+ }
+ else if (isdigit(c)) {
+ t = numlit();
+ }
+ else if (c == '@') {
+ t = typaram();
+ }
+ else {
+ t = oper();
+ }
- if (!t || t->type == Terror)
- lfatal(curloc, "Unable to parse token starting with %c", c);
- return t;
+ if (!t || t->type == Terror)
+ lfatal(curloc, "Unable to parse token starting with %c", c);
+ return t;
}
void tokinit(char *file)
{
- int fd;
- int n;
- int nread;
+ int fd;
+ int n;
+ int nread;
+ fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "Unable to open file %s\n", file);
+ exit(1);
+ }
- fd = open(file, O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "Unable to open file %s\n", file);
- exit(1);
- }
+ nread = 0;
+ fbuf = malloc(4096);
+ while (1) {
+ n = read(fd, fbuf + nread, 4096);
+ if (n < 0)
+ fatal(0, 0, "Error reading file %s", file);
+ if (n == 0)
+ break;
+ if (!fbuf)
+ die("Out of memory reading %s", file);
+ nread += n;
+ fbuf = xrealloc(fbuf, nread + 4096);
+ }
- nread = 0;
- fbuf = malloc(4096);
- while (1) {
- n = read(fd, fbuf + nread, 4096);
- if (n < 0)
- fatal(0, 0, "Error reading file %s", file);
- if (n == 0)
- break;
- if (!fbuf)
- die("Out of memory reading %s", file);
- nread += n;
- fbuf = xrealloc(fbuf, nread + 4096);
- }
-
- fbufsz = nread;
- curloc.line = 1;
- curloc.file = 0;
- close(fd);
- filename = strdup(file);
+ fbufsz = nread;
+ curloc.line = 1;
+ curloc.file = 0;
+ close(fd);
+ filename = strdup(file);
}
/* Interface to yacc */
int yylex(void)
{
- curtok = toknext();
- yylval.tok = curtok;
- return curtok->type;
+ curtok = toknext();
+ yylval.tok = curtok;
+ return curtok->type;
}
void yyerror(const char *s)
{
- fprintf(stderr, "%s:%d: %s", filename, curloc.line, s);
- if (curtok->id)
- fprintf(stderr, " near \"%s\"", curtok->id);
- fprintf(stderr, "\n");
- exit(1);
+ fprintf(stderr, "%s:%d: %s", filename, curloc.line, s);
+ if (curtok->id)
+ fprintf(stderr, " near \"%s\"", curtok->id);
+ fprintf(stderr, "\n");
+ exit(1);
}
--- a/parse/type.c
+++ b/parse/type.c
@@ -15,8 +15,8 @@
typedef struct Typename Typename;
struct Typename {
- Ty ty;
- char *name;
+ Ty ty;
+ char *name;
};
Type **tytab = NULL;
@@ -29,49 +29,44 @@
static Trait *traits[Ntypes + 1][4];
static int tybfmt(char *buf, size_t len, Type *t);
-
char stackness[] = {
-#define Ty(t, n, stk) \
- stk,
+#define Ty(t, n, stk) stk,
#include "types.def"
#undef Ty
};
-int isstacktype(Type *t)
-{
- return stackness[tybase(t)->type];
-}
+int isstacktype(Type *t) { return stackness[tybase(t)->type]; }
Type *mktype(Srcloc loc, Ty ty)
{
- Type *t;
- int i;
+ Type *t;
+ int i;
- /* the first 'n' types will be identity mapped: tytab[Tyint], eg,
- * will map to an instantitaion of Tyint.
- *
- * This is accomplished at program startup by calling mktype() on
- * each builtin type in order. As we do this, we put the type into
- * the table as ususal, which gives us an identity mapping.
- */
- if (ty <= Tyvalist && ty < ntypes)
- return types[ty];
+ /* the first 'n' types will be identity mapped: tytab[Tyint], eg,
+ * will map to an instantitaion of Tyint.
+ *
+ * This is accomplished at program startup by calling mktype() on
+ * each builtin type in order. As we do this, we put the type into
+ * the table as ususal, which gives us an identity mapping.
+ */
+ if (ty <= Tyvalist && ty < ntypes)
+ return types[ty];
- t = zalloc(sizeof(Type));
- t->type = ty;
- t->tid = ntypes++;
- t->loc = loc;
- tytab = xrealloc(tytab, ntypes*sizeof(Type*));
- tytab[t->tid] = NULL;
- types = xrealloc(types, ntypes*sizeof(Type*));
- types[t->tid] = t;
- if (ty <= Tyvalist) /* the last builtin atomic type */
- t->vis = Visbuiltin;
+ t = zalloc(sizeof(Type));
+ t->type = ty;
+ t->tid = ntypes++;
+ t->loc = loc;
+ tytab = xrealloc(tytab, ntypes * sizeof(Type *));
+ tytab[t->tid] = NULL;
+ types = xrealloc(types, ntypes * sizeof(Type *));
+ types[t->tid] = t;
+ if (ty <= Tyvalist) /* the last builtin atomic type */
+ t->vis = Visbuiltin;
- for(i = 0; traits[ty][i]; i++)
- settrait(t, traits[ty][i]);
+ for (i = 0; traits[ty][i]; i++)
+ settrait(t, traits[ty][i]);
- return t;
+ return t;
}
/*
@@ -80,34 +75,34 @@
*/
Type *tydup(Type *t)
{
- Type *r;
+ Type *r;
- r = mktype(t->loc, t->type);
- r->resolved = 0; /* re-resolving doesn't hurt */
- r->fixed = 0; /* re-resolving doesn't hurt */
+ r = mktype(t->loc, t->type);
+ r->resolved = 0; /* re-resolving doesn't hurt */
+ r->fixed = 0; /* re-resolving doesn't hurt */
- r->traits = bsdup(t->traits);
- r->traitlist = memdup(t->traitlist, t->ntraitlist * sizeof(Node*));
- r->ntraitlist = t->ntraitlist;
+ r->traits = bsdup(t->traits);
+ r->traitlist = memdup(t->traitlist, t->ntraitlist * sizeof(Node *));
+ r->ntraitlist = t->ntraitlist;
- r->arg = memdup(t->arg, t->narg * sizeof(Type*));
- r->narg = t->narg;
- r->inst = memdup(t->arg, t->narg * sizeof(Type*));
- r->ninst = t->ninst;
+ r->arg = memdup(t->arg, t->narg * sizeof(Type *));
+ r->narg = t->narg;
+ r->inst = memdup(t->arg, t->narg * sizeof(Type *));
+ r->ninst = t->ninst;
- r->sub = memdup(t->sub, t->nsub * sizeof(Type*));
- r->nsub = t->nsub;
- r->nmemb = t->nmemb;
- switch (t->type) {
- case Tyname: r->name = t->name; break;
- case Tyunres: r->name = t->name; break;
- case Tyarray: r->asize = t->asize; break;
- case Typaram: r->pname = strdup(t->pname); break;
- case Tystruct: r->sdecls = memdup(t->sdecls, t->nmemb*sizeof(Node*)); break;
- case Tyunion: r->udecls = memdup(t->udecls, t->nmemb*sizeof(Node*)); break;
- default: break;
- }
- return r;
+ r->sub = memdup(t->sub, t->nsub * sizeof(Type *));
+ r->nsub = t->nsub;
+ r->nmemb = t->nmemb;
+ switch (t->type) {
+ case Tyname: r->name = t->name; break;
+ case Tyunres: r->name = t->name; break;
+ case Tyarray: r->asize = t->asize; break;
+ case Typaram: r->pname = strdup(t->pname); break;
+ case Tystruct: r->sdecls = memdup(t->sdecls, t->nmemb * sizeof(Node *)); break;
+ case Tyunion: r->udecls = memdup(t->udecls, t->nmemb * sizeof(Node *)); break;
+ default: break;
+ }
+ return r;
}
/*
@@ -116,235 +111,238 @@
*/
Type *mktylike(Srcloc loc, Ty like)
{
- Type *t;
- int i;
+ Type *t;
+ int i;
- t = mktyvar(loc);
- for (i = 0; traits[like][i]; i++)
- settrait(t, traits[like][i]);
- return t;
+ t = mktyvar(loc);
+ for (i = 0; traits[like][i]; i++)
+ settrait(t, traits[like][i]);
+ return t;
}
/* steals memb, funcs */
-Trait *mktrait(Srcloc loc, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto)
+Trait *mktrait(Srcloc loc, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs,
+ size_t nfuncs, int isproto)
{
- Trait *t;
+ Trait *t;
- t = zalloc(sizeof(Trait));
- t->uid = ntraittab++;
- t->loc = loc;
- if (t->uid < Ntraits)
- t->vis = Visbuiltin;
- t->vis = Visintern;
- t->name = name;
- t->param = param;
- t->memb = memb;
- t->nmemb = nmemb;
- t->funcs = funcs;
- t->nfuncs = nfuncs;
- t->isproto = isproto;
+ t = zalloc(sizeof(Trait));
+ t->uid = ntraittab++;
+ t->loc = loc;
+ if (t->uid < Ntraits)
+ t->vis = Visbuiltin;
+ t->vis = Visintern;
+ t->name = name;
+ t->param = param;
+ t->memb = memb;
+ t->nmemb = nmemb;
+ t->funcs = funcs;
+ t->nfuncs = nfuncs;
+ t->isproto = isproto;
- traittab = xrealloc(traittab, ntraittab*sizeof(Trait*));
- traittab[t->uid] = t;
- return t;
+ traittab = xrealloc(traittab, ntraittab * sizeof(Trait *));
+ traittab[t->uid] = t;
+ return t;
}
Type *mktyvar(Srcloc loc)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyvar);
- return t;
+ t = mktype(loc, Tyvar);
+ return t;
}
Type *mktyparam(Srcloc loc, char *name)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Typaram);
- t->pname = strdup(name);
- return t;
+ t = mktype(loc, Typaram);
+ t->pname = strdup(name);
+ return t;
}
Type *mktyunres(Srcloc loc, Node *name, Type **arg, size_t narg)
{
- Type *t;
+ Type *t;
- /* resolve it in the type inference stage */
- t = mktype(loc, Tyunres);
- t->name = name;
- t->arg = arg;
- t->narg = narg;
- return t;
+ /* resolve it in the type inference stage */
+ t = mktype(loc, Tyunres);
+ t->name = name;
+ t->arg = arg;
+ t->narg = narg;
+ return t;
}
Type *mktygeneric(Srcloc loc, Node *name, Type **param, size_t nparam, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tygeneric);
- t->name = name;
- t->nsub = 1;
- t->traits = bsdup(base->traits);
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- t->gparam = param;
- t->ngparam = nparam;
- return t;
+ t = mktype(loc, Tygeneric);
+ t->name = name;
+ t->nsub = 1;
+ t->traits = bsdup(base->traits);
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ t->gparam = param;
+ t->ngparam = nparam;
+ return t;
}
Type *mktyname(Srcloc loc, Node *name, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyname);
- t->name = name;
- t->nsub = 1;
- t->traits = bsdup(base->traits);
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Tyname);
+ t->name = name;
+ t->nsub = 1;
+ t->traits = bsdup(base->traits);
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktyarray(Srcloc loc, Type *base, Node *sz)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyarray);
- t->nsub = 1;
- t->nmemb = 1; /* the size is a "member" */
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- t->asize = sz;
+ t = mktype(loc, Tyarray);
+ t->nsub = 1;
+ t->nmemb = 1; /* the size is a "member" */
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ t->asize = sz;
- return t;
+ return t;
}
Type *mktyslice(Srcloc loc, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyslice);
- t->nsub = 1;
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Tyslice);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktyidxhack(Srcloc loc, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyvar);
- t->nsub = 1;
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Tyvar);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktyptr(Srcloc loc, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Typtr);
- t->nsub = 1;
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Typtr);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktytuple(Srcloc loc, Type **sub, size_t nsub)
{
- Type *t;
- size_t i;
+ Type *t;
+ size_t i;
- t = mktype(loc, Tytuple);
- t->nsub = nsub;
- t->sub = xalloc(nsub*sizeof(Type*));
- for (i = 0; i < nsub; i++)
- t->sub[i] = sub[i];
- return t;
+ t = mktype(loc, Tytuple);
+ t->nsub = nsub;
+ t->sub = xalloc(nsub * sizeof(Type *));
+ for (i = 0; i < nsub; i++)
+ t->sub[i] = sub[i];
+ return t;
}
Type *mktyfunc(Srcloc loc, Node **args, size_t nargs, Type *ret)
{
- Type *t;
- size_t i;
+ Type *t;
+ size_t i;
- t = mktype(loc, Tyfunc);
- t->nsub = nargs + 1;
- t->sub = xalloc((1 + nargs)*sizeof(Type*));
- t->sub[0] = ret;
- for (i = 0; i < nargs; i++)
- t->sub[i + 1] = nodetype(args[i]);
- return t;
+ t = mktype(loc, Tyfunc);
+ t->nsub = nargs + 1;
+ t->sub = xalloc((1 + nargs) * sizeof(Type *));
+ t->sub[0] = ret;
+ for (i = 0; i < nargs; i++)
+ t->sub[i + 1] = nodetype(args[i]);
+ return t;
}
Type *mktystruct(Srcloc loc, Node **decls, size_t ndecls)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tystruct);
- t->nsub = 0;
- t->nmemb = ndecls;
- t->sdecls = memdup(decls, ndecls*sizeof(Node *));
- return t;
+ t = mktype(loc, Tystruct);
+ t->nsub = 0;
+ t->nmemb = ndecls;
+ t->sdecls = memdup(decls, ndecls * sizeof(Node *));
+ return t;
}
Type *mktyunion(Srcloc loc, Ucon **decls, size_t ndecls)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyunion);
- t->nmemb = ndecls;
- t->udecls = decls;
- return t;
+ t = mktype(loc, Tyunion);
+ t->nmemb = ndecls;
+ t->udecls = decls;
+ return t;
}
Ucon *finducon(Type *ty, Node *name)
{
- size_t i;
+ size_t i;
- ty = tybase(ty);
- for (i = 0; i < ty->nmemb; i++)
- if (!strcmp(namestr(ty->udecls[i]->name), namestr(name)))
- return ty->udecls[i];
- return NULL;
+ ty = tybase(ty);
+ for (i = 0; i < ty->nmemb; i++)
+ if (!strcmp(namestr(ty->udecls[i]->name), namestr(name)))
+ return ty->udecls[i];
+ return NULL;
}
int istyunsigned(Type *t)
{
- switch (tybase(t)->type) {
- case Tybyte: case Tyuint8: case Tyuint16: case Tyuint:
- case Tychar: case Tyuint32: case Tyuint64:
- case Typtr: case Tybool:
- return 1;
- default:
- return 0;
- }
+ switch (tybase(t)->type) {
+ case Tybyte:
+ case Tyuint8:
+ case Tyuint16:
+ case Tyuint:
+ case Tychar:
+ case Tyuint32:
+ case Tyuint64:
+ case Typtr:
+ case Tybool: return 1;
+ default: return 0;
+ }
}
int istysigned(Type *t)
{
- switch (tybase(t)->type) {
- case Tyint8: case Tyint16: case Tyint:
- case Tyint32: case Tyint64:
- return 1;
- default:
- return 0;
- }
+ switch (tybase(t)->type) {
+ case Tyint8:
+ case Tyint16:
+ case Tyint:
+ case Tyint32:
+ case Tyint64: return 1;
+ default: return 0;
+ }
}
int istyfloat(Type *t)
{
- t = tybase(t);
- return t->type == Tyflt32 || t->type == Tyflt64;
+ t = tybase(t);
+ return t->type == Tyflt32 || t->type == Tyflt64;
}
-int istyprimitive(Type *t)
-{
- return istysigned(t) || istyunsigned(t) || istyfloat(t);
-}
+int istyprimitive(Type *t) { return istysigned(t) || istyunsigned(t) || istyfloat(t); }
/*
* Checks if a type contains any type
@@ -352,570 +350,553 @@
*/
int hasparamsrec(Type *t, Bitset *visited)
{
- size_t i;
+ size_t i;
- if (bshas(visited, t->tid))
- return 0;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram:
- case Tygeneric:
- return 1;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- if (hasparamsrec(t->arg[i], visited))
- return 1;
- return hasparamsrec(t->sub[0], visited);
- case Tyunres:
- for (i = 0; i < t->narg; i++)
- if (hasparamsrec(t->arg[i], visited))
- return 1;
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- if (hasparamsrec(t->sdecls[i]->decl.type, visited))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype && hasparamsrec(t->udecls[i]->etype, visited))
- return 1;
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- if (hasparamsrec(t->sub[i], visited))
- return 1;
- break;
- }
- return 0;
+ if (bshas(visited, t->tid))
+ return 0;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram:
+ case Tygeneric: return 1;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ if (hasparamsrec(t->arg[i], visited))
+ return 1;
+ return hasparamsrec(t->sub[0], visited);
+ case Tyunres:
+ for (i = 0; i < t->narg; i++)
+ if (hasparamsrec(t->arg[i], visited))
+ return 1;
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ if (hasparamsrec(t->sdecls[i]->decl.type, visited))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype && hasparamsrec(t->udecls[i]->etype, visited))
+ return 1;
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ if (hasparamsrec(t->sub[i], visited))
+ return 1;
+ break;
+ }
+ return 0;
}
int hasparams(Type *t)
{
- Bitset *visited;
- int r;
+ Bitset *visited;
+ int r;
- visited = mkbs();
- r = hasparamsrec(t, visited);
- bsfree(visited);
- return r;
+ visited = mkbs();
+ r = hasparamsrec(t, visited);
+ bsfree(visited);
+ return r;
}
Type *tybase(Type *t)
{
- assert(t != NULL);
- while (t->type == Tyname || t->type == Tygeneric)
- t = t->sub[0];
- return t;
+ assert(t != NULL);
+ while (t->type == Tyname || t->type == Tygeneric)
+ t = t->sub[0];
+ return t;
}
-
static int namefmt(char *buf, size_t len, Node *n)
{
- char *p;
- char *end;
+ char *p;
+ char *end;
- p = buf;
- end = p + len;
- if (n->name.ns)
- p += bprintf(p, end - p, "%s.", n->name.ns);
- p += bprintf(p, end - p, "%s", n->name.name);
- return len - (end - p);
+ p = buf;
+ end = p + len;
+ if (n->name.ns)
+ p += bprintf(p, end - p, "%s.", n->name.ns);
+ p += bprintf(p, end - p, "%s", n->name.name);
+ return len - (end - p);
}
int settrait(Type *t, Trait *c)
{
- if (!t->traits)
- t->traits = mkbs();
- bsput(t->traits, c->uid);
- return 1;
+ if (!t->traits)
+ t->traits = mkbs();
+ bsput(t->traits, c->uid);
+ return 1;
}
-int hastrait(Type *t, Trait *c)
-{
- return t->traits && bshas(t->traits, c->uid);
-}
+int hastrait(Type *t, Trait *c) { return t->traits && bshas(t->traits, c->uid); }
int traitfmt(char *buf, size_t len, Type *t)
{
- size_t i;
- char *p;
- char *end;
- char *sep;
+ size_t i;
+ char *p;
+ char *end;
+ char *sep;
- if (!t->traits || !bscount(t->traits))
- return 0;
+ if (!t->traits || !bscount(t->traits))
+ return 0;
- p = buf;
- end = p + len;
+ p = buf;
+ end = p + len;
- p += bprintf(p, end - p, " :: ");
- sep = "";
- for (i = 0; i < ntraittab; i++) {
- if (bshas(t->traits, i)) {
- p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
- sep = ",";
- }
- }
- return p - buf;
+ p += bprintf(p, end - p, " :: ");
+ sep = "";
+ for (i = 0; i < ntraittab; i++) {
+ if (bshas(t->traits, i)) {
+ p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
+ sep = ",";
+ }
+ }
+ return p - buf;
}
static int fmtstruct(char *buf, size_t len, Type *t)
{
- size_t i;
- char *end, *p;
- char *name, *ty;
+ size_t i;
+ char *end, *p;
+ char *name, *ty;
- p = buf;
- end = p + len;
- p += bprintf(p, end - p, "struct\n");
- for (i = 0; i < t->nmemb; i++) {
- name = declname(t->sdecls[i]);
- ty = tystr(decltype(t->sdecls[i]));
- p += bprintf(p, end - p, "\t%s:%s\n ", name, ty);
- free(ty);
- }
- p += bprintf(p, end - p, ";;");
- return p - buf;
+ p = buf;
+ end = p + len;
+ p += bprintf(p, end - p, "struct\n");
+ for (i = 0; i < t->nmemb; i++) {
+ name = declname(t->sdecls[i]);
+ ty = tystr(decltype(t->sdecls[i]));
+ p += bprintf(p, end - p, "\t%s:%s\n ", name, ty);
+ free(ty);
+ }
+ p += bprintf(p, end - p, ";;");
+ return p - buf;
}
static int fmtunion(char *buf, size_t len, Type *t)
{
- size_t i;
- char *end, *p;
- char *name, *ty;
+ size_t i;
+ char *end, *p;
+ char *name, *ty;
- p = buf;
- end = p + len;
- p += bprintf(p, end - p, "union\n");
- for (i = 0; i < t->nmemb; i++) {
- name = namestr(t->udecls[i]->name);
- if (t->udecls[i]->etype) {
- ty = tystr(t->udecls[i]->etype);
- p += bprintf(p, end - p, "\t`%s %s\n", name, ty);
- free(ty);
- } else {
- p += bprintf(p, end - p, "\t`%s\n", name);
- }
- }
- p += bprintf(p, end - p, ";;");
- return p - buf;
+ p = buf;
+ end = p + len;
+ p += bprintf(p, end - p, "union\n");
+ for (i = 0; i < t->nmemb; i++) {
+ name = namestr(t->udecls[i]->name);
+ if (t->udecls[i]->etype) {
+ ty = tystr(t->udecls[i]->etype);
+ p += bprintf(p, end - p, "\t`%s %s\n", name, ty);
+ free(ty);
+ }
+ else {
+ p += bprintf(p, end - p, "\t`%s\n", name);
+ }
+ }
+ p += bprintf(p, end - p, ";;");
+ return p - buf;
}
static int fmtlist(char *buf, size_t len, Type **arg, size_t narg)
{
- char *end, *p, *sep;
- size_t i;
+ char *end, *p, *sep;
+ size_t i;
- sep = "";
- p = buf;
- end = p + len;
- p += bprintf(p, end - p, "(");
- for (i = 0; i < narg; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, arg[i]);
- sep = ", ";
- }
- p += bprintf(p, end - p, ")");
- return p - buf;
+ sep = "";
+ p = buf;
+ end = p + len;
+ p += bprintf(p, end - p, "(");
+ for (i = 0; i < narg; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, arg[i]);
+ sep = ", ";
+ }
+ p += bprintf(p, end - p, ")");
+ return p - buf;
}
static int tybfmt(char *buf, size_t len, Type *t)
{
- size_t i;
- char *p;
- char *end;
- char *sep;
+ size_t i;
+ char *p;
+ char *end;
+ char *sep;
- sep = "";
- p = buf;
- end = p + len;
- if (!t) {
- p += bprintf(p, end - p, "tynil");
- return len - (end - p);
- }
- switch (t->type) {
- case Tybad: p += bprintf(p, end - p, "BAD"); break;
- case Tyvoid: p += bprintf(p, end - p, "void"); break;
- case Tybool: p += bprintf(p, end - p, "bool"); break;
- case Tychar: p += bprintf(p, end - p, "char"); break;
- case Tyint8: p += bprintf(p, end - p, "int8"); break;
- case Tyint16: p += bprintf(p, end - p, "int16"); break;
- case Tyint: p += bprintf(p, end - p, "int"); break;
- case Tyint32: p += bprintf(p, end - p, "int32"); break;
- case Tyint64: p += bprintf(p, end - p, "int64"); break;
- case Tybyte: p += bprintf(p, end - p, "byte"); break;
- case Tyuint8: p += bprintf(p, end - p, "uint8"); break;
- case Tyuint16: p += bprintf(p, end - p, "uint16"); break;
- case Tyuint: p += bprintf(p, end - p, "uint"); break;
- case Tyuint32: p += bprintf(p, end - p, "uint32"); break;
- case Tyuint64: p += bprintf(p, end - p, "uint64"); break;
- case Tyflt32: p += bprintf(p, end - p, "flt32"); break;
- case Tyflt64: p += bprintf(p, end - p, "flt64"); break;
- case Tyvalist: p += bprintf(p, end - p, "..."); break;
+ sep = "";
+ p = buf;
+ end = p + len;
+ if (!t) {
+ p += bprintf(p, end - p, "tynil");
+ return len - (end - p);
+ }
+ switch (t->type) {
+ case Tybad: p += bprintf(p, end - p, "BAD"); break;
+ case Tyvoid: p += bprintf(p, end - p, "void"); break;
+ case Tybool: p += bprintf(p, end - p, "bool"); break;
+ case Tychar: p += bprintf(p, end - p, "char"); break;
+ case Tyint8: p += bprintf(p, end - p, "int8"); break;
+ case Tyint16: p += bprintf(p, end - p, "int16"); break;
+ case Tyint: p += bprintf(p, end - p, "int"); break;
+ case Tyint32: p += bprintf(p, end - p, "int32"); break;
+ case Tyint64: p += bprintf(p, end - p, "int64"); break;
+ case Tybyte: p += bprintf(p, end - p, "byte"); break;
+ case Tyuint8: p += bprintf(p, end - p, "uint8"); break;
+ case Tyuint16: p += bprintf(p, end - p, "uint16"); break;
+ case Tyuint: p += bprintf(p, end - p, "uint"); break;
+ case Tyuint32: p += bprintf(p, end - p, "uint32"); break;
+ case Tyuint64: p += bprintf(p, end - p, "uint64"); break;
+ case Tyflt32: p += bprintf(p, end - p, "flt32"); break;
+ case Tyflt64: p += bprintf(p, end - p, "flt64"); break;
+ case Tyvalist: p += bprintf(p, end - p, "..."); break;
- case Typtr:
- p += tybfmt(p, end - p, t->sub[0]);
- p += bprintf(p, end - p, "#");
- break;
- case Tyslice:
- p += tybfmt(p, end - p, t->sub[0]);
- p += bprintf(p, end - p, "[:]");
- break;
- case Tyarray:
- p += tybfmt(p, end - p, t->sub[0]);
- if (t->asize) {
- i = t->asize->expr.args[0]->lit.intval;
- p += bprintf(p, end - p, "[%zd]", i);
- } else {
- p += bprintf(p, end - p, "[]");
- }
- break;
- case Tycode:
- case Tyfunc:
- p += bprintf(p, end - p, "(");
- for (i = 1; i < t->nsub; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->sub[i]);
- sep = ", ";
- }
- p += bprintf(p, end - p, " -> ");
- p += tybfmt(p, end - p, t->sub[0]);
- p += bprintf(p, end - p, ")");
- break;
- case Tytuple:
- p += bprintf(p, end - p, "(");
- for (i = 0; i < t->nsub; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->sub[i]);
- sep = ",";
- }
- p += bprintf(p, end - p, ")");
- break;
- case Tyvar:
- p += bprintf(p, end - p, "$%d", t->tid);
- if (t->nsub) {
- p += bprintf(p, end - p, "(");
- for (i = 0; i < t->nsub; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->sub[i]);
- sep = ", ";
- }
- p += bprintf(p, end - p, ")[]");
- }
- break;
- case Typaram:
- p += bprintf(p, end - p, "@%s", t->pname);
- break;
- case Tyunres:
- p += namefmt(p, end - p, t->name);
- if (t->narg)
- p += fmtlist(p, end - p, t->arg, t->narg);
- break;
- case Tyname:
- if (t->name->name.ns)
- p += bprintf(p, end - p, "%s.", t->name->name.ns);
- p += bprintf(p, end - p, "%s", namestr(t->name));
- if (t->narg)
- p += fmtlist(p, end - p, t->arg, t->narg);
- break;
- case Tygeneric:
- if (t->name->name.ns)
- p += bprintf(p, end - p, "%s.", t->name->name.ns);
- p += bprintf(p, end - p, "%s", namestr(t->name));
- if (t->ngparam)
- p += fmtlist(p, end - p, t->gparam, t->ngparam);
- break;
- case Tystruct: p += fmtstruct(p, end - p, t); break;
- case Tyunion: p += fmtunion(p, end - p, t); break;
- case Ntypes:
- die("Ntypes is not a type");
- break;
- }
+ case Typtr:
+ p += tybfmt(p, end - p, t->sub[0]);
+ p += bprintf(p, end - p, "#");
+ break;
+ case Tyslice:
+ p += tybfmt(p, end - p, t->sub[0]);
+ p += bprintf(p, end - p, "[:]");
+ break;
+ case Tyarray:
+ p += tybfmt(p, end - p, t->sub[0]);
+ if (t->asize) {
+ i = t->asize->expr.args[0]->lit.intval;
+ p += bprintf(p, end - p, "[%zd]", i);
+ }
+ else {
+ p += bprintf(p, end - p, "[]");
+ }
+ break;
+ case Tycode:
+ case Tyfunc:
+ p += bprintf(p, end - p, "(");
+ for (i = 1; i < t->nsub; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->sub[i]);
+ sep = ", ";
+ }
+ p += bprintf(p, end - p, " -> ");
+ p += tybfmt(p, end - p, t->sub[0]);
+ p += bprintf(p, end - p, ")");
+ break;
+ case Tytuple:
+ p += bprintf(p, end - p, "(");
+ for (i = 0; i < t->nsub; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->sub[i]);
+ sep = ",";
+ }
+ p += bprintf(p, end - p, ")");
+ break;
+ case Tyvar:
+ p += bprintf(p, end - p, "$%d", t->tid);
+ if (t->nsub) {
+ p += bprintf(p, end - p, "(");
+ for (i = 0; i < t->nsub; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->sub[i]);
+ sep = ", ";
+ }
+ p += bprintf(p, end - p, ")[]");
+ }
+ break;
+ case Typaram: p += bprintf(p, end - p, "@%s", t->pname); break;
+ case Tyunres:
+ p += namefmt(p, end - p, t->name);
+ if (t->narg)
+ p += fmtlist(p, end - p, t->arg, t->narg);
+ break;
+ case Tyname:
+ if (t->name->name.ns)
+ p += bprintf(p, end - p, "%s.", t->name->name.ns);
+ p += bprintf(p, end - p, "%s", namestr(t->name));
+ if (t->narg)
+ p += fmtlist(p, end - p, t->arg, t->narg);
+ break;
+ case Tygeneric:
+ if (t->name->name.ns)
+ p += bprintf(p, end - p, "%s.", t->name->name.ns);
+ p += bprintf(p, end - p, "%s", namestr(t->name));
+ if (t->ngparam)
+ p += fmtlist(p, end - p, t->gparam, t->ngparam);
+ break;
+ case Tystruct: p += fmtstruct(p, end - p, t); break;
+ case Tyunion: p += fmtunion(p, end - p, t); break;
+ case Ntypes: die("Ntypes is not a type"); break;
+ }
- /* we only show constraints on non-builtin typaram */
- if (t->type == Tyvar || t->type == Typaram)
- p += traitfmt(p, end - p, t);
+ /* we only show constraints on non-builtin typaram */
+ if (t->type == Tyvar || t->type == Typaram)
+ p += traitfmt(p, end - p, t);
- return p - buf;
+ return p - buf;
}
char *tyfmt(char *buf, size_t len, Type *t)
{
- tybfmt(buf, len, t);
- return buf;
+ tybfmt(buf, len, t);
+ return buf;
}
char *traitstr(Type *t)
{
- char buf[1024];
- traitfmt(buf, 1024, t);
- return strdup(buf);
+ char buf[1024];
+ traitfmt(buf, 1024, t);
+ return strdup(buf);
}
char *tystr(Type *t)
{
- char buf[1024];
- tyfmt(buf, 1024, t);
- return strdup(buf);
+ char buf[1024];
+ tyfmt(buf, 1024, t);
+ return strdup(buf);
}
ulong tyhash(void *ty)
{
- size_t i;
- Type *t;
- ulong hash;
+ size_t i;
+ Type *t;
+ ulong hash;
- t = (Type *)ty;
- switch (t->type) {
- /* Important: we want tyhash to be consistent cross-file, since it
- * is used in naming trait impls and such.
- *
- * We should find a better name.
- */
- case Tyvar: hash = inthash(t->tid); break;
- case Typaram: hash = strhash(t->pname); break;
- case Tyunion: hash = inthash(t->type); break;
- case Tystruct: hash = inthash(t->type); break;
- case Tyname: hash = namehash(t->name); break;
- default: hash = inthash(t->type); break;
- }
+ t = (Type *)ty;
+ switch (t->type) {
+ /* Important: we want tyhash to be consistent cross-file, since it
+ * is used in naming trait impls and such.
+ *
+ * We should find a better name.
+ */
+ case Tyvar: hash = inthash(t->tid); break;
+ case Typaram: hash = strhash(t->pname); break;
+ case Tyunion: hash = inthash(t->type); break;
+ case Tystruct: hash = inthash(t->type); break;
+ case Tyname: hash = namehash(t->name); break;
+ default: hash = inthash(t->type); break;
+ }
- for (i = 0; i < t->narg; i++)
- hash ^= tyhash(t->arg[i]);
- return hash;
+ for (i = 0; i < t->narg; i++)
+ hash ^= tyhash(t->arg[i]);
+ return hash;
}
int tyeq_rec(Type *a, Type *b, Bitset *visited)
{
- size_t i;
+ size_t i;
- if (!a || !b)
- return a == b;
- if (a->type != b->type)
- return 0;
- if (a->narg != b->narg)
- return 0;
- if (a->nsub != b->nsub)
- return 0;
- if (a->nmemb != b->nmemb)
- return 0;
+ if (!a || !b)
+ return a == b;
+ if (a->type != b->type)
+ return 0;
+ if (a->narg != b->narg)
+ return 0;
+ if (a->nsub != b->nsub)
+ return 0;
+ if (a->nmemb != b->nmemb)
+ return 0;
- if (a->tid == b->tid)
- return 1;
- if (bshas(visited, a->tid) || bshas(visited, b->tid))
- return 1;
+ if (a->tid == b->tid)
+ return 1;
+ if (bshas(visited, a->tid) || bshas(visited, b->tid))
+ return 1;
- bsput(visited, a->tid);
- bsput(visited, b->tid);
+ bsput(visited, a->tid);
+ bsput(visited, b->tid);
- switch (a->type) {
- case Typaram:
- return streq(a->pname, b->pname);
- break;
- case Tyvar:
- if (a->tid != b->tid)
- return 0;
- break;
- case Tyunres:
- if (!nameeq(a->name, b->name))
- return 0;
- case Tyunion:
- for (i = 0; i < a->nmemb; i++) {
- if (!nameeq(a->udecls[i]->name, b->udecls[i]->name))
- return 0;
- if (!tyeq_rec(a->udecls[i]->etype, b->udecls[i]->etype, visited))
- return 0;
- }
- break;
- case Tystruct:
- for (i = 0; i < a->nmemb; i++) {
- if (strcmp(declname(a->sdecls[i]), declname(b->sdecls[i])) != 0)
- return 0;
- if (!tyeq_rec(decltype(a->sdecls[i]), decltype(b->sdecls[i]), visited))
- return 0;
- }
- break;
- case Tyname:
- if (!nameeq(a->name, b->name))
- return 0;
- for (i = 0; i < a->narg; i++)
- if (!tyeq_rec(a->arg[i], b->arg[i], visited))
- return 0;
- for (i = 0; i < a->nsub; i++)
- if (!tyeq_rec(a->sub[i], b->sub[i], visited))
- return 0;
- break;
- case Tyarray:
- if (arraysz(a->asize) != arraysz(b->asize))
- return 0;
- break;
- default:
- break;
- }
- for (i = 0; i < a->nsub; i++)
- if (!tyeq_rec(a->sub[i], b->sub[i], visited))
- return 0;
- return 1;
+ switch (a->type) {
+ case Typaram: return streq(a->pname, b->pname); break;
+ case Tyvar:
+ if (a->tid != b->tid)
+ return 0;
+ break;
+ case Tyunres:
+ if (!nameeq(a->name, b->name))
+ return 0;
+ case Tyunion:
+ for (i = 0; i < a->nmemb; i++) {
+ if (!nameeq(a->udecls[i]->name, b->udecls[i]->name))
+ return 0;
+ if (!tyeq_rec(a->udecls[i]->etype, b->udecls[i]->etype, visited))
+ return 0;
+ }
+ break;
+ case Tystruct:
+ for (i = 0; i < a->nmemb; i++) {
+ if (strcmp(declname(a->sdecls[i]), declname(b->sdecls[i])) != 0)
+ return 0;
+ if (!tyeq_rec(decltype(a->sdecls[i]), decltype(b->sdecls[i]), visited))
+ return 0;
+ }
+ break;
+ case Tyname:
+ if (!nameeq(a->name, b->name))
+ return 0;
+ for (i = 0; i < a->narg; i++)
+ if (!tyeq_rec(a->arg[i], b->arg[i], visited))
+ return 0;
+ for (i = 0; i < a->nsub; i++)
+ if (!tyeq_rec(a->sub[i], b->sub[i], visited))
+ return 0;
+ break;
+ case Tyarray:
+ if (arraysz(a->asize) != arraysz(b->asize))
+ return 0;
+ break;
+ default: break;
+ }
+ for (i = 0; i < a->nsub; i++)
+ if (!tyeq_rec(a->sub[i], b->sub[i], visited))
+ return 0;
+ return 1;
}
int tyeq(void *a, void *b)
{
- Bitset *bs;
- int eq;
+ Bitset *bs;
+ int eq;
- if (a == b)
- return 1;
- bs = mkbs();
- eq = tyeq_rec(a, b, bs);
- bsfree(bs);
- return eq;
+ if (a == b)
+ return 1;
+ bs = mkbs();
+ eq = tyeq_rec(a, b, bs);
+ bsfree(bs);
+ return eq;
}
size_t tyidfmt(char *buf, size_t sz, Type *ty)
{
- size_t i;
- char *p, *end;
+ size_t i;
+ char *p, *end;
- p = buf;
- end = buf + sz;
- switch (ty->type) {
- case Ntypes:
- case Tybad: die("invalid type"); break;
- case Tyvar: die("tyvar has no idstr"); break;
- case Tyvoid: p += bprintf(p, end - p, "v"); break;
- case Tychar: p += bprintf(p, end - p, "c"); break;
- case Tybool: p += bprintf(p, end - p, "t"); break;
- case Tyint8: p += bprintf(p, end - p, "b"); break;
- case Tyint16: p += bprintf(p, end - p, "s"); break;
- case Tyint: p += bprintf(p, end - p, "i"); break;
- case Tyint32: p += bprintf(p, end - p, "w"); break;
- case Tyint64: p += bprintf(p, end - p, "q"); break;
+ p = buf;
+ end = buf + sz;
+ switch (ty->type) {
+ case Ntypes:
+ case Tybad: die("invalid type"); break;
+ case Tyvar: die("tyvar has no idstr"); break;
+ case Tyvoid: p += bprintf(p, end - p, "v"); break;
+ case Tychar: p += bprintf(p, end - p, "c"); break;
+ case Tybool: p += bprintf(p, end - p, "t"); break;
+ case Tyint8: p += bprintf(p, end - p, "b"); break;
+ case Tyint16: p += bprintf(p, end - p, "s"); break;
+ case Tyint: p += bprintf(p, end - p, "i"); break;
+ case Tyint32: p += bprintf(p, end - p, "w"); break;
+ case Tyint64: p += bprintf(p, end - p, "q"); break;
- case Tybyte: p += bprintf(p, end - p, "H"); break;
- case Tyuint8: p += bprintf(p, end - p, "B"); break;
- case Tyuint16: p += bprintf(p, end - p, "S"); break;
- case Tyuint: p += bprintf(p, end - p, "I"); break;
- case Tyuint32: p += bprintf(p, end - p, "W"); break;
- case Tyuint64: p += bprintf(p, end - p, "Q"); break;
- case Tyflt32: p += bprintf(p, end - p, "f"); break;
- case Tyflt64: p += bprintf(p, end - p, "d"); break;
- case Tyvalist: p += bprintf(p, end - p, "V"); break;
- case Typtr:
- p += bprintf(p, end - p, "$p");
- p += tyidfmt(p, end - p, ty->sub[0]);
- break;
- case Tyarray:
- p += bprintf(p, end - p, "$a%lld", (vlong)arraysz(ty->asize));
- p += tyidfmt(p, end - p, ty->sub[0]);
- break;
- case Tyslice:
- p += bprintf(p, end - p, "$s");
- p += tyidfmt(p, end - p, ty->sub[0]);
- break;
- case Tycode:
- p += bprintf(p, end - p, "$F");
- for (i = 0; i < ty->nsub; i++) {
- p += tyidfmt(p, end - p, ty->sub[i]);
- p += bprintf(p, end - p, "$");
- }
- break;
- case Tyfunc:
- p += bprintf(p, end - p, "$f");
- for (i = 0; i < ty->nsub; i++) {
- p += tyidfmt(p, end - p, ty->sub[i]);
- p += bprintf(p, end - p, "$");
- }
- break;
- case Tytuple:
- p += bprintf(p, end - p, "$e");
- for (i = 0; i < ty->nsub; i++) {
- p += tyidfmt(p, end - p, ty->sub[i]);
- }
- p += bprintf(p, end - p, "$");
- break;
- case Tystruct:
- p += bprintf(p, end - p, "$t%lld", ty->tid);
- break;
- case Tyunion:
- p += bprintf(p, end - p, "$u%lld", ty->tid);
- break;
- case Typaram:
- p += bprintf(p, end - p, "$r%s", ty->pname);
- break;
- case Tyunres:
- case Tyname:
- p += bprintf(p, end - p, "$n");
- if (ty->name->name.ns)
- p += bprintf(p, end - p, "%s", ty->name->name.ns);
- p += bprintf(p, end - p, "$%s", ty->name->name.name);
- if (ty->arg)
- for (i = 0; i < ty->narg; i++)
- p += tyidfmt(p, end - p, ty->arg[i]);
- else if (ty->gparam)
- for (i = 0; i < ty->ngparam; i++)
- p += tyidfmt(p, end - p, ty->gparam[i]);
- break;
- case Tygeneric:
- break;
- }
- return p - buf;
+ case Tybyte: p += bprintf(p, end - p, "H"); break;
+ case Tyuint8: p += bprintf(p, end - p, "B"); break;
+ case Tyuint16: p += bprintf(p, end - p, "S"); break;
+ case Tyuint: p += bprintf(p, end - p, "I"); break;
+ case Tyuint32: p += bprintf(p, end - p, "W"); break;
+ case Tyuint64: p += bprintf(p, end - p, "Q"); break;
+ case Tyflt32: p += bprintf(p, end - p, "f"); break;
+ case Tyflt64: p += bprintf(p, end - p, "d"); break;
+ case Tyvalist: p += bprintf(p, end - p, "V"); break;
+ case Typtr:
+ p += bprintf(p, end - p, "$p");
+ p += tyidfmt(p, end - p, ty->sub[0]);
+ break;
+ case Tyarray:
+ p += bprintf(p, end - p, "$a%lld", (vlong)arraysz(ty->asize));
+ p += tyidfmt(p, end - p, ty->sub[0]);
+ break;
+ case Tyslice:
+ p += bprintf(p, end - p, "$s");
+ p += tyidfmt(p, end - p, ty->sub[0]);
+ break;
+ case Tycode:
+ p += bprintf(p, end - p, "$F");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ p += bprintf(p, end - p, "$");
+ }
+ break;
+ case Tyfunc:
+ p += bprintf(p, end - p, "$f");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ p += bprintf(p, end - p, "$");
+ }
+ break;
+ case Tytuple:
+ p += bprintf(p, end - p, "$e");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ }
+ p += bprintf(p, end - p, "$");
+ break;
+ case Tystruct: p += bprintf(p, end - p, "$t%lld", ty->tid); break;
+ case Tyunion: p += bprintf(p, end - p, "$u%lld", ty->tid); break;
+ case Typaram: p += bprintf(p, end - p, "$r%s", ty->pname); break;
+ case Tyunres:
+ case Tyname:
+ p += bprintf(p, end - p, "$n");
+ if (ty->name->name.ns)
+ p += bprintf(p, end - p, "%s", ty->name->name.ns);
+ p += bprintf(p, end - p, "$%s", ty->name->name.name);
+ if (ty->arg)
+ for (i = 0; i < ty->narg; i++)
+ p += tyidfmt(p, end - p, ty->arg[i]);
+ else if (ty->gparam)
+ for (i = 0; i < ty->ngparam; i++)
+ p += tyidfmt(p, end - p, ty->gparam[i]);
+ break;
+ case Tygeneric:
+ break;
+ }
+ return p - buf;
}
void tyinit(Stab *st)
{
- int i;
- Type *ty;
+ int i;
+ Type *ty;
-/* this must be done after all the types are created, otherwise we will
- * clobber the memoized bunch of types with the type params. */
-#define Tc(c, n) \
- mktrait(Zloc, mkname(Zloc, n), NULL, NULL, 0, NULL, 0, 0);
+ /* this must be done after all the types are created, otherwise we will
+ * clobber the memoized bunch of types with the type params. */
+#define Tc(c, n) mktrait(Zloc, mkname(Zloc, n), NULL, NULL, 0, NULL, 0, 0);
#include "trait.def"
#undef Tc
- /* char::(numeric,integral) */
- traits[Tychar][0] = traittab[Tcnum];
- traits[Tychar][1] = traittab[Tcint];
+ /* char::(numeric,integral) */
+ traits[Tychar][0] = traittab[Tcnum];
+ traits[Tychar][1] = traittab[Tcint];
- traits[Tybyte][0] = traittab[Tcnum];
- traits[Tybyte][1] = traittab[Tcint];
+ traits[Tybyte][0] = traittab[Tcnum];
+ traits[Tybyte][1] = traittab[Tcint];
- /* <integer types>::(numeric,integral) */
- for (i = Tyint8; i < Tyflt32; i++) {
- traits[i][0] = traittab[Tcnum];
- traits[i][1] = traittab[Tcint];
- }
+ /* <integer types>::(numeric,integral) */
+ for (i = Tyint8; i < Tyflt32; i++) {
+ traits[i][0] = traittab[Tcnum];
+ traits[i][1] = traittab[Tcint];
+ }
- /* <floats>::(numeric,floating) */
- traits[Tyflt32][0] = traittab[Tcnum];
- traits[Tyflt32][1] = traittab[Tcfloat];
- traits[Tyflt64][0] = traittab[Tcnum];
- traits[Tyflt64][1] = traittab[Tcfloat];
+ /* <floats>::(numeric,floating) */
+ traits[Tyflt32][0] = traittab[Tcnum];
+ traits[Tyflt32][1] = traittab[Tcfloat];
+ traits[Tyflt64][0] = traittab[Tcnum];
+ traits[Tyflt64][1] = traittab[Tcfloat];
- /* @a*::(sliceable) */
- traits[Typtr][0] = traittab[Tcslice];
+ /* @a*::(sliceable) */
+ traits[Typtr][0] = traittab[Tcslice];
- /* @a[:]::(indexable,sliceable) */
- traits[Tyslice][0] = traittab[Tcslice];
- traits[Tyslice][1] = traittab[Tcidx];
+ /* @a[:]::(indexable,sliceable) */
+ traits[Tyslice][0] = traittab[Tcslice];
+ traits[Tyslice][1] = traittab[Tcidx];
- /* @a[SZ]::(indexable,sliceable) */
- traits[Tyarray][0] = traittab[Tcidx];
- traits[Tyarray][1] = traittab[Tcslice];
+ /* @a[SZ]::(indexable,sliceable) */
+ traits[Tyarray][0] = traittab[Tcidx];
+ traits[Tyarray][1] = traittab[Tcslice];
- /* @a::function */
- traits[Tyfunc][0] = traittab[Tcfunc];
+ /* @a::function */
+ traits[Tyfunc][0] = traittab[Tcfunc];
-/* Definining and registering the types has to go after we define the
- * constraints, otherwise they will have no constraints set on them. */
-#define Ty(t, n, stk) \
- if (t != Ntypes) {\
- ty = mktype(Zloc, t); \
- if (n) { \
- puttype(st, mkname(Zloc, n), ty); \
- } \
- }
+ /* Definining and registering the types has to go after we define the
+ * constraints, otherwise they will have no constraints set on them. */
+#define Ty(t, n, stk) \
+ if (t != Ntypes) { \
+ ty = mktype(Zloc, t); \
+ if (n) { \
+ puttype(st, mkname(Zloc, n), ty); \
+ } \
+ }
#include "types.def"
#undef Ty
}
--- a/parse/use.c
+++ b/parse/use.c
@@ -22,35 +22,34 @@
static Node *unpickle(FILE *fd);
/* type fixup list */
-static Htab *tydedup; /* map from name -> type, contains all Tynames loaded ever */
-static Htab *tidmap; /* map from tid -> type */
-static Htab *trmap; /* map from trait id -> trait */
-static Htab *initmap; /* map from init name -> int */
+static Htab *tydedup; /* map from name -> type, contains all Tynames loaded ever */
+static Htab *tidmap; /* map from tid -> type */
+static Htab *trmap; /* map from trait id -> trait */
+static Htab *initmap; /* map from init name -> int */
#define Builtinmask (1 << 30)
-static Type ***typefixdest; /* list of types we need to replace */
-static size_t ntypefixdest; /* size of replacement list */
-static intptr_t *typefixid; /* list of types we need to replace */
-static size_t ntypefixid; /* size of replacement list */
+static Type ***typefixdest; /* list of types we need to replace */
+static size_t ntypefixdest; /* size of replacement list */
+static intptr_t *typefixid; /* list of types we need to replace */
+static size_t ntypefixid; /* size of replacement list */
-static Trait ***traitfixdest; /* list of traits we need to replace */
-static size_t ntraitfixdest; /* size of replacement list */
-static Type **traitfixtype; /* list of types we need to set the trait on */
-static size_t ntraitfixtype; /* size of replacement list */
-static intptr_t *traitfixid; /* list of traits we need to replace */
-static size_t ntraitfixid; /* size of replacement list */
+static Trait ***traitfixdest; /* list of traits we need to replace */
+static size_t ntraitfixdest; /* size of replacement list */
+static Type **traitfixtype; /* list of types we need to set the trait on */
+static size_t ntraitfixtype; /* size of replacement list */
+static intptr_t *traitfixid; /* list of traits we need to replace */
+static size_t ntraitfixid; /* size of replacement list */
-
void addextlibs(Node *file, char **libs, size_t nlibs)
{
- size_t i, j;
+ size_t i, j;
- for (i = 0; i < nlibs; i++) {
- for (j = 0; j < file->file.nextlibs; j++)
- if (!strcmp(file->file.extlibs[j], libs[i]))
- continue;
- lappend(&file->file.extlibs, &file->file.nextlibs, libs[i]);
- }
+ for (i = 0; i < nlibs; i++) {
+ for (j = 0; j < file->file.nextlibs; j++)
+ if (!strcmp(file->file.extlibs[j], libs[i]))
+ continue;
+ lappend(&file->file.extlibs, &file->file.nextlibs, libs[i]);
+ }
}
/* Outputs a symbol table to file in a way that can be
@@ -58,27 +57,26 @@
* and sub-namespaces. Captured variables are ommitted. */
static void wrstab(FILE *fd, Stab *val)
{
- size_t n, i;
- void **keys;
+ size_t n, i;
+ void **keys;
- wrstr(fd, val->name);
+ wrstr(fd, val->name);
- /* write decls */
- keys = htkeys(val->dcl, &n);
- wrint(fd, n);
- for (i = 0; i < n; i++)
- wrsym(fd, getdcl(val, keys[i]));
- free(keys);
+ /* write decls */
+ keys = htkeys(val->dcl, &n);
+ wrint(fd, n);
+ for (i = 0; i < n; i++)
+ wrsym(fd, getdcl(val, keys[i]));
+ free(keys);
- /* write types */
- keys = htkeys(val->ty, &n);
- wrint(fd, n);
- for (i = 0; i < n; i++) {
- pickle(fd, keys[i]); /* name */
- wrtype(fd, gettype(val, keys[i])); /* type */
- }
- free(keys);
-
+ /* write types */
+ keys = htkeys(val->ty, &n);
+ wrint(fd, n);
+ for (i = 0; i < n; i++) {
+ pickle(fd, keys[i]); /* name */
+ wrtype(fd, gettype(val, keys[i])); /* type */
+ }
+ free(keys);
}
/* Reads a symbol table from file. The converse
@@ -85,62 +83,62 @@
* of wrstab. */
static Stab *rdstab(FILE *fd, int isfunc)
{
- Stab *st;
- Type *ty;
- Node *nm;
- int n;
- int i;
+ Stab *st;
+ Type *ty;
+ Node *nm;
+ int n;
+ int i;
- /* read dcls */
- st = mkstab(isfunc);
- st->name = rdstr(fd);
- n = rdint(fd);
- for (i = 0; i < n; i++)
- putdcl(st, rdsym(fd, NULL));
+ /* read dcls */
+ st = mkstab(isfunc);
+ st->name = rdstr(fd);
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ putdcl(st, rdsym(fd, NULL));
- /* read types */
- n = rdint(fd);
- for (i = 0; i < n; i++) {
- nm = unpickle(fd);
- rdtype(fd, &ty);
- puttype(st, nm, ty);
- }
- return st;
+ /* read types */
+ n = rdint(fd);
+ for (i = 0; i < n; i++) {
+ nm = unpickle(fd);
+ rdtype(fd, &ty);
+ puttype(st, nm, ty);
+ }
+ return st;
}
static void wrucon(FILE *fd, Ucon *uc)
{
- wrint(fd, uc->loc.line);
- wrint(fd, uc->id);
- wrbool(fd, uc->synth);
- pickle(fd, uc->name);
- wrbool(fd, uc->etype != NULL);
- if (uc->etype)
- wrtype(fd, uc->etype);
+ wrint(fd, uc->loc.line);
+ wrint(fd, uc->id);
+ wrbool(fd, uc->synth);
+ pickle(fd, uc->name);
+ wrbool(fd, uc->etype != NULL);
+ if (uc->etype)
+ wrtype(fd, uc->etype);
}
static Ucon *rducon(FILE *fd, Type *ut)
{
- Type *et;
- Node *name;
- Ucon *uc;
- size_t id;
- int line;
- int synth;
+ Type *et;
+ Node *name;
+ Ucon *uc;
+ size_t id;
+ int line;
+ int synth;
- et = NULL;
- line = rdint(fd);
- id = rdint(fd);
- synth = rdbool(fd);
- name = unpickle(fd);
- uc = mkucon(Zloc, name, ut, et);
- uc->loc.line = line;
- uc->loc.file = file->file.nfiles - 1;
- if (rdbool(fd))
- rdtype(fd, &uc->etype);
- uc->id = id;
- uc->synth = synth;
- return uc;
+ et = NULL;
+ line = rdint(fd);
+ id = rdint(fd);
+ synth = rdbool(fd);
+ name = unpickle(fd);
+ uc = mkucon(Zloc, name, ut, et);
+ uc->loc.line = line;
+ uc->loc.file = file->file.nfiles - 1;
+ if (rdbool(fd))
+ rdtype(fd, &uc->etype);
+ uc->id = id;
+ uc->synth = synth;
+ return uc;
}
/* Writes the name and type of a variable,
@@ -149,52 +147,52 @@
* the only cross-file inline is generics) */
static void wrsym(FILE *fd, Node *val)
{
- /* sym */
- wrint(fd, val->loc.line);
- pickle(fd, val->decl.name);
- wrtype(fd, val->decl.type);
+ /* sym */
+ wrint(fd, val->loc.line);
+ pickle(fd, val->decl.name);
+ wrtype(fd, val->decl.type);
- /* symflags */
- wrint(fd, val->decl.vis);
- wrbool(fd, val->decl.isconst);
- wrbool(fd, val->decl.isgeneric);
- wrbool(fd, val->decl.isextern);
- wrbool(fd, val->decl.ispkglocal);
- wrbool(fd, val->decl.isnoret);
- wrbool(fd, val->decl.isexportinit);
- wrbool(fd, val->decl.isinit);
- if (val->decl.isexportinit) {
- pickle(fd, val->decl.init);
- }
+ /* symflags */
+ wrint(fd, val->decl.vis);
+ wrbool(fd, val->decl.isconst);
+ wrbool(fd, val->decl.isgeneric);
+ wrbool(fd, val->decl.isextern);
+ wrbool(fd, val->decl.ispkglocal);
+ wrbool(fd, val->decl.isnoret);
+ wrbool(fd, val->decl.isexportinit);
+ wrbool(fd, val->decl.isinit);
+ if (val->decl.isexportinit) {
+ pickle(fd, val->decl.init);
+ }
}
static Node *rdsym(FILE *fd, Trait *ctx)
{
- int line;
- Node *name;
- Node *n;
+ int line;
+ Node *name;
+ Node *n;
- line = rdint(fd);
- name = unpickle(fd);
- n = mkdecl(Zloc, name, NULL);
- n->loc.line = line;
- n->loc.file = file->file.nfiles - 1;
- rdtype(fd, &n->decl.type);
+ line = rdint(fd);
+ name = unpickle(fd);
+ n = mkdecl(Zloc, name, NULL);
+ n->loc.line = line;
+ n->loc.file = file->file.nfiles - 1;
+ rdtype(fd, &n->decl.type);
- if (rdint(fd) == Vishidden)
- n->decl.ishidden = 1;
- n->decl.trait = ctx;
- n->decl.isconst = rdbool(fd);
- n->decl.isgeneric = rdbool(fd);
- n->decl.isextern = rdbool(fd);
- n->decl.ispkglocal = rdbool(fd);
- n->decl.isnoret = rdbool(fd);
- n->decl.isimport = 1;
- n->decl.isexportinit = rdbool(fd);
- n->decl.isinit = rdbool(fd);
- if (n->decl.isexportinit)
- n->decl.init = unpickle(fd);
- return n;
+ if (rdint(fd) == Vishidden)
+ n->decl.ishidden = 1;
+ n->decl.trait = ctx;
+ n->decl.isconst = rdbool(fd);
+ n->decl.isgeneric = rdbool(fd);
+ n->decl.isextern = rdbool(fd);
+ n->decl.ispkglocal = rdbool(fd);
+ n->decl.isnoret = rdbool(fd);
+ n->decl.isimport = 1;
+ n->decl.isexportinit = rdbool(fd);
+ n->decl.isinit = rdbool(fd);
+ if (n->decl.isexportinit)
+ n->decl.init = unpickle(fd);
+ return n;
}
/* Writes types to a file. Errors on
@@ -202,134 +200,129 @@
* will not be meaningful in another file*/
static void typickle(FILE *fd, Type *ty)
{
- size_t i;
+ size_t i;
- if (!ty) {
- die("trying to pickle null type\n");
- return;
- }
- wrbyte(fd, ty->type);
- wrbyte(fd, ty->vis);
- /* tid is generated; don't write */
- /* FIXME: since we only support hardcoded traits, we just write
- * out the set of them. we should write out the trait list as
- * well */
- if (!ty->traits) {
- wrint(fd, 0);
- } else {
- wrint(fd, bscount(ty->traits));
- for (i = 0; bsiter(ty->traits, &i); i++) {
- if (i < Ntraits)
- wrint(fd, i | Builtinmask);
- else
- wrint(fd, i);
- }
- }
- wrint(fd, ty->nsub);
- switch (ty->type) {
- case Tyunres:
- pickle(fd, ty->name);
- break;
- case Typaram:
- wrstr(fd, ty->pname);
- break;
- case Tystruct:
- wrint(fd, ty->nmemb);
- for (i = 0; i < ty->nmemb; i++)
- pickle(fd, ty->sdecls[i]);
- break;
- case Tyunion:
- wrint(fd, ty->nmemb);
- for (i = 0; i < ty->nmemb; i++)
- wrucon(fd, ty->udecls[i]);
- break;
- case Tyarray:
- wrtype(fd, ty->sub[0]);
- pickle(fd, ty->asize);
- break;
- case Tyslice:
- wrtype(fd, ty->sub[0]);
- break;
- case Tyvar:
- die("Attempting to pickle %s. This will not work.\n", tystr(ty));
- break;
- case Tyname:
- pickle(fd, ty->name);
- wrbool(fd, ty->issynth);
- wrint(fd, ty->narg);
- for (i = 0; i < ty->narg; i++)
- wrtype(fd, ty->arg[i]);
- wrtype(fd, ty->sub[0]);
- break;
- case Tygeneric:
- pickle(fd, ty->name);
- wrbool(fd, ty->issynth);
- wrint(fd, ty->ngparam);
- for (i = 0; i < ty->ngparam; i++)
- wrtype(fd, ty->gparam[i]);
- wrtype(fd, ty->sub[0]);
- break;
- default:
- for (i = 0; i < ty->nsub; i++)
- wrtype(fd, ty->sub[i]);
- break;
- }
+ if (!ty) {
+ die("trying to pickle null type\n");
+ return;
+ }
+ wrbyte(fd, ty->type);
+ wrbyte(fd, ty->vis);
+ /* tid is generated; don't write */
+ /* FIXME: since we only support hardcoded traits, we just write
+ * out the set of them. we should write out the trait list as
+ * well */
+ if (!ty->traits) {
+ wrint(fd, 0);
+ }
+ else {
+ wrint(fd, bscount(ty->traits));
+ for (i = 0; bsiter(ty->traits, &i); i++) {
+ if (i < Ntraits)
+ wrint(fd, i | Builtinmask);
+ else
+ wrint(fd, i);
+ }
+ }
+ wrint(fd, ty->nsub);
+ switch (ty->type) {
+ case Tyunres: pickle(fd, ty->name); break;
+ case Typaram: wrstr(fd, ty->pname); break;
+ case Tystruct:
+ wrint(fd, ty->nmemb);
+ for (i = 0; i < ty->nmemb; i++)
+ pickle(fd, ty->sdecls[i]);
+ break;
+ case Tyunion:
+ wrint(fd, ty->nmemb);
+ for (i = 0; i < ty->nmemb; i++)
+ wrucon(fd, ty->udecls[i]);
+ break;
+ case Tyarray:
+ wrtype(fd, ty->sub[0]);
+ pickle(fd, ty->asize);
+ break;
+ case Tyslice: wrtype(fd, ty->sub[0]); break;
+ case Tyvar: die("Attempting to pickle %s. This will not work.\n", tystr(ty)); break;
+ case Tyname:
+ pickle(fd, ty->name);
+ wrbool(fd, ty->issynth);
+ wrint(fd, ty->narg);
+ for (i = 0; i < ty->narg; i++)
+ wrtype(fd, ty->arg[i]);
+ wrtype(fd, ty->sub[0]);
+ break;
+ case Tygeneric:
+ pickle(fd, ty->name);
+ wrbool(fd, ty->issynth);
+ wrint(fd, ty->ngparam);
+ for (i = 0; i < ty->ngparam; i++)
+ wrtype(fd, ty->gparam[i]);
+ wrtype(fd, ty->sub[0]);
+ break;
+ default:
+ for (i = 0; i < ty->nsub; i++)
+ wrtype(fd, ty->sub[i]);
+ break;
+ }
}
static void traitpickle(FILE *fd, Trait *tr)
{
- size_t i;
+ size_t i;
- wrint(fd, tr->uid);
- wrbool(fd, tr->ishidden);
- pickle(fd, tr->name);
- typickle(fd, tr->param);
- wrint(fd, tr->nmemb);
- for (i = 0; i < tr->nmemb; i++)
- wrsym(fd, tr->memb[i]);
- wrint(fd, tr->nfuncs);
- for (i = 0; i < tr->nfuncs; i++)
- wrsym(fd, tr->funcs[i]);
+ wrint(fd, tr->uid);
+ wrbool(fd, tr->ishidden);
+ pickle(fd, tr->name);
+ typickle(fd, tr->param);
+ wrint(fd, tr->nmemb);
+ for (i = 0; i < tr->nmemb; i++)
+ wrsym(fd, tr->memb[i]);
+ wrint(fd, tr->nfuncs);
+ for (i = 0; i < tr->nfuncs; i++)
+ wrsym(fd, tr->funcs[i]);
}
static void wrtype(FILE *fd, Type *ty)
{
- if (ty->tid >= Builtinmask)
- die("Type id %d for %s too big", ty->tid, tystr(ty));
- if (ty->vis == Visbuiltin)
- wrint(fd, ty->type | Builtinmask);
- else
- wrint(fd, ty->tid);
+ if (ty->tid >= Builtinmask)
+ die("Type id %d for %s too big", ty->tid, tystr(ty));
+ if (ty->vis == Visbuiltin)
+ wrint(fd, ty->type | Builtinmask);
+ else
+ wrint(fd, ty->tid);
}
static void rdtype(FILE *fd, Type **dest)
{
- uintptr_t tid;
+ uintptr_t tid;
- tid = rdint(fd);
- if (tid & Builtinmask) {
- *dest = mktype(Zloc, tid & ~Builtinmask);
- } else {
- lappend(&typefixdest, &ntypefixdest, dest);
- lappend(&typefixid, &ntypefixid, itop(tid));
- }
+ tid = rdint(fd);
+ if (tid & Builtinmask) {
+ *dest = mktype(Zloc, tid & ~Builtinmask);
+ }
+ else {
+ lappend(&typefixdest, &ntypefixdest, dest);
+ lappend(&typefixid, &ntypefixid, itop(tid));
+ }
}
static void rdtrait(FILE *fd, Trait **dest, Type *ty)
{
- uintptr_t tid;
+ uintptr_t tid;
- tid = rdint(fd);
- if (tid & Builtinmask) {
- if (dest)
- *dest = traittab[tid & ~Builtinmask];
- if (ty)
- settrait(ty, traittab[tid & ~Builtinmask]);
- } else {
- lappend(&traitfixdest, &ntraitfixdest, dest);
- lappend(&traitfixtype, &ntraitfixtype, ty);
- lappend(&traitfixid, &ntraitfixid, itop(tid));
- }
+ tid = rdint(fd);
+ if (tid & Builtinmask) {
+ if (dest)
+ *dest = traittab[tid & ~Builtinmask];
+ if (ty)
+ settrait(ty, traittab[tid & ~Builtinmask]);
+ }
+ else {
+ lappend(&traitfixdest, &ntraitfixdest, dest);
+ lappend(&traitfixtype, &ntraitfixtype, ty);
+ lappend(&traitfixid, &ntraitfixid, itop(tid));
+ }
}
/* Writes types to a file. Errors on
@@ -337,94 +330,90 @@
* will not be meaningful in another file */
static Type *tyunpickle(FILE *fd)
{
- size_t i, n;
- Type *ty;
- Ty t;
+ size_t i, n;
+ Type *ty;
+ Ty t;
- t = rdbyte(fd);
- ty = mktype(Zloc, t);
- ty->isimport = 1;
- if (rdbyte(fd) == Vishidden)
- ty->ishidden = 1;
- /* tid is generated; don't write */
- n = rdint(fd);
- for (i = 0; i < n; i++)
- rdtrait(fd, NULL, ty);
- ty->nsub = rdint(fd);
- if (ty->nsub > 0)
- ty->sub = zalloc(ty->nsub * sizeof(Type*));
- switch (ty->type) {
- case Tyunres:
- ty->name = unpickle(fd);
- break;
- case Typaram:
- ty->pname = rdstr(fd);
- break;
- case Tystruct:
- ty->nmemb = rdint(fd);
- ty->sdecls = zalloc(ty->nmemb * sizeof(Node*));
- for (i = 0; i < ty->nmemb; i++)
- ty->sdecls[i] = unpickle(fd);
- break;
- case Tyunion:
- ty->nmemb = rdint(fd);
- ty->udecls = zalloc(ty->nmemb * sizeof(Node*));
- for (i = 0; i < ty->nmemb; i++)
- ty->udecls[i] = rducon(fd, ty);
- break;
- case Tyarray:
- rdtype(fd, &ty->sub[0]);
- ty->asize = unpickle(fd);
- break;
- case Tyslice:
- rdtype(fd, &ty->sub[0]);
- break;
- case Tyname:
- ty->name = unpickle(fd);
- ty->issynth = rdbool(fd);
- ty->narg = rdint(fd);
- ty->arg = zalloc(ty->narg * sizeof(Type *));
- for (i = 0; i < ty->narg; i++)
- rdtype(fd, &ty->arg[i]);
- rdtype(fd, &ty->sub[0]);
- break;
- case Tygeneric:
- ty->name = unpickle(fd);
- ty->issynth = rdbool(fd);
- ty->ngparam = rdint(fd);
- ty->gparam = zalloc(ty->ngparam * sizeof(Type *));
- for (i = 0; i < ty->ngparam; i++)
- rdtype(fd, &ty->gparam[i]);
- rdtype(fd, &ty->sub[0]);
- break;
- default:
- for (i = 0; i < ty->nsub; i++)
- rdtype(fd, &ty->sub[i]);
- break;
- }
- return ty;
+ t = rdbyte(fd);
+ ty = mktype(Zloc, t);
+ ty->isimport = 1;
+ if (rdbyte(fd) == Vishidden)
+ ty->ishidden = 1;
+ /* tid is generated; don't write */
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ rdtrait(fd, NULL, ty);
+ ty->nsub = rdint(fd);
+ if (ty->nsub > 0)
+ ty->sub = zalloc(ty->nsub * sizeof(Type *));
+ switch (ty->type) {
+ case Tyunres: ty->name = unpickle(fd); break;
+ case Typaram: ty->pname = rdstr(fd); break;
+ case Tystruct:
+ ty->nmemb = rdint(fd);
+ ty->sdecls = zalloc(ty->nmemb * sizeof(Node *));
+ for (i = 0; i < ty->nmemb; i++)
+ ty->sdecls[i] = unpickle(fd);
+ break;
+ case Tyunion:
+ ty->nmemb = rdint(fd);
+ ty->udecls = zalloc(ty->nmemb * sizeof(Node *));
+ for (i = 0; i < ty->nmemb; i++)
+ ty->udecls[i] = rducon(fd, ty);
+ break;
+ case Tyarray:
+ rdtype(fd, &ty->sub[0]);
+ ty->asize = unpickle(fd);
+ break;
+ case Tyslice:
+ rdtype(fd, &ty->sub[0]);
+ break;
+ case Tyname:
+ ty->name = unpickle(fd);
+ ty->issynth = rdbool(fd);
+ ty->narg = rdint(fd);
+ ty->arg = zalloc(ty->narg * sizeof(Type *));
+ for (i = 0; i < ty->narg; i++)
+ rdtype(fd, &ty->arg[i]);
+ rdtype(fd, &ty->sub[0]);
+ break;
+ case Tygeneric:
+ ty->name = unpickle(fd);
+ ty->issynth = rdbool(fd);
+ ty->ngparam = rdint(fd);
+ ty->gparam = zalloc(ty->ngparam * sizeof(Type *));
+ for (i = 0; i < ty->ngparam; i++)
+ rdtype(fd, &ty->gparam[i]);
+ rdtype(fd, &ty->sub[0]);
+ break;
+ default:
+ for (i = 0; i < ty->nsub; i++)
+ rdtype(fd, &ty->sub[i]);
+ break;
+ }
+ return ty;
}
Trait *traitunpickle(FILE *fd)
{
- Trait *tr;
- size_t i, n;
- intptr_t uid;
+ Trait *tr;
+ size_t i, n;
+ intptr_t uid;
- /* create an empty trait */
- tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0);
- uid = rdint(fd);
- tr->ishidden = rdbool(fd);
- tr->name = unpickle(fd);
- tr->param = tyunpickle(fd);
- n = rdint(fd);
- for (i = 0; i < n; i++)
- lappend(&tr->memb, &tr->nmemb, rdsym(fd, tr));
- n = rdint(fd);
- for (i = 0; i < n; i++)
- lappend(&tr->funcs, &tr->nfuncs, rdsym(fd, tr));
- htput(trmap, itop(uid), tr);
- return tr;
+ /* create an empty trait */
+ tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0);
+ uid = rdint(fd);
+ tr->ishidden = rdbool(fd);
+ tr->name = unpickle(fd);
+ tr->param = tyunpickle(fd);
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ lappend(&tr->memb, &tr->nmemb, rdsym(fd, tr));
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ lappend(&tr->funcs, &tr->nfuncs, rdsym(fd, tr));
+ htput(trmap, itop(uid), tr);
+ return tr;
}
/* Pickles a node to a file. The format
@@ -435,127 +424,125 @@
* crash the compiler */
static void pickle(FILE *fd, Node *n)
{
- size_t i;
+ size_t i;
- if (!n) {
- wrbyte(fd, Nnone);
- return;
- }
- wrbyte(fd, n->type);
- wrint(fd, n->loc.line);
- switch (n->type) {
- case Nfile:
- wrstr(fd, n->file.files[0]);
- wrint(fd, n->file.nuses);
- for (i = 0; i < n->file.nuses; i++)
- pickle(fd, n->file.uses[i]);
- wrint(fd, n->file.nstmts);
- for (i = 0; i < n->file.nstmts; i++)
- pickle(fd, n->file.stmts[i]);
- wrstab(fd, n->file.globls);
- break;
+ if (!n) {
+ wrbyte(fd, Nnone);
+ return;
+ }
+ wrbyte(fd, n->type);
+ wrint(fd, n->loc.line);
+ switch (n->type) {
+ case Nfile:
+ wrstr(fd, n->file.files[0]);
+ wrint(fd, n->file.nuses);
+ for (i = 0; i < n->file.nuses; i++)
+ pickle(fd, n->file.uses[i]);
+ wrint(fd, n->file.nstmts);
+ for (i = 0; i < n->file.nstmts; i++)
+ pickle(fd, n->file.stmts[i]);
+ wrstab(fd, n->file.globls);
+ break;
- case Nexpr:
- wrbyte(fd, n->expr.op);
- wrtype(fd, n->expr.type);
- wrbool(fd, n->expr.isconst);
- pickle(fd, n->expr.idx);
- wrint(fd, n->expr.nargs);
- for (i = 0; i < n->expr.nargs; i++)
- pickle(fd, n->expr.args[i]);
- break;
- case Nname:
- wrbool(fd, n->name.ns != NULL);
- if (n->name.ns) {
- wrstr(fd, n->name.ns);
- }
- wrstr(fd, n->name.name);
- break;
- case Nuse:
- wrbool(fd, n->use.islocal);
- wrstr(fd, n->use.name);
- break;
- case Nlit:
- wrbyte(fd, n->lit.littype);
- wrtype(fd, n->lit.type);
- wrint(fd, n->lit.nelt);
- switch (n->lit.littype) {
- case Lchr: wrint(fd, n->lit.chrval); break;
- case Lint: wrint(fd, n->lit.intval); break;
- case Lflt: wrflt(fd, n->lit.fltval); break;
- case Lstr: wrlenstr(fd, n->lit.strval); break;
- case Llbl: wrstr(fd, n->lit.lblval); break;
- case Lbool: wrbool(fd, n->lit.boolval); break;
- case Lfunc: pickle(fd, n->lit.fnval); break;
- }
- break;
- case Nloopstmt:
- pickle(fd, n->loopstmt.init);
- pickle(fd, n->loopstmt.cond);
- pickle(fd, n->loopstmt.step);
- pickle(fd, n->loopstmt.body);
- break;
- case Niterstmt:
- pickle(fd, n->iterstmt.elt);
- pickle(fd, n->iterstmt.seq);
- pickle(fd, n->iterstmt.body);
- break;
- case Nmatchstmt:
- pickle(fd, n->matchstmt.val);
- wrint(fd, n->matchstmt.nmatches);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- pickle(fd, n->matchstmt.matches[i]);
- break;
- case Nmatch:
- pickle(fd, n->match.pat);
- pickle(fd, n->match.block);
- break;
- case Nifstmt:
- pickle(fd, n->ifstmt.cond);
- pickle(fd, n->ifstmt.iftrue);
- pickle(fd, n->ifstmt.iffalse);
- break;
- case Nblock:
- wrstab(fd, n->block.scope);
- wrint(fd, n->block.nstmts);
- for (i = 0; i < n->block.nstmts; i++)
- pickle(fd, n->block.stmts[i]);
- break;
- case Ndecl:
- /* sym */
- pickle(fd, n->decl.name);
- wrtype(fd, n->decl.type);
+ case Nexpr:
+ wrbyte(fd, n->expr.op);
+ wrtype(fd, n->expr.type);
+ wrbool(fd, n->expr.isconst);
+ pickle(fd, n->expr.idx);
+ wrint(fd, n->expr.nargs);
+ for (i = 0; i < n->expr.nargs; i++)
+ pickle(fd, n->expr.args[i]);
+ break;
+ case Nname:
+ wrbool(fd, n->name.ns != NULL);
+ if (n->name.ns) {
+ wrstr(fd, n->name.ns);
+ }
+ wrstr(fd, n->name.name);
+ break;
+ case Nuse:
+ wrbool(fd, n->use.islocal);
+ wrstr(fd, n->use.name);
+ break;
+ case Nlit:
+ wrbyte(fd, n->lit.littype);
+ wrtype(fd, n->lit.type);
+ wrint(fd, n->lit.nelt);
+ switch (n->lit.littype) {
+ case Lchr: wrint(fd, n->lit.chrval); break;
+ case Lint: wrint(fd, n->lit.intval); break;
+ case Lflt: wrflt(fd, n->lit.fltval); break;
+ case Lstr: wrlenstr(fd, n->lit.strval); break;
+ case Llbl: wrstr(fd, n->lit.lblval); break;
+ case Lbool: wrbool(fd, n->lit.boolval); break;
+ case Lfunc: pickle(fd, n->lit.fnval); break;
+ }
+ break;
+ case Nloopstmt:
+ pickle(fd, n->loopstmt.init);
+ pickle(fd, n->loopstmt.cond);
+ pickle(fd, n->loopstmt.step);
+ pickle(fd, n->loopstmt.body);
+ break;
+ case Niterstmt:
+ pickle(fd, n->iterstmt.elt);
+ pickle(fd, n->iterstmt.seq);
+ pickle(fd, n->iterstmt.body);
+ break;
+ case Nmatchstmt:
+ pickle(fd, n->matchstmt.val);
+ wrint(fd, n->matchstmt.nmatches);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ pickle(fd, n->matchstmt.matches[i]);
+ break;
+ case Nmatch:
+ pickle(fd, n->match.pat);
+ pickle(fd, n->match.block);
+ break;
+ case Nifstmt:
+ pickle(fd, n->ifstmt.cond);
+ pickle(fd, n->ifstmt.iftrue);
+ pickle(fd, n->ifstmt.iffalse);
+ break;
+ case Nblock:
+ wrstab(fd, n->block.scope);
+ wrint(fd, n->block.nstmts);
+ for (i = 0; i < n->block.nstmts; i++)
+ pickle(fd, n->block.stmts[i]);
+ break;
+ case Ndecl:
+ /* sym */
+ pickle(fd, n->decl.name);
+ wrtype(fd, n->decl.type);
- /* symflags */
- wrbool(fd, n->decl.isconst);
- wrbool(fd, n->decl.isgeneric);
- wrbool(fd, n->decl.isextern);
- wrbool(fd, n->decl.isnoret);
- wrbool(fd, n->decl.ispkglocal);
+ /* symflags */
+ wrbool(fd, n->decl.isconst);
+ wrbool(fd, n->decl.isgeneric);
+ wrbool(fd, n->decl.isextern);
+ wrbool(fd, n->decl.isnoret);
+ wrbool(fd, n->decl.ispkglocal);
- /* init */
- pickle(fd, n->decl.init);
- break;
- case Nfunc:
- wrtype(fd, n->func.type);
- wrstab(fd, n->func.scope);
- wrint(fd, n->func.nargs);
- for (i = 0; i < n->func.nargs; i++)
- pickle(fd, n->func.args[i]);
- pickle(fd, n->func.body);
- break;
- case Nimpl:
- pickle(fd, n->impl.traitname);
- wrint(fd, n->impl.trait->uid);
- wrtype(fd, n->impl.type);
- wrint(fd, n->impl.ndecls);
- for (i = 0; i < n->impl.ndecls; i++)
- wrsym(fd, n->impl.decls[i]);
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
+ /* init */
+ pickle(fd, n->decl.init);
+ break;
+ case Nfunc:
+ wrtype(fd, n->func.type);
+ wrstab(fd, n->func.scope);
+ wrint(fd, n->func.nargs);
+ for (i = 0; i < n->func.nargs; i++)
+ pickle(fd, n->func.args[i]);
+ pickle(fd, n->func.body);
+ break;
+ case Nimpl:
+ pickle(fd, n->impl.traitname);
+ wrint(fd, n->impl.trait->uid);
+ wrtype(fd, n->impl.type);
+ wrint(fd, n->impl.ndecls);
+ for (i = 0; i < n->impl.ndecls; i++)
+ wrsym(fd, n->impl.decls[i]);
+ break;
+ case Nnone: die("Nnone should not be seen as node type!"); break;
+ }
}
/* Unpickles a node from a file. Minimal checking
@@ -563,243 +550,243 @@
* sane arities, a bad file can crash the compiler */
static Node *unpickle(FILE *fd)
{
- size_t i;
- Ntype type;
- Node *n;
+ size_t i;
+ Ntype type;
+ Node *n;
- type = rdbyte(fd);
- if (type == Nnone)
- return NULL;
- n = mknode(Zloc, type);
- n->loc.line = rdint(fd);
- n->loc.file = file->file.nfiles - 1;
- switch (n->type) {
- case Nfile:
- lappend(&n->file.files, &n->file.nfiles, rdstr(fd));
- n->file.nuses = rdint(fd);
- n->file.uses = zalloc(sizeof(Node*)*n->file.nuses);
- for (i = 0; i < n->file.nuses; i++)
- n->file.uses[i] = unpickle(fd);
- n->file.nstmts = rdint(fd);
- n->file.stmts = zalloc(sizeof(Node*)*n->file.nstmts);
- for (i = 0; i < n->file.nstmts; i++)
- n->file.stmts[i] = unpickle(fd);
- n->file.globls = rdstab(fd, 0);
- break;
+ type = rdbyte(fd);
+ if (type == Nnone)
+ return NULL;
+ n = mknode(Zloc, type);
+ n->loc.line = rdint(fd);
+ n->loc.file = file->file.nfiles - 1;
+ switch (n->type) {
+ case Nfile:
+ lappend(&n->file.files, &n->file.nfiles, rdstr(fd));
+ n->file.nuses = rdint(fd);
+ n->file.uses = zalloc(sizeof(Node *) * n->file.nuses);
+ for (i = 0; i < n->file.nuses; i++)
+ n->file.uses[i] = unpickle(fd);
+ n->file.nstmts = rdint(fd);
+ n->file.stmts = zalloc(sizeof(Node *) * n->file.nstmts);
+ for (i = 0; i < n->file.nstmts; i++)
+ n->file.stmts[i] = unpickle(fd);
+ n->file.globls = rdstab(fd, 0);
+ break;
- case Nexpr:
- n->expr.op = rdbyte(fd);
- rdtype(fd, &n->expr.type);
- n->expr.isconst = rdbool(fd);
- n->expr.idx = unpickle(fd);
- n->expr.nargs = rdint(fd);
- n->expr.args = zalloc(sizeof(Node *)*n->expr.nargs);
- for (i = 0; i < n->expr.nargs; i++)
- n->expr.args[i] = unpickle(fd);
- break;
- case Nname:
- if (rdbool(fd))
- n->name.ns = rdstr(fd);
- n->name.name = rdstr(fd);
- break;
- case Nuse:
- n->use.islocal = rdbool(fd);
- n->use.name = rdstr(fd);
- break;
- case Nlit:
- n->lit.littype = rdbyte(fd);
- rdtype(fd, &n->lit.type);
- n->lit.nelt = rdint(fd);
- switch (n->lit.littype) {
- case Lchr: n->lit.chrval = rdint(fd); break;
- case Lint: n->lit.intval = rdint(fd); break;
- case Lflt: n->lit.fltval = rdflt(fd); break;
- case Lstr: rdlenstr(fd, &n->lit.strval); break;
- case Llbl: n->lit.lblval = rdstr(fd); break;
- case Lbool: n->lit.boolval = rdbool(fd); break;
- case Lfunc: n->lit.fnval = unpickle(fd); break;
- }
- break;
- case Nloopstmt:
- n->loopstmt.init = unpickle(fd);
- n->loopstmt.cond = unpickle(fd);
- n->loopstmt.step = unpickle(fd);
- n->loopstmt.body = unpickle(fd);
- break;
- case Niterstmt:
- n->iterstmt.elt = unpickle(fd);
- n->iterstmt.seq = unpickle(fd);
- n->iterstmt.body = unpickle(fd);
- break;
- case Nmatchstmt:
- n->matchstmt.val = unpickle(fd);
- n->matchstmt.nmatches = rdint(fd);
- n->matchstmt.matches = zalloc(sizeof(Node *)*n->matchstmt.nmatches);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- n->matchstmt.matches[i] = unpickle(fd);
- break;
- case Nmatch:
- n->match.pat = unpickle(fd);
- n->match.block = unpickle(fd);
- break;
- case Nifstmt:
- n->ifstmt.cond = unpickle(fd);
- n->ifstmt.iftrue = unpickle(fd);
- n->ifstmt.iffalse = unpickle(fd);
- break;
- case Nblock:
- n->block.scope = rdstab(fd, 0);
- n->block.nstmts = rdint(fd);
- n->block.stmts = zalloc(sizeof(Node *)*n->block.nstmts);
- n->block.scope->super = curstab();
- pushstab(n->func.scope->super);
- for (i = 0; i < n->block.nstmts; i++)
- n->block.stmts[i] = unpickle(fd);
- popstab();
- break;
- case Ndecl:
- n->decl.did = ndecls; /* unique within file */
- /* sym */
- n->decl.name = unpickle(fd);
- rdtype(fd, &n->decl.type);
+ case Nexpr:
+ n->expr.op = rdbyte(fd);
+ rdtype(fd, &n->expr.type);
+ n->expr.isconst = rdbool(fd);
+ n->expr.idx = unpickle(fd);
+ n->expr.nargs = rdint(fd);
+ n->expr.args = zalloc(sizeof(Node *) * n->expr.nargs);
+ for (i = 0; i < n->expr.nargs; i++)
+ n->expr.args[i] = unpickle(fd);
+ break;
+ case Nname:
+ if (rdbool(fd))
+ n->name.ns = rdstr(fd);
+ n->name.name = rdstr(fd);
+ break;
+ case Nuse:
+ n->use.islocal = rdbool(fd);
+ n->use.name = rdstr(fd);
+ break;
+ case Nlit:
+ n->lit.littype = rdbyte(fd);
+ rdtype(fd, &n->lit.type);
+ n->lit.nelt = rdint(fd);
+ switch (n->lit.littype) {
+ case Lchr: n->lit.chrval = rdint(fd); break;
+ case Lint: n->lit.intval = rdint(fd); break;
+ case Lflt: n->lit.fltval = rdflt(fd); break;
+ case Lstr: rdlenstr(fd, &n->lit.strval); break;
+ case Llbl: n->lit.lblval = rdstr(fd); break;
+ case Lbool: n->lit.boolval = rdbool(fd); break;
+ case Lfunc: n->lit.fnval = unpickle(fd); break;
+ }
+ break;
+ case Nloopstmt:
+ n->loopstmt.init = unpickle(fd);
+ n->loopstmt.cond = unpickle(fd);
+ n->loopstmt.step = unpickle(fd);
+ n->loopstmt.body = unpickle(fd);
+ break;
+ case Niterstmt:
+ n->iterstmt.elt = unpickle(fd);
+ n->iterstmt.seq = unpickle(fd);
+ n->iterstmt.body = unpickle(fd);
+ break;
+ case Nmatchstmt:
+ n->matchstmt.val = unpickle(fd);
+ n->matchstmt.nmatches = rdint(fd);
+ n->matchstmt.matches = zalloc(sizeof(Node *) * n->matchstmt.nmatches);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ n->matchstmt.matches[i] = unpickle(fd);
+ break;
+ case Nmatch:
+ n->match.pat = unpickle(fd);
+ n->match.block = unpickle(fd);
+ break;
+ case Nifstmt:
+ n->ifstmt.cond = unpickle(fd);
+ n->ifstmt.iftrue = unpickle(fd);
+ n->ifstmt.iffalse = unpickle(fd);
+ break;
+ case Nblock:
+ n->block.scope = rdstab(fd, 0);
+ n->block.nstmts = rdint(fd);
+ n->block.stmts = zalloc(sizeof(Node *) * n->block.nstmts);
+ n->block.scope->super = curstab();
+ pushstab(n->func.scope->super);
+ for (i = 0; i < n->block.nstmts; i++)
+ n->block.stmts[i] = unpickle(fd);
+ popstab();
+ break;
+ case Ndecl:
+ n->decl.did = ndecls; /* unique within file */
+ /* sym */
+ n->decl.name = unpickle(fd);
+ rdtype(fd, &n->decl.type);
- /* symflags */
- n->decl.isconst = rdbool(fd);
- n->decl.isgeneric = rdbool(fd);
- n->decl.isextern = rdbool(fd);
- n->decl.isnoret = rdbool(fd);
- n->decl.ispkglocal = rdbool(fd);
+ /* symflags */
+ n->decl.isconst = rdbool(fd);
+ n->decl.isgeneric = rdbool(fd);
+ n->decl.isextern = rdbool(fd);
+ n->decl.isnoret = rdbool(fd);
+ n->decl.ispkglocal = rdbool(fd);
- /* init */
- n->decl.init = unpickle(fd);
- lappend(&decls, &ndecls, n);
- break;
- case Nfunc:
- rdtype(fd, &n->func.type);
- n->func.scope = rdstab(fd, 1);
- n->func.nargs = rdint(fd);
- n->func.args = zalloc(sizeof(Node *)*n->func.nargs);
- n->func.scope->super = curstab();
- pushstab(n->func.scope->super);
- for (i = 0; i < n->func.nargs; i++)
- n->func.args[i] = unpickle(fd);
- n->func.body = unpickle(fd);
- popstab();
- break;
- case Nimpl:
- n->impl.traitname = unpickle(fd);
- i = rdint(fd);
- rdtrait(fd, &n->impl.trait, NULL);
- rdtype(fd, &n->impl.type);
- n->impl.ndecls = rdint(fd);
- n->impl.decls = zalloc(sizeof(Node *)*n->impl.ndecls);
- for (i = 0; i < n->impl.ndecls; i++)
- n->impl.decls[i] = rdsym(fd, n->impl.trait);
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
- return n;
+ /* init */
+ n->decl.init = unpickle(fd);
+ lappend(&decls, &ndecls, n);
+ break;
+ case Nfunc:
+ rdtype(fd, &n->func.type);
+ n->func.scope = rdstab(fd, 1);
+ n->func.nargs = rdint(fd);
+ n->func.args = zalloc(sizeof(Node *) * n->func.nargs);
+ n->func.scope->super = curstab();
+ pushstab(n->func.scope->super);
+ for (i = 0; i < n->func.nargs; i++)
+ n->func.args[i] = unpickle(fd);
+ n->func.body = unpickle(fd);
+ popstab();
+ break;
+ case Nimpl:
+ n->impl.traitname = unpickle(fd);
+ i = rdint(fd);
+ rdtrait(fd, &n->impl.trait, NULL);
+ rdtype(fd, &n->impl.type);
+ n->impl.ndecls = rdint(fd);
+ n->impl.decls = zalloc(sizeof(Node *) * n->impl.ndecls);
+ for (i = 0; i < n->impl.ndecls; i++)
+ n->impl.decls[i] = rdsym(fd, n->impl.trait);
+ break;
+ case Nnone:
+ die("Nnone should not be seen as node type!");
+ break;
+ }
+ return n;
}
static Stab *findstab(Stab *st, char *pkg)
{
- Stab *s;
+ Stab *s;
- if (!pkg) {
- if (!st->name)
- return st;
- else
- return NULL;
- }
+ if (!pkg) {
+ if (!st->name)
+ return st;
+ else
+ return NULL;
+ }
- s = getns(file, pkg);
- if (!s) {
- s = mkstab(0);
- s->name = strdup(pkg);
- putns(file, s);
- }
- return s;
+ s = getns(file, pkg);
+ if (!s) {
+ s = mkstab(0);
+ s->name = strdup(pkg);
+ putns(file, s);
+ }
+ return s;
}
static int isspecialization(Type *t1, Type *t2)
{
- if ((t1->type != Tygeneric || t2->type != Tyname) &&
- (t1->type != Tyname || t2->type != Tygeneric) &&
- (t1->type != Tyname || t2->type != Tyname))
- return 0;
- /* FIXME: this should be done better */
- return nameeq(t1->name, t2->name);
+ if ((t1->type != Tygeneric || t2->type != Tyname) &&
+ (t1->type != Tyname || t2->type != Tygeneric) &&
+ (t1->type != Tyname || t2->type != Tyname))
+ return 0;
+ /* FIXME: this should be done better */
+ return nameeq(t1->name, t2->name);
}
static void fixtypemappings(Stab *st)
{
- size_t i;
- Type *t, *old;
+ size_t i;
+ Type *t, *old;
+ /*
+ * merge duplicate definitions.
+ * This allows us to compare named types by id, instead
+ * of doing a deep walk through the type. This ability is
+ * depended on when we do type inference.
+ */
+ for (i = 0; i < ntypefixdest; i++) {
+ t = htget(tidmap, itop(typefixid[i]));
+ if (!t)
+ die("Unable to find type for id %zd\n", typefixid[i]);
+ *typefixdest[i] = t;
+ }
+ for (i = 0; i < ntypefixdest; i++) {
+ old = *typefixdest[i];
+ if (old->type == Tyname || old->type == Tygeneric) {
+ t = htget(tydedup, old);
+ if (!t) {
+ t = old;
+ htput(tydedup, old, old);
+ }
+ *typefixdest[i] = t;
+ }
+ }
- /*
- * merge duplicate definitions.
- * This allows us to compare named types by id, instead
- * of doing a deep walk through the type. This ability is
- * depended on when we do type inference.
- */
- for (i = 0; i < ntypefixdest; i++) {
- t = htget(tidmap, itop(typefixid[i]));
- if (!t)
- die("Unable to find type for id %zd\n", typefixid[i]);
- *typefixdest[i] = t;
- }
- for (i = 0; i < ntypefixdest; i++) {
- old = *typefixdest[i];
- if (old->type == Tyname || old->type == Tygeneric) {
- t = htget(tydedup, old);
- if (!t) {
- t = old;
- htput(tydedup, old, old);
- }
- *typefixdest[i] = t;
- }
- }
-
- /* check for duplicate type definitions */
- for (i = 0; i < ntypefixdest; i++) {
- t = htget(tidmap, itop(typefixid[i]));
- if ((t->type != Tyname && t->type != Tygeneric) || t->issynth)
- continue;
- old = htget(tydedup, t);
- if (old && !tyeq(t, old) && !isspecialization(t, old))
- lfatal(t->loc, "Duplicate definition of type %s on %s:%d", tystr(old), file->file.files[old->loc.file], old->loc.line);
- }
- for (i = 0; i < ntypefixdest; i++)
- lfree(&typefixdest, &ntypefixdest);
- lfree(&typefixid, &ntypefixid);
+ /* check for duplicate type definitions */
+ for (i = 0; i < ntypefixdest; i++) {
+ t = htget(tidmap, itop(typefixid[i]));
+ if ((t->type != Tyname && t->type != Tygeneric) || t->issynth)
+ continue;
+ old = htget(tydedup, t);
+ if (old && !tyeq(t, old) && !isspecialization(t, old))
+ lfatal(t->loc, "Duplicate definition of type %s on %s:%d", tystr(old),
+ file->file.files[old->loc.file], old->loc.line);
+ }
+ for (i = 0; i < ntypefixdest; i++)
+ lfree(&typefixdest, &ntypefixdest);
+ lfree(&typefixid, &ntypefixid);
}
static void fixtraitmappings(Stab *st)
{
- size_t i;
- Trait *t;
+ size_t i;
+ Trait *t;
- /*
- * merge duplicate definitions.
- * This allows us to compare named types by id, instead
- * of doing a deep walk through the type. This ability is
- * depended on when we do type inference.
- */
- for (i = 0; i < ntraitfixdest; i++) {
- t = htget(trmap, itop(traitfixid[i]));
- if (!t)
- die("Unable to find trait for id %zd\n", traitfixid[i]);
- if (traitfixdest[i])
- *traitfixdest[i] = t;
- if (traitfixtype[i])
- settrait(traitfixtype[i], t);
- }
+ /*
+ * merge duplicate definitions.
+ * This allows us to compare named types by id, instead
+ * of doing a deep walk through the type. This ability is
+ * depended on when we do type inference.
+ */
+ for (i = 0; i < ntraitfixdest; i++) {
+ t = htget(trmap, itop(traitfixid[i]));
+ if (!t)
+ die("Unable to find trait for id %zd\n", traitfixid[i]);
+ if (traitfixdest[i])
+ *traitfixdest[i] = t;
+ if (traitfixtype[i])
+ settrait(traitfixtype[i], t);
+ }
- lfree(&traitfixdest, &ntraitfixdest);
- lfree(&traitfixid, &ntraitfixid);
+ lfree(&traitfixdest, &ntraitfixdest);
+ lfree(&traitfixid, &ntraitfixid);
}
/* Usefile format:
@@ -812,169 +799,172 @@
*/
int loaduse(char *path, FILE *f, Stab *st, Vis vis)
{
- intptr_t tid;
- size_t i;
- int v;
- char *pkg;
- Node *dcl, *impl, *init;
- Stab *s;
- Type *ty;
- Trait *tr;
- char *lib;
- int c;
+ intptr_t tid;
+ size_t i;
+ int v;
+ char *pkg;
+ Node *dcl, *impl, *init;
+ Stab *s;
+ Type *ty;
+ Trait *tr;
+ char *lib;
+ int c;
- pushstab(file->file.globls);
- if (!tydedup)
- tydedup = mkht(tyhash, tyeq);
- if (fgetc(f) != 'U')
- return 0;
- v = rdint(f);
- if (v != Abiversion) {
- fprintf(stderr, "%s: abi version %d, expected %d\n", path, v, Abiversion);
- return 0;
- }
- pkg = rdstr(f);
- /* if the package names match up, or the usefile has no declared
- * package, then we simply add to the current stab. Otherwise,
- * we add a new stab under the current one */
- if (st->name) {
- if (pkg && !strcmp(pkg, st->name)) {
- s = st;
- } else {
- s = findstab(st, pkg);
- }
- } else {
- if (pkg) {
- s = findstab(st, pkg);
- } else {
- s = st;
- }
- }
- if (!streq(st->name, pkg))
- vis = Visintern;
- if (!s) {
- printf("could not find matching package for merge: %s in %s\n", st->name, path);
- exit(1);
- }
- tidmap = mkht(ptrhash, ptreq);
- trmap = mkht(ptrhash, ptreq);
- if (!initmap)
- initmap = mkht(namehash, nameeq);
- /* builtin traits */
- for (i = 0; i < Ntraits; i++)
- htput(trmap, itop(i), traittab[i]);
- while ((c = fgetc(f)) != EOF) {
- switch(c) {
- case 'L':
- lib = rdstr(f);
- for (i = 0; i < file->file.nlibdeps; i++)
- if (!strcmp(file->file.libdeps[i], lib))
- /* break out of both loop and switch */
- goto foundlib;
- lappend(&file->file.libdeps, &file->file.nlibdeps, lib);
+ pushstab(file->file.globls);
+ if (!tydedup)
+ tydedup = mkht(tyhash, tyeq);
+ if (fgetc(f) != 'U')
+ return 0;
+ v = rdint(f);
+ if (v != Abiversion) {
+ fprintf(stderr, "%s: abi version %d, expected %d\n", path, v, Abiversion);
+ return 0;
+ }
+ pkg = rdstr(f);
+ /* if the package names match up, or the usefile has no declared
+ * package, then we simply add to the current stab. Otherwise,
+ * we add a new stab under the current one */
+ if (st->name) {
+ if (pkg && !strcmp(pkg, st->name)) {
+ s = st;
+ }
+ else {
+ s = findstab(st, pkg);
+ }
+ }
+ else {
+ if (pkg) {
+ s = findstab(st, pkg);
+ }
+ else {
+ s = st;
+ }
+ }
+ if (!streq(st->name, pkg))
+ vis = Visintern;
+ if (!s) {
+ printf("could not find matching package for merge: %s in %s\n", st->name, path);
+ exit(1);
+ }
+ tidmap = mkht(ptrhash, ptreq);
+ trmap = mkht(ptrhash, ptreq);
+ if (!initmap)
+ initmap = mkht(namehash, nameeq);
+ /* builtin traits */
+ for (i = 0; i < Ntraits; i++)
+ htput(trmap, itop(i), traittab[i]);
+ while ((c = fgetc(f)) != EOF) {
+ switch (c) {
+ case 'L':
+ lib = rdstr(f);
+ for (i = 0; i < file->file.nlibdeps; i++)
+ if (!strcmp(file->file.libdeps[i], lib))
+ /* break out of both loop and switch */
+ goto foundlib;
+ lappend(&file->file.libdeps, &file->file.nlibdeps, lib);
foundlib:
- break;
- case 'X':
- lib = rdstr(f);
- for (i = 0; i < file->file.nextlibs; i++)
- if (!strcmp(file->file.extlibs[i], lib))
- /* break out of both loop and switch */
- goto foundextlib;
- lappend(&file->file.extlibs, &file->file.nextlibs, lib);
+ break;
+ case 'X':
+ lib = rdstr(f);
+ for (i = 0; i < file->file.nextlibs; i++)
+ if (!strcmp(file->file.extlibs[i], lib))
+ /* break out of both loop and switch */
+ goto foundextlib;
+ lappend(&file->file.extlibs, &file->file.nextlibs, lib);
foundextlib:
- break;
- case 'F':
- lappend(&file->file.files, &file->file.nfiles, rdstr(f));
- break;
- case 'G':
- case 'D':
- dcl = rdsym(f, NULL);
- dcl->decl.vis = vis;
- dcl->decl.isglobl = 1;
- putdcl(s, dcl);
- break;
- case 'S':
- init = unpickle(f);
- if (!hthas(initmap, init)) {
- htput(initmap, init, init);
- lappend(&file->file.init, &file->file.ninit, init);
- }
- break;
- case 'R':
- tr = traitunpickle(f);
- tr->vis = vis;
- puttrait(s, tr->name, tr);
- for (i = 0; i < tr->nfuncs; i++)
- putdcl(s, tr->funcs[i]);
- break;
- case 'T':
- tid = rdint(f);
- ty = tyunpickle(f);
- if(!ty->ishidden)
- ty->vis = vis;
- htput(tidmap, itop(tid), ty);
- /* fix up types */
- if (ty->type == Tyname || ty->type == Tygeneric) {
- if (ty->issynth)
- break;
- if (!streq(s->name, ty->name->name.ns))
- ty->ishidden = 1;
- if (!gettype(s, ty->name) && !ty->ishidden)
- puttype(s, ty->name, ty);
- } else if (ty->type == Tyunion) {
- for (i = 0; i < ty->nmemb; i++)
- if (!getucon(s, ty->udecls[i]->name) && !ty->udecls[i]->synth)
- putucon(s, ty->udecls[i]);
- }
- break;
- case 'I':
- impl = unpickle(f);
- putimpl(s, impl);
- /* specialized declarations always go into the global stab */
- for (i = 0; i < impl->impl.ndecls; i++)
- putdcl(file->file.globls, impl->impl.decls[i]);
- break;
- case EOF:
- break;
- }
- }
- fixtypemappings(s);
- fixtraitmappings(s);
- htfree(tidmap);
- popstab();
- return 1;
-}
+ break;
+ case 'F': lappend(&file->file.files, &file->file.nfiles, rdstr(f)); break;
+ case 'G':
+ case 'D':
+ dcl = rdsym(f, NULL);
+ dcl->decl.vis = vis;
+ dcl->decl.isglobl = 1;
+ putdcl(s, dcl);
+ break;
+ case 'S':
+ init = unpickle(f);
+ if (!hthas(initmap, init)) {
+ htput(initmap, init, init);
+ lappend(&file->file.init, &file->file.ninit, init);
+ }
+ break;
+ case 'R':
+ tr = traitunpickle(f);
+ tr->vis = vis;
+ puttrait(s, tr->name, tr);
+ for (i = 0; i < tr->nfuncs; i++)
+ putdcl(s, tr->funcs[i]);
+ break;
+ case 'T':
+ tid = rdint(f);
+ ty = tyunpickle(f);
+ if (!ty->ishidden)
+ ty->vis = vis;
+ htput(tidmap, itop(tid), ty);
+ /* fix up types */
+ if (ty->type == Tyname || ty->type == Tygeneric) {
+ if (ty->issynth)
+ break;
+ if (!streq(s->name, ty->name->name.ns))
+ ty->ishidden = 1;
+ if (!gettype(s, ty->name) && !ty->ishidden)
+ puttype(s, ty->name, ty);
+ }
+ else if (ty->type == Tyunion) {
+ for (i = 0; i < ty->nmemb; i++)
+ if (!getucon(s, ty->udecls[i]->name) &&
+ !ty->udecls[i]->synth)
+ putucon(s, ty->udecls[i]);
+ }
+ break;
+ case 'I':
+ impl = unpickle(f);
+ putimpl(s, impl);
+ /* specialized declarations always go into the global stab */
+ for (i = 0; i < impl->impl.ndecls; i++)
+ putdcl(file->file.globls, impl->impl.decls[i]);
+ break;
+ case EOF: break;
+ }
+ }
+ fixtypemappings(s);
+ fixtraitmappings(s);
+ htfree(tidmap);
+ popstab();
+ return 1;
+}
void readuse(Node *use, Stab *st, Vis vis)
{
- size_t i;
- FILE *fd;
- char *t, *p;
+ size_t i;
+ FILE *fd;
+ char *t, *p;
- /* local (quoted) uses are always relative to the cwd */
- fd = NULL;
- p = NULL;
- if (use->use.islocal) {
- p = strdup(use->use.name);
- fd = fopen(p, "r");
- /* nonlocal (barename) uses are always searched on the include path */
- } else {
- for (i = 0; i < nincpaths; i++) {
- t = strjoin(incpaths[i], "/");
- p = strjoin(t, use->use.name);
- fd = fopen(p, "r");
- if (fd) {
- free(t);
- break;
- }
- }
- }
- if (!fd)
- fatal(use, "Could not open %s", use->use.name);
+ /* local (quoted) uses are always relative to the cwd */
+ fd = NULL;
+ p = NULL;
+ if (use->use.islocal) {
+ p = strdup(use->use.name);
+ fd = fopen(p, "r");
+ /* nonlocal (barename) uses are always searched on the include path */
+ }
+ else {
+ for (i = 0; i < nincpaths; i++) {
+ t = strjoin(incpaths[i], "/");
+ p = strjoin(t, use->use.name);
+ fd = fopen(p, "r");
+ if (fd) {
+ free(t);
+ break;
+ }
+ }
+ }
+ if (!fd)
+ fatal(use, "Could not open %s", use->use.name);
- if (!loaduse(p, fd, st, vis))
- die("Could not load usefile %s from %s", use->use.name, p);
- free(p);
+ if (!loaduse(p, fd, st, vis))
+ die("Could not load usefile %s from %s", use->use.name, p);
+ free(p);
}
/* Usefile format:
@@ -988,92 +978,92 @@
*/
void writeuse(FILE *f, Node *file)
{
- Stab *st;
- void **k;
- Node *s, *u;
- size_t i, n;
+ Stab *st;
+ void **k;
+ Node *s, *u;
+ size_t i, n;
- assert(file->type == Nfile);
- st = file->file.globls;
+ assert(file->type == Nfile);
+ st = file->file.globls;
- /* usefile name */
- wrbyte(f, 'U');
- wrint(f, Abiversion); /* use version */
- if (st->name)
- wrstr(f, st->name);
- else
- wrstr(f, NULL);
+ /* usefile name */
+ wrbyte(f, 'U');
+ wrint(f, Abiversion); /* use version */
+ if (st->name)
+ wrstr(f, st->name);
+ else
+ wrstr(f, NULL);
- /* library deps */
- for (i = 0; i < file->file.nuses; i++) {
- u = file->file.uses[i];
- if (!u->use.islocal) {
- wrbyte(f, 'L');
- wrstr(f, u->use.name);
- }
- }
- for (i = 0; i < file->file.nlibdeps; i++) {
- wrbyte(f, 'L');
- wrstr(f, file->file.libdeps[i]);
- }
- for (i = 0; i < file->file.nextlibs; i++) {
- wrbyte(f, 'X');
- wrstr(f, file->file.extlibs[i]);
- }
+ /* library deps */
+ for (i = 0; i < file->file.nuses; i++) {
+ u = file->file.uses[i];
+ if (!u->use.islocal) {
+ wrbyte(f, 'L');
+ wrstr(f, u->use.name);
+ }
+ }
+ for (i = 0; i < file->file.nlibdeps; i++) {
+ wrbyte(f, 'L');
+ wrstr(f, file->file.libdeps[i]);
+ }
+ for (i = 0; i < file->file.nextlibs; i++) {
+ wrbyte(f, 'X');
+ wrstr(f, file->file.extlibs[i]);
+ }
- /* source file name */
- wrbyte(f, 'F');
- wrstr(f, file->file.files[0]);
+ /* source file name */
+ wrbyte(f, 'F');
+ wrstr(f, file->file.files[0]);
- for (i = 0; i < ntypes; i++) {
- if (types[i]->vis == Visexport || types[i]->vis == Vishidden) {
- wrbyte(f, 'T');
- wrint(f, types[i]->tid);
- typickle(f, types[i]);
- }
- }
+ for (i = 0; i < ntypes; i++) {
+ if (types[i]->vis == Visexport || types[i]->vis == Vishidden) {
+ wrbyte(f, 'T');
+ wrint(f, types[i]->tid);
+ typickle(f, types[i]);
+ }
+ }
- for (i = 0; i < ntraittab; i++) {
- if (traittab[i]->vis == Visexport || traittab[i]->vis == Vishidden) {
- wrbyte(f, 'R');
- traitpickle(f, traittab[i]);
- }
- }
+ for (i = 0; i < ntraittab; i++) {
+ if (traittab[i]->vis == Visexport || traittab[i]->vis == Vishidden) {
+ wrbyte(f, 'R');
+ traitpickle(f, traittab[i]);
+ }
+ }
- k = htkeys(st->impl, &n);
- for (i = 0; i < n; i++) {
- /* merging during inference should remove all protos */
- s = getimpl(st, k[i]);
- assert(!s->impl.isproto);
- if (s->impl.vis == Visexport || s->impl.vis == Vishidden) {
- wrbyte(f, 'I');
- pickle(f, s);
- }
- }
- free(k);
+ k = htkeys(st->impl, &n);
+ for (i = 0; i < n; i++) {
+ /* merging during inference should remove all protos */
+ s = getimpl(st, k[i]);
+ assert(!s->impl.isproto);
+ if (s->impl.vis == Visexport || s->impl.vis == Vishidden) {
+ wrbyte(f, 'I');
+ pickle(f, s);
+ }
+ }
+ free(k);
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- s = getdcl(st, k[i]);
- assert(s != NULL);
- if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin)
- continue;
- /* trait functions get written out with their traits */
- if (s->decl.trait || s->decl.isinit)
- continue;
- else if (s->decl.isgeneric)
- wrbyte(f, 'G');
- else
- wrbyte(f, 'D');
- wrsym(f, s);
- }
- for (i = 0; i < file->file.ninit; i++) {
- wrbyte(f, 'S');
- pickle(f, file->file.init[i]);
- }
- if (file->file.localinit) {
- wrbyte(f, 'S');
- pickle(f, file->file.localinit->decl.name);
- }
- free(k);
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ s = getdcl(st, k[i]);
+ assert(s != NULL);
+ if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin)
+ continue;
+ /* trait functions get written out with their traits */
+ if (s->decl.trait || s->decl.isinit)
+ continue;
+ else if (s->decl.isgeneric)
+ wrbyte(f, 'G');
+ else
+ wrbyte(f, 'D');
+ wrsym(f, s);
+ }
+ for (i = 0; i < file->file.ninit; i++) {
+ wrbyte(f, 'S');
+ pickle(f, file->file.init[i]);
+ }
+ if (file->file.localinit) {
+ wrbyte(f, 'S');
+ pickle(f, file->file.localinit->decl.name);
+ }
+ free(k);
}
--- a/parse/util.c
+++ b/parse/util.c
@@ -16,546 +16,543 @@
/* malloc wrappers */
void *zalloc(size_t sz)
{
- void *mem;
+ void *mem;
- mem = calloc(1, sz);
- if (!mem && sz)
- die("Out of memory");
- return mem;
+ mem = calloc(1, sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
}
-
void *xalloc(size_t sz)
{
- void *mem;
+ void *mem;
- mem = malloc(sz);
- if (!mem && sz)
- die("Out of memory");
- return mem;
+ mem = malloc(sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
}
void *zrealloc(void *mem, size_t oldsz, size_t sz)
{
- char *p;
+ char *p;
- p = xrealloc(mem, sz);
- if (sz > oldsz)
- memset(&p[oldsz], 0, sz - oldsz);
- return p;
+ p = xrealloc(mem, sz);
+ if (sz > oldsz)
+ memset(&p[oldsz], 0, sz - oldsz);
+ return p;
}
void *xrealloc(void *mem, size_t sz)
{
- mem = realloc(mem, sz);
- if (!mem && sz)
- die("Out of memory");
- return mem;
+ mem = realloc(mem, sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
}
/* errors */
void die(char *msg, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, msg);
- vfprintf(stderr, msg, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- abort();
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
}
void fatal(Node *n, char *msg, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, msg);
- lfatalv(n->loc, msg, ap);
- va_end(ap);
+ va_start(ap, msg);
+ lfatalv(n->loc, msg, ap);
+ va_end(ap);
}
void lfatal(Srcloc l, char *msg, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, msg);
- lfatalv(l, msg, ap);
- va_end(ap);
+ va_start(ap, msg);
+ lfatalv(l, msg, ap);
+ va_end(ap);
}
void lfatalv(Srcloc l, char *msg, va_list ap)
{
- fprintf(stdout, "%s:%d: ", fname(l), lnum(l));
- vfprintf(stdout, msg, ap);
- fprintf(stdout, "\n");
- exit(1);
+ fprintf(stdout, "%s:%d: ", fname(l), lnum(l));
+ vfprintf(stdout, msg, ap);
+ fprintf(stdout, "\n");
+ exit(1);
}
/* Some systems don't have strndup. */
char *strdupn(char *s, size_t len)
{
- char *ret;
+ char *ret;
- ret = xalloc(len + 1);
- memcpy(ret, s, len);
- ret[len] = '\0';
- return ret;
+ ret = xalloc(len + 1);
+ memcpy(ret, s, len);
+ ret[len] = '\0';
+ return ret;
}
char *strjoin(char *u, char *v)
{
- size_t n;
- char *s;
+ size_t n;
+ char *s;
- n = strlen(u) + strlen(v) + 1;
- s = xalloc(n);
- bprintf(s, n + 1, "%s%s", u, v);
- return s;
+ n = strlen(u) + strlen(v) + 1;
+ s = xalloc(n);
+ bprintf(s, n + 1, "%s%s", u, v);
+ return s;
}
void *memdup(void *mem, size_t len)
{
- void *ret;
+ void *ret;
- ret = xalloc(len);
- return memcpy(ret, mem, len);
+ ret = xalloc(len);
+ return memcpy(ret, mem, len);
}
/* lists */
void lappend(void *l, size_t *len, void *n)
{
- void ***pl;
+ void ***pl;
- pl = l;
- *pl = xrealloc(*pl, (*len + 1)*sizeof(void*));
- (*pl)[*len] = n;
- (*len)++;
+ pl = l;
+ *pl = xrealloc(*pl, (*len + 1) * sizeof(void *));
+ (*pl)[*len] = n;
+ (*len)++;
}
void *lpop(void *l, size_t *len)
{
- void ***pl;
- void *v;
+ void ***pl;
+ void *v;
- pl = l;
- (*len)--;
- v = (*pl)[*len];
- *pl = xrealloc(*pl, *len * sizeof(void*));
- return v;
+ pl = l;
+ (*len)--;
+ v = (*pl)[*len];
+ *pl = xrealloc(*pl, *len * sizeof(void *));
+ return v;
}
void linsert(void *p, size_t *len, size_t idx, void *v)
{
- void ***pl, **l;
+ void ***pl, **l;
- pl = p;
- *pl = xrealloc(*pl, (*len + 1)*sizeof(void*));
- l = *pl;
+ pl = p;
+ *pl = xrealloc(*pl, (*len + 1) * sizeof(void *));
+ l = *pl;
- memmove(&l[idx + 1], &l[idx], (*len - idx)*sizeof(void*));
- l[idx] = v;
- (*len)++;
+ memmove(&l[idx + 1], &l[idx], (*len - idx) * sizeof(void *));
+ l[idx] = v;
+ (*len)++;
}
void ldel(void *p, size_t *len, size_t idx)
{
- void ***pl, **l;
+ void ***pl, **l;
- assert(p != NULL);
- assert(idx < *len);
- pl = p;
- l = *pl;
- memmove(&l[idx], &l[idx + 1], (*len - idx - 1)*sizeof(void*));
- (*len)--;
- *pl = xrealloc(l, *len * sizeof(void*));
+ assert(p != NULL);
+ assert(idx < *len);
+ pl = p;
+ l = *pl;
+ memmove(&l[idx], &l[idx + 1], (*len - idx - 1) * sizeof(void *));
+ (*len)--;
+ *pl = xrealloc(l, *len * sizeof(void *));
}
void lcat(void *dst, size_t *ndst, void *src, size_t nsrc)
{
- size_t i;
- void ***d, **s;
+ size_t i;
+ void ***d, **s;
- d = dst;
- s = src;
- for (i = 0; i < nsrc; i++)
- lappend(d, ndst, s[i]);
+ d = dst;
+ s = src;
+ for (i = 0; i < nsrc; i++)
+ lappend(d, ndst, s[i]);
}
-
void lfree(void *l, size_t *len)
{
- void ***pl;
+ void ***pl;
- assert(l != NULL);
- pl = l;
- free(*pl);
- *pl = NULL;
- *len = 0;
+ assert(l != NULL);
+ pl = l;
+ free(*pl);
+ *pl = NULL;
+ *len = 0;
}
/* endian packing */
void be64(vlong v, byte buf[8])
{
- buf[0] = (v >> 56) & 0xff;
- buf[1] = (v >> 48) & 0xff;
- buf[2] = (v >> 40) & 0xff;
- buf[3] = (v >> 32) & 0xff;
- buf[4] = (v >> 24) & 0xff;
- buf[5] = (v >> 16) & 0xff;
- buf[6] = (v >> 8) & 0xff;
- buf[7] = (v >> 0) & 0xff;
+ buf[0] = (v >> 56) & 0xff;
+ buf[1] = (v >> 48) & 0xff;
+ buf[2] = (v >> 40) & 0xff;
+ buf[3] = (v >> 32) & 0xff;
+ buf[4] = (v >> 24) & 0xff;
+ buf[5] = (v >> 16) & 0xff;
+ buf[6] = (v >> 8) & 0xff;
+ buf[7] = (v >> 0) & 0xff;
}
vlong host64(byte buf[8])
{
- vlong v = 0;
+ vlong v = 0;
- v |= ((vlong)buf[0] << 56LL);
- v |= ((vlong)buf[1] << 48LL);
- v |= ((vlong)buf[2] << 40LL);
- v |= ((vlong)buf[3] << 32LL);
- v |= ((vlong)buf[4] << 24LL);
- v |= ((vlong)buf[5] << 16LL);
- v |= ((vlong)buf[6] << 8LL);
- v |= ((vlong)buf[7] << 0LL);
- return v;
+ v |= ((vlong)buf[0] << 56LL);
+ v |= ((vlong)buf[1] << 48LL);
+ v |= ((vlong)buf[2] << 40LL);
+ v |= ((vlong)buf[3] << 32LL);
+ v |= ((vlong)buf[4] << 24LL);
+ v |= ((vlong)buf[5] << 16LL);
+ v |= ((vlong)buf[6] << 8LL);
+ v |= ((vlong)buf[7] << 0LL);
+ return v;
}
void be32(long v, byte buf[4])
{
- buf[0] = (v >> 24) & 0xff;
- buf[1] = (v >> 16) & 0xff;
- buf[2] = (v >> 8) & 0xff;
- buf[3] = (v >> 0) & 0xff;
+ buf[0] = (v >> 24) & 0xff;
+ buf[1] = (v >> 16) & 0xff;
+ buf[2] = (v >> 8) & 0xff;
+ buf[3] = (v >> 0) & 0xff;
}
long host32(byte buf[4])
{
- int32_t v = 0;
- v |= ((long)buf[0] << 24);
- v |= ((long)buf[1] << 16);
- v |= ((long)buf[2] << 8);
- v |= ((long)buf[3] << 0);
- return v;
+ int32_t v = 0;
+ v |= ((long)buf[0] << 24);
+ v |= ((long)buf[1] << 16);
+ v |= ((long)buf[2] << 8);
+ v |= ((long)buf[3] << 0);
+ return v;
}
void wrbuf(FILE *fd, void *p, size_t sz)
{
- size_t n;
- char *buf;
+ size_t n;
+ char *buf;
- n = 0;
- buf = p;
- while (n < sz) {
- n += fwrite(buf + n, 1, sz - n, fd);
- if (feof(fd))
- die("Unexpected EOF");
- if (ferror(fd))
- die("Error writing");
- }
+ n = 0;
+ buf = p;
+ while (n < sz) {
+ n += fwrite(buf + n, 1, sz - n, fd);
+ if (feof(fd))
+ die("Unexpected EOF");
+ if (ferror(fd))
+ die("Error writing");
+ }
}
void rdbuf(FILE *fd, void *buf, size_t sz)
{
- size_t n;
+ size_t n;
- n = sz;
- while (n > 0) {
- n -= fread(buf, 1, n, fd);
- if (feof(fd))
- die("Unexpected EOF");
- if (ferror(fd))
- die("Error writing");
- }
+ n = sz;
+ while (n > 0) {
+ n -= fread(buf, 1, n, fd);
+ if (feof(fd))
+ die("Unexpected EOF");
+ if (ferror(fd))
+ die("Error writing");
+ }
}
void wrbyte(FILE *fd, char val)
{
- if (fputc(val, fd) == EOF)
- die("Unexpected EOF");
+ if (fputc(val, fd) == EOF)
+ die("Unexpected EOF");
}
char rdbyte(FILE *fd)
{
- int c;
- c = fgetc(fd);
- if (c == EOF)
- die("Unexpected EOF");
- return c;
+ int c;
+ c = fgetc(fd);
+ if (c == EOF)
+ die("Unexpected EOF");
+ return c;
}
void wrint(FILE *fd, long val)
{
- byte buf[4];
- be32(val, buf);
- wrbuf(fd, buf, 4);
+ byte buf[4];
+ be32(val, buf);
+ wrbuf(fd, buf, 4);
}
long rdint(FILE *fd)
{
- byte buf[4];
- rdbuf(fd, buf, 4);
- return host32(buf);
+ byte buf[4];
+ rdbuf(fd, buf, 4);
+ return host32(buf);
}
void wrstr(FILE *fd, char *val)
{
- size_t len;
+ size_t len;
- if (!val) {
- wrint(fd, -1);
- } else {
- wrint(fd, strlen(val));
- len = strlen(val);
- wrbuf(fd, val, len);
- }
+ if (!val) {
+ wrint(fd, -1);
+ }
+ else {
+ wrint(fd, strlen(val));
+ len = strlen(val);
+ wrbuf(fd, val, len);
+ }
}
char *rdstr(FILE *fd)
{
- ssize_t len;
- char *s;
+ ssize_t len;
+ char *s;
- len = rdint(fd);
- if (len == -1) {
- return NULL;
- } else {
- s = xalloc(len + 1);
- rdbuf(fd, s, len);
- s[len] = '\0';
- return s;
- }
+ len = rdint(fd);
+ if (len == -1) {
+ return NULL;
+ }
+ else {
+ s = xalloc(len + 1);
+ rdbuf(fd, s, len);
+ s[len] = '\0';
+ return s;
+ }
}
void wrlenstr(FILE *fd, Str str)
{
- wrint(fd, str.len);
- wrbuf(fd, str.buf, str.len);
+ wrint(fd, str.len);
+ wrbuf(fd, str.buf, str.len);
}
void rdlenstr(FILE *fd, Str *str)
{
- str->len = rdint(fd);
- str->buf = xalloc(str->len + 1);
- rdbuf(fd, str->buf, str->len);
- str->buf[str->len] = '\0';
+ str->len = rdint(fd);
+ str->buf = xalloc(str->len + 1);
+ rdbuf(fd, str->buf, str->len);
+ str->buf[str->len] = '\0';
}
void wrflt(FILE *fd, double val)
{
- byte buf[8];
- /* Assumption: We have 'val' in 64 bit IEEE format */
- union {
- uvlong ival;
- double fval;
- } u;
+ byte buf[8];
+ /* Assumption: We have 'val' in 64 bit IEEE format */
+ union {
+ uvlong ival;
+ double fval;
+ } u;
- u.fval = val;
- be64(u.ival, buf);
- wrbuf(fd, buf, 8);
+ u.fval = val;
+ be64(u.ival, buf);
+ wrbuf(fd, buf, 8);
}
double rdflt(FILE *fd)
{
- byte buf[8];
- union {
- uvlong ival;
- double fval;
- } u;
+ byte buf[8];
+ union {
+ uvlong ival;
+ double fval;
+ } u;
- if (fread(buf, 8, 1, fd) < 8)
- die("Unexpected EOF");
- u.ival = host64(buf);
- return u.fval;
+ if (fread(buf, 8, 1, fd) < 8)
+ die("Unexpected EOF");
+ u.ival = host64(buf);
+ return u.fval;
}
size_t bprintf(char *buf, size_t sz, char *fmt, ...)
{
- va_list ap;
- size_t n;
+ va_list ap;
+ size_t n;
- va_start(ap, fmt);
- n = vsnprintf(buf, sz, fmt, ap);
- assert(n <= sz);
- va_end(ap);
+ va_start(ap, fmt);
+ n = vsnprintf(buf, sz, fmt, ap);
+ assert(n <= sz);
+ va_end(ap);
- return n;
+ return n;
}
-void wrbool(FILE *fd, int val)
-{
- wrbyte(fd, val);
-}
+void wrbool(FILE *fd, int val) { wrbyte(fd, val); }
-int rdbool(FILE *fd)
-{
- return rdbyte(fd);
-}
+int rdbool(FILE *fd) { return rdbyte(fd); }
char *swapsuffix(char *buf, size_t sz, char *s, char *suf, char *swap)
{
- size_t slen, suflen, swaplen;
+ size_t slen, suflen, swaplen;
- slen = strlen(s);
- suflen = strlen(suf);
- swaplen = strlen(swap);
+ slen = strlen(s);
+ suflen = strlen(suf);
+ swaplen = strlen(swap);
- if (slen < suflen)
- return NULL;
- if (slen + swaplen >= sz)
- die("swapsuffix: buf too small");
+ if (slen < suflen)
+ return NULL;
+ if (slen + swaplen >= sz)
+ die("swapsuffix: buf too small");
- buf[0] = '\0';
- /* if we have matching suffixes */
- if (suflen < slen && !strcmp(suf, &s[slen - suflen])) {
- strncat(buf, s, slen - suflen);
- strncat(buf, swap, swaplen);
- } else {
- bprintf(buf, sz, "%s%s", s, swap);
- }
+ buf[0] = '\0';
+ /* if we have matching suffixes */
+ if (suflen < slen && !strcmp(suf, &s[slen - suflen])) {
+ strncat(buf, s, slen - suflen);
+ strncat(buf, swap, swaplen);
+ }
+ else {
+ bprintf(buf, sz, "%s%s", s, swap);
+ }
- return buf;
+ return buf;
}
size_t max(size_t a, size_t b)
{
- if (a > b)
- return a;
- else
- return b;
+ if (a > b)
+ return a;
+ else
+ return b;
}
size_t min(size_t a, size_t b)
{
- if (a < b)
- return a;
- else
- return b;
+ if (a < b)
+ return a;
+ else
+ return b;
}
size_t align(size_t sz, size_t a)
{
- /* align to 0 just returns sz */
- if (a == 0)
- return sz;
- return (sz + a - 1) & ~(a - 1);
+ /* align to 0 just returns sz */
+ if (a == 0)
+ return sz;
+ return (sz + a - 1) & ~(a - 1);
}
void indentf(int depth, char *fmt, ...)
{
- va_list ap;
- va_start(ap, fmt);
- vfindentf(stdout, depth, fmt, ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, fmt);
+ vfindentf(stdout, depth, fmt, ap);
+ va_end(ap);
}
void findentf(FILE *fd, int depth, char *fmt, ...)
{
- va_list ap;
- va_start(ap, fmt);
- vfindentf(fd, depth, fmt, ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, fmt);
+ vfindentf(fd, depth, fmt, ap);
+ va_end(ap);
}
void vfindentf(FILE *fd, int depth, char *fmt, va_list ap)
{
- ssize_t i;
+ ssize_t i;
- for (i = 0; i < depth; i++)
- fprintf(fd, "\t");
- vfprintf(fd, fmt, ap);
+ for (i = 0; i < depth; i++)
+ fprintf(fd, "\t");
+ vfprintf(fd, fmt, ap);
}
static int optinfo(Optctx *ctx, char arg, int *take, int *mand)
{
- char *s;
+ char *s;
- for (s = ctx->optstr; *s != '\0'; s++) {
- if (*s == arg) {
- s++;
- if (*s == ':') {
- *take = 1;
- *mand = 1;
- return 1;
- } else if (*s == '?') {
- *take = 1;
- *mand = 0;
- return 1;
- } else {
- *take = 0;
- *mand = 0;
- return 1;
- }
- }
- }
- return 0;
+ for (s = ctx->optstr; *s != '\0'; s++) {
+ if (*s == arg) {
+ s++;
+ if (*s == ':') {
+ *take = 1;
+ *mand = 1;
+ return 1;
+ }
+ else if (*s == '?') {
+ *take = 1;
+ *mand = 0;
+ return 1;
+ }
+ else {
+ *take = 0;
+ *mand = 0;
+ return 1;
+ }
+ }
+ }
+ return 0;
}
static int findnextopt(Optctx *ctx)
{
- size_t i;
+ size_t i;
- for (i = ctx->argidx + 1; i < ctx->noptargs; i++) {
- if (ctx->optargs[i][0] == '-')
- goto foundopt;
- else
- lappend(&ctx->args, &ctx->nargs, ctx->optargs[i]);
- }
- ctx->finished = 1;
- return 0;
+ for (i = ctx->argidx + 1; i < ctx->noptargs; i++) {
+ if (ctx->optargs[i][0] == '-')
+ goto foundopt;
+ else
+ lappend(&ctx->args, &ctx->nargs, ctx->optargs[i]);
+ }
+ ctx->finished = 1;
+ return 0;
foundopt:
- ctx->argidx = i;
- ctx->curarg = ctx->optargs[i] + 1; /* skip initial '-' */
- return 1;
+ ctx->argidx = i;
+ ctx->curarg = ctx->optargs[i] + 1; /* skip initial '-' */
+ return 1;
}
void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs)
{
- ctx->args = NULL;
- ctx->nargs = 0;
+ ctx->args = NULL;
+ ctx->nargs = 0;
- ctx->optstr = optstr;
- ctx->optargs = optargs;
- ctx->noptargs = noptargs;
- ctx->optdone = 0;
- ctx->finished = 0;
- ctx->argidx = 0;
- ctx->curarg = "";
- findnextopt(ctx);
+ ctx->optstr = optstr;
+ ctx->optargs = optargs;
+ ctx->noptargs = noptargs;
+ ctx->optdone = 0;
+ ctx->finished = 0;
+ ctx->argidx = 0;
+ ctx->curarg = "";
+ findnextopt(ctx);
}
int optnext(Optctx *ctx)
{
- int take, mand;
- int c;
+ int take, mand;
+ int c;
- c = *ctx->curarg;
- ctx->curarg++;
- if (!optinfo(ctx, c, &take, &mand)) {
- printf("Unexpected argument %c\n", *ctx->curarg);
- exit(1);
- }
+ c = *ctx->curarg;
+ ctx->curarg++;
+ if (!optinfo(ctx, c, &take, &mand)) {
+ printf("Unexpected argument %c\n", *ctx->curarg);
+ exit(1);
+ }
- ctx->optarg = NULL;
- if (take) {
- if (*ctx->curarg) {
- ctx->optarg = ctx->curarg;
- ctx->curarg += strlen(ctx->optarg);
- } else if (ctx->argidx < ctx->noptargs - 1) {
- ctx->optarg = ctx->optargs[ctx->argidx + 1];
- ctx->argidx++;
- } else if (mand) {
- fprintf(stderr, "expected argument for %c\n", *ctx->curarg);
- }
- findnextopt(ctx);
- } else {
- if (*ctx->curarg == '\0')
- findnextopt(ctx);
- }
- return c;
+ ctx->optarg = NULL;
+ if (take) {
+ if (*ctx->curarg) {
+ ctx->optarg = ctx->curarg;
+ ctx->curarg += strlen(ctx->optarg);
+ }
+ else if (ctx->argidx < ctx->noptargs - 1) {
+ ctx->optarg = ctx->optargs[ctx->argidx + 1];
+ ctx->argidx++;
+ }
+ else if (mand) {
+ fprintf(stderr, "expected argument for %c\n", *ctx->curarg);
+ }
+ findnextopt(ctx);
+ }
+ else {
+ if (*ctx->curarg == '\0')
+ findnextopt(ctx);
+ }
+ return c;
}
-int optdone(Optctx *ctx)
-{
- return *ctx->curarg == '\0' && ctx->finished;
-}
+int optdone(Optctx *ctx) { return *ctx->curarg == '\0' && ctx->finished; }