New EH representation for MSVC compatibility

This introduces new instructions neccessary to implement MSVC-compatible
exception handling support.  Most of the middle-end and none of the
back-end haven't been audited or updated to take them into account.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243766 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2015-07-31 17:58:14 +00:00
parent aa50fa7c2f
commit 4a45f0871a
39 changed files with 2313 additions and 121 deletions

View File

@ -4741,7 +4741,12 @@ control flow, not values (the one exception being the
The terminator instructions are: ':ref:`ret <i_ret>`',
':ref:`br <i_br>`', ':ref:`switch <i_switch>`',
':ref:`indirectbr <i_indirectbr>`', ':ref:`invoke <i_invoke>`',
':ref:`resume <i_resume>`', and ':ref:`unreachable <i_unreachable>`'.
':ref:`resume <i_resume>`', ':ref:`catchpad <i_catchpad>`',
':ref:`catchendpad <i_catchendpad>`',
':ref:`catchret <i_catchret>`',
':ref:`cleanupret <i_cleanupret>`',
':ref:`terminatepad <i_terminatepad>`',
and ':ref:`unreachable <i_unreachable>`'.
.. _i_ret:
@ -5095,6 +5100,301 @@ Example:
resume { i8*, i32 } %exn
.. _i_catchpad:
'``catchpad``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
<resultval> = catchpad <resultty> [<args>*]
to label <normal label> unwind label <exception label>
Overview:
"""""""""
The '``catchpad``' instruction is used by `LLVM's exception handling
system <ExceptionHandling.html#overview>`_ to specify that a basic block
is a catch block --- one where a personality routine attempts to transfer
control to catch an exception.
The ``args`` correspond to whatever information the personality
routine requires to know if this is an appropriate place to catch the
exception. Control is tranfered to the ``exception`` label if the
``catchpad`` is not an appropriate handler for the in-flight exception.
The ``normal`` label should contain the code found in the ``catch``
portion of a ``try``/``catch`` sequence. It defines values supplied by
the :ref:`personality function <personalityfn>` upon re-entry to the
function. The ``resultval`` has the type ``resultty``.
Arguments:
""""""""""
The instruction takes a list of arbitrary values which are interpreted
by the :ref:`personality function <personalityfn>`.
The ``catchpad`` must be provided a ``normal`` label to transfer control
to if the ``catchpad`` matches the exception and an ``exception``
label to transfer control to if it doesn't.
Semantics:
""""""""""
The '``catchpad``' instruction defines the values which are set by the
:ref:`personality function <personalityfn>` upon re-entry to the function, and
therefore the "result type" of the ``catchpad`` instruction. As with
calling conventions, how the personality function results are
represented in LLVM IR is target specific.
When the call stack is being unwound due to an exception being thrown,
the exception is compared against the ``args``. If it doesn't match,
then control is transfered to the ``exception`` basic block.
The ``catchpad`` instruction has several restrictions:
- A catch block is a basic block which is the unwind destination of
an exceptional instruction.
- A catch block must have a '``catchpad``' instruction as its
first non-PHI instruction.
- A catch block's ``exception`` edge must refer to a catch block or a
catch-end block.
- There can be only one '``catchpad``' instruction within the
catch block.
- A basic block that is not a catch block may not include a
'``catchpad``' instruction.
- It is undefined behavior for control to transfer from a ``catchpad`` to a
``cleanupret`` without first executing a ``catchret`` and a subsequent
``cleanuppad``.
- It is undefined behavior for control to transfer from a ``catchpad`` to a
``ret`` without first executing a ``catchret``.
Example:
""""""""
.. code-block:: llvm
;; A catch block which can catch an integer.
%res = catchpad { i8*, i32 } [i8** @_ZTIi]
to label %int.handler unwind label %terminate
.. _i_catchendpad:
'``catchendpad``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
catchendpad unwind label <nextaction>
catchendpad unwind to caller
Overview:
"""""""""
The '``catchendpad``' instruction is used by `LLVM's exception handling
system <ExceptionHandling.html#overview>`_ to communicate to the
:ref:`personality function <personalityfn>` which invokes are associated
with a chain of :ref:`catchpad <i_catchpad>` instructions.
The ``nextaction`` label indicates where control should transfer to if
none of the ``catchpad`` instructions are suitable for catching the
in-flight exception.
If a ``nextaction`` label is not present, the instruction unwinds out of
its parent function. The
:ref:`personality function <personalityfn>` will continue processing
exception handling actions in the caller.
Arguments:
""""""""""
The instruction optionally takes a label, ``nextaction``, indicating
where control should transfer to if none of the preceding
``catchpad`` instructions are suitable for the in-flight exception.
Semantics:
""""""""""
When the call stack is being unwound due to an exception being thrown
and none of the constituent ``catchpad`` instructions match, then
control is transfered to ``nextaction`` if it is present. If it is not
present, control is transfered to the caller.
The ``catchendpad`` instruction has several restrictions:
- A catch-end block is a basic block which is the unwind destination of
an exceptional instruction.
- A catch-end block must have a '``catchendpad``' instruction as its
first non-PHI instruction.
- There can be only one '``catchendpad``' instruction within the
catch block.
- A basic block that is not a catch-end block may not include a
'``catchendpad``' instruction.
- Exactly one catch block may unwind to a ``catchendpad``.
- The unwind target of invokes between a ``catchpad`` and a
corresponding ``catchret`` must be its ``catchendpad``.
Example:
""""""""
.. code-block:: llvm
catchendpad unwind label %terminate
catchendpad unwind to caller
.. _i_catchret:
'``catchret``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
catchret label <normal>
Overview:
"""""""""
The '``catchret``' instruction is a terminator instruction that has a
single successor.
Arguments:
""""""""""
The '``catchret``' instruction requires one argument which specifies
where control will transfer to next.
Semantics:
""""""""""
The '``catchret``' instruction ends the existing (in-flight) exception
whose unwinding was interrupted with a
:ref:`catchpad <i_catchpad>` instruction.
The :ref:`personality function <personalityfn>` gets a chance to execute
arbitrary code to, for example, run a C++ destructor.
Control then transfers to ``normal``.
Example:
""""""""
.. code-block:: llvm
catchret label %continue
.. _i_cleanupret:
'``cleanupret``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
cleanupret <type> <value> unwind label <continue>
cleanupret <type> <value> unwind to caller
Overview:
"""""""""
The '``cleanupret``' instruction is a terminator instruction that has
an optional successor.
Arguments:
""""""""""
The '``cleanupret``' instruction requires one argument, which must have the
same type as the result of any '``cleanuppad``' instruction in the same
function. It also has an optional successor, ``continue``.
Semantics:
""""""""""
The '``cleanupret``' instruction indicates to the
:ref:`personality function <personalityfn>` that one
:ref:`cleanuppad <i_cleanuppad>` it transferred control to has ended.
It transfers control to ``continue`` or unwinds out of the function.
Example:
""""""""
.. code-block:: llvm
cleanupret void unwind to caller
cleanupret { i8*, i32 } %exn unwind label %continue
.. _i_terminatepad:
'``terminatepad``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
terminatepad [<args>*] unwind label <exception label>
terminatepad [<args>*] unwind to caller
Overview:
"""""""""
The '``terminatepad``' instruction is used by `LLVM's exception handling
system <ExceptionHandling.html#overview>`_ to specify that a basic block
is a terminate block --- one where a personality routine may decide to
terminate the program.
The ``args`` correspond to whatever information the personality
routine requires to know if this is an appropriate place to terminate the
program. Control is transferred to the ``exception`` label if the
personality routine decides not to terminate the program for the
in-flight exception.
Arguments:
""""""""""
The instruction takes a list of arbitrary values which are interpreted
by the :ref:`personality function <personalityfn>`.
The ``terminatepad`` may be given an ``exception`` label to
transfer control to if the in-flight exception matches the ``args``.
Semantics:
""""""""""
When the call stack is being unwound due to an exception being thrown,
the exception is compared against the ``args``. If it matches,
then control is transfered to the ``exception`` basic block. Otherwise,
the program is terminated via personality-specific means. Typically,
the first argument to ``terminatepad`` specifies what function the
personality should defer to in order to terminate the program.
The ``terminatepad`` instruction has several restrictions:
- A terminate block is a basic block which is the unwind destination of
an exceptional instruction.
- A terminate block must have a '``terminatepad``' instruction as its
first non-PHI instruction.
- There can be only one '``terminatepad``' instruction within the
terminate block.
- A basic block that is not a terminate block may not include a
'``terminatepad``' instruction.
Example:
""""""""
.. code-block:: llvm
;; A terminate block which only permits integers.
terminatepad [i8** @_ZTIi] unwind label %continue
.. _i_unreachable:
'``unreachable``' Instruction
@ -8052,6 +8352,72 @@ Example:
catch i8** @_ZTIi
filter [1 x i8**] [@_ZTId]
.. _i_cleanuppad:
'``cleanuppad``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
<resultval> = cleanuppad <resultty> [<args>*]
Overview:
"""""""""
The '``cleanuppad``' instruction is used by `LLVM's exception handling
system <ExceptionHandling.html#overview>`_ to specify that a basic block
is a cleanup block --- one where a personality routine attempts to
transfer control to run cleanup actions.
The ``args`` correspond to whatever additional
information the :ref:`personality function <personalityfn>` requires to
execute the cleanup.
The ``resultval`` has the type ``resultty``.
Arguments:
""""""""""
The instruction takes a list of arbitrary values which are interpreted
by the :ref:`personality function <personalityfn>`.
Semantics:
""""""""""
The '``cleanuppad``' instruction defines the values which are set by the
:ref:`personality function <personalityfn>` upon re-entry to the function, and
therefore the "result type" of the ``cleanuppad`` instruction. As with
calling conventions, how the personality function results are
represented in LLVM IR is target specific.
When the call stack is being unwound due to an exception being thrown,
the :ref:`personality function <personalityfn>` transfers control to the
``cleanuppad`` with the aid of the personality-specific arguments.
The ``cleanuppad`` instruction has several restrictions:
- A cleanup block is a basic block which is the unwind destination of
an exceptional instruction.
- A cleanup block must have a '``cleanuppad``' instruction as its
first non-PHI instruction.
- There can be only one '``cleanuppad``' instruction within the
cleanup block.
- A basic block that is not a cleanup block may not include a
'``cleanuppad``' instruction.
- It is undefined behavior for control to transfer from a ``cleanuppad`` to a
``catchret`` without first executing a ``cleanupret`` and a subsequent
``catchpad``.
- It is undefined behavior for control to transfer from a ``cleanuppad`` to a
``ret`` without first executing a ``cleanupret``.
Example:
""""""""
.. code-block:: llvm
%res = cleanuppad { i8*, i32 } [label %nextaction]
.. _intrinsics:
Intrinsic Functions

View File

@ -248,7 +248,13 @@ typedef enum {
/* Exception Handling Operators */
LLVMResume = 58,
LLVMLandingPad = 59
LLVMLandingPad = 59,
LLVMCleanupRet = 61,
LLVMCatchRet = 62,
LLVMCatchPad = 63,
LLVMTerminatePad = 64,
LLVMCleanupPad = 65,
LLVMCatchEndPad = 66
} LLVMOpcode;
@ -1203,6 +1209,7 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(InsertElementInst) \
macro(InsertValueInst) \
macro(LandingPadInst) \
macro(CleanupPadInst) \
macro(PHINode) \
macro(SelectInst) \
macro(ShuffleVectorInst) \
@ -1215,6 +1222,11 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(SwitchInst) \
macro(UnreachableInst) \
macro(ResumeInst) \
macro(CleanupReturnInst) \
macro(CatchReturnInst) \
macro(CatchPadInst) \
macro(TerminatePadInst) \
macro(CatchEndPadInst) \
macro(UnaryInstruction) \
macro(AllocaInst) \
macro(CastInst) \

View File

@ -354,6 +354,12 @@ namespace bitc {
FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align,
// vol,ordering,synchscope]
FUNC_CODE_INST_LANDINGPAD = 47, // LANDINGPAD: [ty,val,num,id0,val0...]
FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [] or [val] or [bb#] or [val,bb#]
FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [bb#]
FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [ty,val,val,num,args...]
FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...]
FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...]
FUNC_CODE_INST_CATCHENDPAD = 53, // CATCHENDPAD: [] or [bb#]
};
enum UseListCodes {

View File

@ -283,6 +283,8 @@ public:
/// should be called while the predecessor still refers to this block.
void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false);
bool canSplitPredecessors() const;
/// \brief Split the basic block into two basic blocks at the specified
/// instruction.
///
@ -309,6 +311,9 @@ public:
/// basic block \p New instead of to it.
void replaceSuccessorsPhiUsesWith(BasicBlock *New);
/// \brief Return true if this basic block is an exception handling block.
bool isEHPad() const { return getFirstNonPHI()->isEHPad(); }
/// \brief Return true if this basic block is a landing pad.
///
/// Being a ``landing pad'' means that the basic block is the destination of

View File

@ -672,6 +672,38 @@ public:
return Insert(ResumeInst::Create(Exn));
}
CleanupReturnInst *CreateCleanupRet(BasicBlock *UnwindBB = nullptr,
Value *RetVal = nullptr) {
return Insert(CleanupReturnInst::Create(Context, RetVal, UnwindBB));
}
CatchPadInst *CreateCatchPad(Type *Ty, BasicBlock *NormalDest,
BasicBlock *UnwindDest,
ArrayRef<Value *> Args,
const Twine &Name = "") {
return Insert(CatchPadInst::Create(Ty, NormalDest, UnwindDest, Args),
Name);
}
CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) {
return Insert(CatchEndPadInst::Create(Context, UnwindBB));
}
TerminatePadInst *CreateTerminatePad(BasicBlock *UnwindBB = nullptr,
ArrayRef<Value *> Args = {},
const Twine &Name = "") {
return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name);
}
CleanupPadInst *CreateCleanupPad(Type *Ty, ArrayRef<Value *> Args,
const Twine &Name = "") {
return Insert(CleanupPadInst::Create(Ty, Args), Name);
}
CatchReturnInst *CreateCatchRet(BasicBlock *BB) {
return Insert(CatchReturnInst::Create(BB));
}
UnreachableInst *CreateUnreachable() {
return Insert(new UnreachableInst(Context));
}

View File

@ -169,6 +169,11 @@ public:
RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);}
RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);}
RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);}
RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst);}
RetTy visitCatchPadInst(CatchPadInst &I) { DELEGATE(TerminatorInst);}
RetTy visitCatchEndPadInst(CatchEndPadInst &I) { DELEGATE(TerminatorInst); }
RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);}
RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);}
RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);}
RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);}
@ -200,6 +205,7 @@ public:
RetTy visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);}
RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); }
RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); }
RetTy visitCleanupPadInst(CleanupPadInst &I) { DELEGATE(Instruction); }
// Handle the special instrinsic instruction classes.
RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);}

View File

@ -75,6 +75,22 @@ public:
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
// \brief Returns true if this terminator relates to exception handling.
bool isExceptional() const {
switch (getOpcode()) {
case Instruction::CatchPad:
case Instruction::CatchEndPad:
case Instruction::CatchRet:
case Instruction::CleanupRet:
case Instruction::Invoke:
case Instruction::Resume:
case Instruction::TerminatePad:
return true;
default:
return false;
}
}
};

View File

@ -94,86 +94,92 @@
// instructions for it to be a well formed basic block.
//
FIRST_TERM_INST ( 1)
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
HANDLE_TERM_INST ( 2, Br , BranchInst)
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst)
HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
HANDLE_TERM_INST ( 6, Resume , ResumeInst)
HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst)
LAST_TERM_INST ( 7)
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
HANDLE_TERM_INST ( 2, Br , BranchInst)
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst)
HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
HANDLE_TERM_INST ( 6, Resume , ResumeInst)
HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst)
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
HANDLE_TERM_INST (10, CatchPad , CatchPadInst)
HANDLE_TERM_INST (11, TerminatePad, TerminatePadInst)
HANDLE_TERM_INST (12, CatchEndPad , CatchEndPadInst)
LAST_TERM_INST (12)
// Standard binary operators...
FIRST_BINARY_INST( 8)
HANDLE_BINARY_INST( 8, Add , BinaryOperator)
HANDLE_BINARY_INST( 9, FAdd , BinaryOperator)
HANDLE_BINARY_INST(10, Sub , BinaryOperator)
HANDLE_BINARY_INST(11, FSub , BinaryOperator)
HANDLE_BINARY_INST(12, Mul , BinaryOperator)
HANDLE_BINARY_INST(13, FMul , BinaryOperator)
HANDLE_BINARY_INST(14, UDiv , BinaryOperator)
HANDLE_BINARY_INST(15, SDiv , BinaryOperator)
HANDLE_BINARY_INST(16, FDiv , BinaryOperator)
HANDLE_BINARY_INST(17, URem , BinaryOperator)
HANDLE_BINARY_INST(18, SRem , BinaryOperator)
HANDLE_BINARY_INST(19, FRem , BinaryOperator)
FIRST_BINARY_INST(13)
HANDLE_BINARY_INST(13, Add , BinaryOperator)
HANDLE_BINARY_INST(14, FAdd , BinaryOperator)
HANDLE_BINARY_INST(15, Sub , BinaryOperator)
HANDLE_BINARY_INST(16, FSub , BinaryOperator)
HANDLE_BINARY_INST(17, Mul , BinaryOperator)
HANDLE_BINARY_INST(18, FMul , BinaryOperator)
HANDLE_BINARY_INST(19, UDiv , BinaryOperator)
HANDLE_BINARY_INST(20, SDiv , BinaryOperator)
HANDLE_BINARY_INST(21, FDiv , BinaryOperator)
HANDLE_BINARY_INST(22, URem , BinaryOperator)
HANDLE_BINARY_INST(23, SRem , BinaryOperator)
HANDLE_BINARY_INST(24, FRem , BinaryOperator)
// Logical operators (integer operands)
HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(23, And , BinaryOperator)
HANDLE_BINARY_INST(24, Or , BinaryOperator)
HANDLE_BINARY_INST(25, Xor , BinaryOperator)
LAST_BINARY_INST(25)
HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(28, And , BinaryOperator)
HANDLE_BINARY_INST(29, Or , BinaryOperator)
HANDLE_BINARY_INST(30, Xor , BinaryOperator)
LAST_BINARY_INST(30)
// Memory operators...
FIRST_MEMORY_INST(26)
HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(28, Store , StoreInst )
HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(30, Fence , FenceInst )
HANDLE_MEMORY_INST(31, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(32, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(32)
FIRST_MEMORY_INST(31)
HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(33, Store , StoreInst )
HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(35, Fence , FenceInst )
HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(37)
// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
FIRST_CAST_INST(33)
HANDLE_CAST_INST(33, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(34, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(35, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(36, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(37, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(38, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(39, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(40, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(45, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(45)
FIRST_CAST_INST(38)
HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(50)
// Other operators...
FIRST_OTHER_INST(46)
HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction.
LAST_OTHER_INST(59)
FIRST_OTHER_INST(51)
HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(65, CleanupPad, CleanupPadInst)
LAST_OTHER_INST(65)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST

View File

@ -388,6 +388,20 @@ public:
return mayWriteToMemory() || mayThrow() || !mayReturn();
}
/// \brief Return true if the instruction is a variety of EH-block.
bool isEHPad() const {
switch (getOpcode()) {
case Instruction::CatchPad:
case Instruction::CatchEndPad:
case Instruction::CleanupPad:
case Instruction::LandingPad:
case Instruction::TerminatePad:
return true;
default:
return false;
}
}
/// clone() - Create a copy of 'this' instruction that is identical in all
/// ways except the following:
/// * The instruction has no parent

View File

@ -3569,6 +3569,528 @@ struct OperandTraits<ResumeInst> :
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
//===----------------------------------------------------------------------===//
// CleanupReturnInst Class
//===----------------------------------------------------------------------===//
class CleanupReturnInst : public TerminatorInst {
CleanupReturnInst(const CleanupReturnInst &RI);
private:
void init(Value *RetVal, BasicBlock *UnwindBB);
CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB,
unsigned Values, Instruction *InsertBefore = nullptr);
CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB,
unsigned Values, BasicBlock *InsertAtEnd);
int getUnwindLabelOpIdx() const {
assert(hasUnwindDest());
return 0;
}
int getRetValOpIdx() const {
assert(hasReturnValue());
if (hasUnwindDest())
return 1;
return 0;
}
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
CleanupReturnInst *cloneImpl() const;
public:
static CleanupReturnInst *Create(LLVMContext &C,
Value *RetVal = nullptr,
BasicBlock *UnwindBB = nullptr,
Instruction *InsertBefore = nullptr) {
unsigned Values = 0;
if (RetVal)
++Values;
if (UnwindBB)
++Values;
return new (Values)
CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertBefore);
}
static CleanupReturnInst *Create(LLVMContext &C, Value *RetVal,
BasicBlock *UnwindBB,
BasicBlock *InsertAtEnd) {
unsigned Values = 0;
if (RetVal)
++Values;
if (UnwindBB)
++Values;
return new (Values)
CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
bool unwindsToCaller() const { return !hasUnwindDest(); }
bool hasReturnValue() const { return getSubclassDataFromInstruction() & 2; }
/// Convenience accessor. Returns null if there is no return value.
Value *getReturnValue() const {
if (!hasReturnValue())
return nullptr;
return getOperand(getRetValOpIdx());
}
void setReturnValue(Value *RetVal) {
assert(hasReturnValue());
setOperand(getRetValOpIdx(), RetVal);
}
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
BasicBlock *getUnwindDest() const;
void setUnwindDest(BasicBlock *NewDest);
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::CleanupRet);
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
BasicBlock *getSuccessorV(unsigned Idx) const override;
unsigned getNumSuccessorsV() const override;
void setSuccessorV(unsigned Idx, BasicBlock *B) override;
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
};
template <>
struct OperandTraits<CleanupReturnInst>
: public VariadicOperandTraits<CleanupReturnInst> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value)
//===----------------------------------------------------------------------===//
// CatchEndPadInst Class
//===----------------------------------------------------------------------===//
class CatchEndPadInst : public TerminatorInst {
CatchEndPadInst(const CatchEndPadInst &RI);
private:
void init(BasicBlock *UnwindBB);
CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
Instruction *InsertBefore = nullptr);
CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
CatchEndPadInst *cloneImpl() const;
public:
static CatchEndPadInst *Create(LLVMContext &C,
BasicBlock *UnwindBB = nullptr,
Instruction *InsertBefore = nullptr) {
unsigned Values = UnwindBB ? 1 : 0;
return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertBefore);
}
static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB,
BasicBlock *InsertAtEnd) {
unsigned Values = UnwindBB ? 1 : 0;
return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
bool unwindsToCaller() const { return !hasUnwindDest(); }
/// Convenience accessor. Returns null if there is no return value.
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
BasicBlock *getUnwindDest() const {
return hasUnwindDest() ? cast<BasicBlock>(Op<-1>()) : nullptr;
}
void setUnwindDest(BasicBlock *NewDest) {
assert(NewDest);
Op<-1>() = NewDest;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::CatchEndPad);
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
BasicBlock *getSuccessorV(unsigned Idx) const override;
unsigned getNumSuccessorsV() const override;
void setSuccessorV(unsigned Idx, BasicBlock *B) override;
private:
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
};
template <>
struct OperandTraits<CatchEndPadInst>
: public VariadicOperandTraits<CatchEndPadInst> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchEndPadInst, Value)
//===----------------------------------------------------------------------===//
// CatchPadInst Class
//===----------------------------------------------------------------------===//
class CatchPadInst : public TerminatorInst {
private:
void init(BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, const Twine &NameStr);
CatchPadInst(const CatchPadInst &CPI);
explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
unsigned Values, const Twine &NameStr,
Instruction *InsertBefore);
explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
unsigned Values, const Twine &NameStr,
BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
CatchPadInst *cloneImpl() const;
public:
static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = unsigned(Args.size()) + 2;
return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args,
Values, NameStr, InsertBefore);
}
static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
const Twine &NameStr, BasicBlock *InsertAtEnd) {
unsigned Values = unsigned(Args.size()) + 2;
return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args,
Values, NameStr, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// getNumArgOperands - Return the number of catchpad arguments.
///
unsigned getNumArgOperands() const { return getNumOperands() - 2; }
/// getArgOperand/setArgOperand - Return/set the i-th catchpad argument.
///
Value *getArgOperand(unsigned i) const { return getOperand(i); }
void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
/// arg_operands - iteration adapter for range-for loops.
iterator_range<op_iterator> arg_operands() {
return iterator_range<op_iterator>(op_begin(), op_end() - 2);
}
/// arg_operands - iteration adapter for range-for loops.
iterator_range<const_op_iterator> arg_operands() const {
return iterator_range<const_op_iterator>(op_begin(), op_end() - 2);
}
/// \brief Wrappers for getting the \c Use of a catchpad argument.
const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
// get*Dest - Return the destination basic blocks...
BasicBlock *getNormalDest() const { return cast<BasicBlock>(Op<-2>()); }
BasicBlock *getUnwindDest() const { return cast<BasicBlock>(Op<-1>()); }
void setNormalDest(BasicBlock *B) { Op<-2>() = reinterpret_cast<Value *>(B); }
void setUnwindDest(BasicBlock *B) { Op<-1>() = reinterpret_cast<Value *>(B); }
BasicBlock *getSuccessor(unsigned i) const {
assert(i < 2 && "Successor # out of range for catchpad!");
return i == 0 ? getNormalDest() : getUnwindDest();
}
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
assert(idx < 2 && "Successor # out of range for catchpad!");
*(&Op<-2>() + idx) = reinterpret_cast<Value *>(NewSucc);
}
unsigned getNumSuccessors() const { return 2; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::CatchPad;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
BasicBlock *getSuccessorV(unsigned idx) const override;
unsigned getNumSuccessorsV() const override;
void setSuccessorV(unsigned idx, BasicBlock *B) override;
};
template <>
struct OperandTraits<CatchPadInst>
: public VariadicOperandTraits<CatchPadInst, /*MINARITY=*/2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchPadInst, Value)
//===----------------------------------------------------------------------===//
// TerminatePadInst Class
//===----------------------------------------------------------------------===//
class TerminatePadInst : public TerminatorInst {
private:
void init(BasicBlock *BB, ArrayRef<Value *> Args, const Twine &NameStr);
TerminatePadInst(const TerminatePadInst &TPI);
explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
const Twine &NameStr, Instruction *InsertBefore);
explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
const Twine &NameStr, BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
TerminatePadInst *cloneImpl() const;
public:
static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB = nullptr,
ArrayRef<Value *> Args = {},
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = unsigned(Args.size());
if (BB)
++Values;
return new (Values)
TerminatePadInst(C, BB, Args, Values, NameStr, InsertBefore);
}
static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB,
ArrayRef<Value *> Args,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
unsigned Values = unsigned(Args.size());
if (BB)
++Values;
return new (Values)
TerminatePadInst(C, BB, Args, Values, NameStr, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
bool unwindsToCaller() const { return !hasUnwindDest(); }
/// getNumArgOperands - Return the number of terminatepad arguments.
///
unsigned getNumArgOperands() const {
unsigned NumOperands = getNumOperands();
if (hasUnwindDest())
return NumOperands - 1;
return NumOperands;
}
/// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument.
///
Value *getArgOperand(unsigned i) const { return getOperand(i); }
void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
const_op_iterator arg_end() const {
if (hasUnwindDest())
return op_end() - 1;
return op_end();
}
op_iterator arg_end() {
if (hasUnwindDest())
return op_end() - 1;
return op_end();
}
/// arg_operands - iteration adapter for range-for loops.
iterator_range<op_iterator> arg_operands() {
return iterator_range<op_iterator>(op_begin(), arg_end());
}
/// arg_operands - iteration adapter for range-for loops.
iterator_range<const_op_iterator> arg_operands() const {
return iterator_range<const_op_iterator>(op_begin(), arg_end());
}
/// \brief Wrappers for getting the \c Use of a terminatepad argument.
const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
// get*Dest - Return the destination basic blocks...
BasicBlock *getUnwindDest() const {
if (!hasUnwindDest())
return nullptr;
return cast<BasicBlock>(Op<-1>());
}
void setUnwindDest(BasicBlock *B) {
assert(B && hasUnwindDest());
Op<-1>() = reinterpret_cast<Value *>(B);
}
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::TerminatePad;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
BasicBlock *getSuccessorV(unsigned idx) const override;
unsigned getNumSuccessorsV() const override;
void setSuccessorV(unsigned idx, BasicBlock *B) override;
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
};
template <>
struct OperandTraits<TerminatePadInst>
: public VariadicOperandTraits<TerminatePadInst, /*MINARITY=*/1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value)
//===----------------------------------------------------------------------===//
// CleanupPadInst Class
//===----------------------------------------------------------------------===//
class CleanupPadInst : public Instruction {
private:
void init(ArrayRef<Value *> Args, const Twine &NameStr);
CleanupPadInst(const CleanupPadInst &CPI);
explicit CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore);
explicit CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
const Twine &NameStr, BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
CleanupPadInst *cloneImpl() const;
public:
static CleanupPadInst *Create(Type *RetTy, ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
return new (Args.size())
CleanupPadInst(RetTy, Args, NameStr, InsertBefore);
}
static CleanupPadInst *Create(Type *RetTy, ArrayRef<Value *> Args,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
return new (Args.size())
CleanupPadInst(RetTy, Args, NameStr, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::CleanupPad;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
template <>
struct OperandTraits<CleanupPadInst>
: public VariadicOperandTraits<CleanupPadInst, /*MINARITY=*/0> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value)
//===----------------------------------------------------------------------===//
// CatchReturnInst Class
//===----------------------------------------------------------------------===//
class CatchReturnInst : public TerminatorInst {
CatchReturnInst(const CatchReturnInst &RI);
private:
void init(Value *RetVal, BasicBlock *UnwindBB);
CatchReturnInst(BasicBlock *BB, Instruction *InsertBefore = nullptr);
CatchReturnInst(BasicBlock *BB, BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
CatchReturnInst *cloneImpl() const;
public:
static CatchReturnInst *Create(BasicBlock *BB,
Instruction *InsertBefore = nullptr) {
return new (1) CatchReturnInst(BB, InsertBefore);
}
static CatchReturnInst *Create(BasicBlock *BB, BasicBlock *InsertAtEnd) {
return new (1) CatchReturnInst(BB, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// Convenience accessors.
BasicBlock *getSuccessor() const { return cast<BasicBlock>(Op<0>()); }
void setSuccessor(BasicBlock *NewSucc) { Op<0>() = (Value *)NewSucc; }
unsigned getNumSuccessors() const { return 1; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::CatchRet);
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
BasicBlock *getSuccessorV(unsigned Idx) const override;
unsigned getNumSuccessorsV() const override;
void setSuccessorV(unsigned Idx, BasicBlock *B) override;
};
template <>
struct OperandTraits<CatchReturnInst>
: public FixedNumOperandTraits<CatchReturnInst, /*ARITY=*/1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
//===----------------------------------------------------------------------===//
// UnreachableInst Class
//===----------------------------------------------------------------------===//

View File

@ -156,6 +156,8 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
bool visitSwitchInst(SwitchInst &SI);
bool visitIndirectBrInst(IndirectBrInst &IBI);
bool visitResumeInst(ResumeInst &RI);
bool visitCleanupReturnInst(CleanupReturnInst &RI);
bool visitCatchReturnInst(CatchReturnInst &RI);
bool visitUnreachableInst(UnreachableInst &I);
public:
@ -903,6 +905,18 @@ bool CallAnalyzer::visitResumeInst(ResumeInst &RI) {
return false;
}
bool CallAnalyzer::visitCleanupReturnInst(CleanupReturnInst &CRI) {
// FIXME: It's not clear that a single instruction is an accurate model for
// the inline cost of a cleanupret instruction.
return false;
}
bool CallAnalyzer::visitCatchReturnInst(CatchReturnInst &CRI) {
// FIXME: It's not clear that a single instruction is an accurate model for
// the inline cost of a cleanupret instruction.
return false;
}
bool CallAnalyzer::visitUnreachableInst(UnreachableInst &I) {
// FIXME: It might be reasonably to discount the cost of instructions leading
// to unreachable as they have the lowest possible impact on both runtime and

View File

@ -102,8 +102,8 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
return false;
if (I->mayReadFromMemory())
return false;
// The landingpad instruction is immobile.
if (isa<LandingPadInst>(I))
// EH block instructions are immobile.
if (I->isEHPad())
return false;
// Determine the insertion point, unless one was given.
if (!InsertPt) {

View File

@ -3147,10 +3147,16 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
case Instruction::Switch:
case Instruction::Unreachable:
case Instruction::Fence:
case Instruction::LandingPad:
case Instruction::AtomicRMW:
case Instruction::AtomicCmpXchg:
case Instruction::LandingPad:
case Instruction::Resume:
case Instruction::CatchPad:
case Instruction::CatchEndPad:
case Instruction::CatchRet:
case Instruction::CleanupPad:
case Instruction::CleanupRet:
case Instruction::TerminatePad:
return false; // Misc instructions which have effects
}
}

View File

@ -524,6 +524,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(undef);
KEYWORD(null);
KEYWORD(to);
KEYWORD(caller);
KEYWORD(tail);
KEYWORD(musttail);
KEYWORD(target);
@ -749,6 +750,12 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(extractvalue, ExtractValue);
INSTKEYWORD(insertvalue, InsertValue);
INSTKEYWORD(landingpad, LandingPad);
INSTKEYWORD(cleanupret, CleanupRet);
INSTKEYWORD(catchret, CatchRet);
INSTKEYWORD(catchpad, CatchPad);
INSTKEYWORD(terminatepad, TerminatePad);
INSTKEYWORD(cleanuppad, CleanupPad);
INSTKEYWORD(catchendpad, CatchEndPad);
#undef INSTKEYWORD
#define DWKEYWORD(TYPE, TOKEN) \

View File

@ -4532,6 +4532,12 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS);
case lltok::kw_invoke: return ParseInvoke(Inst, PFS);
case lltok::kw_resume: return ParseResume(Inst, PFS);
case lltok::kw_cleanupret: return ParseCleanupRet(Inst, PFS);
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
@ -4936,6 +4942,161 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) {
return false;
}
bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
PerFunctionState &PFS) {
if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
return true;
while (Lex.getKind() != lltok::rsquare) {
// If this isn't the first argument, we need a comma.
if (!Args.empty() &&
ParseToken(lltok::comma, "expected ',' in argument list"))
return true;
// Parse the argument.
LocTy ArgLoc;
Type *ArgTy = nullptr;
if (ParseType(ArgTy, ArgLoc))
return true;
Value *V;
if (ArgTy->isMetadataTy()) {
if (ParseMetadataAsValue(V, PFS))
return true;
} else {
if (ParseValue(ArgTy, V, PFS))
return true;
}
Args.push_back(V);
}
Lex.Lex(); // Lex the ']'.
return false;
}
/// ParseCleanupRet
/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
Type *RetTy = nullptr;
Value *RetVal = nullptr;
if (ParseType(RetTy, /*AllowVoid=*/true))
return true;
if (!RetTy->isVoidTy())
if (ParseValue(RetTy, RetVal, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (ParseToken(lltok::kw_caller, "expected 'caller' in cleanupret"))
return true;
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
return false;
}
/// ParseCatchRet
/// ::= 'catchret' TypeAndValue
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
BasicBlock *BB;
if (ParseTypeAndBasicBlock(BB, PFS))
return true;
Inst = CatchReturnInst::Create(BB);
return false;
}
/// ParseCatchPad
/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
Type *RetType = nullptr;
SmallVector<Value *, 8> Args;
if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
return true;
BasicBlock *NormalBB, *UnwindBB;
if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
ParseTypeAndBasicBlock(NormalBB, PFS) ||
ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
return false;
}
/// ParseTerminatePad
/// ::= 'terminatepad' ParamList 'to' TypeAndValue
bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
SmallVector<Value *, 8> Args;
if (ParseExceptionArgs(Args, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
return true;
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
return false;
}
/// ParseCleanupPad
/// ::= 'cleanuppad' ParamList
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
Type *RetType = nullptr;
SmallVector<Value *, 8> Args;
if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
return true;
Inst = CleanupPadInst::Create(RetType, Args);
return false;
}
/// ParseCatchEndPad
/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (Lex.getKind() == lltok::kw_caller) {
Lex.Lex();
} else {
return true;
}
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = CatchEndPadInst::Create(Context, UnwindBB);
return false;
}
//===----------------------------------------------------------------------===//
// Binary Operators.
//===----------------------------------------------------------------------===//

View File

@ -385,6 +385,9 @@ namespace llvm {
bool IsMustTailCall = false,
bool InVarArgsFunc = false);
bool ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
PerFunctionState &PFS);
// Constant Parsing.
bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr);
bool ParseGlobalValue(Type *Ty, Constant *&V);
@ -445,6 +448,12 @@ namespace llvm {
bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS);
bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS);
bool ParseResume(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
unsigned OperandType);

View File

@ -51,6 +51,7 @@ namespace lltok {
kw_zeroinitializer,
kw_undef, kw_null,
kw_to,
kw_caller,
kw_tail,
kw_musttail,
kw_target,
@ -177,7 +178,8 @@ namespace lltok {
kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter,
kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
kw_unreachable,
kw_unreachable, kw_cleanupret, kw_catchret, kw_catchpad,
kw_terminatepad, kw_cleanuppad, kw_catchendpad,
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
kw_getelementptr,

View File

@ -3811,6 +3811,134 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
}
break;
}
// CLEANUPRET: [] or [ty,val] or [bb#] or [ty,val,bb#]
case bitc::FUNC_CODE_INST_CLEANUPRET: {
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
bool HasReturnValue = !!Record[Idx++];
bool HasUnwindDest = !!Record[Idx++];
Value *RetVal = nullptr;
BasicBlock *UnwindDest = nullptr;
if (HasReturnValue && getValueTypePair(Record, Idx, NextValueNo, RetVal))
return error("Invalid record");
if (HasUnwindDest) {
if (Idx == Record.size())
return error("Invalid record");
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
if (Record.size() != Idx)
return error("Invalid record");
I = CleanupReturnInst::Create(Context, RetVal, UnwindDest);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [bb#]
if (Record.size() != 1)
return error("Invalid record");
BasicBlock *BB = getBasicBlock(Record[0]);
if (!BB)
return error("Invalid record");
I = CatchReturnInst::Create(BB);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHPAD: { // CATCHPAD: [ty,bb#,bb#,num,(ty,val)*]
if (Record.size() < 4)
return error("Invalid record");
unsigned Idx = 0;
Type *Ty = getTypeByID(Record[Idx++]);
if (!Ty)
return error("Invalid record");
BasicBlock *NormalBB = getBasicBlock(Record[Idx++]);
if (!NormalBB)
return error("Invalid record");
BasicBlock *UnwindBB = getBasicBlock(Record[Idx++]);
if (!UnwindBB)
return error("Invalid record");
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
I = CatchPadInst::Create(Ty, NormalBB, UnwindBB, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [bb#,num,(ty,val)*]
if (Record.size() < 1)
return error("Invalid record");
unsigned Idx = 0;
bool HasUnwindDest = !!Record[Idx++];
BasicBlock *UnwindDest = nullptr;
if (HasUnwindDest) {
if (Idx == Record.size())
return error("Invalid record");
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
I = TerminatePadInst::Create(Context, UnwindDest, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CLEANUPPAD: { // CLEANUPPAD: [ty, num,(ty,val)*]
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
Type *Ty = getTypeByID(Record[Idx++]);
if (!Ty)
return error("Invalid record");
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
I = CleanupPadInst::Create(Ty, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHENDPAD: { // CATCHENDPADINST: [bb#] or []
if (Record.size() > 1)
return error("Invalid record");
BasicBlock *BB = nullptr;
if (Record.size() == 1) {
BB = getBasicBlock(Record[0]);
if (!BB)
return error("Invalid record");
}
I = CatchEndPadInst::Create(Context, BB);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
// Check magic
if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {

View File

@ -1851,6 +1851,64 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Code = bitc::FUNC_CODE_INST_RESUME;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
break;
case Instruction::CleanupRet: {
Code = bitc::FUNC_CODE_INST_CLEANUPRET;
const auto &CRI = cast<CleanupReturnInst>(I);
Vals.push_back(CRI.hasReturnValue());
Vals.push_back(CRI.hasUnwindDest());
if (CRI.hasReturnValue())
PushValueAndType(CRI.getReturnValue(), InstID, Vals, VE);
if (CRI.hasUnwindDest())
Vals.push_back(VE.getValueID(CRI.getUnwindDest()));
break;
}
case Instruction::CatchRet: {
Code = bitc::FUNC_CODE_INST_CATCHRET;
const auto &CRI = cast<CatchReturnInst>(I);
Vals.push_back(VE.getValueID(CRI.getSuccessor()));
break;
}
case Instruction::CatchPad: {
Code = bitc::FUNC_CODE_INST_CATCHPAD;
const auto &CPI = cast<CatchPadInst>(I);
Vals.push_back(VE.getTypeID(CPI.getType()));
Vals.push_back(VE.getValueID(CPI.getNormalDest()));
Vals.push_back(VE.getValueID(CPI.getUnwindDest()));
unsigned NumArgOperands = CPI.getNumArgOperands();
Vals.push_back(NumArgOperands);
for (unsigned Op = 0; Op != NumArgOperands; ++Op)
PushValueAndType(CPI.getArgOperand(Op), InstID, Vals, VE);
break;
}
case Instruction::TerminatePad: {
Code = bitc::FUNC_CODE_INST_TERMINATEPAD;
const auto &TPI = cast<TerminatePadInst>(I);
Vals.push_back(TPI.hasUnwindDest());
if (TPI.hasUnwindDest())
Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
unsigned NumArgOperands = TPI.getNumArgOperands();
Vals.push_back(NumArgOperands);
for (unsigned Op = 0; Op != NumArgOperands; ++Op)
PushValueAndType(TPI.getArgOperand(Op), InstID, Vals, VE);
break;
}
case Instruction::CleanupPad: {
Code = bitc::FUNC_CODE_INST_CLEANUPPAD;
const auto &CPI = cast<CleanupPadInst>(I);
Vals.push_back(VE.getTypeID(CPI.getType()));
unsigned NumOperands = CPI.getNumOperands();
Vals.push_back(NumOperands);
for (unsigned Op = 0; Op != NumOperands; ++Op)
PushValueAndType(CPI.getOperand(Op), InstID, Vals, VE);
break;
}
case Instruction::CatchEndPad: {
Code = bitc::FUNC_CODE_INST_CATCHENDPAD;
const auto &CEPI = cast<CatchEndPadInst>(I);
if (CEPI.hasUnwindDest())
Vals.push_back(VE.getValueID(CEPI.getUnwindDest()));
break;
}
case Instruction::Unreachable:
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;

View File

@ -1158,6 +1158,30 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
llvm_unreachable("Can't get register for value!");
}
void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
report_fatal_error("visitCleanupRet not yet implemented!");
}
void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
report_fatal_error("visitCatchEndPad not yet implemented!");
}
void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
report_fatal_error("visitCatchRet not yet implemented!");
}
void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
report_fatal_error("visitCatchPad not yet implemented!");
}
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
report_fatal_error("visitTerminatePad not yet implemented!");
}
void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
report_fatal_error("visitCleanupPad not yet implemented!");
}
void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
auto &DL = DAG.getDataLayout();

View File

@ -735,6 +735,12 @@ private:
void visitSwitch(const SwitchInst &I);
void visitIndirectBr(const IndirectBrInst &I);
void visitUnreachable(const UnreachableInst &I);
void visitCleanupRet(const CleanupReturnInst &I);
void visitCatchEndPad(const CatchEndPadInst &I);
void visitCatchRet(const CatchReturnInst &I);
void visitCatchPad(const CatchPadInst &I);
void visitTerminatePad(const TerminatePadInst &TPI);
void visitCleanupPad(const CleanupPadInst &CPI);
uint32_t getEdgeWeight(const MachineBasicBlock *Src,
const MachineBasicBlock *Dst) const;

View File

@ -1571,6 +1571,12 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
case Invoke: return 0;
case Resume: return 0;
case Unreachable: return 0;
case CleanupRet: return 0;
case CatchEndPad: return 0;
case CatchRet: return 0;
case CatchPad: return 0;
case TerminatePad: return 0;
case CleanupPad: return 0;
case Add: return ISD::ADD;
case FAdd: return ISD::FADD;
case Sub: return ISD::SUB;

View File

@ -2861,8 +2861,66 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(LPI->getClause(i), true);
}
} else if (const auto *CPI = dyn_cast<CatchPadInst>(&I)) {
Out << ' ';
TypePrinter.print(I.getType(), Out);
Out << " [";
for (unsigned Op = 0, NumOps = CPI->getNumArgOperands(); Op < NumOps;
++Op) {
if (Op > 0)
Out << ", ";
writeOperand(CPI->getArgOperand(Op), /*PrintType=*/true);
}
Out << "] to ";
writeOperand(CPI->getNormalDest(), /*PrintType=*/true);
Out << " unwind ";
writeOperand(CPI->getUnwindDest(), /*PrintType=*/true);
} else if (const auto *TPI = dyn_cast<TerminatePadInst>(&I)) {
Out << " [";
for (unsigned Op = 0, NumOps = TPI->getNumArgOperands(); Op < NumOps;
++Op) {
if (Op > 0)
Out << ", ";
writeOperand(TPI->getArgOperand(Op), /*PrintType=*/true);
}
Out << "] unwind ";
if (TPI->hasUnwindDest())
writeOperand(TPI->getUnwindDest(), /*PrintType=*/true);
else
Out << "to caller";
} else if (const auto *CPI = dyn_cast<CleanupPadInst>(&I)) {
Out << ' ';
TypePrinter.print(I.getType(), Out);
Out << " [";
for (unsigned Op = 0, NumOps = CPI->getNumOperands(); Op < NumOps; ++Op) {
if (Op > 0)
Out << ", ";
writeOperand(CPI->getOperand(Op), /*PrintType=*/true);
}
Out << "]";
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
if (CRI->hasReturnValue()) {
Out << ' ';
writeOperand(CRI->getReturnValue(), /*PrintType=*/true);
} else {
Out << " void";
}
Out << " unwind ";
if (CRI->hasUnwindDest())
writeOperand(CRI->getUnwindDest(), /*PrintType=*/true);
else
Out << "to caller";
} else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(&I)) {
Out << " unwind ";
if (CEPI->hasUnwindDest())
writeOperand(CEPI->getUnwindDest(), /*PrintType=*/true);
else
Out << "to caller";
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
// Print the calling convention being used.
if (CI->getCallingConv() != CallingConv::C) {

View File

@ -197,7 +197,7 @@ BasicBlock::iterator BasicBlock::getFirstInsertionPt() {
return end();
iterator InsertPt = FirstNonPHI;
if (isa<LandingPadInst>(InsertPt)) ++InsertPt;
if (InsertPt->isEHPad()) ++InsertPt;
return InsertPt;
}
@ -333,6 +333,17 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
}
}
bool BasicBlock::canSplitPredecessors() const {
const Instruction *FirstNonPHI = getFirstNonPHI();
if (isa<LandingPadInst>(FirstNonPHI))
return true;
// This is perhaps a little conservative because constructs like
// CleanupBlockInst are pretty easy to split. However, SplitBlockPredecessors
// cannot handle such things just yet.
if (FirstNonPHI->isEHPad())
return false;
return true;
}
/// This splits a basic block into two at the specified
/// instruction. Note that all instructions BEFORE the specified iterator stay

View File

@ -196,6 +196,11 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Invoke: return "invoke";
case Resume: return "resume";
case Unreachable: return "unreachable";
case CleanupRet: return "cleanupret";
case CatchEndPad: return "catchendpad";
case CatchRet: return "catchret";
case CatchPad: return "catchpad";
case TerminatePad: return "terminatepad";
// Standard binary operators...
case Add: return "add";
@ -256,6 +261,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case ExtractValue: return "extractvalue";
case InsertValue: return "insertvalue";
case LandingPad: return "landingpad";
case CleanupPad: return "cleanuppad";
default: return "<Invalid operator> ";
}
@ -407,6 +413,8 @@ bool Instruction::mayReadFromMemory() const {
case Instruction::Fence: // FIXME: refine definition of mayReadFromMemory
case Instruction::AtomicCmpXchg:
case Instruction::AtomicRMW:
case Instruction::CatchRet:
case Instruction::TerminatePad:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->doesNotAccessMemory();
@ -427,6 +435,8 @@ bool Instruction::mayWriteToMemory() const {
case Instruction::VAArg:
case Instruction::AtomicCmpXchg:
case Instruction::AtomicRMW:
case Instruction::CatchRet:
case Instruction::TerminatePad:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->onlyReadsMemory();
@ -455,6 +465,12 @@ bool Instruction::isAtomic() const {
bool Instruction::mayThrow() const {
if (const CallInst *CI = dyn_cast<CallInst>(this))
return !CI->doesNotThrow();
if (const auto *CRI = dyn_cast<CleanupReturnInst>(this))
return CRI->unwindsToCaller();
if (const auto *CEPI = dyn_cast<CatchEndPadInst>(this))
return CEPI->unwindsToCaller();
if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
return TPI->unwindsToCaller();
return isa<ResumeInst>(this);
}

View File

@ -670,6 +670,303 @@ BasicBlock *ResumeInst::getSuccessorV(unsigned idx) const {
llvm_unreachable("ResumeInst has no successors!");
}
//===----------------------------------------------------------------------===//
// CleanupReturnInst Implementation
//===----------------------------------------------------------------------===//
CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI)
: TerminatorInst(CRI.getType(), Instruction::CleanupRet,
OperandTraits<CleanupReturnInst>::op_end(this) -
CRI.getNumOperands(),
CRI.getNumOperands()) {
SubclassOptionalData = CRI.SubclassOptionalData;
if (Value *RetVal = CRI.getReturnValue())
setReturnValue(RetVal);
if (BasicBlock *UnwindDest = CRI.getUnwindDest())
setUnwindDest(UnwindDest);
}
void CleanupReturnInst::init(Value *RetVal, BasicBlock *UnwindBB) {
SubclassOptionalData = 0;
if (UnwindBB)
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
if (RetVal)
setInstructionSubclassData(getSubclassDataFromInstruction() | 2);
if (UnwindBB)
setUnwindDest(UnwindBB);
if (RetVal)
setReturnValue(RetVal);
}
CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
BasicBlock *UnwindBB, unsigned Values,
Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
Values, InsertBefore) {
init(RetVal, UnwindBB);
}
CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
BasicBlock *UnwindBB, unsigned Values,
BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
Values, InsertAtEnd) {
init(RetVal, UnwindBB);
}
BasicBlock *CleanupReturnInst::getUnwindDest() const {
if (hasUnwindDest())
return cast<BasicBlock>(getOperand(getUnwindLabelOpIdx()));
return nullptr;
}
void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
assert(NewDest);
setOperand(getUnwindLabelOpIdx(), NewDest);
}
BasicBlock *CleanupReturnInst::getSuccessorV(unsigned Idx) const {
assert(Idx == 0);
return getUnwindDest();
}
unsigned CleanupReturnInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
void CleanupReturnInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
assert(Idx == 0);
setUnwindDest(B);
}
//===----------------------------------------------------------------------===//
// CatchEndPadInst Implementation
//===----------------------------------------------------------------------===//
CatchEndPadInst::CatchEndPadInst(const CatchEndPadInst &CRI)
: TerminatorInst(CRI.getType(), Instruction::CatchEndPad,
OperandTraits<CatchEndPadInst>::op_end(this) -
CRI.getNumOperands(),
CRI.getNumOperands()) {
SubclassOptionalData = CRI.SubclassOptionalData;
if (BasicBlock *UnwindDest = CRI.getUnwindDest())
setUnwindDest(UnwindDest);
}
void CatchEndPadInst::init(BasicBlock *UnwindBB) {
SubclassOptionalData = 0;
if (UnwindBB) {
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
setUnwindDest(UnwindBB);
}
}
CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
unsigned Values, Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
OperandTraits<CatchEndPadInst>::op_end(this) - Values,
Values, InsertBefore) {
init(UnwindBB);
}
CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
unsigned Values, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
OperandTraits<CatchEndPadInst>::op_end(this) - Values,
Values, InsertAtEnd) {
init(UnwindBB);
}
BasicBlock *CatchEndPadInst::getSuccessorV(unsigned Idx) const {
assert(Idx == 0);
return getUnwindDest();
}
unsigned CatchEndPadInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
void CatchEndPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
assert(Idx == 0);
setUnwindDest(B);
}
//===----------------------------------------------------------------------===//
// CatchReturnInst Implementation
//===----------------------------------------------------------------------===//
CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI)
: TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet,
OperandTraits<CatchReturnInst>::op_end(this) -
CRI.getNumOperands(),
CRI.getNumOperands()) {
Op<0>() = CRI.Op<0>();
}
CatchReturnInst::CatchReturnInst(BasicBlock *BB, Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
OperandTraits<CatchReturnInst>::op_begin(this), 1,
InsertBefore) {
Op<0>() = BB;
}
CatchReturnInst::CatchReturnInst(BasicBlock *BB, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
OperandTraits<CatchReturnInst>::op_begin(this), 1,
InsertAtEnd) {
Op<0>() = BB;
}
BasicBlock *CatchReturnInst::getSuccessorV(unsigned Idx) const {
assert(Idx == 0);
return getSuccessor();
}
unsigned CatchReturnInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
void CatchReturnInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
assert(Idx == 0);
setSuccessor(B);
}
//===----------------------------------------------------------------------===//
// CatchPadInst Implementation
//===----------------------------------------------------------------------===//
void CatchPadInst::init(BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, const Twine &NameStr) {
assert(getNumOperands() == 2 + Args.size() && "NumOperands not set up?");
Op<-2>() = IfNormal;
Op<-1>() = IfException;
std::copy(Args.begin(), Args.end(), op_begin());
setName(NameStr);
}
CatchPadInst::CatchPadInst(const CatchPadInst &CPI)
: TerminatorInst(CPI.getType(), Instruction::CatchPad,
OperandTraits<CatchPadInst>::op_end(this) -
CPI.getNumOperands(),
CPI.getNumOperands()) {
std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
}
CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
unsigned Values, const Twine &NameStr,
Instruction *InsertBefore)
: TerminatorInst(RetTy, Instruction::CatchPad,
OperandTraits<CatchPadInst>::op_end(this) - Values,
Values, InsertBefore) {
init(IfNormal, IfException, Args, NameStr);
}
CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
unsigned Values, const Twine &NameStr,
BasicBlock *InsertAtEnd)
: TerminatorInst(RetTy, Instruction::CatchPad,
OperandTraits<CatchPadInst>::op_end(this) - Values,
Values, InsertAtEnd) {
init(IfNormal, IfException, Args, NameStr);
}
BasicBlock *CatchPadInst::getSuccessorV(unsigned Idx) const {
return getSuccessor(Idx);
}
unsigned CatchPadInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
void CatchPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
return setSuccessor(Idx, B);
}
//===----------------------------------------------------------------------===//
// TerminatePadInst Implementation
//===----------------------------------------------------------------------===//
void TerminatePadInst::init(BasicBlock *BB, ArrayRef<Value *> Args,
const Twine &NameStr) {
SubclassOptionalData = 0;
if (BB)
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
if (BB)
Op<-1>() = BB;
std::copy(Args.begin(), Args.end(), op_begin());
setName(NameStr);
}
TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI)
: TerminatorInst(TPI.getType(), Instruction::TerminatePad,
OperandTraits<TerminatePadInst>::op_end(this) -
TPI.getNumOperands(),
TPI.getNumOperands()) {
SubclassOptionalData = TPI.SubclassOptionalData;
std::copy(TPI.op_begin(), TPI.op_end(), op_begin());
}
TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
const Twine &NameStr,
Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
OperandTraits<TerminatePadInst>::op_end(this) - Values,
Values, InsertBefore) {
init(BB, Args, NameStr);
}
TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
OperandTraits<TerminatePadInst>::op_end(this) - Values,
Values, InsertAtEnd) {
init(BB, Args, NameStr);
}
BasicBlock *TerminatePadInst::getSuccessorV(unsigned Idx) const {
assert(Idx == 0);
return getUnwindDest();
}
unsigned TerminatePadInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
void TerminatePadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
assert(Idx == 0);
return setUnwindDest(B);
}
//===----------------------------------------------------------------------===//
// CleanupPadInst Implementation
//===----------------------------------------------------------------------===//
void CleanupPadInst::init(ArrayRef<Value *> Args, const Twine &NameStr) {
assert(getNumOperands() == Args.size() && "NumOperands not set up?");
std::copy(Args.begin(), Args.end(), op_begin());
setName(NameStr);
}
CleanupPadInst::CleanupPadInst(const CleanupPadInst &CPI)
: Instruction(CPI.getType(), Instruction::CleanupPad,
OperandTraits<CleanupPadInst>::op_end(this) -
CPI.getNumOperands(),
CPI.getNumOperands()) {
std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
}
CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
const Twine &NameStr,
Instruction *InsertBefore)
: Instruction(RetTy, Instruction::CleanupPad,
OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
Args.size(), InsertBefore) {
init(Args, NameStr);
}
CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
: Instruction(RetTy, Instruction::CleanupPad,
OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
Args.size(), InsertAtEnd) {
init(Args, NameStr);
}
//===----------------------------------------------------------------------===//
// UnreachableInst Implementation
//===----------------------------------------------------------------------===//
@ -3618,6 +3915,30 @@ InvokeInst *InvokeInst::cloneImpl() const {
ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
return new (getNumOperands()) CleanupReturnInst(*this);
}
CatchEndPadInst *CatchEndPadInst::cloneImpl() const {
return new (getNumOperands()) CatchEndPadInst(*this);
}
CatchReturnInst *CatchReturnInst::cloneImpl() const {
return new (1) CatchReturnInst(*this);
}
CatchPadInst *CatchPadInst::cloneImpl() const {
return new (getNumOperands()) CatchPadInst(*this);
}
TerminatePadInst *TerminatePadInst::cloneImpl() const {
return new (getNumOperands()) TerminatePadInst(*this);
}
CleanupPadInst *CleanupPadInst::cloneImpl() const {
return new (getNumOperands()) CleanupPadInst(*this);
}
UnreachableInst *UnreachableInst::cloneImpl() const {
LLVMContext &Context = getContext();
return new UnreachableInst(Context);

View File

@ -184,6 +184,15 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// \brief Track unresolved string-based type references.
SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs;
/// \brief The result type for a catchpad.
Type *CatchPadResultTy;
/// \brief The result type for a cleanuppad.
Type *CleanupPadResultTy;
/// \brief The result type for a landingpad.
Type *LandingPadResultTy;
/// \brief Whether we've seen a call to @llvm.localescape in this function
/// already.
bool SawFrameEscape;
@ -194,7 +203,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
public:
explicit Verifier(raw_ostream &OS)
: VerifierSupport(OS), Context(nullptr), SawFrameEscape(false) {}
: VerifierSupport(OS), Context(nullptr), CatchPadResultTy(nullptr),
CleanupPadResultTy(nullptr), LandingPadResultTy(nullptr),
SawFrameEscape(false) {}
bool verify(const Function &F) {
M = F.getParent();
@ -228,6 +239,9 @@ public:
// FIXME: We strip const here because the inst visitor strips const.
visit(const_cast<Function &>(F));
InstsInThisBlock.clear();
CatchPadResultTy = nullptr;
CleanupPadResultTy = nullptr;
LandingPadResultTy = nullptr;
SawFrameEscape = false;
return !Broken;
@ -379,6 +393,11 @@ private:
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
void visitLandingPadInst(LandingPadInst &LPI);
void visitCatchPadInst(CatchPadInst &CPI);
void visitCatchEndPadInst(CatchEndPadInst &CEPI);
void visitCleanupPadInst(CleanupPadInst &CPI);
void visitCleanupReturnInst(CleanupReturnInst &CRI);
void visitTerminatePadInst(TerminatePadInst &TPI);
void VerifyCallSite(CallSite CS);
void verifyMustTailCall(CallInst &CI);
@ -2385,10 +2404,12 @@ void Verifier::visitCallInst(CallInst &CI) {
void Verifier::visitInvokeInst(InvokeInst &II) {
VerifyCallSite(&II);
// Verify that there is a landingpad instruction as the first non-PHI
// instruction of the 'unwind' destination.
Assert(II.getUnwindDest()->isLandingPad(),
"The unwind destination does not have a landingpad instruction!", &II);
// Verify that the first non-PHI instruction of the unwind destination is an
// exception handling instruction.
Assert(
II.getUnwindDest()->isEHPad(),
"The unwind destination does not have an exception handling instruction!",
&II);
visitTerminatorInst(II);
}
@ -2774,6 +2795,14 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
&LPI);
}
if (!LandingPadResultTy)
LandingPadResultTy = LPI.getType();
else
Assert(LandingPadResultTy == LPI.getType(),
"The landingpad instruction should have a consistent result type "
"inside a function.",
&LPI);
Function *F = LPI.getParent()->getParent();
Assert(F->hasPersonalityFn(),
"LandingPadInst needs to be in a function with a personality.", &LPI);
@ -2799,6 +2828,132 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
visitInstruction(LPI);
}
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
BasicBlock *BB = CPI.getParent();
if (!CatchPadResultTy)
CatchPadResultTy = CPI.getType();
else
Assert(CatchPadResultTy == CPI.getType(),
"The catchpad instruction should have a consistent result type "
"inside a function.",
&CPI);
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"CatchPadInst needs to be in a function with a personality.", &CPI);
// The catchpad instruction must be the first non-PHI instruction in the
// block.
Assert(BB->getFirstNonPHI() == &CPI,
"CatchPadInst not the first non-PHI instruction in the block.",
&CPI);
BasicBlock *UnwindDest = CPI.getUnwindDest();
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(
isa<CatchPadInst>(I) || isa<CatchEndPadInst>(I),
"CatchPadInst must unwind to a CatchPadInst or a CatchEndPadInst.",
&CPI);
visitTerminatorInst(CPI);
}
void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) {
BasicBlock *BB = CEPI.getParent();
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"CatchEndPadInst needs to be in a function with a personality.",
&CEPI);
// The catchendpad instruction must be the first non-PHI instruction in the
// block.
Assert(BB->getFirstNonPHI() == &CEPI,
"CatchEndPadInst not the first non-PHI instruction in the block.",
&CEPI);
unsigned CatchPadsSeen = 0;
for (BasicBlock *PredBB : predecessors(BB))
if (isa<CatchPadInst>(PredBB->getTerminator()))
++CatchPadsSeen;
Assert(CatchPadsSeen <= 1, "CatchEndPadInst must have no more than one "
"CatchPadInst predecessor.",
&CEPI);
if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) {
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(
I->isEHPad() && !isa<LandingPadInst>(I),
"CatchEndPad must unwind to an EH block which is not a landingpad.",
&CEPI);
}
visitTerminatorInst(CEPI);
}
void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
BasicBlock *BB = CPI.getParent();
if (!CleanupPadResultTy)
CleanupPadResultTy = CPI.getType();
else
Assert(CleanupPadResultTy == CPI.getType(),
"The cleanuppad instruction should have a consistent result type "
"inside a function.",
&CPI);
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"CleanupPadInst needs to be in a function with a personality.", &CPI);
// The cleanuppad instruction must be the first non-PHI instruction in the
// block.
Assert(BB->getFirstNonPHI() == &CPI,
"CleanupPadInst not the first non-PHI instruction in the block.",
&CPI);
visitInstruction(CPI);
}
void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
if (BasicBlock *UnwindDest = CRI.getUnwindDest()) {
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(I->isEHPad() && !isa<LandingPadInst>(I),
"CleanupReturnInst must unwind to an EH block which is not a "
"landingpad.",
&CRI);
}
visitTerminatorInst(CRI);
}
void Verifier::visitTerminatePadInst(TerminatePadInst &TPI) {
BasicBlock *BB = TPI.getParent();
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"TerminatePadInst needs to be in a function with a personality.",
&TPI);
// The terminatepad instruction must be the first non-PHI instruction in the
// block.
Assert(BB->getFirstNonPHI() == &TPI,
"TerminatePadInst not the first non-PHI instruction in the block.",
&TPI);
if (BasicBlock *UnwindDest = TPI.getUnwindDest()) {
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(I->isEHPad() && !isa<LandingPadInst>(I),
"TerminatePadInst must unwind to an EH block which is not a "
"landingpad.",
&TPI);
}
visitTerminatorInst(TPI);
}
void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
Instruction *Op = cast<Instruction>(I.getOperand(i));
// If the we have an invalid invoke, don't try to compute the dominance.

View File

@ -2653,6 +2653,30 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
setOrigin(&I, getCleanOrigin());
}
void visitCleanupPadInst(CleanupPadInst &I) {
if (!I.getType()->isVoidTy()) {
setShadow(&I, getCleanShadow(&I));
setOrigin(&I, getCleanOrigin());
}
}
void visitCatchPad(CatchPadInst &I) {
if (!I.getType()->isVoidTy()) {
setShadow(&I, getCleanShadow(&I));
setOrigin(&I, getCleanOrigin());
}
}
void visitTerminatePad(TerminatePadInst &I) {
DEBUG(dbgs() << "TerminatePad: " << I << "\n");
// Nothing to do here.
}
void visitCatchEndPadInst(CatchEndPadInst &I) {
DEBUG(dbgs() << "CatchEndPad: " << I << "\n");
// Nothing to do here.
}
void visitGetElementPtrInst(GetElementPtrInst &I) {
handleShadowOr(I);
}
@ -2696,6 +2720,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// Nothing to do here.
}
void visitCleanupReturnInst(CleanupReturnInst &CRI) {
DEBUG(dbgs() << "CleanupReturn: " << CRI << "\n");
// Nothing to do here.
}
void visitCatchReturnInst(CatchReturnInst &CRI) {
DEBUG(dbgs() << "CatchReturn: " << CRI << "\n");
// Nothing to do here.
}
void visitInstruction(Instruction &I) {
// Everything else: stop propagating and check for poisoned shadow.
if (ClDumpStrictInstructions)

View File

@ -58,8 +58,8 @@ bool ADCE::runOnFunction(Function& F) {
// Collect the set of "root" instructions that are known live.
for (Instruction &I : inst_range(F)) {
if (isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
isa<LandingPadInst>(I) || I.mayHaveSideEffects()) {
if (isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || I.isEHPad() ||
I.mayHaveSideEffects()) {
Alive.insert(&I);
Worklist.push_back(&I);
}

View File

@ -77,8 +77,8 @@ INITIALIZE_PASS_END(BDCE, "bdce", "Bit-Tracking Dead Code Elimination",
false, false)
static bool isAlwaysLive(Instruction *I) {
return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
isa<LandingPadInst>(I) || I->mayHaveSideEffects();
return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || I->isEHPad() ||
I->mayHaveSideEffects();
}
void BDCE::determineLiveOperandBits(const Instruction *UserI,

View File

@ -669,7 +669,8 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
// because now the condition in this block can be threaded through
// predecessors of our predecessor block.
if (BasicBlock *SinglePred = BB->getSinglePredecessor()) {
if (SinglePred->getTerminator()->getNumSuccessors() == 1 &&
const TerminatorInst *TI = SinglePred->getTerminator();
if (!TI->isExceptional() && TI->getNumSuccessors() == 1 &&
SinglePred != BB && !hasAddressTakenAndUsed(BB)) {
// If SinglePred was a loop header, BB becomes one.
if (LoopHeaders.erase(SinglePred))

View File

@ -539,9 +539,9 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
return;
}
if (isa<InvokeInst>(TI)) {
// Invoke instructions successors are always executable.
Succs[0] = Succs[1] = true;
// Unwinding instructions successors are always executable.
if (TI.isExceptional()) {
Succs.assign(TI.getNumSuccessors(), true);
return;
}
@ -605,8 +605,8 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
return BI->getSuccessor(CI->isZero()) == To;
}
// Invoke instructions successors are always executable.
if (isa<InvokeInst>(TI))
// Unwinding instructions successors are always executable.
if (TI->isExceptional())
return true;
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {

View File

@ -117,8 +117,9 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT,
// Don't break self-loops.
if (PredBB == BB) return false;
// Don't break invokes.
if (isa<InvokeInst>(PredBB->getTerminator())) return false;
// Don't break unwinding instructions.
if (PredBB->getTerminator()->isExceptional())
return false;
succ_iterator SI(succ_begin(PredBB)), SE(succ_end(PredBB));
BasicBlock *OnlySucc = BB;
@ -283,7 +284,7 @@ llvm::SplitAllCriticalEdges(Function &F,
BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
DominatorTree *DT, LoopInfo *LI) {
BasicBlock::iterator SplitIt = SplitPt;
while (isa<PHINode>(SplitIt) || isa<LandingPadInst>(SplitIt))
while (isa<PHINode>(SplitIt) || SplitIt->isEHPad())
++SplitIt;
BasicBlock *New = Old->splitBasicBlock(SplitIt, Old->getName()+".split");
@ -474,6 +475,10 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix, DominatorTree *DT,
LoopInfo *LI, bool PreserveLCSSA) {
// Do not attempt to split that which cannot be split.
if (!BB->canSplitPredecessors())
return nullptr;
// For the landingpads we need to act a bit differently.
// Delegate this work to the SplitLandingPadPredecessors.
if (BB->isLandingPad()) {

View File

@ -63,8 +63,8 @@ bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
}
namespace {
/// A class for recording information about inlining through an invoke.
class InvokeInliningInfo {
/// A class for recording information about inlining a landing pad.
class LandingPadInliningInfo {
BasicBlock *OuterResumeDest; ///< Destination of the invoke's unwind.
BasicBlock *InnerResumeDest; ///< Destination for the callee's resume.
LandingPadInst *CallerLPad; ///< LandingPadInst associated with the invoke.
@ -72,7 +72,7 @@ namespace {
SmallVector<Value*, 8> UnwindDestPHIValues;
public:
InvokeInliningInfo(InvokeInst *II)
LandingPadInliningInfo(InvokeInst *II)
: OuterResumeDest(II->getUnwindDest()), InnerResumeDest(nullptr),
CallerLPad(nullptr), InnerEHValuesPHI(nullptr) {
// If there are PHI nodes in the unwind destination block, we need to keep
@ -124,7 +124,7 @@ namespace {
}
/// Get or create a target for the branch from ResumeInsts.
BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
BasicBlock *LandingPadInliningInfo::getInnerResumeDest() {
if (InnerResumeDest) return InnerResumeDest;
// Split the landing pad.
@ -162,8 +162,8 @@ BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
/// When the landing pad block has only one predecessor, this is a simple
/// branch. When there is more than one predecessor, we need to split the
/// landing pad block after the landingpad instruction and jump to there.
void InvokeInliningInfo::forwardResume(ResumeInst *RI,
SmallPtrSetImpl<LandingPadInst*> &InlinedLPads) {
void LandingPadInliningInfo::forwardResume(
ResumeInst *RI, SmallPtrSetImpl<LandingPadInst *> &InlinedLPads) {
BasicBlock *Dest = getInnerResumeDest();
BasicBlock *Src = RI->getParent();
@ -182,8 +182,8 @@ void InvokeInliningInfo::forwardResume(ResumeInst *RI,
/// This function analyze BB to see if there are any calls, and if so,
/// it rewrites them to be invokes that jump to InvokeDest and fills in the PHI
/// nodes in that block with the values specified in InvokeDestPHIValues.
static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
InvokeInliningInfo &Invoke) {
static BasicBlock *
HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, BasicBlock *UnwindEdge) {
for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
Instruction *I = BBI++;
@ -206,8 +206,7 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
// Create the new invoke instruction.
ImmutableCallSite CS(CI);
SmallVector<Value*, 8> InvokeArgs(CS.arg_begin(), CS.arg_end());
InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split,
Invoke.getOuterResumeDest(),
InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split, UnwindEdge,
InvokeArgs, CI->getName(), BB);
II->setDebugLoc(CI->getDebugLoc());
II->setCallingConv(CI->getCallingConv());
@ -219,12 +218,9 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
// Delete the original call
Split->getInstList().pop_front();
// Update any PHI nodes in the exceptional block to indicate that there is
// now a new entry in them.
Invoke.addIncomingPHIValuesFor(BB);
return;
return BB;
}
return nullptr;
}
/// If we inlined an invoke site, we need to convert calls
@ -233,8 +229,8 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
/// II is the invoke instruction being inlined. FirstNewBlock is the first
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
ClonedCodeInfo &InlinedCodeInfo) {
static void HandleInlinedLandingPad(InvokeInst *II, BasicBlock *FirstNewBlock,
ClonedCodeInfo &InlinedCodeInfo) {
BasicBlock *InvokeDest = II->getUnwindDest();
Function *Caller = FirstNewBlock->getParent();
@ -242,7 +238,7 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
// The inlined code is currently at the end of the function, scan from the
// start of the inlined code to its end, checking for stuff we need to
// rewrite.
InvokeInliningInfo Invoke(II);
LandingPadInliningInfo Invoke(II);
// Get all of the inlined landing pad instructions.
SmallPtrSet<LandingPadInst*, 16> InlinedLPads;
@ -264,7 +260,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB){
if (InlinedCodeInfo.ContainsCalls)
HandleCallsInBlockInlinedThroughInvoke(BB, Invoke);
if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
BB, Invoke.getOuterResumeDest()))
// Update any PHI nodes in the exceptional block to indicate that there
// is now a new entry in them.
Invoke.addIncomingPHIValuesFor(NewBB);
// Forward any resumes that are remaining here.
if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator()))
@ -278,6 +278,102 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
InvokeDest->removePredecessor(II->getParent());
}
/// If we inlined an invoke site, we need to convert calls
/// in the body of the inlined function into invokes.
///
/// II is the invoke instruction being inlined. FirstNewBlock is the first
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
ClonedCodeInfo &InlinedCodeInfo) {
BasicBlock *UnwindDest = II->getUnwindDest();
Function *Caller = FirstNewBlock->getParent();
assert(UnwindDest->getFirstNonPHI()->isEHPad() && "unexpected BasicBlock!");
// If there are PHI nodes in the unwind destination block, we need to keep
// track of which values came into them from the invoke before removing the
// edge from this block.
SmallVector<Value *, 8> UnwindDestPHIValues;
llvm::BasicBlock *InvokeBB = II->getParent();
for (Instruction &I : *UnwindDest) {
// Save the value to use for this edge.
PHINode *PHI = dyn_cast<PHINode>(&I);
if (!PHI)
break;
UnwindDestPHIValues.push_back(PHI->getIncomingValueForBlock(InvokeBB));
}
// Add incoming-PHI values to the unwind destination block for the given basic
// block, using the values for the original invoke's source block.
auto UpdatePHINodes = [&](BasicBlock *Src) {
BasicBlock::iterator I = UnwindDest->begin();
for (Value *V : UnwindDestPHIValues) {
PHINode *PHI = cast<PHINode>(I);
PHI->addIncoming(V, Src);
++I;
}
};
// Forward EH terminator instructions to the caller's invoke destination.
// This is as simple as connect all the instructions which 'unwind to caller'
// to the invoke destination.
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
++BB) {
Instruction *I = BB->getFirstNonPHI();
if (I->isEHPad()) {
if (auto *CEPI = dyn_cast<CatchEndPadInst>(I)) {
if (CEPI->unwindsToCaller()) {
CatchEndPadInst::Create(CEPI->getContext(), UnwindDest, CEPI);
CEPI->eraseFromParent();
UpdatePHINodes(BB);
}
} else if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
if (TPI->unwindsToCaller()) {
SmallVector<Value *, 3> TerminatePadArgs;
for (Value *Operand : TPI->operands())
TerminatePadArgs.push_back(Operand);
TerminatePadInst::Create(TPI->getContext(), UnwindDest, TPI);
TPI->eraseFromParent();
UpdatePHINodes(BB);
}
} else if (auto *CPI = dyn_cast<CleanupPadInst>(I)) {
if (CPI->getNumOperands() == 0) {
CleanupPadInst::Create(CPI->getType(), {UnwindDest}, CPI->getName(),
CPI);
CPI->eraseFromParent();
}
} else {
assert(isa<CatchPadInst>(I));
}
}
if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) {
if (CRI->unwindsToCaller()) {
CleanupReturnInst::Create(CRI->getContext(), CRI->getReturnValue(),
UnwindDest, CRI);
CRI->eraseFromParent();
UpdatePHINodes(BB);
}
}
}
if (InlinedCodeInfo.ContainsCalls)
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
++BB)
if (BasicBlock *NewBB =
HandleCallsInBlockInlinedThroughInvoke(BB, UnwindDest))
// Update any PHI nodes in the exceptional block to indicate that there
// is now a new entry in them.
UpdatePHINodes(NewBB);
// Now that everything is happy, we have one final detail. The PHI nodes in
// the exception destination block still have entries due to the original
// invoke instruction. Eliminate these entries (which might even delete the
// PHI node) now.
UnwindDest->removePredecessor(InvokeBB);
}
/// When inlining a function that contains noalias scope metadata,
/// this metadata needs to be cloned so that the inlined blocks
/// have different "unqiue scopes" at every call site. Were this not done, then
@ -1204,8 +1300,15 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
// If we are inlining for an invoke instruction, we must make sure to rewrite
// any call instructions into invoke instructions.
if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall))
HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo);
if (auto *II = dyn_cast<InvokeInst>(TheCall)) {
BasicBlock *UnwindDest = II->getUnwindDest();
Instruction *FirstNonPHI = UnwindDest->getFirstNonPHI();
if (isa<LandingPadInst>(FirstNonPHI)) {
HandleInlinedLandingPad(II, FirstNewBlock, InlinedFunctionInfo);
} else {
HandleInlinedEHPad(II, FirstNewBlock, InlinedFunctionInfo);
}
}
// Handle any inlined musttail call sites. In order for a new call site to be
// musttail, the source of the clone and the inlined call site must have been

View File

@ -283,8 +283,9 @@ bool llvm::isInstructionTriviallyDead(Instruction *I,
const TargetLibraryInfo *TLI) {
if (!I->use_empty() || isa<TerminatorInst>(I)) return false;
// We don't want the landingpad instruction removed by anything this general.
if (isa<LandingPadInst>(I))
// We don't want the landingpad-like instructions removed by anything this
// general.
if (I->isEHPad())
return false;
// We don't want debug info removed by anything this general, unless

View File

@ -142,6 +142,8 @@ BasicBlock *llvm::InsertPreheaderForLoop(Loop *L, Pass *PP) {
BasicBlock *PreheaderBB;
PreheaderBB = SplitBlockPredecessors(Header, OutsideBlocks, ".preheader", DT,
LI, PreserveLCSSA);
if (!PreheaderBB)
return nullptr;
DEBUG(dbgs() << "LoopSimplify: Creating pre-header "
<< PreheaderBB->getName() << "\n");
@ -178,6 +180,8 @@ static BasicBlock *rewriteLoopExitBlock(Loop *L, BasicBlock *Exit,
NewExitBB = SplitBlockPredecessors(Exit, LoopBlocks, ".loopexit", DT, LI,
PreserveLCSSA);
if (!NewExitBB)
return nullptr;
DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "
<< NewExitBB->getName() << "\n");
@ -256,8 +260,10 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
return nullptr;
// The header is not a landing pad; preheader insertion should ensure this.
assert(!L->getHeader()->isLandingPad() &&
"Can't insert backedge to landing pad");
BasicBlock *Header = L->getHeader();
assert(!Header->isLandingPad() && "Can't insert backedge to landing pad");
if (!Header->canSplitPredecessors())
return nullptr;
PHINode *PN = findPHIToPartitionLoops(L, DT, AC);
if (!PN) return nullptr; // No known way to partition.
@ -285,7 +291,6 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
bool PreserveLCSSA = PP->mustPreserveAnalysisID(LCSSAID);
BasicBlock *Header = L->getHeader();
BasicBlock *NewBB = SplitBlockPredecessors(Header, OuterLoopPreds, ".outer",
DT, LI, PreserveLCSSA);

View File

@ -25,3 +25,74 @@ lpad: ; preds = %entry
declare void @_Z3quxv() optsize
declare i32 @__gxx_personality_v0(...)
define void @cleanupret0() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %bb
bb:
cleanuppad void [i7 4]
cleanupret i8 0 unwind label %bb
}
define void @cleanupret1() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %bb
bb:
cleanuppad void [i7 4]
cleanupret void unwind label %bb
}
define void @cleanupret2() personality i32 (...)* @__gxx_personality_v0 {
entry:
cleanupret i8 0 unwind to caller
}
define void @cleanupret3() personality i32 (...)* @__gxx_personality_v0 {
cleanupret void unwind to caller
}
define void @catchret() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %bb
bb:
catchret label %bb
}
define i8 @catchpad() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %bb2
bb:
ret i8 %cbv
bb2:
%cbv = catchpad i8 [i7 4] to label %bb unwind label %bb2
}
define void @terminatepad0() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %bb
bb:
terminatepad [i7 4] unwind label %bb
}
define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 {
entry:
terminatepad [i7 4] unwind to caller
}
define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 {
entry:
cleanuppad void [i7 4]
ret void
}
define void @catchendpad0() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %bb
bb:
catchendpad unwind label %bb
}
define void @catchendpad1() personality i32 (...)* @__gxx_personality_v0 {
entry:
catchendpad unwind to caller
}

View File

@ -2,7 +2,7 @@
; PR1042
define i32 @foo() {
; CHECK: The unwind destination does not have a landingpad instruction
; CHECK: The unwind destination does not have an exception handling instruction
%A = invoke i32 @foo( )
to label %L unwind label %L ; <i32> [#uses=1]
L: ; preds = %0, %0
@ -18,7 +18,7 @@ L1: ; preds = %0
L2: ; preds = %0
br label %L
L: ; preds = %L2, %L1, %L1
; CHECK: The unwind destination does not have a landingpad instruction
; CHECK: The unwind destination does not have an exception handling instruction
ret i32 %A
}

View File

@ -241,6 +241,11 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)
STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)
STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
STRINGIFY_CODE(FUNC_CODE, INST_CATCHENDPAD)
STRINGIFY_CODE(FUNC_CODE, INST_TERMINATEPAD)
STRINGIFY_CODE(FUNC_CODE, INST_PHI)
STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
STRINGIFY_CODE(FUNC_CODE, INST_LOAD)