From 729aa97b799f72afdec3604f96526760701f36bc Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Wed, 30 Mar 2016 12:04:43 -0400 Subject: cleanup error handling --- all.h | 5 +++-- copy.c | 34 +++++++++++++++------------------- emit.c | 40 ++++++++++++++++++++-------------------- isel.c | 48 +++++++++++++++++++++++------------------------- mem.c | 2 +- parse.c | 12 ++++-------- rega.c | 4 ++-- spill.c | 10 ++++------ ssa.c | 6 +++--- util.c | 17 +++++++++++------ 10 files changed, 86 insertions(+), 92 deletions(-) diff --git a/all.h b/all.h index 40c80f6..51b641a 100644 --- a/all.h +++ b/all.h @@ -6,6 +6,7 @@ #include #define MAKESURE(what, x) typedef char make_sure_##what[(x)?1:-1] +#define die(...) die_(__FILE__, __VA_ARGS__) typedef unsigned int uint; typedef unsigned short ushort; @@ -481,7 +482,7 @@ extern char debug['Z'+1]; /* util.c */ extern Typ typ[NTyp]; extern Ins insb[NIns], *curi; -void diag(char *) __attribute__((noreturn)); +void die_(char *, char *, ...) __attribute__((noreturn)); void *emalloc(size_t); void *alloc(size_t); void freeall(void); @@ -522,7 +523,7 @@ extern OpDesc opdesc[NOp]; void parse(FILE *, char *, void (Dat *), void (Fn *)); void printfn(Fn *, FILE *); void printref(Ref, Fn *, FILE *); -void err(char *, ...); +void err(char *, ...) __attribute__((noreturn)); /* mem.c */ void memopt(Fn *); diff --git a/copy.c b/copy.c index ef2d01d..419b079 100644 --- a/copy.c +++ b/copy.c @@ -47,7 +47,6 @@ visitphi(Phi *p, Ref *cp, RList **w) break; } } - assert(!req(r, R)); update(p->to, r, cp, w); } @@ -65,6 +64,15 @@ visitins(Ins *i, Ref *cp, RList **w) } } +static void +subst(Ref *r, Ref *cp, Fn *fn) +{ + if (rtype(*r) == RTmp && req(copyof(*r, cp), R)) + err("temporary %%%s is used undefined", + fn->tmp[r->val].name); + *r = copyof(*r, cp); +} + void copy(Fn *fn) { @@ -93,8 +101,6 @@ copy(Fn *fn) u1 = u + fn->tmp[t].nuse; for (; utype) { - default: - diag("copy: invalid use"); case UPhi: visitphi(u->u.phi, cp, &w); break; @@ -103,6 +109,8 @@ copy(Fn *fn) break; case UJmp: break; + default: + die("invalid use %d", u->type); } } for (b=fn->start; b; b=b->link) { @@ -113,31 +121,19 @@ copy(Fn *fn) continue; } for (a=0; anarg; a++) - if (rtype(p->arg[a]) == RTmp) { - r = cp[p->arg[a].val]; - assert(!req(r, R)); - p->arg[a] = r; - } + subst(&p->arg[a], cp, fn); pp=&p->link; } for (i=b->ins; i-b->ins < b->nins; i++) { - r = cp[i->to.val]; + r = copyof(i->to, cp); if (!req(r, i->to)) { *i = (Ins){.op = ONop}; continue; } for (a=0; a<2; a++) - if (rtype(i->arg[a]) == RTmp) { - r = cp[i->arg[a].val]; - assert(!req(r, R)); - i->arg[a] = r; - } - } - if (rtype(b->jmp.arg) == RTmp) { - r = cp[b->jmp.arg.val]; - assert(!req(r, R)); - b->jmp.arg = r; + subst(&i->arg[a], cp, fn); } + subst(&b->jmp.arg, cp, fn); } if (debug['C']) { fprintf(stderr, "\n> Copy information:"); diff --git a/emit.c b/emit.c index 7309170..32e4078 100644 --- a/emit.c +++ b/emit.c @@ -133,7 +133,7 @@ slot(int s, Fn *fn) /* sign extend s using a bitfield */ x.i = s; - assert(NAlign == 3); + /* specific to NAlign == 3 */ if (x.i < 0) return -4 * x.i; else { @@ -146,8 +146,6 @@ static void emitcon(Con *con, FILE *f) { switch (con->type) { - default: - diag("emit: invalid constant"); case CAddr: if (con->local) fprintf(f, "%s%s", locprefix, con->label); @@ -159,6 +157,8 @@ emitcon(Con *con, FILE *f) case CBits: fprintf(f, "%"PRId64, con->bits.i); break; + default: + die("unreachable"); } } @@ -178,14 +178,14 @@ static Ref getarg(char c, Ins *i) { switch (c) { - default: - diag("emit: 0, 1, = expected in format"); case '0': return i->arg[0]; case '1': return i->arg[1]; case '=': return i->to; + default: + die("invalid arg letter %c", c); } } @@ -222,8 +222,8 @@ emitf(char *s, Ins *i, Fn *fn, FILE *f) } /* fall through */ case '-': - if (req(i->arg[1], i->to) && !req(i->arg[0], i->to)) - diag("emit: cannot convert to 2-address"); + assert((!req(i->arg[1], i->to) || req(i->arg[0], i->to)) && + "cannot convert to 2-address"); emitcopy(i->to, i->arg[0], i->cls, fn, f); s++; break; @@ -238,8 +238,6 @@ Next: } else fputc(c, f); switch ((c = *s++)) { - default: - diag("emit: invalid escape"); case '%': fputc('%', f); break; @@ -258,8 +256,6 @@ Next: c = *s++; ref = getarg(c, i); switch (rtype(ref)) { - default: - diag("emit: invalid reference"); case RTmp: assert(isreg(ref)); fprintf(f, "%%%s", regtoa(ref.val, sz)); @@ -294,6 +290,8 @@ Next: fputc('$', f); emitcon(&fn->con[ref.val], f); break; + default: + die("unreachable"); } break; case 'L': @@ -312,8 +310,6 @@ Next: c = *s++; ref = getarg(c, i); switch (rtype(ref)) { - default: - diag("emit: invalid memory reference"); case RAMem: goto Mem; case RSlot: @@ -327,8 +323,12 @@ Next: assert(isreg(ref)); fprintf(f, "(%%%s)", regtoa(ref.val, SLong)); break; + default: + die("unreachable"); } break; + default: + die("invalid format specifier %%%c", c); } goto Next; } @@ -350,7 +350,7 @@ emitins(Ins i, Fn *fn, FILE *f) /* this linear search should really be a binary * search */ if (omap[o].op == NOp) - diag("emit: no entry found for instruction"); + die("not match for %d(%d)", i.op, i.cls); if (omap[o].op == i.op) if (omap[o].cls == i.cls || (omap[o].cls == Ki && KBASE(i.cls) == 0) @@ -412,8 +412,6 @@ emitins(Ins i, Fn *fn, FILE *f) /* calls simply have a weird syntax in AT&T * assembly... */ switch (rtype(i.arg[0])) { - default: - diag("emit: invalid call instruction"); case RCon: fprintf(f, "\tcallq "); emitcon(&fn->con[i.arg[0].val], f); @@ -422,6 +420,8 @@ emitins(Ins i, Fn *fn, FILE *f) case RTmp: emitf("callq *%L0", &i, fn, f); break; + default: + die("invalid call argument"); } break; case OSAlloc: @@ -450,7 +450,7 @@ static int cneg(int cmp) { switch (cmp) { - default: diag("emit: cneg() unhandled comparison"); + default: die("invalid int comparison %d", cmp); case ICule: return ICugt; case ICult: return ICuge; case ICsle: return ICsgt; @@ -471,7 +471,7 @@ framesz(Fn *fn) { int i, o, f; - assert(NAlign == 3); + /* specific to NAlign == 3 */ for (i=0, o=0; ireg >> rclob[i]); f = fn->slot; @@ -549,12 +549,12 @@ emitfn(Fn *fn, FILE *f) c = cneg(c); s = b->s2; } else - diag("emit: unhandled jump (1)"); + die("unhandled jump"); fprintf(f, "\tj%s %sbb%d /* %s */\n", ctoa[c], locprefix, id0+s->id, s->name); break; } - diag("emit: unhandled jump (2)"); + die("unhandled jump %d", b->jmp.type); } } id0 += fn->nblk; diff --git a/isel.c b/isel.c index 2a55733..6d19ccc 100644 --- a/isel.c +++ b/isel.c @@ -35,7 +35,7 @@ static int fcmptoi(int fc) { switch (fc) { - default: diag("isel: fcmptoi defaulted"); + default: die("invalid fp comparison %d", fc); case FCle: return ICule; case FClt: return ICult; case FCgt: return ICugt; @@ -85,8 +85,6 @@ noimm(Ref r, Fn *fn) if (rtype(r) != RCon) return 0; switch (fn->con[r.val].type) { - default: - diag("isel: invalid constant"); case CAddr: /* we only support the 'small' * code model of the ABI, this @@ -97,6 +95,8 @@ noimm(Ref r, Fn *fn) case CBits: val = fn->con[r.val].bits.i; return (val < INT32_MIN || val > INT32_MAX); + default: + die("invalid constant"); } } @@ -208,7 +208,7 @@ sel(Ins i, ANum *an, Fn *fn) { Ref r0, r1; int x, k, kc; - int64_t val; + int64_t sz; Ins *i0; if (rtype(i.to) == RTmp) @@ -308,12 +308,11 @@ Emit: * (rsp = 0) mod 16 */ if (rtype(i.arg[0]) == RCon) { - assert(fn->con[i.arg[0].val].type == CBits); - val = fn->con[i.arg[0].val].bits.i; - val = (val + 15) & ~INT64_C(15); - if (val < 0 || val > INT32_MAX) - diag("isel: alloc too large"); - emit(OSAlloc, Kl, i.to, getcon(val, fn), R); + sz = fn->con[i.arg[0].val].bits.i; + if (sz < 0 || sz >= INT_MAX-15) + err("invalid alloc size %"PRId64, sz); + sz = (sz + 15) & -16; + emit(OSAlloc, Kl, i.to, getcon(sz, fn), R); } else { /* r0 = (i.arg[0] + 15) & -16 */ r0 = newtmp("isel", Kl, fn); @@ -335,13 +334,13 @@ Emit: selcmp(i.arg, kc, fn); break; } - diag("isel: non-exhaustive implementation"); + die("unknown instruction"); } - while (i0 > curi && --i0) - if (rslot(i0->arg[0], fn) != -1 - || rslot(i0->arg[1], fn) != -1) - diag("isel: usupported address argument"); + while (i0 > curi && --i0) { + assert(rslot(i0->arg[0], fn) == -1); + assert(rslot(i0->arg[1], fn) == -1); + } } static Ins * @@ -733,7 +732,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap) } /* allocate return pad */ ra = alloc(sizeof *ra); - assert(NAlign == 3); + /* specific to NAlign == 3 */ aret.align -= 2; if (aret.align < 0) aret.align = 0; @@ -822,7 +821,7 @@ selpar(Fn *fn, Ins *i0, Ins *i1) } else classify(i0, i1, ac, OPar, 0); - assert(NAlign == 3); + /* specific to NAlign == 3 */ s = 4; for (i=i0, a=ac; iop != OParc || a->inmem) continue; - assert(NAlign == 3); for (al=0; a->align >> (al+2); al++) ; r = TMP(a->cls[0]); @@ -876,12 +874,12 @@ static int aref(Ref r, ANum *ai) { switch (rtype(r)) { - default: - diag("isel: aref defaulted"); case RCon: return 2; case RTmp: return ai[r.val].n; + default: + die("constant or temporary expected"); } } @@ -986,8 +984,6 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top) } } switch (ai[r.val].n) { - default: - diag("isel: amatch defaulted"); case 3: /* s * i */ if (!top) { a->index = al; @@ -1023,6 +1019,8 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top) amatch(a, ar, ai, fn, 0); amatch(a, al, ai, fn, 0); break; + default: + die("unreachable"); } } @@ -1092,15 +1090,15 @@ isel(Fn *fn) /* assign slots to fast allocs */ b = fn->start; - assert(NAlign == 3 && "change n=4 and sz /= 4 below"); + /* specific to NAlign == 3 */ /* or change n=4 and sz /= 4 below */ for (al=OAlloc, n=4; al<=OAlloc1; al++, n*=2) for (i=b->ins; i-b->ins < b->nins; i++) if (i->op == al) { if (rtype(i->arg[0]) != RCon) break; sz = fn->con[i->arg[0].val].bits.i; - if (sz < 0 || sz >= INT_MAX-3) - diag("isel: invalid alloc size"); + if (sz < 0 || sz >= INT_MAX-15) + err("invalid alloc size %"PRId64, sz); sz = (sz + n-1) & -n; sz /= 4; fn->tmp[i->to.val].slot = fn->slot; diff --git a/mem.c b/mem.c index bda43d7..98556e1 100644 --- a/mem.c +++ b/mem.c @@ -22,7 +22,7 @@ memopt(Fn *fn) for (i=b->ins; i-b->ins < b->nins; i++) { if (OAlloc > i->op || i->op > OAlloc1) continue; - assert(NAlign == 3); + /* specific to NAlign == 3 */ assert(rtype(i->to) == RTmp); t = &fn->tmp[i->to.val]; for (u=t->use; u != &t->use[t->nuse]; u++) { diff --git a/parse.c b/parse.c index 2590971..1fd032a 100644 --- a/parse.c +++ b/parse.c @@ -159,18 +159,14 @@ static int ntyp; void err(char *s, ...) { - char buf[100], *p, *end; va_list ap; - p = buf; - end = buf + sizeof(buf); - va_start(ap, s); - p += snprintf(p, end - p, "%s:%d: ", inpath, lnum); - p += vsnprintf(p, end - p, s, ap); + fprintf(stderr, "%s:%d: ", inpath, lnum); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); va_end(ap); - - diag(buf); + exit(1); } static int diff --git a/rega.c b/rega.c index 7f8edcf..0f1ad17 100644 --- a/rega.c +++ b/rega.c @@ -125,7 +125,7 @@ ralloc(RMap *m, int t) for (r=r0; rb, r)) goto Found; - diag("rega: no more regs"); + die("no more regs"); } Found: radd(m, t, r); @@ -170,7 +170,7 @@ pmadd(Ref src, Ref dst, int k) cpm = cpm * 2 + 16; pm = realloc(pm, cpm * sizeof pm[0]); if (!pm) - diag("pmadd: out of memory"); + die("pmadd, out of memory"); } pm[npm].src = src; pm[npm].dst = dst; diff --git a/spill.c b/spill.c index 72f8106..8684993 100644 --- a/spill.c +++ b/spill.c @@ -94,8 +94,7 @@ fillcost(Fn *fn) tmpuse(p->to, 0, 0, fn); for (a=0; anarg; a++) { n = p->blk[a]->loop; - assert(b->npred==p->narg && - "wrong cfg"); + assert(b->npred==p->narg && "wrong cfg"); n /= b->npred; tmpuse(p->arg[a], 1, n, fn); } @@ -146,11 +145,10 @@ slot(int t) { int s; - if (t < Tmp0) - diag("spill: cannot spill register"); + assert(t >= Tmp0 && "cannot spill register"); s = tmp[t].slot; if (s == -1) { - assert(NAlign == 3); + /* specific to NAlign == 3 */ /* nice logic to pack stack slots * on demand, there can be only * one hole and slot4 points to it @@ -491,7 +489,7 @@ spill(Fn *fn) } /* align the locals to a 16 byte boundary */ - assert(NAlign == 3); + /* specific to NAlign == 3 */ slot8 += slot8 & 3; fn->slot += slot8; diff --git a/ssa.c b/ssa.c index 0c163aa..201f22c 100644 --- a/ssa.c +++ b/ssa.c @@ -15,8 +15,6 @@ adduse(Tmp *tmp, int ty, Blk *b, ...) u->type = ty; u->bid = b->id; switch (ty) { - default: - diag("ssa: adduse defaulted"); case UPhi: u->u.phi = va_arg(ap, Phi *); break; @@ -25,6 +23,8 @@ adduse(Tmp *tmp, int ty, Blk *b, ...) break; case UJmp: break; + default: + die("unreachable"); } va_end(ap); } @@ -465,7 +465,7 @@ renblk(Blk *b, Name **stk, Fn *fn) if ((t=fn->tmp[t].visit)) { m = p->narg++; if (m == NPred) - diag("ssa: too many phi arguments"); + die("renblk, too many phi args"); p->arg[m] = getstk(t, b, stk); p->blk[m] = b; } diff --git a/util.c b/util.c index 65b3ff8..1654491 100644 --- a/util.c +++ b/util.c @@ -1,4 +1,5 @@ #include "all.h" +#include typedef struct Bitset Bitset; typedef struct Vec Vec; @@ -28,9 +29,14 @@ static void **pool = ptr; static int nptr = 1; void -diag(char *s) +die_(char *file, char *s, ...) { - fputs(s, stderr); + va_list ap; + + fprintf(stderr, "%s: dying: ", file); + va_start(ap, s); + vfprintf(stderr, s, ap); + va_end(ap); fputc('\n', stderr); abort(); } @@ -42,7 +48,7 @@ emalloc(size_t n) p = calloc(1, n); if (!p) - diag("emalloc: out of memory"); + die("emalloc, out of memory"); return p; } @@ -95,7 +101,7 @@ void emit(int op, int k, Ref to, Ref arg0, Ref arg1) { if (curi == insb) - diag("emit: too many instructions"); + die("emit, too many instructions"); *--curi = (Ins){ .op = op, .cls = k, .to = to, .arg = {arg0, arg1} @@ -210,8 +216,7 @@ addcon(Con *c0, Con *c1) *c0 = *c1; else { if (c1->type == CAddr) { - if (c0->type == CAddr) - diag("addcon: adding two addresses"); + assert(c0->type != CAddr && "adding two addresses"); c0->type = CAddr; strcpy(c0->label, c1->label); } -- cgit 1.4.1