Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt to nightly linetable changes #122

Merged
merged 2 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/ir/ir.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
using Core.Compiler: LineInfoNode
import Base: push!, insert!, getindex, setindex!, iterate, length

# We have our own versions of these in order to
# (1) be more robust to Base IR changes, and
# (2) make sure that mistakes/bugs do not cause bad LLVM IR.

"""
LineInfoNode(file::Symbol, line::Int32, [inlined_at::Int32])

Represents line information about a statement; Inlined statements has a non-zero
`inlined_at` which represents the "parent" location in the linetable array.
"""
struct LineInfoNode
file::Symbol
line::Int32
inlined_at::Int32
end
LineInfoNode(file, line) = LineInfoNode(file, line, Int32(0))

struct Undefined end
const undef = Undefined()

Expand Down
79 changes: 72 additions & 7 deletions src/ir/wrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@ using MacroTools: isexpr, prewalk

using ..Inner, ..IRTools
import ..Inner: IR, Variable, Statement, Branch, BasicBlock, Meta, block!,
unreachable, varmap, argument!, branch!, return!
unreachable, varmap, argument!, branch!, return!, LineInfoNode
import Core: CodeInfo, GotoNode, SSAValue
import Core.Compiler: IRCode, CFG, GotoIfNot, ReturnNode, StmtRange

@static if VERSION > v"1.6-"
import Core.Compiler: InstructionStream
end

@static if VERSION ≥ v"1.9.0-DEV.502"
const LineType = Int32
else
const LineType = Int
end

@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

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

function IRCode(ir::IR)
Expand All @@ -34,7 +46,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 +64,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 +73,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 +85,39 @@ 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
mod, meth = ir.meta isa Meta ? (ir.meta.method.module, ir.meta.method) : (Main, nothing)
linetable = map(li -> Core.LineInfoNode(mod, meth, li.file, LineType(li.line), LineType(li.inlined_at)),
ir.lines)
IRCode(stmts, cfg, linetable, 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 +163,27 @@ 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 = 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)
linode = first(LI) # ::Base.IRShow.LineInfoNode
push!(linetable, LineInfoNode(linode.file, linode.line))
codelocs[pc] = length(linetable)
end
end

codelocs, linetable
else
ci.codelocs, map(li -> LineInfoNode(li.file, li.line), 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 +216,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
Loading