Skip to content

Commit

Permalink
Allow using ReturnNode() in @generated code (#51715)
Browse files Browse the repository at this point in the history
IRTools.jl currently tries to use `ReturnNode()` to model unreachable
block terminators but it fails in `find_ssavalue_uses`. This PR adds a
check to enable using `ReturnNode()` in untyped code.

One other alternative for frontends is to use an instruction known to
terminate (`Core.throw`) instead. See
FluxML/IRTools.jl#115 for more context.
  • Loading branch information
Pangoraw committed Oct 16, 2023
1 parent 0acca3c commit ff03e51
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
1 change: 1 addition & 0 deletions base/compiler/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ function find_ssavalue_uses(body::Vector{Any}, nvals::Int)
for line in 1:length(body)
e = body[line]
if isa(e, ReturnNode)
isdefined(e, :val) || continue
e = e.val
elseif isa(e, GotoIfNot)
e = e.cond
Expand Down
29 changes: 29 additions & 0 deletions test/staged.jl
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,32 @@ let world = Base.get_world_counter()
@test all(lin->lin.method === :sin, src.linetable)
@test sin_generated(42) == sin(42)
end

# Allow passing unreachable insts in generated codeinfo
let
dummy() = return
dummy_m = which(dummy, Tuple{})

src = Base.uncompressed_ir(dummy_m)
src.code = Any[
# block 1
Core.ReturnNode(nothing),
# block 2
Core.ReturnNode(),
]
nstmts = length(src.code)
nslots = 1
src.ssavaluetypes = nstmts
src.codelocs = fill(Int32(1), nstmts)
src.ssaflags = fill(Int32(0), nstmts)
src.slotflags = fill(0, nslots)
src.slottypes = Any[Any]

@eval function f_unreachable()
$(Expr(:meta, :generated, Returns(src)))
$(Expr(:meta, :generated_only))
end

ir, _ = Base.code_ircode(f_unreachable, ()) |> only
@test length(ir.cfg.blocks) == 1
end

0 comments on commit ff03e51

Please sign in to comment.