diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-05-06 18:13:50 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-05-06 18:13:50 -0700 |
commit | 9bbe6908eeb15650a5f065c8aea8142d1ce905ff (patch) | |
tree | 377ad14e171a0dca10ee2325d93eb225664f896c | |
parent | e68983d3805bbf857361b69b96407c2ff75b7b27 (diff) | |
download | mc-9bbe6908eeb15650a5f065c8aea8142d1ce905ff.tar.gz |
Compile error on reaching end of func without return.
-rw-r--r-- | 6/gen.c | 1 | ||||
-rw-r--r-- | 6/isel.c | 3 | ||||
-rw-r--r-- | 6/simp.c | 4 | ||||
-rw-r--r-- | libbio/puti.myr | 4 | ||||
-rw-r--r-- | libstd/getcwd.myr | 2 | ||||
-rw-r--r-- | libstd/htab.myr | 1 | ||||
-rw-r--r-- | libstd/spork.myr | 5 | ||||
-rw-r--r-- | libstd/sys+linux-x64.myr | 2 | ||||
-rw-r--r-- | libstd/wait+posixy.myr | 1 | ||||
-rw-r--r-- | mbld/deps.myr | 1 | ||||
-rw-r--r-- | mi/cfg.c | 49 | ||||
-rw-r--r-- | mi/dfcheck.c | 9 | ||||
-rw-r--r-- | parse/infer.c | 2 | ||||
-rw-r--r-- | parse/ops.def | 5 |
14 files changed, 53 insertions, 36 deletions
@@ -40,7 +40,6 @@ char *genlblstr(char *buf, size_t sz) return buf; } - /* * For x86, the assembly names are generated as follows: * local symbols: .name @@ -776,6 +776,9 @@ Loc *selexpr(Isel *s, Node *n) else g(s, Icvttss2sd, a, r, NULL); break; + case Odead: + /* nothing */ + break; /* These operators should never show up in the reduced trees, * since they should have been replaced with more primitive @@ -661,6 +661,7 @@ static void simpmatch(Simp *s, Node *n) jmp(s, end); append(s, next); } + append(s, mkexpr(n->loc, Odead, NULL)); append(s, end); } @@ -1675,8 +1676,7 @@ static Func *simpfn(Simp *s, char *name, Node *dcl) } cfg = mkcfg(dcl, s->stmts, s->nstmts); - if (extracheck) - check(cfg); + check(cfg); if (debugopt['t'] || debugopt['s']) dumpcfg(cfg, stdout); diff --git a/libbio/puti.myr b/libbio/puti.myr index efb79c2..16f014a 100644 --- a/libbio/puti.myr +++ b/libbio/puti.myr @@ -40,7 +40,7 @@ const putle = {f, v, n buf[5] = (v >> 40) & 0xff castto(byte) buf[6] = (v >> 48) & 0xff castto(byte) buf[7] = (v >> 56) & 0xff castto(byte) - write(f, buf[:n]) + -> write(f, buf[:n]) } const putbe = {f, v, n @@ -57,6 +57,6 @@ const putbe = {f, v, n buf[5] = (v >> 16) & 0xff castto(byte) buf[6] = (v >> 8) & 0xff castto(byte) buf[7] = (v >> 0) & 0xff castto(byte) - write(f, buf[8-n:]) + -> write(f, buf[8-n:]) } diff --git a/libstd/getcwd.myr b/libstd/getcwd.myr index 4c53bb2..c9dbbea 100644 --- a/libstd/getcwd.myr +++ b/libstd/getcwd.myr @@ -25,5 +25,7 @@ const getcwd = { len *= 2 ;; ;; + /* unreachable; shut up return without value analysis */ + -> "" } diff --git a/libstd/htab.myr b/libstd/htab.myr index 5c311b1..c8cb694 100644 --- a/libstd/htab.myr +++ b/libstd/htab.myr @@ -90,6 +90,7 @@ generic idx = {ht, k -> `Some i ;; ;; + -> `None /* fixme; while true should flag this as unreachable */ } generic mkht = {h, eq diff --git a/libstd/spork.myr b/libstd/spork.myr index 8baa82d..1778037 100644 --- a/libstd/spork.myr +++ b/libstd/spork.myr @@ -52,9 +52,8 @@ const sporkfd = {cmd, infd, outfd ;; close(infd) close(outfd) - if execvp(cmd[0], cmd) < 0 - fatal(1, "failed to exec %s\n") - ;; + execvp(cmd[0], cmd) < 0 + fatal(1, "failed to exec %s\n") /* parent */ else -> `Ok pid diff --git a/libstd/sys+linux-x64.myr b/libstd/sys+linux-x64.myr index 2642b65..4a3e3ea 100644 --- a/libstd/sys+linux-x64.myr +++ b/libstd/sys+linux-x64.myr @@ -43,6 +43,7 @@ pkg sys = `Waitexit int32 `Waitsig int32 `Waitstop int32 + `Waitfail int32 ;; type timespec = struct @@ -796,4 +797,5 @@ const waitstatus = {st elif (((st & 0xffff)*0x10001)>>8) > 0x7f00 -> `Waitstop ((st & 0xff00) >> 8) ;; + -> `Waitfail st /* wait failed to give a result */ } diff --git a/libstd/wait+posixy.myr b/libstd/wait+posixy.myr index 55efd9e..a690feb 100644 --- a/libstd/wait+posixy.myr +++ b/libstd/wait+posixy.myr @@ -26,6 +26,7 @@ const wait = {pid a process exits. Loop instead. */ | `sys.Waitstop sig: goto again + | `sys.Waitfail fail: -> `Waiterror | `sys.Waitsig sig: -> `Wsignalled | `sys.Waitexit status: if status == 0 diff --git a/mbld/deps.myr b/mbld/deps.myr index 0720dcf..d714d40 100644 --- a/mbld/deps.myr +++ b/mbld/deps.myr @@ -214,6 +214,7 @@ const getdeps = {b, ds, path -> deps ;; ;; + std.die("unreachable") } const scrapelibs = {dg, lib, incs @@ -124,10 +124,20 @@ void delete(Cfg *cfg, Bb *bb) cfg->bb[bb->id] = NULL; } -void trimdead(Bb *bb) +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); +} + +void trimdead(Cfg *cfg, Bb *bb) { 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 @@ -137,11 +147,17 @@ void trimdead(Bb *bb) case Oret: bb->nnl = i + 1; return; - case Ocall: - if (!isnonretcall(bb->nl[i]->expr.args[0])) - break; + 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; @@ -153,22 +169,6 @@ void trim(Cfg *cfg) { Bb *bb; size_t i; - - /* delete empty blocks and trivially unreachable code */ - for (i = 0; i < cfg->nbb; i++) { - - bb = cfg->bb[i]; - if (bb->nnl == 0) - delete(cfg, bb); - else - trimdead(bb); - } -} - -void delunreachable(Cfg *cfg) -{ - Bb *bb; - size_t i; int deleted; deleted = 1; @@ -178,6 +178,7 @@ void delunreachable(Cfg *cfg) 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; @@ -192,6 +193,8 @@ Cfg *mkcfg(Node *fn, Node **nl, size_t nn) Bb *pre, *post; Bb *bb, *targ; Node *a, *b; + static int nextret; + char buf[32]; size_t i; cfg = zalloc(sizeof(Cfg)); @@ -215,13 +218,15 @@ Cfg *mkcfg(Node *fn, Node **nl, size_t nn) } } post = mkbb(cfg); + snprintf(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); - trim(cfg); for (i = 0; i < cfg->nfixjmp; i++) { bb = cfg->fixblk[i]; @@ -257,7 +262,7 @@ Cfg *mkcfg(Node *fn, Node **nl, size_t nn) bsput(targ->pred, bb->id); } } - delunreachable(cfg); + trim(cfg); return cfg; } diff --git a/mi/dfcheck.c b/mi/dfcheck.c index bbe5cb6..4371922 100644 --- a/mi/dfcheck.c +++ b/mi/dfcheck.c @@ -38,15 +38,18 @@ static void checkreach(Cfg *cfg) static void checkpredret(Cfg *cfg, Bb *bb) { 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 if (exprop(pred->nl[pred->nnl - 1]) != Oret) { - dumpcfg(cfg, stdout); - fatal(pred->nl[pred->nnl-1], "Reaches end of function without return\n"); + } 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"); + } } } } diff --git a/parse/infer.c b/parse/infer.c index 1006a3d..477c1fb 100644 --- a/parse/infer.c +++ b/parse/infer.c @@ -1446,7 +1446,7 @@ static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret) } settype(st, n, type(st, args[0])); break; - case Obad: case Ocjmp: case Ojtab: case Oset: + case Obad: case Ocjmp: case Ojtab: case Oset: case Odead: case Oslbase: case Osllen: case Outag: case Oblit: case Oclear: case Oudata: case Otrunc: case Oswiden: case Ozwiden: diff --git a/parse/ops.def b/parse/ops.def index 2569668..caa6f56 100644 --- a/parse/ops.def +++ b/parse/ops.def @@ -56,8 +56,9 @@ O(Ostruct, 1, OTmisc, NULL) O(Oarr, 1, OTmisc, NULL) /* all below this point are backend-only */ -O(Ocjmp, 1, OTmisc, NULL) /* conditional jump */ -O(Ojtab, 1, OTmisc, NULL) /* jump table */ +O(Odead, 0, OTmisc, "DEAD") /* unreachable code */ +O(Ocjmp, 1, OTmisc, "CJMP") /* conditional jump */ +O(Ojtab, 1, OTmisc, "JTAB") /* jump table */ O(Oset, 1, OTbin, "=") /* store to var */ O(Osllen, 1, OTpre, "SLLEN") /* size of slice */ O(Oslbase, 1, OTpre, "SLBASE") /* base of sice */ |