@@ -20,6 +20,28 @@ const llstyle = Dict{Symbol, Tuple{Bool, Union{Symbol, Int}}}(
2020 :funcname => (false , :light_yellow ),
2121)
2222
23+ struct ArgInfo
24+ oc:: Union{Core.OpaqueClosure,Nothing}
25+ tt:: Type{<:Tuple}
26+
27+ # Construct from a function object + argtypes
28+ function ArgInfo (@nospecialize (f), @nospecialize (t))
29+ if isa (f, Core. Builtin)
30+ throw (ArgumentError (" argument is not a generic function" ))
31+ elseif f isa Core. OpaqueClosure
32+ return new (f, Base. to_tuple_type (t))
33+ else
34+ return new (nothing , signature_type (f, t))
35+ end
36+ end
37+
38+ # Construct from argtypes (incl. arg0)
39+ function ArgInfo (@nospecialize (argtypes:: Union{Tuple,Type{<:Tuple}} ))
40+ tt = Base. to_tuple_type (argtypes)
41+ return new (nothing , tt)
42+ end
43+ end
44+
2345function printstyled_ll (io:: IO , x, s:: Symbol , trailing_spaces= " " )
2446 printstyled (io, x, bold= llstyle[s][1 ], color= llstyle[s][2 ])
2547 print (io, trailing_spaces)
@@ -143,7 +165,7 @@ See the [`@code_warntype`](@ref man-code-warntype) section in the Performance Ti
143165
144166See also: [`@code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_llvm`](@ref), [`code_native`](@ref).
145167"""
146- function code_warntype (io:: IO , @nospecialize (f), @nospecialize (tt = Base . default_tt (f)) ;
168+ function code_warntype (io:: IO , arginfo :: ArgInfo ;
147169 world= Base. get_world_counter (),
148170 interp:: Base.Compiler.AbstractInterpreter = Base. Compiler. NativeInterpreter (world),
149171 debuginfo:: Symbol = :default , optimize:: Bool = false , kwargs... )
@@ -152,13 +174,14 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(tt=Base.default_t
152174 debuginfo = Base. IRShow. debuginfo (debuginfo)
153175 lineprinter = Base. IRShow. __debuginfo[debuginfo]
154176 nargs:: Int = 0
155- if isa (f, Core. OpaqueClosure)
156- isa (f. source, Method) && (nargs = f. source. nargs)
157- print_warntype_codeinfo (io, Base. code_typed_opaque_closure (f, tt)[1 ]. .. , nargs;
177+ if arginfo. oc != = nothing
178+ (; oc, tt) = arginfo
179+ isa (oc. source, Method) && (nargs = oc. source. nargs)
180+ print_warntype_codeinfo (io, Base. code_typed_opaque_closure (oc, tt)[1 ]. .. , nargs;
158181 lineprinter, label_dynamic_calls = optimize)
159182 return nothing
160183 end
161- tt = Base . signature_type (f, tt)
184+ tt = arginfo . tt
162185 matches = findall (tt, Base. Compiler. method_table (interp))
163186 matches === nothing && Base. raise_match_failure (:code_warntype , tt)
164187 for match in matches. matches
@@ -176,6 +199,8 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(tt=Base.default_t
176199 end
177200 nothing
178201end
202+ code_warntype (io:: IO , @nospecialize (f), @nospecialize (tt= Base. default_tt (f)); kwargs... ) = code_warntype (io, ArgInfo (f, tt); kwargs... )
203+ code_warntype (io:: IO , @nospecialize (argtypes:: Union{Tuple,Type{<:Tuple}} ); kwargs... ) = code_warntype (io, ArgInfo (argtypes); kwargs... )
179204code_warntype (args... ; kwargs... ) = (@nospecialize ; code_warntype (stdout , args... ; kwargs... ))
180205
181206using Base: CodegenParams
@@ -189,33 +214,30 @@ const OC_MISMATCH_WARNING =
189214
190215# Printing code representations in IR and assembly
191216
192- function _dump_function (@nospecialize (f), @nospecialize (t) , native:: Bool , wrapper:: Bool ,
217+ function _dump_function (arginfo :: ArgInfo , native:: Bool , wrapper:: Bool ,
193218 raw:: Bool , dump_module:: Bool , syntax:: Symbol ,
194219 optimize:: Bool , debuginfo:: Symbol , binary:: Bool ,
195220 params:: CodegenParams = CodegenParams (debug_info_kind= Cint (0 ), debug_info_level= Cint (2 ), safepoint_on_entry= raw, gcstack_arg= raw))
196221 ccall (:jl_is_in_pure_context , Bool, ()) && error (" code reflection cannot be used from generated functions" )
197- if isa (f, Core. Builtin)
198- throw (ArgumentError (" argument is not a generic function" ))
199- end
200222 warning = " "
201223 # get the MethodInstance for the method match
202- if ! isa (f, Core . OpaqueClosure)
224+ if arginfo . oc === nothing
203225 world = Base. get_world_counter ()
204- match = Base. _which (signature_type (f, t) ; world)
226+ match = Base. _which (arginfo . tt ; world)
205227 mi = Base. specialize_method (match)
206228 # TODO : use jl_is_cacheable_sig instead of isdispatchtuple
207229 isdispatchtuple (mi. specTypes) || (warning = GENERIC_SIG_WARNING)
208230 else
209- world = UInt64 (f . world)
210- tt = Base . to_tuple_type (t )
211- if ! isdefined (f . source, :source )
231+ (; oc, tt) = arginfo
232+ world = UInt64 (oc . world )
233+ if ! isdefined (oc . source, :source )
212234 # OC was constructed from inferred source. There's only one
213235 # specialization and we can't infer anything more precise either.
214- world = f . source. primary_world
215- mi = f . source. specializations:: Core.MethodInstance
216- Base. hasintersect (typeof (f ). parameters[1 ], tt) || (warning = OC_MISMATCH_WARNING)
236+ world = oc . source. primary_world
237+ mi = oc . source. specializations:: Core.MethodInstance
238+ Base. hasintersect (typeof (oc ). parameters[1 ], tt) || (warning = OC_MISMATCH_WARNING)
217239 else
218- mi = Base. specialize_method (f . source, Tuple{typeof (f . captures), tt. parameters... }, Core. svec ())
240+ mi = Base. specialize_method (oc . source, Tuple{typeof (oc . captures), tt. parameters... }, Core. svec ())
219241 isdispatchtuple (mi. specTypes) || (warning = GENERIC_SIG_WARNING)
220242 end
221243 end
@@ -236,19 +258,19 @@ function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrappe
236258 end
237259 if isempty (str)
238260 # if that failed (or we want metadata), use LLVM to generate more accurate assembly output
239- if ! isa (f, Core . OpaqueClosure)
261+ if arginfo . oc === nothing
240262 src = Base. Compiler. typeinf_code (Base. Compiler. NativeInterpreter (world), mi, true )
241263 else
242- src, rt = Base. get_oc_code_rt (nothing , f, tt, true )
264+ src, rt = Base. get_oc_code_rt (nothing , arginfo . oc, arginfo . tt, true )
243265 end
244266 src isa Core. CodeInfo || error (" failed to infer source for $mi " )
245267 str = _dump_function_native_assembly (mi, src, wrapper, syntax, debuginfo, binary, raw, params)
246268 end
247269 else
248- if ! isa (f, Core . OpaqueClosure)
270+ if arginfo . oc === nothing
249271 src = Base. Compiler. typeinf_code (Base. Compiler. NativeInterpreter (world), mi, true )
250272 else
251- src, rt = Base. get_oc_code_rt (nothing , f, tt, true )
273+ src, rt = Base. get_oc_code_rt (nothing , arginfo . oc, arginfo . tt, true )
252274 end
253275 src isa Core. CodeInfo || error (" failed to infer source for $mi " )
254276 str = _dump_function_llvm (mi, src, wrapper, ! raw, dump_module, optimize, debuginfo, params)
@@ -311,16 +333,18 @@ Keyword argument `debuginfo` may be one of source (default) or none, to specify
311333
312334See also: [`@code_llvm`](@ref), [`code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_native`](@ref).
313335"""
314- function code_llvm (io:: IO , @nospecialize (f), @nospecialize (types = Base . default_tt (f)) ;
336+ function code_llvm (io:: IO , arginfo :: ArgInfo ;
315337 raw:: Bool = false , dump_module:: Bool = false , optimize:: Bool = true , debuginfo:: Symbol = :default ,
316338 params:: CodegenParams = CodegenParams (debug_info_kind= Cint (0 ), debug_info_level= Cint (2 ), safepoint_on_entry= raw, gcstack_arg= raw))
317- d = _dump_function (f, types , false , false , raw, dump_module, :intel , optimize, debuginfo, false , params)
339+ d = _dump_function (arginfo , false , false , raw, dump_module, :intel , optimize, debuginfo, false , params)
318340 if highlighting[:llvm ] && get (io, :color , false ):: Bool
319341 print_llvm (io, d)
320342 else
321343 print (io, d)
322344 end
323345end
346+ code_llvm (io:: IO , @nospecialize (argtypes:: Union{Tuple,Type{<:Tuple}} ); kwargs... ) = code_llvm (io, ArgInfo (argtypes); kwargs... )
347+ code_llvm (io:: IO , @nospecialize (f), @nospecialize (types= Base. default_tt (f)); kwargs... ) = code_llvm (io, ArgInfo (f, types); kwargs... )
324348code_llvm (args... ; kwargs... ) = (@nospecialize ; code_llvm (stdout , args... ; kwargs... ))
325349
326350"""
@@ -337,17 +361,19 @@ generic function and type signature to `io`.
337361
338362See also: [`@code_native`](@ref), [`code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_llvm`](@ref).
339363"""
340- function code_native (io:: IO , @nospecialize (f), @nospecialize (types = Base . default_tt (f)) ;
364+ function code_native (io:: IO , arginfo :: ArgInfo ;
341365 dump_module:: Bool = true , syntax:: Symbol = :intel , raw:: Bool = false ,
342366 debuginfo:: Symbol = :default , binary:: Bool = false ,
343367 params:: CodegenParams = CodegenParams (debug_info_kind= Cint (0 ), debug_info_level= Cint (2 ), safepoint_on_entry= raw, gcstack_arg= raw))
344- d = _dump_function (f, types , true , false , raw, dump_module, syntax, true , debuginfo, binary, params)
368+ d = _dump_function (arginfo , true , false , raw, dump_module, syntax, true , debuginfo, binary, params)
345369 if highlighting[:native ] && get (io, :color , false ):: Bool
346370 print_native (io, d)
347371 else
348372 print (io, d)
349373 end
350374end
375+ code_native (io:: IO , @nospecialize (argtypes:: Union{Tuple,Type{<:Tuple}} ); kwargs... ) = code_native (io, ArgInfo (argtypes); kwargs... )
376+ code_native (io:: IO , @nospecialize (f), @nospecialize (types= Base. default_tt (f)); kwargs... ) = code_native (io, ArgInfo (f, types); kwargs... )
351377code_native (args... ; kwargs... ) = (@nospecialize ; code_native (stdout , args... ; kwargs... ))
352378
353379# # colorized IR and assembly printing
0 commit comments