Skip to content

Commit fd48002

Browse files
authored
Add statment offset to branch address in CodeInfo conversion (#60)
When pushing :meta expressions to the start of the CodeInfo block we need to offset goto branch addresses in addition to SSA indices, but this was forgotten.
1 parent 067fa53 commit fd48002

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

src/eval.jl

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ function to_code_info(ex, mod, funcname, slots)
154154
end
155155
end
156156

157-
ssa_offset = length(stmts)
157+
stmt_offset = length(stmts)
158158
for stmt in children(ex)
159-
push!(stmts, to_lowered_expr(mod, stmt, ssa_offset))
159+
push!(stmts, to_lowered_expr(mod, stmt, stmt_offset))
160160
add_ir_debug_info!(current_codelocs_stack, stmt)
161161
end
162162

@@ -223,7 +223,7 @@ function to_code_info(ex, mod, funcname, slots)
223223
)
224224
end
225225

226-
function to_lowered_expr(mod, ex, ssa_offset=0)
226+
function to_lowered_expr(mod, ex, stmt_offset=0)
227227
k = kind(ex)
228228
if is_literal(k)
229229
ex.value
@@ -257,9 +257,9 @@ function to_lowered_expr(mod, ex, ssa_offset=0)
257257
elseif k == K"static_parameter"
258258
Expr(:static_parameter, ex.var_id)
259259
elseif k == K"SSAValue"
260-
Core.SSAValue(ex.var_id + ssa_offset)
260+
Core.SSAValue(ex.var_id + stmt_offset)
261261
elseif k == K"return"
262-
Core.ReturnNode(to_lowered_expr(mod, ex[1], ssa_offset))
262+
Core.ReturnNode(to_lowered_expr(mod, ex[1], stmt_offset))
263263
elseif k == K"inert"
264264
e1 = ex[1]
265265
getmeta(ex, :as_Expr, false) ? QuoteNode(Expr(e1)) : e1
@@ -276,38 +276,38 @@ function to_lowered_expr(mod, ex, ssa_offset=0)
276276
elseif k == K"Value"
277277
ex.value
278278
elseif k == K"goto"
279-
Core.GotoNode(ex[1].id)
279+
Core.GotoNode(ex[1].id + stmt_offset)
280280
elseif k == K"gotoifnot"
281-
Core.GotoIfNot(to_lowered_expr(mod, ex[1], ssa_offset), ex[2].id)
281+
Core.GotoIfNot(to_lowered_expr(mod, ex[1], stmt_offset), ex[2].id + stmt_offset)
282282
elseif k == K"enter"
283283
catch_idx = ex[1].id
284284
numchildren(ex) == 1 ?
285285
Core.EnterNode(catch_idx) :
286-
Core.EnterNode(catch_idx, to_lowered_expr(mod, ex[2], ssa_offset))
286+
Core.EnterNode(catch_idx, to_lowered_expr(mod, ex[2], stmt_offset))
287287
elseif k == K"method"
288-
cs = map(e->to_lowered_expr(mod, e, ssa_offset), children(ex))
288+
cs = map(e->to_lowered_expr(mod, e, stmt_offset), children(ex))
289289
# Ad-hoc unwrapping to satisfy `Expr(:method)` expectations
290290
c1 = cs[1] isa QuoteNode ? cs[1].value : cs[1]
291291
Expr(:method, c1, cs[2:end]...)
292292
elseif k == K"newvar"
293-
Core.NewvarNode(to_lowered_expr(mod, ex[1], ssa_offset))
293+
Core.NewvarNode(to_lowered_expr(mod, ex[1], stmt_offset))
294294
elseif k == K"opaque_closure_method"
295-
args = map(e->to_lowered_expr(mod, e, ssa_offset), children(ex))
295+
args = map(e->to_lowered_expr(mod, e, stmt_offset), children(ex))
296296
# opaque_closure_method has special non-evaluated semantics for the
297297
# `functionloc` line number node so we need to undo a level of quoting
298298
@assert args[4] isa QuoteNode
299299
args[4] = args[4].value
300300
Expr(:opaque_closure_method, args...)
301301
elseif k == K"meta"
302-
args = Any[to_lowered_expr(mod, e, ssa_offset) for e in children(ex)]
302+
args = Any[to_lowered_expr(mod, e, stmt_offset) for e in children(ex)]
303303
# Unpack K"Symbol" QuoteNode as `Expr(:meta)` requires an identifier here.
304304
args[1] = args[1].value
305305
Expr(:meta, args...)
306306
elseif k == K"static_eval"
307307
@assert numchildren(ex) == 1
308-
to_lowered_expr(mod, ex[1], ssa_offset)
308+
to_lowered_expr(mod, ex[1], stmt_offset)
309309
elseif k == K"cfunction"
310-
args = Any[to_lowered_expr(mod, e, ssa_offset) for e in children(ex)]
310+
args = Any[to_lowered_expr(mod, e, stmt_offset) for e in children(ex)]
311311
if kind(ex[2]) == K"static_eval"
312312
args[2] = QuoteNode(args[2])
313313
end
@@ -339,7 +339,7 @@ function to_lowered_expr(mod, ex, ssa_offset=0)
339339
if isnothing(head)
340340
throw(LoweringError(ex, "Unhandled form for kind $k"))
341341
end
342-
Expr(head, map(e->to_lowered_expr(mod, e, ssa_offset), children(ex))...)
342+
Expr(head, map(e->to_lowered_expr(mod, e, stmt_offset), children(ex))...)
343343
end
344344
end
345345

@@ -355,7 +355,7 @@ function Core.eval(mod::Module, ex::SyntaxTree; expr_compat_mode::Bool=false)
355355
return x
356356
end
357357
linear_ir = lower(mod, ex, expr_compat_mode)
358-
expr_form = to_lowered_expr(mod, linear_ir)
358+
expr_form = to_lowered_expr(mod, linear_ir, 0)
359359
eval(mod, expr_form)
360360
end
361361

test/functions.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,20 @@ end
287287
""")
288288
@test only(methods(test_mod.f_slotflags)).called == 0b0100
289289

290+
# Branching combined with nospecialize meta in CodeInfo
291+
@test JuliaLowering.include_string(test_mod, """
292+
begin
293+
function f_branch_meta(@nospecialize(x), cond)
294+
if cond
295+
x + 1
296+
else
297+
x + 2
298+
end
299+
end
300+
301+
(f_branch_meta(10, false), f_branch_meta(20, true))
302+
end
303+
""") == (12, 21)
290304
end
291305

292306
@testset "Keyword functions" begin

0 commit comments

Comments
 (0)