Skip to content

Commit

Permalink
changes to adapt to compressed line table format (#526)
Browse files Browse the repository at this point in the history
Co-authored-by: Shuhei Kadowaki <[email protected]>
  • Loading branch information
vtjnash and aviatesk authored Mar 26, 2024
1 parent f3dd6cd commit 09c4fed
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 34 deletions.
101 changes: 79 additions & 22 deletions TypedSyntax/src/node.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ function TypedSyntaxNode(rootnode::SyntaxNode, src::CodeInfo, mappings, symtyps)
# There may be ambiguous assignments back to the source; preserve just the unambiguous ones
node2ssa = IdDict{SyntaxNode,Int}(only(list) => i for (i, list) in pairs(mappings) if length(list) == 1)
# Copy `rootnode`, adding type annotations
trootnode = TypedSyntaxNode(nothing, nothing, TypedSyntaxData(rootnode.data::SyntaxData, src, gettyp(node2ssa, rootnode, src)))
typ = gettyp(node2ssa, rootnode, src)
trootnode = TypedSyntaxNode(nothing, nothing, TypedSyntaxData(rootnode.data::SyntaxData, src, typ))
addchildren!(trootnode, rootnode, src, node2ssa, symtyps, mappings)
# Add argtyps to signature
fnode = get_function_def(trootnode)
Expand Down Expand Up @@ -439,6 +440,76 @@ 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
@static if VERSION v"1.12.0-DEV.173"
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)
ltnext = lt.linetable
if ltnext === nothing
return line
end
i = line
lt = ltnext
end
end
function getnextline(lt::Core.DebugInfo, i::Int, Δline)
while true
codeloc = Base.IRShow.getdebugidx(lt, i)
line::Int = codeloc[1]
line < 0 && return typemax(Int) # broken or disabled debug info?
if line == 0
i += 1
continue
end
ltnext = lt.linetable
if ltnext === nothing
break
end
i = line
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+1
currline = Base.IRShow.getdebugidx(lt, i)[1]
while j typemax(Int)
codeloc = Base.IRShow.getdebugidx(lt, j)
line::Int = codeloc[1]
line < 0 && break
if line == 0 || currline == line
j += 1
else
return line + Δline
end
end
return typemax(Int)
end

else # VERSION < v"1.12.0-DEV.173"
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 # @static if

# 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
Expand Down Expand Up @@ -471,8 +542,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
@static if VERSION v"1.12.0-DEV.173"
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
Expand Down Expand Up @@ -853,25 +929,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
Expand Down
3 changes: 0 additions & 3 deletions src/codeview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/interpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
22 changes: 15 additions & 7 deletions src/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ function find_caller_of(interp::AbstractInterpreter, callee::MethodInstance, cal
callsites, _ = find_callsites(interp′, src, infos, caller, slottypes, optimize)
callsites = allow_unspecialized ? filter(cs->maybe_callsite(cs, callee), callsites) :
filter(cs->is_callsite(cs, callee), callsites)
foreach(cs -> add_sourceline!(locs, src, cs.id), callsites)
foreach(cs -> add_sourceline!(locs, src, cs.id, caller), callsites)
end
# Consolidate by method, but preserve the order
prlookup = Dict{Tuple{Symbol,Symbol},Int}()
Expand All @@ -335,17 +335,25 @@ function find_caller_of(interp::AbstractInterpreter, callee::MethodInstance, cal
return ulocs
end

function add_sourceline!(locs, CI, stmtidx::Int)
if isa(CI, IRCode)
stack = Base.IRShow.compute_loc_stack(CI.linetable, CI.stmts.line[stmtidx])
function add_sourceline!(locs::Vector{Tuple{Core.LineInfoNode,Int}}, src::Union{CodeInfo,IRCode}, stmtidx::Int, caller::MethodInstance)
@static if VERSION v"1.12.0-DEV.173"
stack = Base.IRShow.buildLineInfoNode(src.debuginfo, caller, stmtidx)
for (i, di) in enumerate(stack)
loc = Core.LineInfoNode(Main, di.method, di.file, di.line, zero(Int32))
push!(locs, (loc, i-1))
end
else # VERSION < v"1.12.0-DEV.173"
if isa(src, IRCode)
stack = Base.IRShow.compute_loc_stack(src.linetable, src.stmts.line[stmtidx])
for (i, idx) in enumerate(stack)
line = CI.linetable[idx]
line = src.linetable[idx]
line.line == 0 && continue
push!(locs, (CI.linetable[idx], i-1))
push!(locs, (src.linetable[idx], i-1))
end
else
push!(locs, (CI.linetable[CI.codelocs[stmtidx]], 0))
push!(locs, (src.linetable[src.codelocs[stmtidx]], 0))
end
end # @static if
return locs
end

Expand Down
1 change: 0 additions & 1 deletion test/test_Cthulhu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,6 @@ end
@test lines == [line2]
end


@testset "ascend interface" begin
m = Module()
@eval m begin
Expand Down

0 comments on commit 09c4fed

Please sign in to comment.