summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-05-06 18:13:50 -0700
committerOri Bernstein <ori@eigenstate.org>2015-05-06 18:13:50 -0700
commit9bbe6908eeb15650a5f065c8aea8142d1ce905ff (patch)
tree377ad14e171a0dca10ee2325d93eb225664f896c
parente68983d3805bbf857361b69b96407c2ff75b7b27 (diff)
downloadmc-9bbe6908eeb15650a5f065c8aea8142d1ce905ff.tar.gz
Compile error on reaching end of func without return.
-rw-r--r--6/gen.c1
-rw-r--r--6/isel.c3
-rw-r--r--6/simp.c4
-rw-r--r--libbio/puti.myr4
-rw-r--r--libstd/getcwd.myr2
-rw-r--r--libstd/htab.myr1
-rw-r--r--libstd/spork.myr5
-rw-r--r--libstd/sys+linux-x64.myr2
-rw-r--r--libstd/wait+posixy.myr1
-rw-r--r--mbld/deps.myr1
-rw-r--r--mi/cfg.c49
-rw-r--r--mi/dfcheck.c9
-rw-r--r--parse/infer.c2
-rw-r--r--parse/ops.def5
14 files changed, 53 insertions, 36 deletions
diff --git a/6/gen.c b/6/gen.c
index d45cb40..76d15f5 100644
--- a/6/gen.c
+++ b/6/gen.c
@@ -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
diff --git a/6/isel.c b/6/isel.c
index 0a0f1c8..42d94c9 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -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
diff --git a/6/simp.c b/6/simp.c
index 62899a9..333902e 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -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
diff --git a/mi/cfg.c b/mi/cfg.c
index fc1cacf..18eb838 100644
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -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 */