@@ -20,6 +20,28 @@ const llstyle = Dict{Symbol, Tuple{Bool, Union{Symbol, Int}}}(
20
20
:funcname => (false , :light_yellow ),
21
21
)
22
22
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
+
23
45
function printstyled_ll (io:: IO , x, s:: Symbol , trailing_spaces= " " )
24
46
printstyled (io, x, bold= llstyle[s][1 ], color= llstyle[s][2 ])
25
47
print (io, trailing_spaces)
@@ -143,7 +165,7 @@ See the [`@code_warntype`](@ref man-code-warntype) section in the Performance Ti
143
165
144
166
See also: [`@code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_llvm`](@ref), [`code_native`](@ref).
145
167
"""
146
- function code_warntype (io:: IO , @nospecialize (f), @nospecialize (tt = Base . default_tt (f)) ;
168
+ function code_warntype (io:: IO , arginfo :: ArgInfo ;
147
169
world= Base. get_world_counter (),
148
170
interp:: Base.Compiler.AbstractInterpreter = Base. Compiler. NativeInterpreter (world),
149
171
debuginfo:: Symbol = :default , optimize:: Bool = false , kwargs... )
@@ -152,13 +174,14 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(tt=Base.default_t
152
174
debuginfo = Base. IRShow. debuginfo (debuginfo)
153
175
lineprinter = Base. IRShow. __debuginfo[debuginfo]
154
176
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;
158
181
lineprinter, label_dynamic_calls = optimize)
159
182
return nothing
160
183
end
161
- tt = Base . signature_type (f, tt)
184
+ tt = arginfo . tt
162
185
matches = findall (tt, Base. Compiler. method_table (interp))
163
186
matches === nothing && Base. raise_match_failure (:code_warntype , tt)
164
187
for match in matches. matches
@@ -176,6 +199,8 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(tt=Base.default_t
176
199
end
177
200
nothing
178
201
end
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... )
179
204
code_warntype (args... ; kwargs... ) = (@nospecialize ; code_warntype (stdout , args... ; kwargs... ))
180
205
181
206
using Base: CodegenParams
@@ -189,33 +214,30 @@ const OC_MISMATCH_WARNING =
189
214
190
215
# Printing code representations in IR and assembly
191
216
192
- function _dump_function (@nospecialize (f), @nospecialize (t) , native:: Bool , wrapper:: Bool ,
217
+ function _dump_function (arginfo :: ArgInfo , native:: Bool , wrapper:: Bool ,
193
218
raw:: Bool , dump_module:: Bool , syntax:: Symbol ,
194
219
optimize:: Bool , debuginfo:: Symbol , binary:: Bool ,
195
220
params:: CodegenParams = CodegenParams (debug_info_kind= Cint (0 ), debug_info_level= Cint (2 ), safepoint_on_entry= raw, gcstack_arg= raw))
196
221
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
200
222
warning = " "
201
223
# get the MethodInstance for the method match
202
- if ! isa (f, Core . OpaqueClosure)
224
+ if arginfo . oc === nothing
203
225
world = Base. get_world_counter ()
204
- match = Base. _which (signature_type (f, t) ; world)
226
+ match = Base. _which (arginfo . tt ; world)
205
227
mi = Base. specialize_method (match)
206
228
# TODO : use jl_is_cacheable_sig instead of isdispatchtuple
207
229
isdispatchtuple (mi. specTypes) || (warning = GENERIC_SIG_WARNING)
208
230
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 )
212
234
# OC was constructed from inferred source. There's only one
213
235
# 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)
217
239
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 ())
219
241
isdispatchtuple (mi. specTypes) || (warning = GENERIC_SIG_WARNING)
220
242
end
221
243
end
@@ -236,19 +258,19 @@ function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrappe
236
258
end
237
259
if isempty (str)
238
260
# 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
240
262
src = Base. Compiler. typeinf_code (Base. Compiler. NativeInterpreter (world), mi, true )
241
263
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 )
243
265
end
244
266
src isa Core. CodeInfo || error (" failed to infer source for $mi " )
245
267
str = _dump_function_native_assembly (mi, src, wrapper, syntax, debuginfo, binary, raw, params)
246
268
end
247
269
else
248
- if ! isa (f, Core . OpaqueClosure)
270
+ if arginfo . oc === nothing
249
271
src = Base. Compiler. typeinf_code (Base. Compiler. NativeInterpreter (world), mi, true )
250
272
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 )
252
274
end
253
275
src isa Core. CodeInfo || error (" failed to infer source for $mi " )
254
276
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
311
333
312
334
See also: [`@code_llvm`](@ref), [`code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_native`](@ref).
313
335
"""
314
- function code_llvm (io:: IO , @nospecialize (f), @nospecialize (types = Base . default_tt (f)) ;
336
+ function code_llvm (io:: IO , arginfo :: ArgInfo ;
315
337
raw:: Bool = false , dump_module:: Bool = false , optimize:: Bool = true , debuginfo:: Symbol = :default ,
316
338
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)
318
340
if highlighting[:llvm ] && get (io, :color , false ):: Bool
319
341
print_llvm (io, d)
320
342
else
321
343
print (io, d)
322
344
end
323
345
end
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... )
324
348
code_llvm (args... ; kwargs... ) = (@nospecialize ; code_llvm (stdout , args... ; kwargs... ))
325
349
326
350
"""
@@ -337,17 +361,19 @@ generic function and type signature to `io`.
337
361
338
362
See also: [`@code_native`](@ref), [`code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_llvm`](@ref).
339
363
"""
340
- function code_native (io:: IO , @nospecialize (f), @nospecialize (types = Base . default_tt (f)) ;
364
+ function code_native (io:: IO , arginfo :: ArgInfo ;
341
365
dump_module:: Bool = true , syntax:: Symbol = :intel , raw:: Bool = false ,
342
366
debuginfo:: Symbol = :default , binary:: Bool = false ,
343
367
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)
345
369
if highlighting[:native ] && get (io, :color , false ):: Bool
346
370
print_native (io, d)
347
371
else
348
372
print (io, d)
349
373
end
350
374
end
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... )
351
377
code_native (args... ; kwargs... ) = (@nospecialize ; code_native (stdout , args... ; kwargs... ))
352
378
353
379
# # colorized IR and assembly printing
0 commit comments