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

updates with the incoming type lattice overhaul #238

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
59 changes: 51 additions & 8 deletions src/Cthulhu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ using InteractiveUtils
using UUIDs
using REPL: REPL, AbstractTerminal

using Core: MethodInstance
import Core: MethodInstance, OpaqueClosure
const Compiler = Core.Compiler
import Core.Compiler: MethodMatch, LimitedAccuracy, ignorelimited, specialize_method
import Core.Compiler: MethodMatch, specialize_method, widenconst,
LimitedAccuracy, Const, PartialStruct, InterConditional, PartialOpaque
import Base: unwrapva, isvarargtype, unwrap_unionall, rewrap_unionall

const mapany = Base.mapany

# branch on https://github.com/JuliaLang/julia/pull/42125
Expand All @@ -21,6 +23,17 @@ else
macro constprop(_, ex); esc(ex); end
end

const IS_OVERHAULED = isdefined(Core.Compiler, :LatticeElement)
@static if IS_OVERHAULED
import Core.Compiler: ⊤, ⊥, LatticeElement, NativeType, LatticeElement, isConst,
isLimitedAccuracy, Argtypes, SSAValueTypes
ignorelimited(@nospecialize x) = isa(x, LatticeElement) ? Core.Compiler.ignorelimited(x) : x
else
import Core.Compiler: ignorelimited
const Argtypes = Vector{Any}
const SSAValueTypes = Vector{Any}
end

Base.@kwdef mutable struct CthulhuConfig
enable_highlighter::Bool = false
highlighter::Cmd = `pygmentize -l`
Expand Down Expand Up @@ -212,15 +225,36 @@ end

descend(interp::CthulhuInterpreter, mi::MethodInstance; kwargs...) = _descend(interp, mi; iswarn=false, interruptexc=false, kwargs...)

@static if IS_OVERHAULED
import Core.Compiler: ConditionalInfo
function codeinst_rt(code::CodeInstance)
rettype = code.rettype
if isdefined(code, :rettype_const)
rettype_const = code.rettype_const
if isa(rettype_const, Vector{Any}) && !(Vector{Any} <: rettype)
return Core.PartialStruct(rettype, rettype_const)
elseif isa(rettype_const, Core.PartialOpaque) && rettype <: Core.OpaqueClosure
return PartialStruct(rettype, rettype_const)
elseif isa(rettype_const, PartialOpaque) && rettype <: OpaqueClosure
return rettype_const
elseif isa(rettype_const, Core.InterConditional) && !(Core.InterConditional <: rettype)
elseif isa(rettype_const, ConditionalInfo) && !(ConditionalInfo <: rettype)
@assert rettype_const.inter
return InterConditional(rettype_const.slot_id, rettype_const.vtype, rettype_const.elsetype), mi
else
return Const(rettype_const)
end
else
return rettype
end
end
else # @static if IS_OVERHAULED
function codeinst_rt(code::CodeInstance)
rettype = code.rettype
if isdefined(code, :rettype_const)
rettype_const = code.rettype_const
if isa(rettype_const, Vector{Any}) && !(Vector{Any} <: rettype)
return PartialStruct(rettype, rettype_const)
elseif isa(rettype_const, PartialOpaque) && rettype <: OpaqueClosure
return rettype_const
elseif isa(rettype_const, InterConditional) && !(InterConditional <: rettype)
return rettype_const
else
return Const(rettype_const)
Expand All @@ -229,6 +263,7 @@ function codeinst_rt(code::CodeInstance)
return rettype
end
end
end # @static if IS_OVERHAULED

# `@constprop :aggressive` here in order to make sure the constant propagation of `allow_no_src`
@constprop :aggressive function lookup(interp::CthulhuInterpreter, mi::MethodInstance, optimize::Bool; allow_no_src::Bool=false)
Expand All @@ -238,7 +273,11 @@ end
infos = interp.unopt[mi].stmt_info
slottypes = src.slottypes
if isnothing(slottypes)
slottypes = Any[ Any for i = 1:length(src.slotflags) ]
@static if IS_OVERHAULED
slottypes = LatticeElement[ ⊤ for i = 1:length(src.slotflags) ]
else
slottypes = Any[ Any for i = 1:length(src.slotflags) ]
end
end
else
codeinst = interp.opt[mi]
Expand All @@ -255,7 +294,11 @@ end
# But with coverage on, the empty function body isn't empty due to :code_coverage_effect expressions.
codeinf = src = nothing
infos = []
slottypes = Any[Base.unwrap_unionall(mi.specTypes).parameters...]
@static if IS_OVERHAULED
slottypes = AbstractLatticce[NativeType(t) for t in Base.unwrap_unionall(mi.specTypes).parameters]
else
slottypes = Any[Base.unwrap_unionall(mi.specTypes).parameters...]
end
else
Core.eval(Main, quote
interp = $interp
Expand All @@ -266,7 +309,7 @@ end
end
end
# NOTE return `codeinf::CodeInfo` in any case since it can provide additional information on slot names
(; src, rt, infos, slottypes, codeinf)
return (; src, rt, infos, slottypes, codeinf)
end

##
Expand Down
8 changes: 4 additions & 4 deletions src/callsite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct MICallInfo <: CallInfo
mi::MethodInstance
rt
function MICallInfo(mi::MethodInstance, @nospecialize(rt))
if isa(rt, LimitedAccuracy)
if @static IS_OVERHAULED ? isLimitedAccuracy(rt) : isa(rt, LimitedAccuracy)
return LimitedCallInfo(new(mi, ignorelimited(rt)))
else
return new(mi, rt)
Expand Down Expand Up @@ -36,9 +36,9 @@ struct UncachedCallInfo <: WrappedCallInfo
end

struct PureCallInfo <: CallInfo
argtypes::Vector{Any}
argtypes::Argtypes
rt
PureCallInfo(argtypes::Vector{Any}, @nospecialize(rt)) =
PureCallInfo(argtypes::Argtypes, @nospecialize(rt)) =
new(argtypes, rt)
end
get_mi(::PureCallInfo) = nothing
Expand Down Expand Up @@ -242,7 +242,7 @@ end
function show_callinfo(limiter, ci::Union{MultiCallInfo, FailedCallInfo, GeneratedCallInfo})
types = (ci.sig::DataType).parameters
ft, tt = types[1], types[2:end]
f = Compiler.singleton_type(ft)
f = Compiler.singleton_type((@static IS_OVERHAULED ? LatticeElement : identity)(ft))
if f !== nothing
name = "→ $f"
elseif ft isa Union
Expand Down
14 changes: 10 additions & 4 deletions src/codeview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ function cthulhu_typed(io::IO, debuginfo::Symbol,
if isa(src, Core.CodeInfo)
# we're working on pre-optimization state, need to ignore `LimitedAccuracy`
src = copy(src)
src.ssavaluetypes = Base.mapany(ignorelimited, src.ssavaluetypes::Vector{Any})
@static if IS_OVERHAULED
src.ssavaluetypes = SSAValueTypes([ignorelimited(t) for t in src.ssavaluetypes::SSAValueTypes])
else
src.ssavaluetypes = Base.mapany(ignorelimited, src.ssavaluetypes::SSAValueTypes)
end
src.rettype = ignorelimited(src.rettype)

if src.slotnames !== nothing
Expand All @@ -144,8 +148,9 @@ function cthulhu_typed(io::IO, debuginfo::Symbol,
isa(mi, MethodInstance) || throw("`mi::MethodInstance` is required")
code = src isa IRCode ? src.stmts.inst : src.code
cst = Vector{Int}(undef, length(code))
sptypes = Core.Compiler.sptypes_from_meth_instance(mi)
params = Core.Compiler.OptimizationParams(interp)
maxcost = Core.Compiler.statement_costs!(cst, code, src, Any[mi.sparam_vals...], false, params)
maxcost = Core.Compiler.statement_costs!(cst, code, src, sptypes, false, params)
nd = ndigits(maxcost)
_lineprinter = lineprinter(src)
function preprinter(io, linestart, idx)
Expand Down Expand Up @@ -195,8 +200,9 @@ function show_variables(io, src, slotnames)
slottypes = src.slottypes
for i = 1:length(slotnames)
print(io, " ", slotnames[i])
if isa(slottypes, Vector{Any})
InteractiveUtils.warntype_type_printer(io, slottypes[i], true)
if isa(slottypes, Argtypes)
typ = (@static IS_OVERHAULED ? Core.Compiler.unwraptype : identity)(slottypes[i])
InteractiveUtils.warntype_type_printer(io, typ, true)
end
println(io)
end
Expand Down
6 changes: 3 additions & 3 deletions src/interpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ end
@static if isdefined(Compiler, :is_stmt_inline)
function Compiler.inlining_policy(
interp::CthulhuInterpreter, @nospecialize(src), stmt_flag::UInt8,
mi::MethodInstance, argtypes::Vector{Any})
@assert isa(src, OptimizedSource) || isnothing(src)
mi::MethodInstance, argtypes::Argtypes)
@assert isa(src, OptimizedSource) || isnothing(src) "`inlining_policy(::CthulhuInterpreter, ...)` got unexpected source: `$(typeof(src))`"
if isa(src, OptimizedSource)
if Compiler.is_stmt_inline(stmt_flag) || src.isinlineable
return src.ir
Expand All @@ -103,7 +103,7 @@ function Compiler.inlining_policy(
# the default inlining policy may try additional effor to find the source in a local cache
return Base.@invoke Compiler.inlining_policy(
interp::AbstractInterpreter, nothing, stmt_flag::UInt8,
mi::MethodInstance, argtypes::Vector{Any})
mi::MethodInstance, argtypes::Argtypes)
end
return nothing
end
Expand Down
14 changes: 7 additions & 7 deletions src/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@ function transform(::Val{:CuFunction}, callsite, callexpr, CI, mi, slottypes; wo
sptypes = sptypes_from_meth_instance(mi)
tt = argextype(callexpr.args[4], CI, sptypes, slottypes)
ft = argextype(callexpr.args[3], CI, sptypes, slottypes)
isa(tt, Const) || return callsite
return Callsite(callsite.id, CuCallInfo(callinfo(Tuple{widenconst(ft), tt.val.parameters...}, Nothing; world)), callsite.head)
(@static IS_OVERHAULED ? isConst(tt) : isa(tt, Const)) || return callsite
return Callsite(callsite.id, CuCallInfo(callinfo(Tuple{widenconst(ft), tt.val.parameters...}, Nothing, world)), callsite.head)
end

const ArgTypes = Vector{Any}

function find_callsites(interp::CthulhuInterpreter, CI::Union{Core.CodeInfo, IRCode},
stmt_info::Union{Vector, Nothing}, mi::Core.MethodInstance,
slottypes::Vector{Any}, optimize::Bool=true)
slottypes::Argtypes, optimize::Bool=true)
sptypes = sptypes_from_meth_instance(mi)
callsites = Callsite[]

Expand All @@ -48,7 +46,9 @@ function find_callsites(interp::CthulhuInterpreter, CI::Union{Core.CodeInfo, IRC
if !optimize
args = (ignorelhs(c)::Expr).args
end
argtypes = mapany(function (@nospecialize(arg),)
argtypes = @static IS_OVERHAULED ?
LatticeElement[argextype(arg, CI, sptypes, slottypes) for arg in args] :
mapany(function (@nospecialize(arg),)
t = argextype(arg, CI, sptypes, slottypes)
return widenconst(ignorelimited(t))
end, args)
Expand Down Expand Up @@ -103,7 +103,7 @@ function find_callsites(interp::CthulhuInterpreter, CI::Union{Core.CodeInfo, IRC
return callsites
end

function process_info(interp, @nospecialize(info), argtypes::ArgTypes, @nospecialize(rt), optimize::Bool)
function process_info(interp, @nospecialize(info), argtypes::Argtypes, @nospecialize(rt), optimize::Bool)
is_cached(@nospecialize(key)) = haskey(optimize ? interp.opt : interp.unopt, key)
process_recursive(@nospecialize(newinfo)) = process_info(interp, newinfo, argtypes, rt, optimize)

Expand Down