[WinEH] Add llvm.eh.exceptionpointer intrinsic
authorJoseph Tremoulet <jotrem@microsoft.com>
Thu, 3 Sep 2015 09:15:32 +0000 (09:15 +0000)
committerJoseph Tremoulet <jotrem@microsoft.com>
Thu, 3 Sep 2015 09:15:32 +0000 (09:15 +0000)
Summary:
This intrinsic can be used to extract a pointer to the exception caught by
a given catchpad.  Its argument has token type and must be a `catchpad`.

Also clarify ExtendingLLVM documentation regarding overloaded intrinsics.

Reviewers: majnemer, andrew.w.kaylor, sanjoy, rnk

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D12533

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246752 91177308-0d34-0410-b5e6-96231b3b80d8

docs/ExceptionHandling.rst
docs/ExtendingLLVM.rst
include/llvm/IR/Intrinsics.td
lib/IR/Verifier.cpp
test/CodeGen/WinEH/wineh-intrinsics-invalid.ll [new file with mode: 0644]
test/CodeGen/WinEH/wineh-intrinsics.ll [new file with mode: 0644]

index 2f09155dff2f3b8fbc0e716ac7f30f70eb505ea1..71efa4bbd531b5e8eb134edce462637f4638d5a8 100644 (file)
@@ -401,6 +401,20 @@ intrinsic serves as a placeholder to delimit code before a catch handler is
 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 3fd54c8360e551931cb68df55c87373f9f070110..87f48c9934257d2aaa499dfe762ca3f550f6292b 100644 (file)
@@ -49,9 +49,9 @@ function and then be turned into an instruction if warranted.
 
    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 31d7c9075f1bd2166852558d01c2ab1828e88413..8c74b1b12e7ea99f69996f866c88b730ed3d38e5 100644 (file)
@@ -436,6 +436,11 @@ def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
                                   [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 44158afeb0707b32006367118bf58dfdc89f56a2..a3808e4ff3a8be68b3bec34664895eaeeb7e0efc 100644 (file)
@@ -3681,6 +3681,11 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
            "gc.relocate: relocating a pointer shouldn't change its address space", CS);
     break;
   }
+  case Intrinsic::eh_exceptionpointer: {
+    Assert(isa<CatchPadInst>(CS.getArgOperand(0)),
+           "eh.exceptionpointer argument must be a catchpad", CS);
+    break;
+  }
   };
 }
 
diff --git a/test/CodeGen/WinEH/wineh-intrinsics-invalid.ll b/test/CodeGen/WinEH/wineh-intrinsics-invalid.ll
new file mode 100644 (file)
index 0000000..17d6e70
--- /dev/null
@@ -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(...)
diff --git a/test/CodeGen/WinEH/wineh-intrinsics.ll b/test/CodeGen/WinEH/wineh-intrinsics.ll
new file mode 100644 (file)
index 0000000..acdeb79
--- /dev/null
@@ -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(...)