diff --git a/src/error.jl b/src/error.jl index 853df974..ffdf49f1 100644 --- a/src/error.jl +++ b/src/error.jl @@ -25,6 +25,19 @@ end Base.show(io::IO, err::KernelError) = showerror(io, err) +""" + unwrap_error(err) + +Unwrap a compiler exception from container exceptions such as the REPL's `err` global +(a `Base.ExceptionStack`) or the `LoadError` thrown by `include`, so that it can be +passed to reflection functions like `code_typed`. Other exceptions are returned as-is. +""" +unwrap_error(err) = err +unwrap_error(err::Base.ExceptionStack) = + isempty(err.stack) ? err : unwrap_error(last(err.stack).exception) +unwrap_error(err::LoadError) = unwrap_error(err.error) + + struct InternalCompilerError <: Exception job::CompilerJob message::String diff --git a/src/validation.jl b/src/validation.jl index c1a86549..b1f762af 100644 --- a/src/validation.jl +++ b/src/validation.jl @@ -153,7 +153,8 @@ function Base.showerror(io::IO, err::InvalidIRError) printstyled(io, "Hint"; bold = true, color = :cyan) printstyled( io, - ": catch this exception as `err` and call `code_typed(err; interactive = true)` to", + ": catch this exception as `err` and call", + " `code_typed(GPUCompiler.unwrap_error(err); interactive = true)` to", " introspect the erroneous code with Cthulhu.jl"; color = :cyan, ) diff --git a/test/native.jl b/test/native.jl index 6e242de0..b536c3fd 100644 --- a/test/native.jl +++ b/test/native.jl @@ -1,3 +1,5 @@ +using InteractiveUtils + @testset "reflection" begin job, _ = Native.create_job(identity, (Int,)) @@ -622,6 +624,25 @@ end end end +@testset "unwrap_error" begin + mod = @eval module $(gensym()) + foobar(i) = println(i) + end + + stack = try + Native.code_execution(mod.foobar, Tuple{Int}) + nothing + catch + current_exceptions() + end + @test stack isa Base.ExceptionStack + err = GPUCompiler.unwrap_error(stack) + @test err isa GPUCompiler.InvalidIRError + @test GPUCompiler.unwrap_error(err) === err + @test GPUCompiler.unwrap_error(LoadError("foo.jl", 1, err)) === err + @test only(code_typed(GPUCompiler.unwrap_error(stack))) isa Pair +end + @testset "invalid LLVM IR (ccall)" begin mod = @eval module $(gensym()) function foobar(p)