# This file is a part of Julia. License is MIT: https://julialang.org/license """ inflate_ir!(ci::CodeInfo, linfo::MethodInstance) -> ir::IRCode inflate_ir!(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{Any}) -> ir::IRCode Inflates `ci::CodeInfo`-IR to `ir::IRCode`-format. This should be used with caution as it is a in-place transformation where the fields of the original `ci::CodeInfo` are modified. """ function inflate_ir!(ci::CodeInfo, linfo::MethodInstance) sptypes = sptypes_from_meth_instance(linfo) argtypes, _ = matching_cache_argtypes(fallback_lattice, linfo) return inflate_ir!(ci, sptypes, argtypes) end function inflate_ir!(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{Any}) code = ci.code cfg = compute_basic_blocks(code) for i = 1:length(code) stmt = code[i] # Translate statement edges to bb_edges if isa(stmt, GotoNode) code[i] = GotoNode(block_for_inst(cfg, stmt.label)) elseif isa(stmt, GotoIfNot) code[i] = GotoIfNot(stmt.cond, block_for_inst(cfg, stmt.dest)) elseif isa(stmt, PhiNode) code[i] = PhiNode(Int32[block_for_inst(cfg, Int(edge)) for edge in stmt.edges], stmt.values) elseif isexpr(stmt, :enter) stmt.args[1] = block_for_inst(cfg, stmt.args[1]::Int) code[i] = stmt end end nstmts = length(code) ssavaluetypes = ci.ssavaluetypes if !isa(ssavaluetypes, Vector{Any}) ssavaluetypes = Any[ Any for i = 1:ssavaluetypes::Int ] end info = CallInfo[NoCallInfo() for i = 1:nstmts] stmts = InstructionStream(code, ssavaluetypes, info, ci.codelocs, ci.ssaflags) linetable = ci.linetable if !isa(linetable, Vector{LineInfoNode}) linetable = collect(LineInfoNode, linetable::Vector{Any})::Vector{LineInfoNode} end meta = Expr[] return IRCode(stmts, cfg, linetable, argtypes, meta, sptypes) end """ inflate_ir(ci::CodeInfo, linfo::MethodInstance) -> ir::IRCode inflate_ir(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{Any}) -> ir::IRCode inflate_ir(ci::CodeInfo) -> ir::IRCode Non-destructive version of `inflate_ir!`. Mainly used for testing or interactive use. """ inflate_ir(ci::CodeInfo, linfo::MethodInstance) = inflate_ir!(copy(ci), linfo) inflate_ir(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{Any}) = inflate_ir!(copy(ci), sptypes, argtypes) function inflate_ir(ci::CodeInfo) parent = ci.parent isa(parent, MethodInstance) && return inflate_ir(ci, parent) # XXX the length of `ci.slotflags` may be different from the actual number of call # arguments, but we really don't know that information in this case argtypes = Any[ Any for i = 1:length(ci.slotflags) ] return inflate_ir(ci, VarState[], argtypes) end function replace_code_newstyle!(ci::CodeInfo, ir::IRCode) @assert isempty(ir.new_nodes) # All but the first `nargs` slots will now be unused nargs = length(ir.argtypes) resize!(ci.slotnames, nargs) resize!(ci.slotflags, nargs) resize!(ci.slottypes, nargs) stmts = ir.stmts code = ci.code = stmts.inst ssavaluetypes = ci.ssavaluetypes = stmts.type codelocs = ci.codelocs = stmts.line ssaflags = ci.ssaflags = stmts.flag linetable = ci.linetable = ir.linetable for metanode in ir.meta push!(code, metanode) push!(codelocs, 1) push!(ssavaluetypes, Any) push!(ssaflags, IR_FLAG_NULL) end # Translate BB Edges to statement edges # (and undo normalization for now) for i = 1:length(code) stmt = code[i] if isa(stmt, GotoNode) code[i] = GotoNode(first(ir.cfg.blocks[stmt.label].stmts)) elseif isa(stmt, GotoIfNot) code[i] = GotoIfNot(stmt.cond, first(ir.cfg.blocks[stmt.dest].stmts)) elseif isa(stmt, PhiNode) code[i] = PhiNode(Int32[edge == 0 ? 0 : last(ir.cfg.blocks[edge].stmts) for edge in stmt.edges], stmt.values) elseif isexpr(stmt, :enter) stmt.args[1] = first(ir.cfg.blocks[stmt.args[1]::Int].stmts) code[i] = stmt end end end