Skip to content

Commit

Permalink
adapt to upstream linetable change
Browse files Browse the repository at this point in the history
`Core.Compiler.LineInfoNode` was removed in JuliaLang/julia#52415
but kept in `Core` for serializer compatibility reasons (see
https://github.com/JuliaLang/julia/blob/e07c0f1ddbfc89ad1ac4dda7246d8ed5d0d57c19/base/boot.jl#L491).

Linetable representation in Julia IR has been changed to be more compact.
This commit updates IRTools to decode and generate valid debug information according to these changes.

Adaptation for IRTools is relatively straightforward in the sense that
IRTools operates on untyped IR which does not contains inline
statements.

However, IRTools contains an inlining pass but it did not account for
linetable information previously. In this change, I have made the choice
to use the same line for all inlined statements. This can be further
improved in the future.
  • Loading branch information
Pangoraw committed Apr 9, 2024
1 parent 538a96d commit dd1aa0d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/ir/ir.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Core.Compiler: LineInfoNode
using Base.IRShow: LineInfoNode
import Base: push!, insert!, getindex, setindex!, iterate, length

# We have our own versions of these in order to
Expand Down
68 changes: 62 additions & 6 deletions src/ir/wrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ end

unvars(ex) = prewalk(x -> x isa Variable ? SSAValue(x.id) : x, ex)


@static if VERSION v"1.12.0-DEV.173"
addline!(lines, li) = push!(lines, li, Int32(0), Int32(0))
else
addline!(lines, li) = push!(lines, li)
end

function IRCode(ir::IR)
defs = Dict()
stmts, types, lines = [], [], Int32[]
Expand All @@ -34,7 +41,7 @@ function IRCode(ir::IR)
end
push!(stmts, ex)
push!(types, st.type)
push!(lines, st.line)
addline!(lines, st.line)
end
for br in BasicBlock(b).branches
if IRTools.isreturn(br)
Expand All @@ -52,7 +59,7 @@ function IRCode(ir::IR)
cond = get(defs, br.condition, br.condition) |> unvars
push!(stmts, GotoIfNot(cond, br.block))
end
push!(types, Any); push!(lines, 0)
push!(types, Any); addline!(lines, Int32(0))
end
push!(index, length(stmts)+1)
end
Expand All @@ -61,7 +68,8 @@ function IRCode(ir::IR)
preds = map.(x -> x.id, IRTools.predecessors.(IRTools.blocks(ir)))
bs = Core.Compiler.BasicBlock.(ranges, preds, succs)
cfg = CFG(bs, index)
flags = [0x00 for _ in stmts]

flags = UInt32[0x00 for _ in stmts]
sps = VERSION > v"1.2-" ? (VERSION >= v"1.10.0-DEV.552" ? Core.Compiler.VarState[] : []) : Core.svec()

@static if VERSION > v"1.6-"
Expand All @@ -72,7 +80,36 @@ function IRCode(ir::IR)
end
stmts = InstructionStream(stmts, types, stmtinfo, lines, flags)
meta = @static VERSION < v"1.9.0-DEV.472" ? [] : Expr[]
IRCode(stmts, cfg, ir.lines, ir.blocks[1].argtypes, meta, sps)
@static if VERSION v"1.12.0-DEV.173"
nlocs = length(types)
codelocs = fill(Int32(0), 3nlocs)

if !isempty(ir.lines)
LI = first(ir.lines)
topfile, topline = LI.file, LI.line

for i in 1:nlocs
lineidx = lines[3i - 2]
if lineidx == 0
continue
end
# TODO: support inlining, see passes/inline.jl
@assert LI.file === topfile && LI.inlined_at == 0
LI = ir.lines[lineidx]
codelocs[3i - 2] = LI.line
end
else
topline = Int32(1)
end
codelocs = @ccall jl_compress_codelocs(topline::Int32, codelocs::Any, nlocs::Csize_t)::Any

debuginfo = Core.Compiler.DebugInfoStream(lines)
debuginfo.def = ir.meta isa Meta ? ir.meta.instance : :var"n/a"
debuginfo.linetable = Core.DebugInfo(debuginfo.def, nothing, Core.svec(), codelocs)
IRCode(stmts, cfg, debuginfo, ir.blocks[1].argtypes, meta, sps)
else
IRCode(stmts, cfg, ir.lines, ir.blocks[1].argtypes, meta, sps)
end
else
IRCode(stmts, types, lines, flags, cfg, ir.lines, ir.blocks[1].argtypes, [], sps)
end
Expand Down Expand Up @@ -118,7 +155,26 @@ slotname(ci, s) = Symbol(:_, s.id)

function IR(ci::CodeInfo, nargs::Integer; meta = nothing)
bs = blockstarts(ci)
ir = IR(Core.LineInfoNode[ci.linetable...], meta = meta)
codelocs, linetable = @static if VERSION v"1.12.0-DEV.173"
def = isnothing(meta) ? :var"n/a" : meta.instance
N = length(ci.code)
codelocs = fill(0, N)
linetable = Base.IRShow.LineInfoNode[]

# NOTE: we could be faster about decoding here and support inlining?
for pc in 1:N
LI = Base.IRShow.buildLineInfoNode(ci.debuginfo, def, pc)
if !isempty(LI)
push!(linetable, first(LI))
codelocs[pc] = length(linetable)
end
end

codelocs, linetable
else
ci.codelocs, Core.LineInfoNode[ci.linetable...]
end
ir = IR(linetable, meta = meta)
_rename = Dict()
rename(ex) = prewalk(ex) do x
haskey(_rename, x) && return _rename[x]
Expand Down Expand Up @@ -151,7 +207,7 @@ function IR(ci::CodeInfo, nargs::Integer; meta = nothing)
elseif isreturn(ex)
return!(ir, rename(retval(ex)))
else
_rename[Core.SSAValue(i)] = push!(ir, IRTools.stmt(rename(ex), line = ci.codelocs[i]))
_rename[Core.SSAValue(i)] = push!(ir, IRTools.stmt(rename(ex), line = codelocs[i]))
end
end
return ir
Expand Down
9 changes: 6 additions & 3 deletions src/passes/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ function fixup_blocks!(ir, n)
end
end

function inlinehere!(ir, source, args...)
function inlinehere!(ir, line, source, args...)
source = merge_returns!(copy(source)) # TODO preserve type info
offset = length(blocks(ir.to))-1
env = Dict()
retvalue = nothing
rename(x::Variable) = env[x]
rename(x::Expr) = Expr(x.head, rename.(x.args)...)
rename(x::Statement) = stmt(x, expr = rename(x.expr))
rename(x::Statement) = stmt(x; expr=rename(x.expr), line=line)
rename(x) = x
for (name, arg) in zip(arguments(source), args)
env[name] = arg
Expand Down Expand Up @@ -78,9 +78,12 @@ function inline(ir::IR, loc::Variable, source::IR)
if v === loc
startblock = length(blocks(pr.to))
fixup_blocks!(pr.to, length(blocks(source)))
# TODO: when inlining, we set all statements from source
# .... at the line from loc. Ideally, we use the `inlined_at` field.
line = ir[loc].line
ex = ir[loc].expr
delete!(pr, v)
v′ = inlinehere!(pr, source, ex.args...)
v′ = inlinehere!(pr, line, source, ex.args...)
substitute!(pr, v, substitute(pr, v′))
end
end
Expand Down
4 changes: 3 additions & 1 deletion src/reflection/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ end

function update!(ci::CodeInfo, ir::Core.Compiler.IRCode)
replace_code_newstyle!(ci, ir, length(ir.argtypes))
ci.inferred = false
@static if VERSION < v"1.12.0-DEV.15"
ci.inferred = false
end
ci.ssavaluetypes = length(ci.code)
slots!(ci)
fill!(ci.slotflags, 0)
Expand Down

0 comments on commit dd1aa0d

Please sign in to comment.