ref: ccee477034a0a63df7a5864b375a243f8e4f246a
parent: 685513dd421ded344ae4a4e2c498928fbdbb00aa
author: Ori Bernstein <[email protected]>
date: Wed May 6 14:13:50 EDT 2015
Compile error on reaching end of func without return.
--- a/6/gen.c
+++ b/6/gen.c
@@ -40,7 +40,6 @@
return buf;
}
-
/*
* For x86, the assembly names are generated as follows:
* local symbols: .name
--- a/6/isel.c
+++ b/6/isel.c
@@ -776,6 +776,9 @@
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
--- a/6/simp.c
+++ b/6/simp.c
@@ -661,6 +661,7 @@
jmp(s, end);
append(s, next);
}
+ append(s, mkexpr(n->loc, Odead, NULL));
append(s, end);
}
@@ -1675,8 +1676,7 @@
}
cfg = mkcfg(dcl, s->stmts, s->nstmts);
- if (extracheck)
- check(cfg);
+ check(cfg);
if (debugopt['t'] || debugopt['s'])
dumpcfg(cfg, stdout);
--- a/libbio/puti.myr
+++ b/libbio/puti.myr
@@ -40,7 +40,7 @@
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 @@
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:])
}
--- a/libstd/getcwd.myr
+++ b/libstd/getcwd.myr
@@ -25,5 +25,7 @@
len *= 2
;;
;;
+ /* unreachable; shut up return without value analysis */
+ -> ""
}
--- a/libstd/htab.myr
+++ b/libstd/htab.myr
@@ -90,6 +90,7 @@
-> `Some i
;;
;;
+ -> `None /* fixme; while true should flag this as unreachable */
}
generic mkht = {h, eq
--- a/libstd/spork.myr
+++ b/libstd/spork.myr
@@ -52,9 +52,8 @@
;;
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
--- a/libstd/sys+linux-x64.myr
+++ b/libstd/sys+linux-x64.myr
@@ -43,6 +43,7 @@
`Waitexit int32
`Waitsig int32
`Waitstop int32
+ `Waitfail int32
;;
type timespec = struct
@@ -796,4 +797,5 @@
elif (((st & 0xffff)*0x10001)>>8) > 0x7f00
-> `Waitstop ((st & 0xff00) >> 8)
;;
+ -> `Waitfail st /* wait failed to give a result */
}
--- a/libstd/wait+posixy.myr
+++ b/libstd/wait+posixy.myr
@@ -26,6 +26,7 @@
a process exits. Loop instead.
*/
| `sys.Waitstop sig: goto again
+ | `sys.Waitfail fail: -> `Waiterror
| `sys.Waitsig sig: -> `Wsignalled
| `sys.Waitexit status:
if status == 0
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -214,6 +214,7 @@
-> deps
;;
;;
+ std.die("unreachable")
}
const scrapelibs = {dg, lib, incs
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -124,10 +124,20 @@
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 @@
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 @@
{
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 @@
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 @@
Bb *pre, *post;
Bb *bb, *targ;
Node *a, *b;
+ static int nextret;
+ char buf[32];
size_t i;
cfg = zalloc(sizeof(Cfg));
@@ -215,6 +218,9 @@
}
}
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);
@@ -221,7 +227,6 @@
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 @@
bsput(targ->pred, bb->id);
}
}
- delunreachable(cfg);
+ trim(cfg);
return cfg;
}
--- a/mi/dfcheck.c
+++ b/mi/dfcheck.c
@@ -38,6 +38,7 @@
static void checkpredret(Cfg *cfg, Bb *bb)
{
Bb *pred;
+ Op op;
size_t i;
for (i = 0; bsiter(bb->pred, &i); i++) {
@@ -44,9 +45,11 @@
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");
+ }
}
}
}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1446,7 +1446,7 @@
}
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:
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -56,8 +56,9 @@
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 */