|
| 1 | +# This file is a part of Julia. License is MIT: https://julialang.org/license |
| 2 | + |
| 3 | +function compute_ir_rettype(ir::IRCode) |
| 4 | + rt = Union{} |
| 5 | + for i = 1:length(ir.stmts) |
| 6 | + stmt = ir[SSAValue(i)][:stmt] |
| 7 | + if isa(stmt, Core.ReturnNode) && isdefined(stmt, :val) |
| 8 | + rt = Compiler.tmerge(Compiler.argextype(stmt.val, ir), rt) |
| 9 | + end |
| 10 | + end |
| 11 | + return Compiler.widenconst(rt) |
| 12 | +end |
| 13 | + |
| 14 | +function compute_oc_signature(ir::IRCode, nargs::Int, isva::Bool) |
| 15 | + argtypes = Vector{Any}(undef, nargs) |
| 16 | + for i = 1:nargs |
| 17 | + argtypes[i] = Compiler.widenconst(ir.argtypes[i+1]) |
| 18 | + end |
| 19 | + if isva |
| 20 | + lastarg = pop!(argtypes) |
| 21 | + if lastarg <: Tuple |
| 22 | + append!(argtypes, lastarg.parameters) |
| 23 | + else |
| 24 | + push!(argtypes, Vararg{Any}) |
| 25 | + end |
| 26 | + end |
| 27 | + return Tuple{argtypes...} |
| 28 | +end |
| 29 | + |
| 30 | +function Core.OpaqueClosure(ir::IRCode, @nospecialize env...; |
| 31 | + isva::Bool = false, |
| 32 | + slotnames::Union{Nothing,Vector{Symbol}}=nothing, |
| 33 | + kwargs...) |
| 34 | + # NOTE: we need ir.argtypes[1] == typeof(env) |
| 35 | + ir = Core.Compiler.copy(ir) |
| 36 | + # if the user didn't specify a definition MethodInstance or filename Symbol to use for the debuginfo, set a filename now |
| 37 | + ir.debuginfo.def === nothing && (ir.debuginfo.def = :var"generated IR for OpaqueClosure") |
| 38 | + nargtypes = length(ir.argtypes) |
| 39 | + nargs = nargtypes-1 |
| 40 | + sig = compute_oc_signature(ir, nargs, isva) |
| 41 | + rt = compute_ir_rettype(ir) |
| 42 | + src = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ()) |
| 43 | + if slotnames === nothing |
| 44 | + src.slotnames = fill(:none, nargtypes) |
| 45 | + else |
| 46 | + length(slotnames) == nargtypes || error("mismatched `argtypes` and `slotnames`") |
| 47 | + src.slotnames = slotnames |
| 48 | + end |
| 49 | + src.slotflags = fill(zero(UInt8), nargtypes) |
| 50 | + src.slottypes = copy(ir.argtypes) |
| 51 | + src.isva = isva |
| 52 | + src.nargs = UInt(nargtypes) |
| 53 | + src = ir_to_codeinf!(src, ir) |
| 54 | + src.rettype = rt |
| 55 | + return Base.Experimental.generate_opaque_closure(sig, Union{}, rt, src, nargs, isva, env...; kwargs...) |
| 56 | +end |
0 commit comments