fix(lower): drop dead statements after a return/raise terminator (issue 0061)
A bare `return X;` / `raise` in the middle of a block closed the current
LLVM basic block, but lowerBlock / lowerBlockValue only stopped the
statement loop on the `block_terminated` flag — which lowerReturn
deliberately never sets (it would leak past an `if cond { return }` merge
block). So trailing dead statements were emitted into the already-closed
block, tripping the LLVM verifier with "Terminator found in the middle of
a basic block".
Fix: also stop the statement loop when currentBlockHasTerminator() is
true. That is CFG-level termination of the *current* block, which is
naturally false at an if / inline-if merge block, so conditional returns
still fall through to their trailing statements.
This unblocks ERR E5.1: the canonical failable-closure form
`closure((x) -> (s32,!) { raise error.X; return x; })` has a dead
`return x;` after the unconditional raise and tripped the verifier.
Regression: examples/0038-basic-dead-code-after-terminator.sx.
This commit is contained in:
@@ -1468,6 +1468,13 @@ pub const Lowering = struct {
|
||||
for (blk.stmts) |stmt| {
|
||||
if (self.block_terminated) break;
|
||||
self.lowerStmt(stmt);
|
||||
// A bare `return`/`raise` mid-block terminates the current
|
||||
// basic block but deliberately does NOT set `block_terminated`
|
||||
// (that flag would leak past an `if cond { return }` merge
|
||||
// block, skipping its trailing statements — see lowerReturn).
|
||||
// Stop here so dead statements after the terminator aren't
|
||||
// emitted into an already-closed block (invalid LLVM IR).
|
||||
if (self.currentBlockHasTerminator()) break;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
@@ -1517,6 +1524,10 @@ pub const Lowering = struct {
|
||||
for (blk.stmts[0 .. blk.stmts.len - 1]) |stmt| {
|
||||
if (self.block_terminated) return null;
|
||||
self.lowerStmt(stmt);
|
||||
// A bare `return`/`raise` mid-block closes the current basic
|
||||
// block (without setting `block_terminated`); the remaining
|
||||
// statements — including the value-expr — are dead.
|
||||
if (self.currentBlockHasTerminator()) return null;
|
||||
}
|
||||
if (self.block_terminated) return null;
|
||||
// Last statement: if it's an expression, return its value
|
||||
|
||||
Reference in New Issue
Block a user