Skip to content

Commit

Permalink
changes needed to adapt to compressed line table format in Julia
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash authored and aviatesk committed Mar 26, 2024
1 parent f3dd6cd commit 2377fb4
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 26 deletions.
96 changes: 75 additions & 21 deletions TypedSyntax/src/node.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
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
7 changes: 6 additions & 1 deletion src/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 2377fb4

Please sign in to comment.