From b2d414391a6cf361b6e2cb1ad32785e669121b9d Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 12 Mar 2015 01:45:37 +0000 Subject: [PATCH] Make llvm.eh.actions an intrinsic and add docs for it These docs *don't* match the way WinEHPrepare uses them yet, and verifier support isn't implemented either. The implementation will come after the documentation text is reviewed and agreed upon. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232003 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ExceptionHandling.rst | 41 +++++++++++++++++++++++++++++++++++++++++ include/llvm/IR/Intrinsics.td | 3 +++ lib/CodeGen/WinEHPrepare.cpp | 8 +++----- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/docs/ExceptionHandling.rst b/docs/ExceptionHandling.rst index bf93fdaaaf4..ee157d096a2 100644 --- a/docs/ExceptionHandling.rst +++ b/docs/ExceptionHandling.rst @@ -498,6 +498,47 @@ When used in the native Windows C++ exception handling implementation, this 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.actions: + +``llvm.eh.actions`` +---------------------- + +.. code-block:: llvm + + void @llvm.eh.actions() + +This intrinsic represents the list of actions to take when an exception is +thrown. It is typically used by Windows exception handling schemes where cleanup +outlining is required by the runtime. The arguments are a sequence of ``i32`` +sentinels indicating the action type followed by some pre-determined number of +arguments required to implement that action. + +A code of ``i32 0`` indicates a cleanup action, which expects one additional +argument. The argument is a pointer to a function that implements the cleanup +action. + +A code of ``i32 1`` indicates a catch action, which expects three additional +arguments. Different EH schemes give different meanings to the three arguments, +but the first argument indicates whether the catch should fire, the second is a +pointer to stack object where the exception object should be stored, and the +third is the code to run to catch the exception. + +For Windows C++ exception handling, the first argument for a catch handler is a +pointer to the RTTI type descriptor for the object to catch. The third argument +is a pointer to a function implementing the catch. This function returns the +address of the basic block where execution should resume after handling the +exception. + +For Windows SEH, the first argument is a pointer to the filter function, which +indicates if the exception should be caught or not. The second argument is +typically null. The third argument is the address of a basic block where the +exception will be handled. In other words, catch handlers are not outlined in +SEH. After running cleanups, execution immediately resumes at this PC. + +In order to preserve the structure of the CFG, a call to '``llvm.eh.actions``' +must be followed by an ':ref:`indirectbr `' instruction that jumps +to the result of the intrinsic call. + SJLJ Intrinsics --------------- diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index bd7f42e6bd9..110d6b22e8a 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -418,6 +418,9 @@ def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [NoCapture<0>, NoCapture<1>]>; def int_eh_endcatch : Intrinsic<[], []>; +// Represents the list of actions to take when an exception is thrown. +def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index bc3cc6b9b85..f68189af399 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -383,12 +383,10 @@ bool WinEHPrepare::prepareCPPEHHandlers( Module *M = F.getParent(); LLVMContext &Context = M->getContext(); - // FIXME: Make this an intrinsic. // Create a new function to receive the handler contents. PointerType *Int8PtrType = Type::getInt8PtrTy(Context); Type *Int32Type = Type::getInt32Ty(Context); - FunctionType *ActionTy = FunctionType::get(Int8PtrType, true); - Value *ActionIntrin = M->getOrInsertFunction("llvm.eh.actions", ActionTy); + Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions); for (LandingPadInst *LPad : LPads) { // Look for evidence that this landingpad has already been processed. @@ -396,8 +394,8 @@ bool WinEHPrepare::prepareCPPEHHandlers( BasicBlock *LPadBB = LPad->getParent(); for (Instruction &Inst : LPadBB->getInstList()) { // FIXME: Make this an intrinsic. - if (auto *Call = dyn_cast(&Inst)) { - if (Call->getCalledFunction()->getName() == "llvm.eh.actions") { + if (auto *IntrinCall = dyn_cast(&Inst)) { + if (IntrinCall->getIntrinsicID() == Intrinsic::eh_actions) { LPadHasActionList = true; break; } -- 2.11.0