Index: docs/ExceptionHandling.rst =================================================================== --- docs/ExceptionHandling.rst +++ docs/ExceptionHandling.rst @@ -401,6 +401,20 @@ outlined. After the handler is outlined, this intrinsic is simply removed. +.. _llvm.eh.exceptionpointer: + +``llvm.eh.exceptionpointer`` +---------------------- + +.. code-block:: llvm + + i8 addrspace(N)* @llvm.eh.padparam.pNi8(token %catchpad) + + +This intrinsic retrieves a pointer to the exception caught by the given +``catchpad``. + + SJLJ Intrinsics --------------- Index: docs/ExtendingLLVM.rst =================================================================== --- docs/ExtendingLLVM.rst +++ docs/ExtendingLLVM.rst @@ -49,9 +49,9 @@ Add an entry for your intrinsic. Describe its memory access characteristics for optimization (this controls whether it will be DCE'd, CSE'd, etc). Note - that any intrinsic using the ``llvm_int_ty`` type for an argument will - be deemed by ``tblgen`` as overloaded and the corresponding suffix will - be required on the intrinsic's name. + that any intrinsic using one of the ``llvm_any*_ty`` types for an argument or + return type will be deemed by ``tblgen`` as overloaded and the corresponding + suffix will be required on the intrinsic's name. #. ``llvm/lib/Analysis/ConstantFolding.cpp``: Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -436,6 +436,11 @@ [NoCapture<0>, NoCapture<1>]>; def int_eh_endcatch : Intrinsic<[], []>; +// eh.exceptionpointer returns the pointer to the exception caught by +// the given `catchpad`. +def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty], + [IntrNoMem]>; + // Represents the list of actions to take when an exception is thrown. def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -3643,6 +3643,11 @@ "gc.relocate: relocating a pointer shouldn't change its address space", CS); break; } + case Intrinsic::eh_exceptionpointer: { + Assert(isa(CS.getArgOperand(0)), + "eh.exceptionpointer argument must be a catchpad", CS); + break; + } }; } Index: test/CodeGen/WinEH/wineh-intrinsics-invalid.ll =================================================================== --- /dev/null +++ test/CodeGen/WinEH/wineh-intrinsics-invalid.ll @@ -0,0 +1,26 @@ +; RUN: sed -e s/.T1:// %s | not opt -lint -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s +; RUN: sed -e s/.T2:// %s | not opt -lint -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s + +target triple = "x86_64-pc-windows-msvc" + +declare void @f() + +;T1: declare i8* @llvm.eh.exceptionpointer.p0i8(i32) +;T1: +;T1: define void @test1() personality i32 (...)* @__CxxFrameHandler3 { +;T1: call i8* @llvm.eh.exceptionpointer.p0i8(i32 0) +;T1: ret void +;T1: } +;CHECK1: Intrinsic has incorrect argument type! +;CHECK1-NEXT: i8* (i32)* @llvm.eh.exceptionpointer.p0i8 + +;T2: declare i8* @llvm.eh.exceptionpointer.p0i8(token) +;T2: +;T2: define void @test2() personality i32 (...)* @__CxxFrameHandler3 { +;T2: call i8* @llvm.eh.exceptionpointer.p0i8(token undef) +;T2: ret void +;T2: } +;CHECK2: eh.exceptionpointer argument must be a catchpad +;CHECK2-NEXT: call i8* @llvm.eh.exceptionpointer.p0i8(token undef) + +declare i32 @__CxxFrameHandler3(...) Index: test/CodeGen/WinEH/wineh-intrinsics.ll =================================================================== --- /dev/null +++ test/CodeGen/WinEH/wineh-intrinsics.ll @@ -0,0 +1,46 @@ +; RUN: opt -lint -disable-output < %s + +; This test is meant to prove that the verifier does not report errors for correct +; use of the llvm.eh.exceptionpointer intrinsic. + +target triple = "x86_64-pc-windows-msvc" + +declare i8* @llvm.eh.exceptionpointer.p0i8(token) +declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token) + +declare void @f(...) + +define void @test1() personality i32 (...)* @__CxxFrameHandler3 { +entry: + invoke void (...) @f(i32 1) + to label %exit unwind label %catchpad +catchpad: + %catch = catchpad [i32 1] to label %do_catch unwind label %catchend +do_catch: + %exn = call i8* @llvm.eh.exceptionpointer.p0i8(token %catch) + call void (...) @f(i8* %exn) + catchret %catch to label %exit +catchend: + catchendpad unwind to caller +exit: + ret void +} + +define void @test2() personality i32 (...)* @ProcessManagedException { +entry: + invoke void (...) @f(i32 1) + to label %exit unwind label %catchpad +catchpad: + %catch = catchpad [i32 1] to label %do_catch unwind label %catchend +do_catch: + %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch) + call void (...) @f(i8 addrspace(1)* %exn) + catchret %catch to label %exit +catchend: + catchendpad unwind to caller +exit: + ret void +} + +declare i32 @__CxxFrameHandler3(...) +declare i32 @ProcessManagedException(...)