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:
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
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
/* Exception Handling Operators */
LLVMResume = 58,
- LLVMLandingPad = 59
+ LLVMLandingPad = 59,
+ LLVMCleanupRet = 61,
+ LLVMCatchRet = 62,
+ LLVMCatchPad = 63,
+ LLVMTerminatePad = 64,
+ LLVMCleanupPad = 65,
+ LLVMCatchEndPad = 66
} LLVMOpcode;
macro(InsertElementInst) \
macro(InsertValueInst) \
macro(LandingPadInst) \
+ macro(CleanupPadInst) \
macro(PHINode) \
macro(SelectInst) \
macro(ShuffleVectorInst) \
macro(SwitchInst) \
macro(UnreachableInst) \
macro(ResumeInst) \
+ macro(CleanupReturnInst) \
+ macro(CatchReturnInst) \
+ macro(CatchPadInst) \
+ macro(TerminatePadInst) \
+ macro(CatchEndPadInst) \
macro(UnaryInstruction) \
macro(AllocaInst) \
macro(CastInst) \
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 {
/// 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.
///
/// 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
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));
}
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);}
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);}
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;
+ }
+ }
};
// 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
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
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
//===----------------------------------------------------------------------===//
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:
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
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) {
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
}
}
KEYWORD(undef);
KEYWORD(null);
KEYWORD(to);
+ KEYWORD(caller);
KEYWORD(tail);
KEYWORD(musttail);
KEYWORD(target);
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) \
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:
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.
//===----------------------------------------------------------------------===//
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);
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);
kw_zeroinitializer,
kw_undef, kw_null,
kw_to,
+ kw_caller,
kw_tail,
kw_musttail,
kw_target,
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,
}
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) {
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;
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();
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;
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;
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) {
return end();
iterator InsertPt = FirstNonPHI;
- if (isa<LandingPadInst>(InsertPt)) ++InsertPt;
+ if (InsertPt->isEHPad()) ++InsertPt;
return InsertPt;
}
}
}
+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
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";
case ExtractValue: return "extractvalue";
case InsertValue: return "insertvalue";
case LandingPad: return "landingpad";
+ case CleanupPad: return "cleanuppad";
default: return "<Invalid operator> ";
}
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();
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();
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);
}
}
//===----------------------------------------------------------------------===//
+// 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
//===----------------------------------------------------------------------===//
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);
/// \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;
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();
// 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;
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);
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);
}
&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);
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.
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);
}
// 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)
// 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);
}
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,
// 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))
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;
}
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)) {
// 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;
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");
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()) {
}
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.
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
}
/// Get or create a target for the branch from ResumeInsts.
-BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
+BasicBlock *LandingPadInliningInfo::getInnerResumeDest() {
if (InnerResumeDest) return InnerResumeDest;
// Split the landing pad.
/// 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();
/// 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++;
// 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());
// 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
/// 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();
// 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;
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()))
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
// 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
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
BasicBlock *PreheaderBB;
PreheaderBB = SplitBlockPredecessors(Header, OutsideBlocks, ".preheader", DT,
LI, PreserveLCSSA);
+ if (!PreheaderBB)
+ return nullptr;
DEBUG(dbgs() << "LoopSimplify: Creating pre-header "
<< PreheaderBB->getName() << "\n");
NewExitBB = SplitBlockPredecessors(Exit, LoopBlocks, ".loopexit", DT, LI,
PreserveLCSSA);
+ if (!NewExitBB)
+ return nullptr;
DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "
<< NewExitBB->getName() << "\n");
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.
bool PreserveLCSSA = PP->mustPreserveAnalysisID(LCSSAID);
- BasicBlock *Header = L->getHeader();
BasicBlock *NewBB = SplitBlockPredecessors(Header, OuterLoopPreds, ".outer",
DT, LI, PreserveLCSSA);
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
+}
; 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
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
}
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)