From 747619e45926dfbe679a003bb5db520ef57dfea7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 12 Dec 2023 20:53:47 +0000 Subject: [PATCH] changes needed to adapt to compressed line table format in Julia For https://github.com/JuliaLang/julia/pull/52415 --- TypedSyntax/src/node.jl | 96 ++++++++++++++++++++++++++++++++--------- src/codeview.jl | 3 -- src/interpreter.jl | 3 +- src/reflection.jl | 7 ++- 4 files changed, 83 insertions(+), 26 deletions(-) diff --git a/TypedSyntax/src/node.jl b/TypedSyntax/src/node.jl index 60c7050d..f2b9eb5f 100644 --- a/TypedSyntax/src/node.jl +++ b/TypedSyntax/src/node.jl @@ -439,6 +439,74 @@ function collect_symbol_nodes!(symlocs::AbstractDict, node) return symlocs end +## utility function to extract the line number at a particular program counter (ignoring inlining). +## return <= 0 if there is no line number change caused by this statement +if VERSION >= v"1.12" || isdefined(Core, :DebugInfo) +function getline(lt::Core.DebugInfo, i::Int) + while true + codeloc = Base.IRShow.getdebugidx(lt, i) + line::Int = codeloc[1] + line < 0 && return 0 # broken or disabled debug info? + line == 0 && return 0 # no line number update (though maybe inlining changed) + i = line + ltnext = lt.linetable + if ltnext === nothing + break + end + lt = ltnext + end + return i +end + +function getnextline(lt::Core.DebugInfo, i::Int, Δline) + while true + codeloc = Base.IRShow.getdebugidx(lt, i) + line::Int = codeloc[1] + line < 0 && return 0 # broken or disabled debug info? + line == 0 && return 0 # no line number update (though maybe inlining changed) + i = line + ltnext = lt.linetable + if ltnext === nothing + break + end + lt = ltnext + end + # now that we have line i and a list of all lines with code on them lt + # find the next largest line number in this list greater than i, or return typemax(Int) + j = i + for k = 0:typemax(Int) + codeloc = Base.IRShow.getdebugidx(lt, k) + line::Int = codeloc[1] + line < 0 && break + if j == i || i < line < j + j = line + end + end + return j == i ? typemax(Int) : j + Δline +end + +else + +function getline(lt, j) + linfo = (j == 0 ? first(lt) : lt[j])::Core.LineInfoNode + linfo.inlined_at == 0 && return linfo.line + @assert linfo.method === Symbol("macro expansion") + linfo = lt[linfo.inlined_at]::Core.LineInfoNode + return linfo.line +end + +function getnextline(lt, j, Δline) + j == 0 && return typemax(Int) + j += 1 + while j <= length(lt) + linfo = lt[j]::Core.LineInfoNode + linfo.inlined_at == 0 && return linfo.line + Δline + j += 1 + end + return typemax(Int) +end +end + # Main logic for mapping `src.code[i]` to node(s) in the SyntaxNode tree # Success: when we map it to a unique node # Δline is the (Revise) offset of the line number @@ -471,8 +539,13 @@ function map_ssas_to_source(src::CodeInfo, mi::MethodInstance, rootnode::SyntaxN # Append (to `mapped`) all nodes in `targets` that are consistent with the line number of the `i`th stmt # (Essentially `copy!(mapped, filter(predicate, targets))`) function append_targets_for_line!(mapped#=::Vector{nodes}=#, i::Int, targets#=::Vector{nodes}=#) - j = src.codelocs[i] - lt = src.linetable::Vector + if isdefined(src, :debuginfo) + j = i + lt = src.debuginfo + else + j = src.codelocs[i] + lt = src.linetable::Vector + end start = getline(lt, j) + Δline stop = getnextline(lt, j, Δline) - 1 linerange = start : stop @@ -853,25 +926,6 @@ function symloc_key(sym::Symbol) return sym end -function getline(lt, j) - linfo = (j == 0 ? first(lt) : lt[j])::Core.LineInfoNode - linfo.inlined_at == 0 && return linfo.line - @assert linfo.method === Symbol("macro expansion") - linfo = lt[linfo.inlined_at]::Core.LineInfoNode - return linfo.line -end - -function getnextline(lt, j, Δline) - j == 0 && return typemax(Int) - j += 1 - while j <= length(lt) - linfo = lt[j]::Core.LineInfoNode - linfo.inlined_at == 0 && return linfo.line + Δline - j += 1 - end - return typemax(Int) -end - function find_identifier_or_tuplechild(node::AbstractSyntaxNode, sym) kind(node) == K"Identifier" && node.val === sym && return node, true if kind(node) == K"tuple" # tuple destructuring diff --git a/src/codeview.jl b/src/codeview.jl index 03ffb008..bc55aa42 100644 --- a/src/codeview.jl +++ b/src/codeview.jl @@ -127,9 +127,6 @@ function cthulhu_typed(io::IO, debuginfo::Symbol, # We empty the body when filling kwargs istruncated = isempty(children(body)) idxend = istruncated ? JuliaSyntax.last_byte(sig) : lastindex(tsn.source) - if any(iszero, src.codelocs) - @warn "Some line information is missing, type-assignment may be incomplete" - end if src.slottypes === nothing @warn "Inference terminated in an incomplete state due to argument-type changes during recursion" end diff --git a/src/interpreter.jl b/src/interpreter.jl index da3e9d9d..2a375457 100644 --- a/src/interpreter.jl +++ b/src/interpreter.jl @@ -153,7 +153,8 @@ function CC.src_inlining_policy(interp::CthulhuInterpreter, src::Any, info::CCCallInfo, stmt_flag::UInt32) end end -CC.retrieve_ir_for_inlining(cached_result::CodeInstance, src::OptimizedSource) = CC.copy(src.ir) +CC.retrieve_ir_for_inlining(cached_result::CodeInstance, src::OptimizedSource) = + CC.retrieve_ir_for_inlining(cached_result.def, src.ir::IRCode, true) CC.retrieve_ir_for_inlining(mi::MethodInstance, src::OptimizedSource, preserve_local_sources::Bool) = CC.retrieve_ir_for_inlining(mi, src.ir, preserve_local_sources) elseif VERSION ≥ v"1.11.0-DEV.879" diff --git a/src/reflection.jl b/src/reflection.jl index a96029b7..2ffc9e8e 100644 --- a/src/reflection.jl +++ b/src/reflection.jl @@ -336,7 +336,12 @@ function find_caller_of(interp::AbstractInterpreter, callee::MethodInstance, cal end function add_sourceline!(locs, CI, stmtidx::Int) - if isa(CI, IRCode) + if isdefined(CI, :debuginfo) # VERSION >= v"1.12" + stack = Base.IRShow.buildLineInfoNode(CI.debuginfo, :var"n/a", i) + for (i, di) in enumerate(stack) + push!(locs, (di, i-1)) + end + elseif isa(CI, IRCode) stack = Base.IRShow.compute_loc_stack(CI.linetable, CI.stmts.line[stmtidx]) for (i, idx) in enumerate(stack) line = CI.linetable[idx]