cleanup error handling

This commit is contained in:
Quentin Carbonneaux 2016-03-30 12:04:43 -04:00
parent beec05cd3b
commit 729aa97b79
10 changed files with 86 additions and 92 deletions

5
all.h
View file

@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
#define MAKESURE(what, x) typedef char make_sure_##what[(x)?1:-1] #define MAKESURE(what, x) typedef char make_sure_##what[(x)?1:-1]
#define die(...) die_(__FILE__, __VA_ARGS__)
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned short ushort; typedef unsigned short ushort;
@ -481,7 +482,7 @@ extern char debug['Z'+1];
/* util.c */ /* util.c */
extern Typ typ[NTyp]; extern Typ typ[NTyp];
extern Ins insb[NIns], *curi; extern Ins insb[NIns], *curi;
void diag(char *) __attribute__((noreturn)); void die_(char *, char *, ...) __attribute__((noreturn));
void *emalloc(size_t); void *emalloc(size_t);
void *alloc(size_t); void *alloc(size_t);
void freeall(void); void freeall(void);
@ -522,7 +523,7 @@ extern OpDesc opdesc[NOp];
void parse(FILE *, char *, void (Dat *), void (Fn *)); void parse(FILE *, char *, void (Dat *), void (Fn *));
void printfn(Fn *, FILE *); void printfn(Fn *, FILE *);
void printref(Ref, Fn *, FILE *); void printref(Ref, Fn *, FILE *);
void err(char *, ...); void err(char *, ...) __attribute__((noreturn));
/* mem.c */ /* mem.c */
void memopt(Fn *); void memopt(Fn *);

34
copy.c
View file

@ -47,7 +47,6 @@ visitphi(Phi *p, Ref *cp, RList **w)
break; break;
} }
} }
assert(!req(r, R));
update(p->to, r, cp, w); 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 void
copy(Fn *fn) copy(Fn *fn)
{ {
@ -93,8 +101,6 @@ copy(Fn *fn)
u1 = u + fn->tmp[t].nuse; u1 = u + fn->tmp[t].nuse;
for (; u<u1; u++) for (; u<u1; u++)
switch (u->type) { switch (u->type) {
default:
diag("copy: invalid use");
case UPhi: case UPhi:
visitphi(u->u.phi, cp, &w); visitphi(u->u.phi, cp, &w);
break; break;
@ -103,6 +109,8 @@ copy(Fn *fn)
break; break;
case UJmp: case UJmp:
break; break;
default:
die("invalid use %d", u->type);
} }
} }
for (b=fn->start; b; b=b->link) { for (b=fn->start; b; b=b->link) {
@ -113,31 +121,19 @@ copy(Fn *fn)
continue; continue;
} }
for (a=0; a<p->narg; a++) for (a=0; a<p->narg; a++)
if (rtype(p->arg[a]) == RTmp) { subst(&p->arg[a], cp, fn);
r = cp[p->arg[a].val];
assert(!req(r, R));
p->arg[a] = r;
}
pp=&p->link; pp=&p->link;
} }
for (i=b->ins; i-b->ins < b->nins; i++) { 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)) { if (!req(r, i->to)) {
*i = (Ins){.op = ONop}; *i = (Ins){.op = ONop};
continue; continue;
} }
for (a=0; a<2; a++) for (a=0; a<2; a++)
if (rtype(i->arg[a]) == RTmp) { subst(&i->arg[a], cp, fn);
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(&b->jmp.arg, cp, fn);
} }
if (debug['C']) { if (debug['C']) {
fprintf(stderr, "\n> Copy information:"); fprintf(stderr, "\n> Copy information:");

40
emit.c
View file

@ -133,7 +133,7 @@ slot(int s, Fn *fn)
/* sign extend s using a bitfield */ /* sign extend s using a bitfield */
x.i = s; x.i = s;
assert(NAlign == 3); /* specific to NAlign == 3 */
if (x.i < 0) if (x.i < 0)
return -4 * x.i; return -4 * x.i;
else { else {
@ -146,8 +146,6 @@ static void
emitcon(Con *con, FILE *f) emitcon(Con *con, FILE *f)
{ {
switch (con->type) { switch (con->type) {
default:
diag("emit: invalid constant");
case CAddr: case CAddr:
if (con->local) if (con->local)
fprintf(f, "%s%s", locprefix, con->label); fprintf(f, "%s%s", locprefix, con->label);
@ -159,6 +157,8 @@ emitcon(Con *con, FILE *f)
case CBits: case CBits:
fprintf(f, "%"PRId64, con->bits.i); fprintf(f, "%"PRId64, con->bits.i);
break; break;
default:
die("unreachable");
} }
} }
@ -178,14 +178,14 @@ static Ref
getarg(char c, Ins *i) getarg(char c, Ins *i)
{ {
switch (c) { switch (c) {
default:
diag("emit: 0, 1, = expected in format");
case '0': case '0':
return i->arg[0]; return i->arg[0];
case '1': case '1':
return i->arg[1]; return i->arg[1];
case '=': case '=':
return i->to; 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 */ /* fall through */
case '-': case '-':
if (req(i->arg[1], i->to) && !req(i->arg[0], i->to)) assert((!req(i->arg[1], i->to) || req(i->arg[0], i->to)) &&
diag("emit: cannot convert to 2-address"); "cannot convert to 2-address");
emitcopy(i->to, i->arg[0], i->cls, fn, f); emitcopy(i->to, i->arg[0], i->cls, fn, f);
s++; s++;
break; break;
@ -238,8 +238,6 @@ Next:
} else } else
fputc(c, f); fputc(c, f);
switch ((c = *s++)) { switch ((c = *s++)) {
default:
diag("emit: invalid escape");
case '%': case '%':
fputc('%', f); fputc('%', f);
break; break;
@ -258,8 +256,6 @@ Next:
c = *s++; c = *s++;
ref = getarg(c, i); ref = getarg(c, i);
switch (rtype(ref)) { switch (rtype(ref)) {
default:
diag("emit: invalid reference");
case RTmp: case RTmp:
assert(isreg(ref)); assert(isreg(ref));
fprintf(f, "%%%s", regtoa(ref.val, sz)); fprintf(f, "%%%s", regtoa(ref.val, sz));
@ -294,6 +290,8 @@ Next:
fputc('$', f); fputc('$', f);
emitcon(&fn->con[ref.val], f); emitcon(&fn->con[ref.val], f);
break; break;
default:
die("unreachable");
} }
break; break;
case 'L': case 'L':
@ -312,8 +310,6 @@ Next:
c = *s++; c = *s++;
ref = getarg(c, i); ref = getarg(c, i);
switch (rtype(ref)) { switch (rtype(ref)) {
default:
diag("emit: invalid memory reference");
case RAMem: case RAMem:
goto Mem; goto Mem;
case RSlot: case RSlot:
@ -327,8 +323,12 @@ Next:
assert(isreg(ref)); assert(isreg(ref));
fprintf(f, "(%%%s)", regtoa(ref.val, SLong)); fprintf(f, "(%%%s)", regtoa(ref.val, SLong));
break; break;
default:
die("unreachable");
} }
break; break;
default:
die("invalid format specifier %%%c", c);
} }
goto Next; goto Next;
} }
@ -350,7 +350,7 @@ emitins(Ins i, Fn *fn, FILE *f)
/* this linear search should really be a binary /* this linear search should really be a binary
* search */ * search */
if (omap[o].op == NOp) 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].op == i.op)
if (omap[o].cls == i.cls if (omap[o].cls == i.cls
|| (omap[o].cls == Ki && KBASE(i.cls) == 0) || (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 /* calls simply have a weird syntax in AT&T
* assembly... */ * assembly... */
switch (rtype(i.arg[0])) { switch (rtype(i.arg[0])) {
default:
diag("emit: invalid call instruction");
case RCon: case RCon:
fprintf(f, "\tcallq "); fprintf(f, "\tcallq ");
emitcon(&fn->con[i.arg[0].val], f); emitcon(&fn->con[i.arg[0].val], f);
@ -422,6 +420,8 @@ emitins(Ins i, Fn *fn, FILE *f)
case RTmp: case RTmp:
emitf("callq *%L0", &i, fn, f); emitf("callq *%L0", &i, fn, f);
break; break;
default:
die("invalid call argument");
} }
break; break;
case OSAlloc: case OSAlloc:
@ -450,7 +450,7 @@ static int
cneg(int cmp) cneg(int cmp)
{ {
switch (cmp) { switch (cmp) {
default: diag("emit: cneg() unhandled comparison"); default: die("invalid int comparison %d", cmp);
case ICule: return ICugt; case ICule: return ICugt;
case ICult: return ICuge; case ICult: return ICuge;
case ICsle: return ICsgt; case ICsle: return ICsgt;
@ -471,7 +471,7 @@ framesz(Fn *fn)
{ {
int i, o, f; int i, o, f;
assert(NAlign == 3); /* specific to NAlign == 3 */
for (i=0, o=0; i<NRClob; i++) for (i=0, o=0; i<NRClob; i++)
o ^= 1 & (fn->reg >> rclob[i]); o ^= 1 & (fn->reg >> rclob[i]);
f = fn->slot; f = fn->slot;
@ -549,12 +549,12 @@ emitfn(Fn *fn, FILE *f)
c = cneg(c); c = cneg(c);
s = b->s2; s = b->s2;
} else } else
diag("emit: unhandled jump (1)"); die("unhandled jump");
fprintf(f, "\tj%s %sbb%d /* %s */\n", fprintf(f, "\tj%s %sbb%d /* %s */\n",
ctoa[c], locprefix, id0+s->id, s->name); ctoa[c], locprefix, id0+s->id, s->name);
break; break;
} }
diag("emit: unhandled jump (2)"); die("unhandled jump %d", b->jmp.type);
} }
} }
id0 += fn->nblk; id0 += fn->nblk;

48
isel.c
View file

@ -35,7 +35,7 @@ static int
fcmptoi(int fc) fcmptoi(int fc)
{ {
switch (fc) { switch (fc) {
default: diag("isel: fcmptoi defaulted"); default: die("invalid fp comparison %d", fc);
case FCle: return ICule; case FCle: return ICule;
case FClt: return ICult; case FClt: return ICult;
case FCgt: return ICugt; case FCgt: return ICugt;
@ -85,8 +85,6 @@ noimm(Ref r, Fn *fn)
if (rtype(r) != RCon) if (rtype(r) != RCon)
return 0; return 0;
switch (fn->con[r.val].type) { switch (fn->con[r.val].type) {
default:
diag("isel: invalid constant");
case CAddr: case CAddr:
/* we only support the 'small' /* we only support the 'small'
* code model of the ABI, this * code model of the ABI, this
@ -97,6 +95,8 @@ noimm(Ref r, Fn *fn)
case CBits: case CBits:
val = fn->con[r.val].bits.i; val = fn->con[r.val].bits.i;
return (val < INT32_MIN || val > INT32_MAX); 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; Ref r0, r1;
int x, k, kc; int x, k, kc;
int64_t val; int64_t sz;
Ins *i0; Ins *i0;
if (rtype(i.to) == RTmp) if (rtype(i.to) == RTmp)
@ -308,12 +308,11 @@ Emit:
* (rsp = 0) mod 16 * (rsp = 0) mod 16
*/ */
if (rtype(i.arg[0]) == RCon) { if (rtype(i.arg[0]) == RCon) {
assert(fn->con[i.arg[0].val].type == CBits); sz = fn->con[i.arg[0].val].bits.i;
val = fn->con[i.arg[0].val].bits.i; if (sz < 0 || sz >= INT_MAX-15)
val = (val + 15) & ~INT64_C(15); err("invalid alloc size %"PRId64, sz);
if (val < 0 || val > INT32_MAX) sz = (sz + 15) & -16;
diag("isel: alloc too large"); emit(OSAlloc, Kl, i.to, getcon(sz, fn), R);
emit(OSAlloc, Kl, i.to, getcon(val, fn), R);
} else { } else {
/* r0 = (i.arg[0] + 15) & -16 */ /* r0 = (i.arg[0] + 15) & -16 */
r0 = newtmp("isel", Kl, fn); r0 = newtmp("isel", Kl, fn);
@ -335,13 +334,13 @@ Emit:
selcmp(i.arg, kc, fn); selcmp(i.arg, kc, fn);
break; break;
} }
diag("isel: non-exhaustive implementation"); die("unknown instruction");
} }
while (i0 > curi && --i0) while (i0 > curi && --i0) {
if (rslot(i0->arg[0], fn) != -1 assert(rslot(i0->arg[0], fn) == -1);
|| rslot(i0->arg[1], fn) != -1) assert(rslot(i0->arg[1], fn) == -1);
diag("isel: usupported address argument"); }
} }
static Ins * static Ins *
@ -733,7 +732,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
} }
/* allocate return pad */ /* allocate return pad */
ra = alloc(sizeof *ra); ra = alloc(sizeof *ra);
assert(NAlign == 3); /* specific to NAlign == 3 */
aret.align -= 2; aret.align -= 2;
if (aret.align < 0) if (aret.align < 0)
aret.align = 0; aret.align = 0;
@ -822,7 +821,7 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
} else } else
classify(i0, i1, ac, OPar, 0); classify(i0, i1, ac, OPar, 0);
assert(NAlign == 3); /* specific to NAlign == 3 */
s = 4; s = 4;
for (i=i0, a=ac; i<i1; i++, a++) { for (i=i0, a=ac; i<i1; i++, a++) {
@ -856,7 +855,6 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
for (i=i0, a=ac; i<i1; i++, a++) { for (i=i0, a=ac; i<i1; i++, a++) {
if (i->op != OParc || a->inmem) if (i->op != OParc || a->inmem)
continue; continue;
assert(NAlign == 3);
for (al=0; a->align >> (al+2); al++) for (al=0; a->align >> (al+2); al++)
; ;
r = TMP(a->cls[0]); r = TMP(a->cls[0]);
@ -876,12 +874,12 @@ static int
aref(Ref r, ANum *ai) aref(Ref r, ANum *ai)
{ {
switch (rtype(r)) { switch (rtype(r)) {
default:
diag("isel: aref defaulted");
case RCon: case RCon:
return 2; return 2;
case RTmp: case RTmp:
return ai[r.val].n; 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) { switch (ai[r.val].n) {
default:
diag("isel: amatch defaulted");
case 3: /* s * i */ case 3: /* s * i */
if (!top) { if (!top) {
a->index = al; 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, ar, ai, fn, 0);
amatch(a, al, ai, fn, 0); amatch(a, al, ai, fn, 0);
break; break;
default:
die("unreachable");
} }
} }
@ -1092,15 +1090,15 @@ isel(Fn *fn)
/* assign slots to fast allocs */ /* assign slots to fast allocs */
b = fn->start; 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 (al=OAlloc, n=4; al<=OAlloc1; al++, n*=2)
for (i=b->ins; i-b->ins < b->nins; i++) for (i=b->ins; i-b->ins < b->nins; i++)
if (i->op == al) { if (i->op == al) {
if (rtype(i->arg[0]) != RCon) if (rtype(i->arg[0]) != RCon)
break; break;
sz = fn->con[i->arg[0].val].bits.i; sz = fn->con[i->arg[0].val].bits.i;
if (sz < 0 || sz >= INT_MAX-3) if (sz < 0 || sz >= INT_MAX-15)
diag("isel: invalid alloc size"); err("invalid alloc size %"PRId64, sz);
sz = (sz + n-1) & -n; sz = (sz + n-1) & -n;
sz /= 4; sz /= 4;
fn->tmp[i->to.val].slot = fn->slot; fn->tmp[i->to.val].slot = fn->slot;

2
mem.c
View file

@ -22,7 +22,7 @@ memopt(Fn *fn)
for (i=b->ins; i-b->ins < b->nins; i++) { for (i=b->ins; i-b->ins < b->nins; i++) {
if (OAlloc > i->op || i->op > OAlloc1) if (OAlloc > i->op || i->op > OAlloc1)
continue; continue;
assert(NAlign == 3); /* specific to NAlign == 3 */
assert(rtype(i->to) == RTmp); assert(rtype(i->to) == RTmp);
t = &fn->tmp[i->to.val]; t = &fn->tmp[i->to.val];
for (u=t->use; u != &t->use[t->nuse]; u++) { for (u=t->use; u != &t->use[t->nuse]; u++) {

12
parse.c
View file

@ -159,18 +159,14 @@ static int ntyp;
void void
err(char *s, ...) err(char *s, ...)
{ {
char buf[100], *p, *end;
va_list ap; va_list ap;
p = buf;
end = buf + sizeof(buf);
va_start(ap, s); va_start(ap, s);
p += snprintf(p, end - p, "%s:%d: ", inpath, lnum); fprintf(stderr, "%s:%d: ", inpath, lnum);
p += vsnprintf(p, end - p, s, ap); vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
va_end(ap); va_end(ap);
exit(1);
diag(buf);
} }
static int static int

4
rega.c
View file

@ -125,7 +125,7 @@ ralloc(RMap *m, int t)
for (r=r0; r<r1; r++) for (r=r0; r<r1; r++)
if (!bshas(m->b, r)) if (!bshas(m->b, r))
goto Found; goto Found;
diag("rega: no more regs"); die("no more regs");
} }
Found: Found:
radd(m, t, r); radd(m, t, r);
@ -170,7 +170,7 @@ pmadd(Ref src, Ref dst, int k)
cpm = cpm * 2 + 16; cpm = cpm * 2 + 16;
pm = realloc(pm, cpm * sizeof pm[0]); pm = realloc(pm, cpm * sizeof pm[0]);
if (!pm) if (!pm)
diag("pmadd: out of memory"); die("pmadd, out of memory");
} }
pm[npm].src = src; pm[npm].src = src;
pm[npm].dst = dst; pm[npm].dst = dst;

10
spill.c
View file

@ -94,8 +94,7 @@ fillcost(Fn *fn)
tmpuse(p->to, 0, 0, fn); tmpuse(p->to, 0, 0, fn);
for (a=0; a<p->narg; a++) { for (a=0; a<p->narg; a++) {
n = p->blk[a]->loop; n = p->blk[a]->loop;
assert(b->npred==p->narg && assert(b->npred==p->narg && "wrong cfg");
"wrong cfg");
n /= b->npred; n /= b->npred;
tmpuse(p->arg[a], 1, n, fn); tmpuse(p->arg[a], 1, n, fn);
} }
@ -146,11 +145,10 @@ slot(int t)
{ {
int s; int s;
if (t < Tmp0) assert(t >= Tmp0 && "cannot spill register");
diag("spill: cannot spill register");
s = tmp[t].slot; s = tmp[t].slot;
if (s == -1) { if (s == -1) {
assert(NAlign == 3); /* specific to NAlign == 3 */
/* nice logic to pack stack slots /* nice logic to pack stack slots
* on demand, there can be only * on demand, there can be only
* one hole and slot4 points to it * one hole and slot4 points to it
@ -491,7 +489,7 @@ spill(Fn *fn)
} }
/* align the locals to a 16 byte boundary */ /* align the locals to a 16 byte boundary */
assert(NAlign == 3); /* specific to NAlign == 3 */
slot8 += slot8 & 3; slot8 += slot8 & 3;
fn->slot += slot8; fn->slot += slot8;

6
ssa.c
View file

@ -15,8 +15,6 @@ adduse(Tmp *tmp, int ty, Blk *b, ...)
u->type = ty; u->type = ty;
u->bid = b->id; u->bid = b->id;
switch (ty) { switch (ty) {
default:
diag("ssa: adduse defaulted");
case UPhi: case UPhi:
u->u.phi = va_arg(ap, Phi *); u->u.phi = va_arg(ap, Phi *);
break; break;
@ -25,6 +23,8 @@ adduse(Tmp *tmp, int ty, Blk *b, ...)
break; break;
case UJmp: case UJmp:
break; break;
default:
die("unreachable");
} }
va_end(ap); va_end(ap);
} }
@ -465,7 +465,7 @@ renblk(Blk *b, Name **stk, Fn *fn)
if ((t=fn->tmp[t].visit)) { if ((t=fn->tmp[t].visit)) {
m = p->narg++; m = p->narg++;
if (m == NPred) if (m == NPred)
diag("ssa: too many phi arguments"); die("renblk, too many phi args");
p->arg[m] = getstk(t, b, stk); p->arg[m] = getstk(t, b, stk);
p->blk[m] = b; p->blk[m] = b;
} }

17
util.c
View file

@ -1,4 +1,5 @@
#include "all.h" #include "all.h"
#include <stdarg.h>
typedef struct Bitset Bitset; typedef struct Bitset Bitset;
typedef struct Vec Vec; typedef struct Vec Vec;
@ -28,9 +29,14 @@ static void **pool = ptr;
static int nptr = 1; static int nptr = 1;
void 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); fputc('\n', stderr);
abort(); abort();
} }
@ -42,7 +48,7 @@ emalloc(size_t n)
p = calloc(1, n); p = calloc(1, n);
if (!p) if (!p)
diag("emalloc: out of memory"); die("emalloc, out of memory");
return p; return p;
} }
@ -95,7 +101,7 @@ void
emit(int op, int k, Ref to, Ref arg0, Ref arg1) emit(int op, int k, Ref to, Ref arg0, Ref arg1)
{ {
if (curi == insb) if (curi == insb)
diag("emit: too many instructions"); die("emit, too many instructions");
*--curi = (Ins){ *--curi = (Ins){
.op = op, .cls = k, .op = op, .cls = k,
.to = to, .arg = {arg0, arg1} .to = to, .arg = {arg0, arg1}
@ -210,8 +216,7 @@ addcon(Con *c0, Con *c1)
*c0 = *c1; *c0 = *c1;
else { else {
if (c1->type == CAddr) { if (c1->type == CAddr) {
if (c0->type == CAddr) assert(c0->type != CAddr && "adding two addresses");
diag("addcon: adding two addresses");
c0->type = CAddr; c0->type = CAddr;
strcpy(c0->label, c1->label); strcpy(c0->label, c1->label);
} }