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

InteractiveUtils: make code_llvm default atype work with no-arg functions #42496

Merged
merged 2 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
make default types work for any function with one method
  • Loading branch information
aviatesk committed Oct 5, 2021
commit 0f2d0e243edc185e0b34545e980de99e9d363584
18 changes: 15 additions & 3 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ additional optimizations, such as inlining, are also applied.
The keyword `debuginfo` controls the amount of code metadata present in the output,
possible options are `:source` or `:none`.
"""
function code_typed(@nospecialize(f), @nospecialize(types=Tuple);
function code_typed(@nospecialize(f), @nospecialize(types=default_tt(f));
optimize=true,
debuginfo::Symbol=:default,
world = get_world_counter(),
Expand All @@ -1181,6 +1181,18 @@ function code_typed(@nospecialize(f), @nospecialize(types=Tuple);
return code_typed_by_type(tt; optimize, debuginfo, world, interp)
end

# returns argument tuple type which is supposed to be used for `code_typed` and its family;
# if there is a single method this functions returns the method argument signature,
# otherwise returns `Tuple` that doesn't match with any signature
function default_tt(@nospecialize(f))
ms = methods(f)
if length(ms) == 1
return tuple_type_tail(only(ms).sig)
else
return Tuple
end
end

"""
code_typed_by_type(types::Type{<:Tuple}; ...)

Expand Down Expand Up @@ -1218,7 +1230,7 @@ function code_typed_by_type(@nospecialize(tt::Type);
return asts
end

function code_typed_opaque_closure(@nospecialize(closure::Core.OpaqueClosure), @nospecialize(types=Tuple{});
function code_typed_opaque_closure(@nospecialize(closure::Core.OpaqueClosure);
optimize=true,
debuginfo::Symbol=:default,
interp = Core.Compiler.NativeInterpreter(closure.world))
Expand All @@ -1232,7 +1244,7 @@ function code_typed_opaque_closure(@nospecialize(closure::Core.OpaqueClosure), @
end
end

function return_types(@nospecialize(f), @nospecialize(types=Tuple), interp=Core.Compiler.NativeInterpreter())
function return_types(@nospecialize(f), @nospecialize(types=default_tt(f)), interp=Core.Compiler.NativeInterpreter())
ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
if isa(f, Core.Builtin)
throw(ArgumentError("argument is not a generic function"))
Expand Down
12 changes: 6 additions & 6 deletions stdlib/InteractiveUtils/src/codeview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Keyword argument `debuginfo` may be one of `:source` or `:none` (default), to sp

See [`@code_warntype`](@ref man-code-warntype) for more information.
"""
function code_warntype(io::IO, @nospecialize(f), @nospecialize(t);
function code_warntype(io::IO, @nospecialize(f), @nospecialize(t=Base.default_tt(f));
debuginfo::Symbol=:default, optimize::Bool=false, kwargs...)
debuginfo = Base.IRShow.debuginfo(debuginfo)
lineprinter = Base.IRShow.__debuginfo[debuginfo]
Expand Down Expand Up @@ -134,7 +134,7 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(t);
end
nothing
end
code_warntype(@nospecialize(f), @nospecialize(t); kwargs...) =
code_warntype(@nospecialize(f), @nospecialize(t=Base.default_tt(f)); kwargs...) =
code_warntype(stdout, f, t; kwargs...)

import Base.CodegenParams
Expand Down Expand Up @@ -224,9 +224,9 @@ function code_llvm(io::IO, @nospecialize(f), @nospecialize(types), raw::Bool,
print(io, d)
end
end
code_llvm(io::IO, @nospecialize(f), @nospecialize(types=Tuple{}); raw::Bool=false, dump_module::Bool=false, optimize::Bool=true, debuginfo::Symbol=:default) =
code_llvm(io::IO, @nospecialize(f), @nospecialize(types=Base.default_tt(f)); raw::Bool=false, dump_module::Bool=false, optimize::Bool=true, debuginfo::Symbol=:default) =
code_llvm(io, f, types, raw, dump_module, optimize, debuginfo)
code_llvm(@nospecialize(f), @nospecialize(types=Tuple{}); raw=false, dump_module=false, optimize=true, debuginfo::Symbol=:default) =
code_llvm(@nospecialize(f), @nospecialize(types=Base.default_tt(f)); raw=false, dump_module=false, optimize=true, debuginfo::Symbol=:default) =
code_llvm(stdout, f, types; raw, dump_module, optimize, debuginfo)

"""
Expand All @@ -238,7 +238,7 @@ Switch assembly syntax using `syntax` symbol parameter set to `:att` for AT&T sy
Keyword argument `debuginfo` may be one of source (default) or none, to specify the verbosity of code comments.
If `binary` is `true`, it also prints the binary machine code for each instruction precedented by an abbreviated address.
"""
function code_native(io::IO, @nospecialize(f), @nospecialize(types=Tuple{});
function code_native(io::IO, @nospecialize(f), @nospecialize(types=Base.default_tt(f));
dump_module::Bool=true, syntax::Symbol=:att, debuginfo::Symbol=:default, binary::Bool=false)
d = _dump_function(f, types, true, false, false, dump_module, syntax, true, debuginfo, binary)
if highlighting[:native] && get(io, :color, false)
Expand All @@ -247,7 +247,7 @@ function code_native(io::IO, @nospecialize(f), @nospecialize(types=Tuple{});
print(io, d)
end
end
code_native(@nospecialize(f), @nospecialize(types=Tuple{}); dump_module::Bool=true, syntax::Symbol=:att, debuginfo::Symbol=:default, binary::Bool=false) =
code_native(@nospecialize(f), @nospecialize(types=Base.default_tt(f)); dump_module::Bool=true, syntax::Symbol=:att, debuginfo::Symbol=:default, binary::Bool=false) =
code_native(stdout, f, types; dump_module, syntax, debuginfo, binary)
code_native(::IO, ::Any, ::Symbol) = error("invalid code_native call") # resolve ambiguous call

Expand Down
22 changes: 17 additions & 5 deletions stdlib/InteractiveUtils/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -625,11 +625,23 @@ end
end
end

let # default arg types should work for no-arg functions
@test (code_llvm() do
let # `default_tt` should work with any function with one method
@test (code_warntype(devnull, function ()
sin(42)
end; true)
@test (code_native() do
end); true)
@test (code_warntype(devnull, function (a::Int)
sin(a)
end); true)
@test (code_llvm(devnull, function ()
sin(42)
end; true)
end); true)
@test (code_llvm(devnull, function (a::Int)
sin(a)
end); true)
@test (code_native(devnull, function ()
sin(42)
end); true)
@test (code_native(devnull, function (a::Int)
sin(a)
end); true)
end
13 changes: 13 additions & 0 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -952,3 +952,16 @@ end
@test only(code_typed(mod.foo, (); world=world1)).second == Int
@test only(code_typed(mod.foo, (); world=world2)).second == Float64
end

@testset "default_tt" begin
m = Module()
@eval m f1() = return
@test Base.default_tt(m.f1) == Tuple{}
@eval m f2(a) = return
@test Base.default_tt(m.f2) == Tuple{Any}
@eval m f3(a::Integer) = return
@test Base.default_tt(m.f3) == Tuple{Integer}
@eval m f4() = return
@eval m f4(a) = return
@test Base.default_tt(m.f4) == Tuple
end