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
This commit is contained in:
Reid Kleckner 2015-03-12 01:45:37 +00:00
parent e4a40f7a1c
commit b2d414391a
3 changed files with 47 additions and 5 deletions

View File

@ -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 <i_indirectbr>`' instruction that jumps
to the result of the intrinsic call.
SJLJ Intrinsics
---------------

View File

@ -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.

View File

@ -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<CallInst>(&Inst)) {
if (Call->getCalledFunction()->getName() == "llvm.eh.actions") {
if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Inst)) {
if (IntrinCall->getIntrinsicID() == Intrinsic::eh_actions) {
LPadHasActionList = true;
break;
}