mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
New EH representation for MSVC compatibility
This introduces new instructions neccessary to implement MSVC-compatible exception handling support. Most of the middle-end and none of the back-end haven't been audited or updated to take them into account. Differential Revision: http://reviews.llvm.org/D11097 llvm-svn: 243766
This commit is contained in:
parent
80ade4fb4d
commit
34ee3789f3
368
docs/LangRef.rst
368
docs/LangRef.rst
@ -4741,7 +4741,12 @@ control flow, not values (the one exception being the
|
||||
The terminator instructions are: ':ref:`ret <i_ret>`',
|
||||
':ref:`br <i_br>`', ':ref:`switch <i_switch>`',
|
||||
':ref:`indirectbr <i_indirectbr>`', ':ref:`invoke <i_invoke>`',
|
||||
':ref:`resume <i_resume>`', and ':ref:`unreachable <i_unreachable>`'.
|
||||
':ref:`resume <i_resume>`', ':ref:`catchpad <i_catchpad>`',
|
||||
':ref:`catchendpad <i_catchendpad>`',
|
||||
':ref:`catchret <i_catchret>`',
|
||||
':ref:`cleanupret <i_cleanupret>`',
|
||||
':ref:`terminatepad <i_terminatepad>`',
|
||||
and ':ref:`unreachable <i_unreachable>`'.
|
||||
|
||||
.. _i_ret:
|
||||
|
||||
@ -5095,6 +5100,301 @@ Example:
|
||||
|
||||
resume { i8*, i32 } %exn
|
||||
|
||||
.. _i_catchpad:
|
||||
|
||||
'``catchpad``' Instruction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
<resultval> = catchpad <resultty> [<args>*]
|
||||
to label <normal label> unwind label <exception label>
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``catchpad``' instruction is used by `LLVM's exception handling
|
||||
system <ExceptionHandling.html#overview>`_ to specify that a basic block
|
||||
is a catch block --- one where a personality routine attempts to transfer
|
||||
control to catch an exception.
|
||||
The ``args`` correspond to whatever information the personality
|
||||
routine requires to know if this is an appropriate place to catch the
|
||||
exception. Control is tranfered to the ``exception`` label if the
|
||||
``catchpad`` is not an appropriate handler for the in-flight exception.
|
||||
The ``normal`` label should contain the code found in the ``catch``
|
||||
portion of a ``try``/``catch`` sequence. It defines values supplied by
|
||||
the :ref:`personality function <personalityfn>` upon re-entry to the
|
||||
function. The ``resultval`` has the type ``resultty``.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The instruction takes a list of arbitrary values which are interpreted
|
||||
by the :ref:`personality function <personalityfn>`.
|
||||
|
||||
The ``catchpad`` must be provided a ``normal`` label to transfer control
|
||||
to if the ``catchpad`` matches the exception and an ``exception``
|
||||
label to transfer control to if it doesn't.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
The '``catchpad``' instruction defines the values which are set by the
|
||||
:ref:`personality function <personalityfn>` upon re-entry to the function, and
|
||||
therefore the "result type" of the ``catchpad`` instruction. As with
|
||||
calling conventions, how the personality function results are
|
||||
represented in LLVM IR is target specific.
|
||||
|
||||
When the call stack is being unwound due to an exception being thrown,
|
||||
the exception is compared against the ``args``. If it doesn't match,
|
||||
then control is transfered to the ``exception`` basic block.
|
||||
|
||||
The ``catchpad`` instruction has several restrictions:
|
||||
|
||||
- A catch block is a basic block which is the unwind destination of
|
||||
an exceptional instruction.
|
||||
- A catch block must have a '``catchpad``' instruction as its
|
||||
first non-PHI instruction.
|
||||
- A catch block's ``exception`` edge must refer to a catch block or a
|
||||
catch-end block.
|
||||
- There can be only one '``catchpad``' instruction within the
|
||||
catch block.
|
||||
- A basic block that is not a catch block may not include a
|
||||
'``catchpad``' instruction.
|
||||
- It is undefined behavior for control to transfer from a ``catchpad`` to a
|
||||
``cleanupret`` without first executing a ``catchret`` and a subsequent
|
||||
``cleanuppad``.
|
||||
- It is undefined behavior for control to transfer from a ``catchpad`` to a
|
||||
``ret`` without first executing a ``catchret``.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
;; A catch block which can catch an integer.
|
||||
%res = catchpad { i8*, i32 } [i8** @_ZTIi]
|
||||
to label %int.handler unwind label %terminate
|
||||
|
||||
.. _i_catchendpad:
|
||||
|
||||
'``catchendpad``' Instruction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
catchendpad unwind label <nextaction>
|
||||
catchendpad unwind to caller
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``catchendpad``' instruction is used by `LLVM's exception handling
|
||||
system <ExceptionHandling.html#overview>`_ to communicate to the
|
||||
:ref:`personality function <personalityfn>` which invokes are associated
|
||||
with a chain of :ref:`catchpad <i_catchpad>` instructions.
|
||||
|
||||
The ``nextaction`` label indicates where control should transfer to if
|
||||
none of the ``catchpad`` instructions are suitable for catching the
|
||||
in-flight exception.
|
||||
|
||||
If a ``nextaction`` label is not present, the instruction unwinds out of
|
||||
its parent function. The
|
||||
:ref:`personality function <personalityfn>` will continue processing
|
||||
exception handling actions in the caller.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The instruction optionally takes a label, ``nextaction``, indicating
|
||||
where control should transfer to if none of the preceding
|
||||
``catchpad`` instructions are suitable for the in-flight exception.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
When the call stack is being unwound due to an exception being thrown
|
||||
and none of the constituent ``catchpad`` instructions match, then
|
||||
control is transfered to ``nextaction`` if it is present. If it is not
|
||||
present, control is transfered to the caller.
|
||||
|
||||
The ``catchendpad`` instruction has several restrictions:
|
||||
|
||||
- A catch-end block is a basic block which is the unwind destination of
|
||||
an exceptional instruction.
|
||||
- A catch-end block must have a '``catchendpad``' instruction as its
|
||||
first non-PHI instruction.
|
||||
- There can be only one '``catchendpad``' instruction within the
|
||||
catch block.
|
||||
- A basic block that is not a catch-end block may not include a
|
||||
'``catchendpad``' instruction.
|
||||
- Exactly one catch block may unwind to a ``catchendpad``.
|
||||
- The unwind target of invokes between a ``catchpad`` and a
|
||||
corresponding ``catchret`` must be its ``catchendpad``.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
catchendpad unwind label %terminate
|
||||
catchendpad unwind to caller
|
||||
|
||||
.. _i_catchret:
|
||||
|
||||
'``catchret``' Instruction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
catchret label <normal>
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``catchret``' instruction is a terminator instruction that has a
|
||||
single successor.
|
||||
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The '``catchret``' instruction requires one argument which specifies
|
||||
where control will transfer to next.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
The '``catchret``' instruction ends the existing (in-flight) exception
|
||||
whose unwinding was interrupted with a
|
||||
:ref:`catchpad <i_catchpad>` instruction.
|
||||
The :ref:`personality function <personalityfn>` gets a chance to execute
|
||||
arbitrary code to, for example, run a C++ destructor.
|
||||
Control then transfers to ``normal``.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
catchret label %continue
|
||||
|
||||
.. _i_cleanupret:
|
||||
|
||||
'``cleanupret``' Instruction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
cleanupret <type> <value> unwind label <continue>
|
||||
cleanupret <type> <value> unwind to caller
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``cleanupret``' instruction is a terminator instruction that has
|
||||
an optional successor.
|
||||
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The '``cleanupret``' instruction requires one argument, which must have the
|
||||
same type as the result of any '``cleanuppad``' instruction in the same
|
||||
function. It also has an optional successor, ``continue``.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
The '``cleanupret``' instruction indicates to the
|
||||
:ref:`personality function <personalityfn>` that one
|
||||
:ref:`cleanuppad <i_cleanuppad>` it transferred control to has ended.
|
||||
It transfers control to ``continue`` or unwinds out of the function.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
cleanupret void unwind to caller
|
||||
cleanupret { i8*, i32 } %exn unwind label %continue
|
||||
|
||||
.. _i_terminatepad:
|
||||
|
||||
'``terminatepad``' Instruction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
terminatepad [<args>*] unwind label <exception label>
|
||||
terminatepad [<args>*] unwind to caller
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``terminatepad``' instruction is used by `LLVM's exception handling
|
||||
system <ExceptionHandling.html#overview>`_ to specify that a basic block
|
||||
is a terminate block --- one where a personality routine may decide to
|
||||
terminate the program.
|
||||
The ``args`` correspond to whatever information the personality
|
||||
routine requires to know if this is an appropriate place to terminate the
|
||||
program. Control is transferred to the ``exception`` label if the
|
||||
personality routine decides not to terminate the program for the
|
||||
in-flight exception.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The instruction takes a list of arbitrary values which are interpreted
|
||||
by the :ref:`personality function <personalityfn>`.
|
||||
|
||||
The ``terminatepad`` may be given an ``exception`` label to
|
||||
transfer control to if the in-flight exception matches the ``args``.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
When the call stack is being unwound due to an exception being thrown,
|
||||
the exception is compared against the ``args``. If it matches,
|
||||
then control is transfered to the ``exception`` basic block. Otherwise,
|
||||
the program is terminated via personality-specific means. Typically,
|
||||
the first argument to ``terminatepad`` specifies what function the
|
||||
personality should defer to in order to terminate the program.
|
||||
|
||||
The ``terminatepad`` instruction has several restrictions:
|
||||
|
||||
- A terminate block is a basic block which is the unwind destination of
|
||||
an exceptional instruction.
|
||||
- A terminate block must have a '``terminatepad``' instruction as its
|
||||
first non-PHI instruction.
|
||||
- There can be only one '``terminatepad``' instruction within the
|
||||
terminate block.
|
||||
- A basic block that is not a terminate block may not include a
|
||||
'``terminatepad``' instruction.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
;; A terminate block which only permits integers.
|
||||
terminatepad [i8** @_ZTIi] unwind label %continue
|
||||
|
||||
.. _i_unreachable:
|
||||
|
||||
'``unreachable``' Instruction
|
||||
@ -8052,6 +8352,72 @@ Example:
|
||||
catch i8** @_ZTIi
|
||||
filter [1 x i8**] [@_ZTId]
|
||||
|
||||
.. _i_cleanuppad:
|
||||
|
||||
'``cleanuppad``' Instruction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
<resultval> = cleanuppad <resultty> [<args>*]
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``cleanuppad``' instruction is used by `LLVM's exception handling
|
||||
system <ExceptionHandling.html#overview>`_ to specify that a basic block
|
||||
is a cleanup block --- one where a personality routine attempts to
|
||||
transfer control to run cleanup actions.
|
||||
The ``args`` correspond to whatever additional
|
||||
information the :ref:`personality function <personalityfn>` requires to
|
||||
execute the cleanup.
|
||||
The ``resultval`` has the type ``resultty``.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The instruction takes a list of arbitrary values which are interpreted
|
||||
by the :ref:`personality function <personalityfn>`.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
The '``cleanuppad``' instruction defines the values which are set by the
|
||||
:ref:`personality function <personalityfn>` upon re-entry to the function, and
|
||||
therefore the "result type" of the ``cleanuppad`` instruction. As with
|
||||
calling conventions, how the personality function results are
|
||||
represented in LLVM IR is target specific.
|
||||
|
||||
When the call stack is being unwound due to an exception being thrown,
|
||||
the :ref:`personality function <personalityfn>` transfers control to the
|
||||
``cleanuppad`` with the aid of the personality-specific arguments.
|
||||
|
||||
The ``cleanuppad`` instruction has several restrictions:
|
||||
|
||||
- A cleanup block is a basic block which is the unwind destination of
|
||||
an exceptional instruction.
|
||||
- A cleanup block must have a '``cleanuppad``' instruction as its
|
||||
first non-PHI instruction.
|
||||
- There can be only one '``cleanuppad``' instruction within the
|
||||
cleanup block.
|
||||
- A basic block that is not a cleanup block may not include a
|
||||
'``cleanuppad``' instruction.
|
||||
- It is undefined behavior for control to transfer from a ``cleanuppad`` to a
|
||||
``catchret`` without first executing a ``cleanupret`` and a subsequent
|
||||
``catchpad``.
|
||||
- It is undefined behavior for control to transfer from a ``cleanuppad`` to a
|
||||
``ret`` without first executing a ``cleanupret``.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%res = cleanuppad { i8*, i32 } [label %nextaction]
|
||||
|
||||
.. _intrinsics:
|
||||
|
||||
Intrinsic Functions
|
||||
|
@ -248,7 +248,13 @@ typedef enum {
|
||||
|
||||
/* Exception Handling Operators */
|
||||
LLVMResume = 58,
|
||||
LLVMLandingPad = 59
|
||||
LLVMLandingPad = 59,
|
||||
LLVMCleanupRet = 61,
|
||||
LLVMCatchRet = 62,
|
||||
LLVMCatchPad = 63,
|
||||
LLVMTerminatePad = 64,
|
||||
LLVMCleanupPad = 65,
|
||||
LLVMCatchEndPad = 66
|
||||
|
||||
} LLVMOpcode;
|
||||
|
||||
@ -1203,6 +1209,7 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(InsertElementInst) \
|
||||
macro(InsertValueInst) \
|
||||
macro(LandingPadInst) \
|
||||
macro(CleanupPadInst) \
|
||||
macro(PHINode) \
|
||||
macro(SelectInst) \
|
||||
macro(ShuffleVectorInst) \
|
||||
@ -1215,6 +1222,11 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(SwitchInst) \
|
||||
macro(UnreachableInst) \
|
||||
macro(ResumeInst) \
|
||||
macro(CleanupReturnInst) \
|
||||
macro(CatchReturnInst) \
|
||||
macro(CatchPadInst) \
|
||||
macro(TerminatePadInst) \
|
||||
macro(CatchEndPadInst) \
|
||||
macro(UnaryInstruction) \
|
||||
macro(AllocaInst) \
|
||||
macro(CastInst) \
|
||||
|
@ -354,6 +354,12 @@ namespace bitc {
|
||||
FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align,
|
||||
// vol,ordering,synchscope]
|
||||
FUNC_CODE_INST_LANDINGPAD = 47, // LANDINGPAD: [ty,val,num,id0,val0...]
|
||||
FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [] or [val] or [bb#] or [val,bb#]
|
||||
FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [bb#]
|
||||
FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [ty,val,val,num,args...]
|
||||
FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...]
|
||||
FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...]
|
||||
FUNC_CODE_INST_CATCHENDPAD = 53, // CATCHENDPAD: [] or [bb#]
|
||||
};
|
||||
|
||||
enum UseListCodes {
|
||||
|
@ -283,6 +283,8 @@ public:
|
||||
/// should be called while the predecessor still refers to this block.
|
||||
void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false);
|
||||
|
||||
bool canSplitPredecessors() const;
|
||||
|
||||
/// \brief Split the basic block into two basic blocks at the specified
|
||||
/// instruction.
|
||||
///
|
||||
@ -309,6 +311,9 @@ public:
|
||||
/// basic block \p New instead of to it.
|
||||
void replaceSuccessorsPhiUsesWith(BasicBlock *New);
|
||||
|
||||
/// \brief Return true if this basic block is an exception handling block.
|
||||
bool isEHPad() const { return getFirstNonPHI()->isEHPad(); }
|
||||
|
||||
/// \brief Return true if this basic block is a landing pad.
|
||||
///
|
||||
/// Being a ``landing pad'' means that the basic block is the destination of
|
||||
|
@ -672,6 +672,38 @@ public:
|
||||
return Insert(ResumeInst::Create(Exn));
|
||||
}
|
||||
|
||||
CleanupReturnInst *CreateCleanupRet(BasicBlock *UnwindBB = nullptr,
|
||||
Value *RetVal = nullptr) {
|
||||
return Insert(CleanupReturnInst::Create(Context, RetVal, UnwindBB));
|
||||
}
|
||||
|
||||
CatchPadInst *CreateCatchPad(Type *Ty, BasicBlock *NormalDest,
|
||||
BasicBlock *UnwindDest,
|
||||
ArrayRef<Value *> Args,
|
||||
const Twine &Name = "") {
|
||||
return Insert(CatchPadInst::Create(Ty, NormalDest, UnwindDest, Args),
|
||||
Name);
|
||||
}
|
||||
|
||||
CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) {
|
||||
return Insert(CatchEndPadInst::Create(Context, UnwindBB));
|
||||
}
|
||||
|
||||
TerminatePadInst *CreateTerminatePad(BasicBlock *UnwindBB = nullptr,
|
||||
ArrayRef<Value *> Args = {},
|
||||
const Twine &Name = "") {
|
||||
return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name);
|
||||
}
|
||||
|
||||
CleanupPadInst *CreateCleanupPad(Type *Ty, ArrayRef<Value *> Args,
|
||||
const Twine &Name = "") {
|
||||
return Insert(CleanupPadInst::Create(Ty, Args), Name);
|
||||
}
|
||||
|
||||
CatchReturnInst *CreateCatchRet(BasicBlock *BB) {
|
||||
return Insert(CatchReturnInst::Create(BB));
|
||||
}
|
||||
|
||||
UnreachableInst *CreateUnreachable() {
|
||||
return Insert(new UnreachableInst(Context));
|
||||
}
|
||||
|
@ -169,6 +169,11 @@ public:
|
||||
RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitCatchPadInst(CatchPadInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitCatchEndPadInst(CatchEndPadInst &I) { DELEGATE(TerminatorInst); }
|
||||
RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);}
|
||||
RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);}
|
||||
RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);}
|
||||
@ -200,6 +205,7 @@ public:
|
||||
RetTy visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);}
|
||||
RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); }
|
||||
RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); }
|
||||
RetTy visitCleanupPadInst(CleanupPadInst &I) { DELEGATE(Instruction); }
|
||||
|
||||
// Handle the special instrinsic instruction classes.
|
||||
RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);}
|
||||
|
@ -75,6 +75,22 @@ public:
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
// \brief Returns true if this terminator relates to exception handling.
|
||||
bool isExceptional() const {
|
||||
switch (getOpcode()) {
|
||||
case Instruction::CatchPad:
|
||||
case Instruction::CatchEndPad:
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::CleanupRet:
|
||||
case Instruction::Invoke:
|
||||
case Instruction::Resume:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -94,86 +94,92 @@
|
||||
// instructions for it to be a well formed basic block.
|
||||
//
|
||||
FIRST_TERM_INST ( 1)
|
||||
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
|
||||
HANDLE_TERM_INST ( 2, Br , BranchInst)
|
||||
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
|
||||
HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst)
|
||||
HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
|
||||
HANDLE_TERM_INST ( 6, Resume , ResumeInst)
|
||||
HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst)
|
||||
LAST_TERM_INST ( 7)
|
||||
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
|
||||
HANDLE_TERM_INST ( 2, Br , BranchInst)
|
||||
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
|
||||
HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst)
|
||||
HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
|
||||
HANDLE_TERM_INST ( 6, Resume , ResumeInst)
|
||||
HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst)
|
||||
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
|
||||
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
|
||||
HANDLE_TERM_INST (10, CatchPad , CatchPadInst)
|
||||
HANDLE_TERM_INST (11, TerminatePad, TerminatePadInst)
|
||||
HANDLE_TERM_INST (12, CatchEndPad , CatchEndPadInst)
|
||||
LAST_TERM_INST (12)
|
||||
|
||||
// Standard binary operators...
|
||||
FIRST_BINARY_INST( 8)
|
||||
HANDLE_BINARY_INST( 8, Add , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 9, FAdd , BinaryOperator)
|
||||
HANDLE_BINARY_INST(10, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(11, FSub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(12, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, FMul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(17, URem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(18, SRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(19, FRem , BinaryOperator)
|
||||
FIRST_BINARY_INST(13)
|
||||
HANDLE_BINARY_INST(13, Add , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, FAdd , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, FSub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(17, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(18, FMul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(19, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(20, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(21, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(22, URem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(23, SRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(24, FRem , BinaryOperator)
|
||||
|
||||
// Logical operators (integer operands)
|
||||
HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical)
|
||||
HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical)
|
||||
HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||
HANDLE_BINARY_INST(23, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(24, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(25, Xor , BinaryOperator)
|
||||
LAST_BINARY_INST(25)
|
||||
HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift left (logical)
|
||||
HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right (logical)
|
||||
HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||
HANDLE_BINARY_INST(28, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(29, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(30, Xor , BinaryOperator)
|
||||
LAST_BINARY_INST(30)
|
||||
|
||||
// Memory operators...
|
||||
FIRST_MEMORY_INST(26)
|
||||
HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(28, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst)
|
||||
HANDLE_MEMORY_INST(30, Fence , FenceInst )
|
||||
HANDLE_MEMORY_INST(31, AtomicCmpXchg , AtomicCmpXchgInst )
|
||||
HANDLE_MEMORY_INST(32, AtomicRMW , AtomicRMWInst )
|
||||
LAST_MEMORY_INST(32)
|
||||
FIRST_MEMORY_INST(31)
|
||||
HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(33, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst)
|
||||
HANDLE_MEMORY_INST(35, Fence , FenceInst )
|
||||
HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst )
|
||||
HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst )
|
||||
LAST_MEMORY_INST(37)
|
||||
|
||||
// Cast operators ...
|
||||
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
||||
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
||||
FIRST_CAST_INST(33)
|
||||
HANDLE_CAST_INST(33, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(34, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(35, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(36, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(37, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(38, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(39, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(40, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast
|
||||
HANDLE_CAST_INST(45, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
|
||||
LAST_CAST_INST(45)
|
||||
FIRST_CAST_INST(38)
|
||||
HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
|
||||
HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
|
||||
LAST_CAST_INST(50)
|
||||
|
||||
// Other operators...
|
||||
FIRST_OTHER_INST(46)
|
||||
HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector
|
||||
HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||
HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate
|
||||
HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction.
|
||||
LAST_OTHER_INST(59)
|
||||
FIRST_OTHER_INST(51)
|
||||
HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
|
||||
HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||
HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate
|
||||
HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction.
|
||||
HANDLE_OTHER_INST(65, CleanupPad, CleanupPadInst)
|
||||
LAST_OTHER_INST(65)
|
||||
|
||||
#undef FIRST_TERM_INST
|
||||
#undef HANDLE_TERM_INST
|
||||
|
@ -388,6 +388,20 @@ public:
|
||||
return mayWriteToMemory() || mayThrow() || !mayReturn();
|
||||
}
|
||||
|
||||
/// \brief Return true if the instruction is a variety of EH-block.
|
||||
bool isEHPad() const {
|
||||
switch (getOpcode()) {
|
||||
case Instruction::CatchPad:
|
||||
case Instruction::CatchEndPad:
|
||||
case Instruction::CleanupPad:
|
||||
case Instruction::LandingPad:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// clone() - Create a copy of 'this' instruction that is identical in all
|
||||
/// ways except the following:
|
||||
/// * The instruction has no parent
|
||||
|
@ -3569,6 +3569,528 @@ struct OperandTraits<ResumeInst> :
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CleanupReturnInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CleanupReturnInst : public TerminatorInst {
|
||||
CleanupReturnInst(const CleanupReturnInst &RI);
|
||||
|
||||
private:
|
||||
void init(Value *RetVal, BasicBlock *UnwindBB);
|
||||
CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB,
|
||||
unsigned Values, Instruction *InsertBefore = nullptr);
|
||||
CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB,
|
||||
unsigned Values, BasicBlock *InsertAtEnd);
|
||||
|
||||
int getUnwindLabelOpIdx() const {
|
||||
assert(hasUnwindDest());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getRetValOpIdx() const {
|
||||
assert(hasReturnValue());
|
||||
if (hasUnwindDest())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
CleanupReturnInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
static CleanupReturnInst *Create(LLVMContext &C,
|
||||
Value *RetVal = nullptr,
|
||||
BasicBlock *UnwindBB = nullptr,
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
unsigned Values = 0;
|
||||
if (RetVal)
|
||||
++Values;
|
||||
if (UnwindBB)
|
||||
++Values;
|
||||
return new (Values)
|
||||
CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertBefore);
|
||||
}
|
||||
static CleanupReturnInst *Create(LLVMContext &C, Value *RetVal,
|
||||
BasicBlock *UnwindBB,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
unsigned Values = 0;
|
||||
if (RetVal)
|
||||
++Values;
|
||||
if (UnwindBB)
|
||||
++Values;
|
||||
return new (Values)
|
||||
CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertAtEnd);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
|
||||
bool unwindsToCaller() const { return !hasUnwindDest(); }
|
||||
bool hasReturnValue() const { return getSubclassDataFromInstruction() & 2; }
|
||||
|
||||
/// Convenience accessor. Returns null if there is no return value.
|
||||
Value *getReturnValue() const {
|
||||
if (!hasReturnValue())
|
||||
return nullptr;
|
||||
return getOperand(getRetValOpIdx());
|
||||
}
|
||||
void setReturnValue(Value *RetVal) {
|
||||
assert(hasReturnValue());
|
||||
setOperand(getRetValOpIdx(), RetVal);
|
||||
}
|
||||
|
||||
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
|
||||
|
||||
BasicBlock *getUnwindDest() const;
|
||||
void setUnwindDest(BasicBlock *NewDest);
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return (I->getOpcode() == Instruction::CleanupRet);
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
private:
|
||||
BasicBlock *getSuccessorV(unsigned Idx) const override;
|
||||
unsigned getNumSuccessorsV() const override;
|
||||
void setSuccessorV(unsigned Idx, BasicBlock *B) override;
|
||||
|
||||
// Shadow Instruction::setInstructionSubclassData with a private forwarding
|
||||
// method so that subclasses cannot accidentally use it.
|
||||
void setInstructionSubclassData(unsigned short D) {
|
||||
Instruction::setInstructionSubclassData(D);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<CleanupReturnInst>
|
||||
: public VariadicOperandTraits<CleanupReturnInst> {};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CatchEndPadInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CatchEndPadInst : public TerminatorInst {
|
||||
CatchEndPadInst(const CatchEndPadInst &RI);
|
||||
|
||||
private:
|
||||
void init(BasicBlock *UnwindBB);
|
||||
CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
|
||||
Instruction *InsertBefore = nullptr);
|
||||
CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
|
||||
BasicBlock *InsertAtEnd);
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
CatchEndPadInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
static CatchEndPadInst *Create(LLVMContext &C,
|
||||
BasicBlock *UnwindBB = nullptr,
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
unsigned Values = UnwindBB ? 1 : 0;
|
||||
return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertBefore);
|
||||
}
|
||||
static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
unsigned Values = UnwindBB ? 1 : 0;
|
||||
return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertAtEnd);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
|
||||
bool unwindsToCaller() const { return !hasUnwindDest(); }
|
||||
|
||||
/// Convenience accessor. Returns null if there is no return value.
|
||||
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
|
||||
|
||||
BasicBlock *getUnwindDest() const {
|
||||
return hasUnwindDest() ? cast<BasicBlock>(Op<-1>()) : nullptr;
|
||||
}
|
||||
void setUnwindDest(BasicBlock *NewDest) {
|
||||
assert(NewDest);
|
||||
Op<-1>() = NewDest;
|
||||
}
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return (I->getOpcode() == Instruction::CatchEndPad);
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
private:
|
||||
BasicBlock *getSuccessorV(unsigned Idx) const override;
|
||||
unsigned getNumSuccessorsV() const override;
|
||||
void setSuccessorV(unsigned Idx, BasicBlock *B) override;
|
||||
|
||||
private:
|
||||
// Shadow Instruction::setInstructionSubclassData with a private forwarding
|
||||
// method so that subclasses cannot accidentally use it.
|
||||
void setInstructionSubclassData(unsigned short D) {
|
||||
Instruction::setInstructionSubclassData(D);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<CatchEndPadInst>
|
||||
: public VariadicOperandTraits<CatchEndPadInst> {};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchEndPadInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CatchPadInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CatchPadInst : public TerminatorInst {
|
||||
private:
|
||||
void init(BasicBlock *IfNormal, BasicBlock *IfException,
|
||||
ArrayRef<Value *> Args, const Twine &NameStr);
|
||||
|
||||
CatchPadInst(const CatchPadInst &CPI);
|
||||
|
||||
explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
|
||||
BasicBlock *IfException, ArrayRef<Value *> Args,
|
||||
unsigned Values, const Twine &NameStr,
|
||||
Instruction *InsertBefore);
|
||||
explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
|
||||
BasicBlock *IfException, ArrayRef<Value *> Args,
|
||||
unsigned Values, const Twine &NameStr,
|
||||
BasicBlock *InsertAtEnd);
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
CatchPadInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal,
|
||||
BasicBlock *IfException, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr = "",
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
unsigned Values = unsigned(Args.size()) + 2;
|
||||
return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args,
|
||||
Values, NameStr, InsertBefore);
|
||||
}
|
||||
static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal,
|
||||
BasicBlock *IfException, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr, BasicBlock *InsertAtEnd) {
|
||||
unsigned Values = unsigned(Args.size()) + 2;
|
||||
return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args,
|
||||
Values, NameStr, InsertAtEnd);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
/// getNumArgOperands - Return the number of catchpad arguments.
|
||||
///
|
||||
unsigned getNumArgOperands() const { return getNumOperands() - 2; }
|
||||
|
||||
/// getArgOperand/setArgOperand - Return/set the i-th catchpad argument.
|
||||
///
|
||||
Value *getArgOperand(unsigned i) const { return getOperand(i); }
|
||||
void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
|
||||
|
||||
/// arg_operands - iteration adapter for range-for loops.
|
||||
iterator_range<op_iterator> arg_operands() {
|
||||
return iterator_range<op_iterator>(op_begin(), op_end() - 2);
|
||||
}
|
||||
|
||||
/// arg_operands - iteration adapter for range-for loops.
|
||||
iterator_range<const_op_iterator> arg_operands() const {
|
||||
return iterator_range<const_op_iterator>(op_begin(), op_end() - 2);
|
||||
}
|
||||
|
||||
/// \brief Wrappers for getting the \c Use of a catchpad argument.
|
||||
const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
|
||||
Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
|
||||
|
||||
// get*Dest - Return the destination basic blocks...
|
||||
BasicBlock *getNormalDest() const { return cast<BasicBlock>(Op<-2>()); }
|
||||
BasicBlock *getUnwindDest() const { return cast<BasicBlock>(Op<-1>()); }
|
||||
void setNormalDest(BasicBlock *B) { Op<-2>() = reinterpret_cast<Value *>(B); }
|
||||
void setUnwindDest(BasicBlock *B) { Op<-1>() = reinterpret_cast<Value *>(B); }
|
||||
|
||||
BasicBlock *getSuccessor(unsigned i) const {
|
||||
assert(i < 2 && "Successor # out of range for catchpad!");
|
||||
return i == 0 ? getNormalDest() : getUnwindDest();
|
||||
}
|
||||
|
||||
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
|
||||
assert(idx < 2 && "Successor # out of range for catchpad!");
|
||||
*(&Op<-2>() + idx) = reinterpret_cast<Value *>(NewSucc);
|
||||
}
|
||||
|
||||
unsigned getNumSuccessors() const { return 2; }
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == Instruction::CatchPad;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
private:
|
||||
BasicBlock *getSuccessorV(unsigned idx) const override;
|
||||
unsigned getNumSuccessorsV() const override;
|
||||
void setSuccessorV(unsigned idx, BasicBlock *B) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<CatchPadInst>
|
||||
: public VariadicOperandTraits<CatchPadInst, /*MINARITY=*/2> {};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchPadInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TerminatePadInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class TerminatePadInst : public TerminatorInst {
|
||||
private:
|
||||
void init(BasicBlock *BB, ArrayRef<Value *> Args, const Twine &NameStr);
|
||||
|
||||
TerminatePadInst(const TerminatePadInst &TPI);
|
||||
|
||||
explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
|
||||
ArrayRef<Value *> Args, unsigned Values,
|
||||
const Twine &NameStr, Instruction *InsertBefore);
|
||||
explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
|
||||
ArrayRef<Value *> Args, unsigned Values,
|
||||
const Twine &NameStr, BasicBlock *InsertAtEnd);
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
TerminatePadInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB = nullptr,
|
||||
ArrayRef<Value *> Args = {},
|
||||
const Twine &NameStr = "",
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
unsigned Values = unsigned(Args.size());
|
||||
if (BB)
|
||||
++Values;
|
||||
return new (Values)
|
||||
TerminatePadInst(C, BB, Args, Values, NameStr, InsertBefore);
|
||||
}
|
||||
static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB,
|
||||
ArrayRef<Value *> Args,
|
||||
const Twine &NameStr,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
unsigned Values = unsigned(Args.size());
|
||||
if (BB)
|
||||
++Values;
|
||||
return new (Values)
|
||||
TerminatePadInst(C, BB, Args, Values, NameStr, InsertAtEnd);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
|
||||
bool unwindsToCaller() const { return !hasUnwindDest(); }
|
||||
|
||||
/// getNumArgOperands - Return the number of terminatepad arguments.
|
||||
///
|
||||
unsigned getNumArgOperands() const {
|
||||
unsigned NumOperands = getNumOperands();
|
||||
if (hasUnwindDest())
|
||||
return NumOperands - 1;
|
||||
return NumOperands;
|
||||
}
|
||||
|
||||
/// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument.
|
||||
///
|
||||
Value *getArgOperand(unsigned i) const { return getOperand(i); }
|
||||
void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
|
||||
|
||||
const_op_iterator arg_end() const {
|
||||
if (hasUnwindDest())
|
||||
return op_end() - 1;
|
||||
return op_end();
|
||||
}
|
||||
|
||||
op_iterator arg_end() {
|
||||
if (hasUnwindDest())
|
||||
return op_end() - 1;
|
||||
return op_end();
|
||||
}
|
||||
|
||||
/// arg_operands - iteration adapter for range-for loops.
|
||||
iterator_range<op_iterator> arg_operands() {
|
||||
return iterator_range<op_iterator>(op_begin(), arg_end());
|
||||
}
|
||||
|
||||
/// arg_operands - iteration adapter for range-for loops.
|
||||
iterator_range<const_op_iterator> arg_operands() const {
|
||||
return iterator_range<const_op_iterator>(op_begin(), arg_end());
|
||||
}
|
||||
|
||||
/// \brief Wrappers for getting the \c Use of a terminatepad argument.
|
||||
const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
|
||||
Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
|
||||
|
||||
// get*Dest - Return the destination basic blocks...
|
||||
BasicBlock *getUnwindDest() const {
|
||||
if (!hasUnwindDest())
|
||||
return nullptr;
|
||||
return cast<BasicBlock>(Op<-1>());
|
||||
}
|
||||
void setUnwindDest(BasicBlock *B) {
|
||||
assert(B && hasUnwindDest());
|
||||
Op<-1>() = reinterpret_cast<Value *>(B);
|
||||
}
|
||||
|
||||
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == Instruction::TerminatePad;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
private:
|
||||
BasicBlock *getSuccessorV(unsigned idx) const override;
|
||||
unsigned getNumSuccessorsV() const override;
|
||||
void setSuccessorV(unsigned idx, BasicBlock *B) override;
|
||||
|
||||
// Shadow Instruction::setInstructionSubclassData with a private forwarding
|
||||
// method so that subclasses cannot accidentally use it.
|
||||
void setInstructionSubclassData(unsigned short D) {
|
||||
Instruction::setInstructionSubclassData(D);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<TerminatePadInst>
|
||||
: public VariadicOperandTraits<TerminatePadInst, /*MINARITY=*/1> {};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CleanupPadInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CleanupPadInst : public Instruction {
|
||||
private:
|
||||
void init(ArrayRef<Value *> Args, const Twine &NameStr);
|
||||
|
||||
CleanupPadInst(const CleanupPadInst &CPI);
|
||||
|
||||
explicit CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr, Instruction *InsertBefore);
|
||||
explicit CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr, BasicBlock *InsertAtEnd);
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
CleanupPadInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
static CleanupPadInst *Create(Type *RetTy, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr = "",
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
return new (Args.size())
|
||||
CleanupPadInst(RetTy, Args, NameStr, InsertBefore);
|
||||
}
|
||||
static CleanupPadInst *Create(Type *RetTy, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
return new (Args.size())
|
||||
CleanupPadInst(RetTy, Args, NameStr, InsertAtEnd);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == Instruction::CleanupPad;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<CleanupPadInst>
|
||||
: public VariadicOperandTraits<CleanupPadInst, /*MINARITY=*/0> {};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CatchReturnInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CatchReturnInst : public TerminatorInst {
|
||||
CatchReturnInst(const CatchReturnInst &RI);
|
||||
|
||||
private:
|
||||
void init(Value *RetVal, BasicBlock *UnwindBB);
|
||||
CatchReturnInst(BasicBlock *BB, Instruction *InsertBefore = nullptr);
|
||||
CatchReturnInst(BasicBlock *BB, BasicBlock *InsertAtEnd);
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
CatchReturnInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
static CatchReturnInst *Create(BasicBlock *BB,
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
return new (1) CatchReturnInst(BB, InsertBefore);
|
||||
}
|
||||
static CatchReturnInst *Create(BasicBlock *BB, BasicBlock *InsertAtEnd) {
|
||||
return new (1) CatchReturnInst(BB, InsertAtEnd);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
/// Convenience accessors.
|
||||
BasicBlock *getSuccessor() const { return cast<BasicBlock>(Op<0>()); }
|
||||
void setSuccessor(BasicBlock *NewSucc) { Op<0>() = (Value *)NewSucc; }
|
||||
unsigned getNumSuccessors() const { return 1; }
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return (I->getOpcode() == Instruction::CatchRet);
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
private:
|
||||
BasicBlock *getSuccessorV(unsigned Idx) const override;
|
||||
unsigned getNumSuccessorsV() const override;
|
||||
void setSuccessorV(unsigned Idx, BasicBlock *B) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<CatchReturnInst>
|
||||
: public FixedNumOperandTraits<CatchReturnInst, /*ARITY=*/1> {};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// UnreachableInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -156,6 +156,8 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
|
||||
bool visitSwitchInst(SwitchInst &SI);
|
||||
bool visitIndirectBrInst(IndirectBrInst &IBI);
|
||||
bool visitResumeInst(ResumeInst &RI);
|
||||
bool visitCleanupReturnInst(CleanupReturnInst &RI);
|
||||
bool visitCatchReturnInst(CatchReturnInst &RI);
|
||||
bool visitUnreachableInst(UnreachableInst &I);
|
||||
|
||||
public:
|
||||
@ -903,6 +905,18 @@ bool CallAnalyzer::visitResumeInst(ResumeInst &RI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallAnalyzer::visitCleanupReturnInst(CleanupReturnInst &CRI) {
|
||||
// FIXME: It's not clear that a single instruction is an accurate model for
|
||||
// the inline cost of a cleanupret instruction.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallAnalyzer::visitCatchReturnInst(CatchReturnInst &CRI) {
|
||||
// FIXME: It's not clear that a single instruction is an accurate model for
|
||||
// the inline cost of a cleanupret instruction.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallAnalyzer::visitUnreachableInst(UnreachableInst &I) {
|
||||
// FIXME: It might be reasonably to discount the cost of instructions leading
|
||||
// to unreachable as they have the lowest possible impact on both runtime and
|
||||
|
@ -102,8 +102,8 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
|
||||
return false;
|
||||
if (I->mayReadFromMemory())
|
||||
return false;
|
||||
// The landingpad instruction is immobile.
|
||||
if (isa<LandingPadInst>(I))
|
||||
// EH block instructions are immobile.
|
||||
if (I->isEHPad())
|
||||
return false;
|
||||
// Determine the insertion point, unless one was given.
|
||||
if (!InsertPt) {
|
||||
|
@ -3147,10 +3147,16 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
|
||||
case Instruction::Switch:
|
||||
case Instruction::Unreachable:
|
||||
case Instruction::Fence:
|
||||
case Instruction::LandingPad:
|
||||
case Instruction::AtomicRMW:
|
||||
case Instruction::AtomicCmpXchg:
|
||||
case Instruction::LandingPad:
|
||||
case Instruction::Resume:
|
||||
case Instruction::CatchPad:
|
||||
case Instruction::CatchEndPad:
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::CleanupPad:
|
||||
case Instruction::CleanupRet:
|
||||
case Instruction::TerminatePad:
|
||||
return false; // Misc instructions which have effects
|
||||
}
|
||||
}
|
||||
|
@ -524,6 +524,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(undef);
|
||||
KEYWORD(null);
|
||||
KEYWORD(to);
|
||||
KEYWORD(caller);
|
||||
KEYWORD(tail);
|
||||
KEYWORD(musttail);
|
||||
KEYWORD(target);
|
||||
@ -749,6 +750,12 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
INSTKEYWORD(extractvalue, ExtractValue);
|
||||
INSTKEYWORD(insertvalue, InsertValue);
|
||||
INSTKEYWORD(landingpad, LandingPad);
|
||||
INSTKEYWORD(cleanupret, CleanupRet);
|
||||
INSTKEYWORD(catchret, CatchRet);
|
||||
INSTKEYWORD(catchpad, CatchPad);
|
||||
INSTKEYWORD(terminatepad, TerminatePad);
|
||||
INSTKEYWORD(cleanuppad, CleanupPad);
|
||||
INSTKEYWORD(catchendpad, CatchEndPad);
|
||||
#undef INSTKEYWORD
|
||||
|
||||
#define DWKEYWORD(TYPE, TOKEN) \
|
||||
|
@ -4532,6 +4532,12 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS);
|
||||
case lltok::kw_invoke: return ParseInvoke(Inst, PFS);
|
||||
case lltok::kw_resume: return ParseResume(Inst, PFS);
|
||||
case lltok::kw_cleanupret: return ParseCleanupRet(Inst, PFS);
|
||||
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
|
||||
case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
|
||||
case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
|
||||
case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
|
||||
case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
|
||||
// Binary Operators.
|
||||
case lltok::kw_add:
|
||||
case lltok::kw_sub:
|
||||
@ -4936,6 +4942,161 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
|
||||
PerFunctionState &PFS) {
|
||||
if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
|
||||
return true;
|
||||
|
||||
while (Lex.getKind() != lltok::rsquare) {
|
||||
// If this isn't the first argument, we need a comma.
|
||||
if (!Args.empty() &&
|
||||
ParseToken(lltok::comma, "expected ',' in argument list"))
|
||||
return true;
|
||||
|
||||
// Parse the argument.
|
||||
LocTy ArgLoc;
|
||||
Type *ArgTy = nullptr;
|
||||
if (ParseType(ArgTy, ArgLoc))
|
||||
return true;
|
||||
|
||||
Value *V;
|
||||
if (ArgTy->isMetadataTy()) {
|
||||
if (ParseMetadataAsValue(V, PFS))
|
||||
return true;
|
||||
} else {
|
||||
if (ParseValue(ArgTy, V, PFS))
|
||||
return true;
|
||||
}
|
||||
Args.push_back(V);
|
||||
}
|
||||
|
||||
Lex.Lex(); // Lex the ']'.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseCleanupRet
|
||||
/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
|
||||
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
Type *RetTy = nullptr;
|
||||
Value *RetVal = nullptr;
|
||||
if (ParseType(RetTy, /*AllowVoid=*/true))
|
||||
return true;
|
||||
|
||||
if (!RetTy->isVoidTy())
|
||||
if (ParseValue(RetTy, RetVal, PFS))
|
||||
return true;
|
||||
|
||||
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
|
||||
return true;
|
||||
|
||||
BasicBlock *UnwindBB = nullptr;
|
||||
if (Lex.getKind() == lltok::kw_to) {
|
||||
Lex.Lex();
|
||||
if (ParseToken(lltok::kw_caller, "expected 'caller' in cleanupret"))
|
||||
return true;
|
||||
} else {
|
||||
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseCatchRet
|
||||
/// ::= 'catchret' TypeAndValue
|
||||
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
BasicBlock *BB;
|
||||
if (ParseTypeAndBasicBlock(BB, PFS))
|
||||
return true;
|
||||
|
||||
Inst = CatchReturnInst::Create(BB);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseCatchPad
|
||||
/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
|
||||
bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
Type *RetType = nullptr;
|
||||
|
||||
SmallVector<Value *, 8> Args;
|
||||
if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
|
||||
return true;
|
||||
|
||||
BasicBlock *NormalBB, *UnwindBB;
|
||||
if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
|
||||
ParseTypeAndBasicBlock(NormalBB, PFS) ||
|
||||
ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
|
||||
ParseTypeAndBasicBlock(UnwindBB, PFS))
|
||||
return true;
|
||||
|
||||
Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseTerminatePad
|
||||
/// ::= 'terminatepad' ParamList 'to' TypeAndValue
|
||||
bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
SmallVector<Value *, 8> Args;
|
||||
if (ParseExceptionArgs(Args, PFS))
|
||||
return true;
|
||||
|
||||
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
|
||||
return true;
|
||||
|
||||
BasicBlock *UnwindBB = nullptr;
|
||||
if (Lex.getKind() == lltok::kw_to) {
|
||||
Lex.Lex();
|
||||
if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
|
||||
return true;
|
||||
} else {
|
||||
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseCleanupPad
|
||||
/// ::= 'cleanuppad' ParamList
|
||||
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
Type *RetType = nullptr;
|
||||
|
||||
SmallVector<Value *, 8> Args;
|
||||
if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
|
||||
return true;
|
||||
|
||||
Inst = CleanupPadInst::Create(RetType, Args);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseCatchEndPad
|
||||
/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
|
||||
bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
|
||||
return true;
|
||||
|
||||
BasicBlock *UnwindBB = nullptr;
|
||||
if (Lex.getKind() == lltok::kw_to) {
|
||||
Lex.Lex();
|
||||
if (Lex.getKind() == lltok::kw_caller) {
|
||||
Lex.Lex();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Inst = CatchEndPadInst::Create(Context, UnwindBB);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Binary Operators.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -385,6 +385,9 @@ namespace llvm {
|
||||
bool IsMustTailCall = false,
|
||||
bool InVarArgsFunc = false);
|
||||
|
||||
bool ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
|
||||
PerFunctionState &PFS);
|
||||
|
||||
// Constant Parsing.
|
||||
bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr);
|
||||
bool ParseGlobalValue(Type *Ty, Constant *&V);
|
||||
@ -445,6 +448,12 @@ namespace llvm {
|
||||
bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseResume(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
|
||||
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
|
||||
unsigned OperandType);
|
||||
|
@ -51,6 +51,7 @@ namespace lltok {
|
||||
kw_zeroinitializer,
|
||||
kw_undef, kw_null,
|
||||
kw_to,
|
||||
kw_caller,
|
||||
kw_tail,
|
||||
kw_musttail,
|
||||
kw_target,
|
||||
@ -177,7 +178,8 @@ namespace lltok {
|
||||
kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter,
|
||||
|
||||
kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
|
||||
kw_unreachable,
|
||||
kw_unreachable, kw_cleanupret, kw_catchret, kw_catchpad,
|
||||
kw_terminatepad, kw_cleanuppad, kw_catchendpad,
|
||||
|
||||
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
|
||||
kw_getelementptr,
|
||||
|
@ -3811,6 +3811,134 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// CLEANUPRET: [] or [ty,val] or [bb#] or [ty,val,bb#]
|
||||
case bitc::FUNC_CODE_INST_CLEANUPRET: {
|
||||
if (Record.size() < 2)
|
||||
return error("Invalid record");
|
||||
unsigned Idx = 0;
|
||||
bool HasReturnValue = !!Record[Idx++];
|
||||
bool HasUnwindDest = !!Record[Idx++];
|
||||
Value *RetVal = nullptr;
|
||||
BasicBlock *UnwindDest = nullptr;
|
||||
|
||||
if (HasReturnValue && getValueTypePair(Record, Idx, NextValueNo, RetVal))
|
||||
return error("Invalid record");
|
||||
if (HasUnwindDest) {
|
||||
if (Idx == Record.size())
|
||||
return error("Invalid record");
|
||||
UnwindDest = getBasicBlock(Record[Idx++]);
|
||||
if (!UnwindDest)
|
||||
return error("Invalid record");
|
||||
}
|
||||
|
||||
if (Record.size() != Idx)
|
||||
return error("Invalid record");
|
||||
|
||||
I = CleanupReturnInst::Create(Context, RetVal, UnwindDest);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [bb#]
|
||||
if (Record.size() != 1)
|
||||
return error("Invalid record");
|
||||
BasicBlock *BB = getBasicBlock(Record[0]);
|
||||
if (!BB)
|
||||
return error("Invalid record");
|
||||
I = CatchReturnInst::Create(BB);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_CATCHPAD: { // CATCHPAD: [ty,bb#,bb#,num,(ty,val)*]
|
||||
if (Record.size() < 4)
|
||||
return error("Invalid record");
|
||||
unsigned Idx = 0;
|
||||
Type *Ty = getTypeByID(Record[Idx++]);
|
||||
if (!Ty)
|
||||
return error("Invalid record");
|
||||
BasicBlock *NormalBB = getBasicBlock(Record[Idx++]);
|
||||
if (!NormalBB)
|
||||
return error("Invalid record");
|
||||
BasicBlock *UnwindBB = getBasicBlock(Record[Idx++]);
|
||||
if (!UnwindBB)
|
||||
return error("Invalid record");
|
||||
unsigned NumArgOperands = Record[Idx++];
|
||||
SmallVector<Value *, 2> Args;
|
||||
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
|
||||
Value *Val;
|
||||
if (getValueTypePair(Record, Idx, NextValueNo, Val))
|
||||
return error("Invalid record");
|
||||
Args.push_back(Val);
|
||||
}
|
||||
if (Record.size() != Idx)
|
||||
return error("Invalid record");
|
||||
|
||||
I = CatchPadInst::Create(Ty, NormalBB, UnwindBB, Args);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [bb#,num,(ty,val)*]
|
||||
if (Record.size() < 1)
|
||||
return error("Invalid record");
|
||||
unsigned Idx = 0;
|
||||
bool HasUnwindDest = !!Record[Idx++];
|
||||
BasicBlock *UnwindDest = nullptr;
|
||||
if (HasUnwindDest) {
|
||||
if (Idx == Record.size())
|
||||
return error("Invalid record");
|
||||
UnwindDest = getBasicBlock(Record[Idx++]);
|
||||
if (!UnwindDest)
|
||||
return error("Invalid record");
|
||||
}
|
||||
unsigned NumArgOperands = Record[Idx++];
|
||||
SmallVector<Value *, 2> Args;
|
||||
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
|
||||
Value *Val;
|
||||
if (getValueTypePair(Record, Idx, NextValueNo, Val))
|
||||
return error("Invalid record");
|
||||
Args.push_back(Val);
|
||||
}
|
||||
if (Record.size() != Idx)
|
||||
return error("Invalid record");
|
||||
|
||||
I = TerminatePadInst::Create(Context, UnwindDest, Args);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_CLEANUPPAD: { // CLEANUPPAD: [ty, num,(ty,val)*]
|
||||
if (Record.size() < 2)
|
||||
return error("Invalid record");
|
||||
unsigned Idx = 0;
|
||||
Type *Ty = getTypeByID(Record[Idx++]);
|
||||
if (!Ty)
|
||||
return error("Invalid record");
|
||||
unsigned NumArgOperands = Record[Idx++];
|
||||
SmallVector<Value *, 2> Args;
|
||||
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
|
||||
Value *Val;
|
||||
if (getValueTypePair(Record, Idx, NextValueNo, Val))
|
||||
return error("Invalid record");
|
||||
Args.push_back(Val);
|
||||
}
|
||||
if (Record.size() != Idx)
|
||||
return error("Invalid record");
|
||||
|
||||
I = CleanupPadInst::Create(Ty, Args);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_CATCHENDPAD: { // CATCHENDPADINST: [bb#] or []
|
||||
if (Record.size() > 1)
|
||||
return error("Invalid record");
|
||||
BasicBlock *BB = nullptr;
|
||||
if (Record.size() == 1) {
|
||||
BB = getBasicBlock(Record[0]);
|
||||
if (!BB)
|
||||
return error("Invalid record");
|
||||
}
|
||||
I = CatchEndPadInst::Create(Context, BB);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
|
||||
// Check magic
|
||||
if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {
|
||||
|
@ -1851,6 +1851,64 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
|
||||
Code = bitc::FUNC_CODE_INST_RESUME;
|
||||
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
||||
break;
|
||||
case Instruction::CleanupRet: {
|
||||
Code = bitc::FUNC_CODE_INST_CLEANUPRET;
|
||||
const auto &CRI = cast<CleanupReturnInst>(I);
|
||||
Vals.push_back(CRI.hasReturnValue());
|
||||
Vals.push_back(CRI.hasUnwindDest());
|
||||
if (CRI.hasReturnValue())
|
||||
PushValueAndType(CRI.getReturnValue(), InstID, Vals, VE);
|
||||
if (CRI.hasUnwindDest())
|
||||
Vals.push_back(VE.getValueID(CRI.getUnwindDest()));
|
||||
break;
|
||||
}
|
||||
case Instruction::CatchRet: {
|
||||
Code = bitc::FUNC_CODE_INST_CATCHRET;
|
||||
const auto &CRI = cast<CatchReturnInst>(I);
|
||||
Vals.push_back(VE.getValueID(CRI.getSuccessor()));
|
||||
break;
|
||||
}
|
||||
case Instruction::CatchPad: {
|
||||
Code = bitc::FUNC_CODE_INST_CATCHPAD;
|
||||
const auto &CPI = cast<CatchPadInst>(I);
|
||||
Vals.push_back(VE.getTypeID(CPI.getType()));
|
||||
Vals.push_back(VE.getValueID(CPI.getNormalDest()));
|
||||
Vals.push_back(VE.getValueID(CPI.getUnwindDest()));
|
||||
unsigned NumArgOperands = CPI.getNumArgOperands();
|
||||
Vals.push_back(NumArgOperands);
|
||||
for (unsigned Op = 0; Op != NumArgOperands; ++Op)
|
||||
PushValueAndType(CPI.getArgOperand(Op), InstID, Vals, VE);
|
||||
break;
|
||||
}
|
||||
case Instruction::TerminatePad: {
|
||||
Code = bitc::FUNC_CODE_INST_TERMINATEPAD;
|
||||
const auto &TPI = cast<TerminatePadInst>(I);
|
||||
Vals.push_back(TPI.hasUnwindDest());
|
||||
if (TPI.hasUnwindDest())
|
||||
Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
|
||||
unsigned NumArgOperands = TPI.getNumArgOperands();
|
||||
Vals.push_back(NumArgOperands);
|
||||
for (unsigned Op = 0; Op != NumArgOperands; ++Op)
|
||||
PushValueAndType(TPI.getArgOperand(Op), InstID, Vals, VE);
|
||||
break;
|
||||
}
|
||||
case Instruction::CleanupPad: {
|
||||
Code = bitc::FUNC_CODE_INST_CLEANUPPAD;
|
||||
const auto &CPI = cast<CleanupPadInst>(I);
|
||||
Vals.push_back(VE.getTypeID(CPI.getType()));
|
||||
unsigned NumOperands = CPI.getNumOperands();
|
||||
Vals.push_back(NumOperands);
|
||||
for (unsigned Op = 0; Op != NumOperands; ++Op)
|
||||
PushValueAndType(CPI.getOperand(Op), InstID, Vals, VE);
|
||||
break;
|
||||
}
|
||||
case Instruction::CatchEndPad: {
|
||||
Code = bitc::FUNC_CODE_INST_CATCHENDPAD;
|
||||
const auto &CEPI = cast<CatchEndPadInst>(I);
|
||||
if (CEPI.hasUnwindDest())
|
||||
Vals.push_back(VE.getValueID(CEPI.getUnwindDest()));
|
||||
break;
|
||||
}
|
||||
case Instruction::Unreachable:
|
||||
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
|
||||
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
|
||||
|
@ -1158,6 +1158,30 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
|
||||
llvm_unreachable("Can't get register for value!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
|
||||
report_fatal_error("visitCleanupRet not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
|
||||
report_fatal_error("visitCatchEndPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
|
||||
report_fatal_error("visitCatchRet not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
|
||||
report_fatal_error("visitCatchPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
|
||||
report_fatal_error("visitTerminatePad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
|
||||
report_fatal_error("visitCleanupPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
|
||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||
auto &DL = DAG.getDataLayout();
|
||||
|
@ -735,6 +735,12 @@ private:
|
||||
void visitSwitch(const SwitchInst &I);
|
||||
void visitIndirectBr(const IndirectBrInst &I);
|
||||
void visitUnreachable(const UnreachableInst &I);
|
||||
void visitCleanupRet(const CleanupReturnInst &I);
|
||||
void visitCatchEndPad(const CatchEndPadInst &I);
|
||||
void visitCatchRet(const CatchReturnInst &I);
|
||||
void visitCatchPad(const CatchPadInst &I);
|
||||
void visitTerminatePad(const TerminatePadInst &TPI);
|
||||
void visitCleanupPad(const CleanupPadInst &CPI);
|
||||
|
||||
uint32_t getEdgeWeight(const MachineBasicBlock *Src,
|
||||
const MachineBasicBlock *Dst) const;
|
||||
|
@ -1571,6 +1571,12 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
|
||||
case Invoke: return 0;
|
||||
case Resume: return 0;
|
||||
case Unreachable: return 0;
|
||||
case CleanupRet: return 0;
|
||||
case CatchEndPad: return 0;
|
||||
case CatchRet: return 0;
|
||||
case CatchPad: return 0;
|
||||
case TerminatePad: return 0;
|
||||
case CleanupPad: return 0;
|
||||
case Add: return ISD::ADD;
|
||||
case FAdd: return ISD::FADD;
|
||||
case Sub: return ISD::SUB;
|
||||
|
@ -2861,8 +2861,66 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||
|
||||
writeOperand(LPI->getClause(i), true);
|
||||
}
|
||||
} else if (const auto *CPI = dyn_cast<CatchPadInst>(&I)) {
|
||||
Out << ' ';
|
||||
TypePrinter.print(I.getType(), Out);
|
||||
|
||||
Out << " [";
|
||||
for (unsigned Op = 0, NumOps = CPI->getNumArgOperands(); Op < NumOps;
|
||||
++Op) {
|
||||
if (Op > 0)
|
||||
Out << ", ";
|
||||
writeOperand(CPI->getArgOperand(Op), /*PrintType=*/true);
|
||||
}
|
||||
Out << "] to ";
|
||||
writeOperand(CPI->getNormalDest(), /*PrintType=*/true);
|
||||
Out << " unwind ";
|
||||
writeOperand(CPI->getUnwindDest(), /*PrintType=*/true);
|
||||
} else if (const auto *TPI = dyn_cast<TerminatePadInst>(&I)) {
|
||||
Out << " [";
|
||||
for (unsigned Op = 0, NumOps = TPI->getNumArgOperands(); Op < NumOps;
|
||||
++Op) {
|
||||
if (Op > 0)
|
||||
Out << ", ";
|
||||
writeOperand(TPI->getArgOperand(Op), /*PrintType=*/true);
|
||||
}
|
||||
Out << "] unwind ";
|
||||
if (TPI->hasUnwindDest())
|
||||
writeOperand(TPI->getUnwindDest(), /*PrintType=*/true);
|
||||
else
|
||||
Out << "to caller";
|
||||
} else if (const auto *CPI = dyn_cast<CleanupPadInst>(&I)) {
|
||||
Out << ' ';
|
||||
TypePrinter.print(I.getType(), Out);
|
||||
|
||||
Out << " [";
|
||||
for (unsigned Op = 0, NumOps = CPI->getNumOperands(); Op < NumOps; ++Op) {
|
||||
if (Op > 0)
|
||||
Out << ", ";
|
||||
writeOperand(CPI->getOperand(Op), /*PrintType=*/true);
|
||||
}
|
||||
Out << "]";
|
||||
} else if (isa<ReturnInst>(I) && !Operand) {
|
||||
Out << " void";
|
||||
} else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
|
||||
if (CRI->hasReturnValue()) {
|
||||
Out << ' ';
|
||||
writeOperand(CRI->getReturnValue(), /*PrintType=*/true);
|
||||
} else {
|
||||
Out << " void";
|
||||
}
|
||||
|
||||
Out << " unwind ";
|
||||
if (CRI->hasUnwindDest())
|
||||
writeOperand(CRI->getUnwindDest(), /*PrintType=*/true);
|
||||
else
|
||||
Out << "to caller";
|
||||
} else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(&I)) {
|
||||
Out << " unwind ";
|
||||
if (CEPI->hasUnwindDest())
|
||||
writeOperand(CEPI->getUnwindDest(), /*PrintType=*/true);
|
||||
else
|
||||
Out << "to caller";
|
||||
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
|
||||
// Print the calling convention being used.
|
||||
if (CI->getCallingConv() != CallingConv::C) {
|
||||
|
@ -197,7 +197,7 @@ BasicBlock::iterator BasicBlock::getFirstInsertionPt() {
|
||||
return end();
|
||||
|
||||
iterator InsertPt = FirstNonPHI;
|
||||
if (isa<LandingPadInst>(InsertPt)) ++InsertPt;
|
||||
if (InsertPt->isEHPad()) ++InsertPt;
|
||||
return InsertPt;
|
||||
}
|
||||
|
||||
@ -333,6 +333,17 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicBlock::canSplitPredecessors() const {
|
||||
const Instruction *FirstNonPHI = getFirstNonPHI();
|
||||
if (isa<LandingPadInst>(FirstNonPHI))
|
||||
return true;
|
||||
// This is perhaps a little conservative because constructs like
|
||||
// CleanupBlockInst are pretty easy to split. However, SplitBlockPredecessors
|
||||
// cannot handle such things just yet.
|
||||
if (FirstNonPHI->isEHPad())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// This splits a basic block into two at the specified
|
||||
/// instruction. Note that all instructions BEFORE the specified iterator stay
|
||||
|
@ -196,6 +196,11 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
||||
case Invoke: return "invoke";
|
||||
case Resume: return "resume";
|
||||
case Unreachable: return "unreachable";
|
||||
case CleanupRet: return "cleanupret";
|
||||
case CatchEndPad: return "catchendpad";
|
||||
case CatchRet: return "catchret";
|
||||
case CatchPad: return "catchpad";
|
||||
case TerminatePad: return "terminatepad";
|
||||
|
||||
// Standard binary operators...
|
||||
case Add: return "add";
|
||||
@ -256,6 +261,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
||||
case ExtractValue: return "extractvalue";
|
||||
case InsertValue: return "insertvalue";
|
||||
case LandingPad: return "landingpad";
|
||||
case CleanupPad: return "cleanuppad";
|
||||
|
||||
default: return "<Invalid operator> ";
|
||||
}
|
||||
@ -407,6 +413,8 @@ bool Instruction::mayReadFromMemory() const {
|
||||
case Instruction::Fence: // FIXME: refine definition of mayReadFromMemory
|
||||
case Instruction::AtomicCmpXchg:
|
||||
case Instruction::AtomicRMW:
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
case Instruction::Call:
|
||||
return !cast<CallInst>(this)->doesNotAccessMemory();
|
||||
@ -427,6 +435,8 @@ bool Instruction::mayWriteToMemory() const {
|
||||
case Instruction::VAArg:
|
||||
case Instruction::AtomicCmpXchg:
|
||||
case Instruction::AtomicRMW:
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
case Instruction::Call:
|
||||
return !cast<CallInst>(this)->onlyReadsMemory();
|
||||
@ -455,6 +465,12 @@ bool Instruction::isAtomic() const {
|
||||
bool Instruction::mayThrow() const {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(this))
|
||||
return !CI->doesNotThrow();
|
||||
if (const auto *CRI = dyn_cast<CleanupReturnInst>(this))
|
||||
return CRI->unwindsToCaller();
|
||||
if (const auto *CEPI = dyn_cast<CatchEndPadInst>(this))
|
||||
return CEPI->unwindsToCaller();
|
||||
if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
|
||||
return TPI->unwindsToCaller();
|
||||
return isa<ResumeInst>(this);
|
||||
}
|
||||
|
||||
|
@ -670,6 +670,303 @@ BasicBlock *ResumeInst::getSuccessorV(unsigned idx) const {
|
||||
llvm_unreachable("ResumeInst has no successors!");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CleanupReturnInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI)
|
||||
: TerminatorInst(CRI.getType(), Instruction::CleanupRet,
|
||||
OperandTraits<CleanupReturnInst>::op_end(this) -
|
||||
CRI.getNumOperands(),
|
||||
CRI.getNumOperands()) {
|
||||
SubclassOptionalData = CRI.SubclassOptionalData;
|
||||
if (Value *RetVal = CRI.getReturnValue())
|
||||
setReturnValue(RetVal);
|
||||
if (BasicBlock *UnwindDest = CRI.getUnwindDest())
|
||||
setUnwindDest(UnwindDest);
|
||||
}
|
||||
|
||||
void CleanupReturnInst::init(Value *RetVal, BasicBlock *UnwindBB) {
|
||||
SubclassOptionalData = 0;
|
||||
if (UnwindBB)
|
||||
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
|
||||
if (RetVal)
|
||||
setInstructionSubclassData(getSubclassDataFromInstruction() | 2);
|
||||
|
||||
if (UnwindBB)
|
||||
setUnwindDest(UnwindBB);
|
||||
if (RetVal)
|
||||
setReturnValue(RetVal);
|
||||
}
|
||||
|
||||
CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
|
||||
BasicBlock *UnwindBB, unsigned Values,
|
||||
Instruction *InsertBefore)
|
||||
: TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
|
||||
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
|
||||
Values, InsertBefore) {
|
||||
init(RetVal, UnwindBB);
|
||||
}
|
||||
|
||||
CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
|
||||
BasicBlock *UnwindBB, unsigned Values,
|
||||
BasicBlock *InsertAtEnd)
|
||||
: TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
|
||||
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
|
||||
Values, InsertAtEnd) {
|
||||
init(RetVal, UnwindBB);
|
||||
}
|
||||
|
||||
BasicBlock *CleanupReturnInst::getUnwindDest() const {
|
||||
if (hasUnwindDest())
|
||||
return cast<BasicBlock>(getOperand(getUnwindLabelOpIdx()));
|
||||
return nullptr;
|
||||
}
|
||||
void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
|
||||
assert(NewDest);
|
||||
setOperand(getUnwindLabelOpIdx(), NewDest);
|
||||
}
|
||||
|
||||
BasicBlock *CleanupReturnInst::getSuccessorV(unsigned Idx) const {
|
||||
assert(Idx == 0);
|
||||
return getUnwindDest();
|
||||
}
|
||||
unsigned CleanupReturnInst::getNumSuccessorsV() const {
|
||||
return getNumSuccessors();
|
||||
}
|
||||
void CleanupReturnInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
|
||||
assert(Idx == 0);
|
||||
setUnwindDest(B);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CatchEndPadInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CatchEndPadInst::CatchEndPadInst(const CatchEndPadInst &CRI)
|
||||
: TerminatorInst(CRI.getType(), Instruction::CatchEndPad,
|
||||
OperandTraits<CatchEndPadInst>::op_end(this) -
|
||||
CRI.getNumOperands(),
|
||||
CRI.getNumOperands()) {
|
||||
SubclassOptionalData = CRI.SubclassOptionalData;
|
||||
if (BasicBlock *UnwindDest = CRI.getUnwindDest())
|
||||
setUnwindDest(UnwindDest);
|
||||
}
|
||||
|
||||
void CatchEndPadInst::init(BasicBlock *UnwindBB) {
|
||||
SubclassOptionalData = 0;
|
||||
if (UnwindBB) {
|
||||
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
|
||||
setUnwindDest(UnwindBB);
|
||||
}
|
||||
}
|
||||
|
||||
CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
|
||||
unsigned Values, Instruction *InsertBefore)
|
||||
: TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
|
||||
OperandTraits<CatchEndPadInst>::op_end(this) - Values,
|
||||
Values, InsertBefore) {
|
||||
init(UnwindBB);
|
||||
}
|
||||
|
||||
CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
|
||||
unsigned Values, BasicBlock *InsertAtEnd)
|
||||
: TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
|
||||
OperandTraits<CatchEndPadInst>::op_end(this) - Values,
|
||||
Values, InsertAtEnd) {
|
||||
init(UnwindBB);
|
||||
}
|
||||
|
||||
BasicBlock *CatchEndPadInst::getSuccessorV(unsigned Idx) const {
|
||||
assert(Idx == 0);
|
||||
return getUnwindDest();
|
||||
}
|
||||
unsigned CatchEndPadInst::getNumSuccessorsV() const {
|
||||
return getNumSuccessors();
|
||||
}
|
||||
void CatchEndPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
|
||||
assert(Idx == 0);
|
||||
setUnwindDest(B);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CatchReturnInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI)
|
||||
: TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet,
|
||||
OperandTraits<CatchReturnInst>::op_end(this) -
|
||||
CRI.getNumOperands(),
|
||||
CRI.getNumOperands()) {
|
||||
Op<0>() = CRI.Op<0>();
|
||||
}
|
||||
|
||||
CatchReturnInst::CatchReturnInst(BasicBlock *BB, Instruction *InsertBefore)
|
||||
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
|
||||
OperandTraits<CatchReturnInst>::op_begin(this), 1,
|
||||
InsertBefore) {
|
||||
Op<0>() = BB;
|
||||
}
|
||||
|
||||
CatchReturnInst::CatchReturnInst(BasicBlock *BB, BasicBlock *InsertAtEnd)
|
||||
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
|
||||
OperandTraits<CatchReturnInst>::op_begin(this), 1,
|
||||
InsertAtEnd) {
|
||||
Op<0>() = BB;
|
||||
}
|
||||
|
||||
BasicBlock *CatchReturnInst::getSuccessorV(unsigned Idx) const {
|
||||
assert(Idx == 0);
|
||||
return getSuccessor();
|
||||
}
|
||||
unsigned CatchReturnInst::getNumSuccessorsV() const {
|
||||
return getNumSuccessors();
|
||||
}
|
||||
void CatchReturnInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
|
||||
assert(Idx == 0);
|
||||
setSuccessor(B);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CatchPadInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
void CatchPadInst::init(BasicBlock *IfNormal, BasicBlock *IfException,
|
||||
ArrayRef<Value *> Args, const Twine &NameStr) {
|
||||
assert(getNumOperands() == 2 + Args.size() && "NumOperands not set up?");
|
||||
Op<-2>() = IfNormal;
|
||||
Op<-1>() = IfException;
|
||||
std::copy(Args.begin(), Args.end(), op_begin());
|
||||
setName(NameStr);
|
||||
}
|
||||
|
||||
CatchPadInst::CatchPadInst(const CatchPadInst &CPI)
|
||||
: TerminatorInst(CPI.getType(), Instruction::CatchPad,
|
||||
OperandTraits<CatchPadInst>::op_end(this) -
|
||||
CPI.getNumOperands(),
|
||||
CPI.getNumOperands()) {
|
||||
std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
|
||||
}
|
||||
|
||||
CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
|
||||
BasicBlock *IfException, ArrayRef<Value *> Args,
|
||||
unsigned Values, const Twine &NameStr,
|
||||
Instruction *InsertBefore)
|
||||
: TerminatorInst(RetTy, Instruction::CatchPad,
|
||||
OperandTraits<CatchPadInst>::op_end(this) - Values,
|
||||
Values, InsertBefore) {
|
||||
init(IfNormal, IfException, Args, NameStr);
|
||||
}
|
||||
|
||||
CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
|
||||
BasicBlock *IfException, ArrayRef<Value *> Args,
|
||||
unsigned Values, const Twine &NameStr,
|
||||
BasicBlock *InsertAtEnd)
|
||||
: TerminatorInst(RetTy, Instruction::CatchPad,
|
||||
OperandTraits<CatchPadInst>::op_end(this) - Values,
|
||||
Values, InsertAtEnd) {
|
||||
init(IfNormal, IfException, Args, NameStr);
|
||||
}
|
||||
|
||||
BasicBlock *CatchPadInst::getSuccessorV(unsigned Idx) const {
|
||||
return getSuccessor(Idx);
|
||||
}
|
||||
unsigned CatchPadInst::getNumSuccessorsV() const {
|
||||
return getNumSuccessors();
|
||||
}
|
||||
void CatchPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
|
||||
return setSuccessor(Idx, B);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TerminatePadInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
void TerminatePadInst::init(BasicBlock *BB, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr) {
|
||||
SubclassOptionalData = 0;
|
||||
if (BB)
|
||||
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
|
||||
if (BB)
|
||||
Op<-1>() = BB;
|
||||
std::copy(Args.begin(), Args.end(), op_begin());
|
||||
setName(NameStr);
|
||||
}
|
||||
|
||||
TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI)
|
||||
: TerminatorInst(TPI.getType(), Instruction::TerminatePad,
|
||||
OperandTraits<TerminatePadInst>::op_end(this) -
|
||||
TPI.getNumOperands(),
|
||||
TPI.getNumOperands()) {
|
||||
SubclassOptionalData = TPI.SubclassOptionalData;
|
||||
std::copy(TPI.op_begin(), TPI.op_end(), op_begin());
|
||||
}
|
||||
|
||||
TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
|
||||
ArrayRef<Value *> Args, unsigned Values,
|
||||
const Twine &NameStr,
|
||||
Instruction *InsertBefore)
|
||||
: TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
|
||||
OperandTraits<TerminatePadInst>::op_end(this) - Values,
|
||||
Values, InsertBefore) {
|
||||
init(BB, Args, NameStr);
|
||||
}
|
||||
|
||||
TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
|
||||
ArrayRef<Value *> Args, unsigned Values,
|
||||
const Twine &NameStr,
|
||||
BasicBlock *InsertAtEnd)
|
||||
: TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
|
||||
OperandTraits<TerminatePadInst>::op_end(this) - Values,
|
||||
Values, InsertAtEnd) {
|
||||
init(BB, Args, NameStr);
|
||||
}
|
||||
|
||||
BasicBlock *TerminatePadInst::getSuccessorV(unsigned Idx) const {
|
||||
assert(Idx == 0);
|
||||
return getUnwindDest();
|
||||
}
|
||||
unsigned TerminatePadInst::getNumSuccessorsV() const {
|
||||
return getNumSuccessors();
|
||||
}
|
||||
void TerminatePadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
|
||||
assert(Idx == 0);
|
||||
return setUnwindDest(B);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CleanupPadInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
void CleanupPadInst::init(ArrayRef<Value *> Args, const Twine &NameStr) {
|
||||
assert(getNumOperands() == Args.size() && "NumOperands not set up?");
|
||||
std::copy(Args.begin(), Args.end(), op_begin());
|
||||
setName(NameStr);
|
||||
}
|
||||
|
||||
CleanupPadInst::CleanupPadInst(const CleanupPadInst &CPI)
|
||||
: Instruction(CPI.getType(), Instruction::CleanupPad,
|
||||
OperandTraits<CleanupPadInst>::op_end(this) -
|
||||
CPI.getNumOperands(),
|
||||
CPI.getNumOperands()) {
|
||||
std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
|
||||
}
|
||||
|
||||
CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr,
|
||||
Instruction *InsertBefore)
|
||||
: Instruction(RetTy, Instruction::CleanupPad,
|
||||
OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
|
||||
Args.size(), InsertBefore) {
|
||||
init(Args, NameStr);
|
||||
}
|
||||
|
||||
CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
|
||||
const Twine &NameStr,
|
||||
BasicBlock *InsertAtEnd)
|
||||
: Instruction(RetTy, Instruction::CleanupPad,
|
||||
OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
|
||||
Args.size(), InsertAtEnd) {
|
||||
init(Args, NameStr);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// UnreachableInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -3618,6 +3915,30 @@ InvokeInst *InvokeInst::cloneImpl() const {
|
||||
|
||||
ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
|
||||
|
||||
CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
|
||||
return new (getNumOperands()) CleanupReturnInst(*this);
|
||||
}
|
||||
|
||||
CatchEndPadInst *CatchEndPadInst::cloneImpl() const {
|
||||
return new (getNumOperands()) CatchEndPadInst(*this);
|
||||
}
|
||||
|
||||
CatchReturnInst *CatchReturnInst::cloneImpl() const {
|
||||
return new (1) CatchReturnInst(*this);
|
||||
}
|
||||
|
||||
CatchPadInst *CatchPadInst::cloneImpl() const {
|
||||
return new (getNumOperands()) CatchPadInst(*this);
|
||||
}
|
||||
|
||||
TerminatePadInst *TerminatePadInst::cloneImpl() const {
|
||||
return new (getNumOperands()) TerminatePadInst(*this);
|
||||
}
|
||||
|
||||
CleanupPadInst *CleanupPadInst::cloneImpl() const {
|
||||
return new (getNumOperands()) CleanupPadInst(*this);
|
||||
}
|
||||
|
||||
UnreachableInst *UnreachableInst::cloneImpl() const {
|
||||
LLVMContext &Context = getContext();
|
||||
return new UnreachableInst(Context);
|
||||
|
@ -184,6 +184,15 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
|
||||
/// \brief Track unresolved string-based type references.
|
||||
SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs;
|
||||
|
||||
/// \brief The result type for a catchpad.
|
||||
Type *CatchPadResultTy;
|
||||
|
||||
/// \brief The result type for a cleanuppad.
|
||||
Type *CleanupPadResultTy;
|
||||
|
||||
/// \brief The result type for a landingpad.
|
||||
Type *LandingPadResultTy;
|
||||
|
||||
/// \brief Whether we've seen a call to @llvm.localescape in this function
|
||||
/// already.
|
||||
bool SawFrameEscape;
|
||||
@ -194,7 +203,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
|
||||
|
||||
public:
|
||||
explicit Verifier(raw_ostream &OS)
|
||||
: VerifierSupport(OS), Context(nullptr), SawFrameEscape(false) {}
|
||||
: VerifierSupport(OS), Context(nullptr), CatchPadResultTy(nullptr),
|
||||
CleanupPadResultTy(nullptr), LandingPadResultTy(nullptr),
|
||||
SawFrameEscape(false) {}
|
||||
|
||||
bool verify(const Function &F) {
|
||||
M = F.getParent();
|
||||
@ -228,6 +239,9 @@ public:
|
||||
// FIXME: We strip const here because the inst visitor strips const.
|
||||
visit(const_cast<Function &>(F));
|
||||
InstsInThisBlock.clear();
|
||||
CatchPadResultTy = nullptr;
|
||||
CleanupPadResultTy = nullptr;
|
||||
LandingPadResultTy = nullptr;
|
||||
SawFrameEscape = false;
|
||||
|
||||
return !Broken;
|
||||
@ -379,6 +393,11 @@ private:
|
||||
void visitExtractValueInst(ExtractValueInst &EVI);
|
||||
void visitInsertValueInst(InsertValueInst &IVI);
|
||||
void visitLandingPadInst(LandingPadInst &LPI);
|
||||
void visitCatchPadInst(CatchPadInst &CPI);
|
||||
void visitCatchEndPadInst(CatchEndPadInst &CEPI);
|
||||
void visitCleanupPadInst(CleanupPadInst &CPI);
|
||||
void visitCleanupReturnInst(CleanupReturnInst &CRI);
|
||||
void visitTerminatePadInst(TerminatePadInst &TPI);
|
||||
|
||||
void VerifyCallSite(CallSite CS);
|
||||
void verifyMustTailCall(CallInst &CI);
|
||||
@ -2385,10 +2404,12 @@ void Verifier::visitCallInst(CallInst &CI) {
|
||||
void Verifier::visitInvokeInst(InvokeInst &II) {
|
||||
VerifyCallSite(&II);
|
||||
|
||||
// Verify that there is a landingpad instruction as the first non-PHI
|
||||
// instruction of the 'unwind' destination.
|
||||
Assert(II.getUnwindDest()->isLandingPad(),
|
||||
"The unwind destination does not have a landingpad instruction!", &II);
|
||||
// Verify that the first non-PHI instruction of the unwind destination is an
|
||||
// exception handling instruction.
|
||||
Assert(
|
||||
II.getUnwindDest()->isEHPad(),
|
||||
"The unwind destination does not have an exception handling instruction!",
|
||||
&II);
|
||||
|
||||
visitTerminatorInst(II);
|
||||
}
|
||||
@ -2774,6 +2795,14 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
|
||||
&LPI);
|
||||
}
|
||||
|
||||
if (!LandingPadResultTy)
|
||||
LandingPadResultTy = LPI.getType();
|
||||
else
|
||||
Assert(LandingPadResultTy == LPI.getType(),
|
||||
"The landingpad instruction should have a consistent result type "
|
||||
"inside a function.",
|
||||
&LPI);
|
||||
|
||||
Function *F = LPI.getParent()->getParent();
|
||||
Assert(F->hasPersonalityFn(),
|
||||
"LandingPadInst needs to be in a function with a personality.", &LPI);
|
||||
@ -2799,6 +2828,132 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
|
||||
visitInstruction(LPI);
|
||||
}
|
||||
|
||||
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
|
||||
BasicBlock *BB = CPI.getParent();
|
||||
|
||||
if (!CatchPadResultTy)
|
||||
CatchPadResultTy = CPI.getType();
|
||||
else
|
||||
Assert(CatchPadResultTy == CPI.getType(),
|
||||
"The catchpad instruction should have a consistent result type "
|
||||
"inside a function.",
|
||||
&CPI);
|
||||
|
||||
Function *F = BB->getParent();
|
||||
Assert(F->hasPersonalityFn(),
|
||||
"CatchPadInst needs to be in a function with a personality.", &CPI);
|
||||
|
||||
// The catchpad instruction must be the first non-PHI instruction in the
|
||||
// block.
|
||||
Assert(BB->getFirstNonPHI() == &CPI,
|
||||
"CatchPadInst not the first non-PHI instruction in the block.",
|
||||
&CPI);
|
||||
|
||||
BasicBlock *UnwindDest = CPI.getUnwindDest();
|
||||
Instruction *I = UnwindDest->getFirstNonPHI();
|
||||
Assert(
|
||||
isa<CatchPadInst>(I) || isa<CatchEndPadInst>(I),
|
||||
"CatchPadInst must unwind to a CatchPadInst or a CatchEndPadInst.",
|
||||
&CPI);
|
||||
|
||||
visitTerminatorInst(CPI);
|
||||
}
|
||||
|
||||
void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) {
|
||||
BasicBlock *BB = CEPI.getParent();
|
||||
|
||||
Function *F = BB->getParent();
|
||||
Assert(F->hasPersonalityFn(),
|
||||
"CatchEndPadInst needs to be in a function with a personality.",
|
||||
&CEPI);
|
||||
|
||||
// The catchendpad instruction must be the first non-PHI instruction in the
|
||||
// block.
|
||||
Assert(BB->getFirstNonPHI() == &CEPI,
|
||||
"CatchEndPadInst not the first non-PHI instruction in the block.",
|
||||
&CEPI);
|
||||
|
||||
unsigned CatchPadsSeen = 0;
|
||||
for (BasicBlock *PredBB : predecessors(BB))
|
||||
if (isa<CatchPadInst>(PredBB->getTerminator()))
|
||||
++CatchPadsSeen;
|
||||
|
||||
Assert(CatchPadsSeen <= 1, "CatchEndPadInst must have no more than one "
|
||||
"CatchPadInst predecessor.",
|
||||
&CEPI);
|
||||
|
||||
if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) {
|
||||
Instruction *I = UnwindDest->getFirstNonPHI();
|
||||
Assert(
|
||||
I->isEHPad() && !isa<LandingPadInst>(I),
|
||||
"CatchEndPad must unwind to an EH block which is not a landingpad.",
|
||||
&CEPI);
|
||||
}
|
||||
|
||||
visitTerminatorInst(CEPI);
|
||||
}
|
||||
|
||||
void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
|
||||
BasicBlock *BB = CPI.getParent();
|
||||
|
||||
if (!CleanupPadResultTy)
|
||||
CleanupPadResultTy = CPI.getType();
|
||||
else
|
||||
Assert(CleanupPadResultTy == CPI.getType(),
|
||||
"The cleanuppad instruction should have a consistent result type "
|
||||
"inside a function.",
|
||||
&CPI);
|
||||
|
||||
Function *F = BB->getParent();
|
||||
Assert(F->hasPersonalityFn(),
|
||||
"CleanupPadInst needs to be in a function with a personality.", &CPI);
|
||||
|
||||
// The cleanuppad instruction must be the first non-PHI instruction in the
|
||||
// block.
|
||||
Assert(BB->getFirstNonPHI() == &CPI,
|
||||
"CleanupPadInst not the first non-PHI instruction in the block.",
|
||||
&CPI);
|
||||
|
||||
visitInstruction(CPI);
|
||||
}
|
||||
|
||||
void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
|
||||
if (BasicBlock *UnwindDest = CRI.getUnwindDest()) {
|
||||
Instruction *I = UnwindDest->getFirstNonPHI();
|
||||
Assert(I->isEHPad() && !isa<LandingPadInst>(I),
|
||||
"CleanupReturnInst must unwind to an EH block which is not a "
|
||||
"landingpad.",
|
||||
&CRI);
|
||||
}
|
||||
|
||||
visitTerminatorInst(CRI);
|
||||
}
|
||||
|
||||
void Verifier::visitTerminatePadInst(TerminatePadInst &TPI) {
|
||||
BasicBlock *BB = TPI.getParent();
|
||||
|
||||
Function *F = BB->getParent();
|
||||
Assert(F->hasPersonalityFn(),
|
||||
"TerminatePadInst needs to be in a function with a personality.",
|
||||
&TPI);
|
||||
|
||||
// The terminatepad instruction must be the first non-PHI instruction in the
|
||||
// block.
|
||||
Assert(BB->getFirstNonPHI() == &TPI,
|
||||
"TerminatePadInst not the first non-PHI instruction in the block.",
|
||||
&TPI);
|
||||
|
||||
if (BasicBlock *UnwindDest = TPI.getUnwindDest()) {
|
||||
Instruction *I = UnwindDest->getFirstNonPHI();
|
||||
Assert(I->isEHPad() && !isa<LandingPadInst>(I),
|
||||
"TerminatePadInst must unwind to an EH block which is not a "
|
||||
"landingpad.",
|
||||
&TPI);
|
||||
}
|
||||
|
||||
visitTerminatorInst(TPI);
|
||||
}
|
||||
|
||||
void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
|
||||
Instruction *Op = cast<Instruction>(I.getOperand(i));
|
||||
// If the we have an invalid invoke, don't try to compute the dominance.
|
||||
|
@ -2653,6 +2653,30 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
||||
setOrigin(&I, getCleanOrigin());
|
||||
}
|
||||
|
||||
void visitCleanupPadInst(CleanupPadInst &I) {
|
||||
if (!I.getType()->isVoidTy()) {
|
||||
setShadow(&I, getCleanShadow(&I));
|
||||
setOrigin(&I, getCleanOrigin());
|
||||
}
|
||||
}
|
||||
|
||||
void visitCatchPad(CatchPadInst &I) {
|
||||
if (!I.getType()->isVoidTy()) {
|
||||
setShadow(&I, getCleanShadow(&I));
|
||||
setOrigin(&I, getCleanOrigin());
|
||||
}
|
||||
}
|
||||
|
||||
void visitTerminatePad(TerminatePadInst &I) {
|
||||
DEBUG(dbgs() << "TerminatePad: " << I << "\n");
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
void visitCatchEndPadInst(CatchEndPadInst &I) {
|
||||
DEBUG(dbgs() << "CatchEndPad: " << I << "\n");
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
void visitGetElementPtrInst(GetElementPtrInst &I) {
|
||||
handleShadowOr(I);
|
||||
}
|
||||
@ -2696,6 +2720,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
void visitCleanupReturnInst(CleanupReturnInst &CRI) {
|
||||
DEBUG(dbgs() << "CleanupReturn: " << CRI << "\n");
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
void visitCatchReturnInst(CatchReturnInst &CRI) {
|
||||
DEBUG(dbgs() << "CatchReturn: " << CRI << "\n");
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
void visitInstruction(Instruction &I) {
|
||||
// Everything else: stop propagating and check for poisoned shadow.
|
||||
if (ClDumpStrictInstructions)
|
||||
|
@ -58,8 +58,8 @@ bool ADCE::runOnFunction(Function& F) {
|
||||
|
||||
// Collect the set of "root" instructions that are known live.
|
||||
for (Instruction &I : inst_range(F)) {
|
||||
if (isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
|
||||
isa<LandingPadInst>(I) || I.mayHaveSideEffects()) {
|
||||
if (isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || I.isEHPad() ||
|
||||
I.mayHaveSideEffects()) {
|
||||
Alive.insert(&I);
|
||||
Worklist.push_back(&I);
|
||||
}
|
||||
|
@ -77,8 +77,8 @@ INITIALIZE_PASS_END(BDCE, "bdce", "Bit-Tracking Dead Code Elimination",
|
||||
false, false)
|
||||
|
||||
static bool isAlwaysLive(Instruction *I) {
|
||||
return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
|
||||
isa<LandingPadInst>(I) || I->mayHaveSideEffects();
|
||||
return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || I->isEHPad() ||
|
||||
I->mayHaveSideEffects();
|
||||
}
|
||||
|
||||
void BDCE::determineLiveOperandBits(const Instruction *UserI,
|
||||
|
@ -669,7 +669,8 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
|
||||
// because now the condition in this block can be threaded through
|
||||
// predecessors of our predecessor block.
|
||||
if (BasicBlock *SinglePred = BB->getSinglePredecessor()) {
|
||||
if (SinglePred->getTerminator()->getNumSuccessors() == 1 &&
|
||||
const TerminatorInst *TI = SinglePred->getTerminator();
|
||||
if (!TI->isExceptional() && TI->getNumSuccessors() == 1 &&
|
||||
SinglePred != BB && !hasAddressTakenAndUsed(BB)) {
|
||||
// If SinglePred was a loop header, BB becomes one.
|
||||
if (LoopHeaders.erase(SinglePred))
|
||||
|
@ -539,9 +539,9 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
|
||||
return;
|
||||
}
|
||||
|
||||
if (isa<InvokeInst>(TI)) {
|
||||
// Invoke instructions successors are always executable.
|
||||
Succs[0] = Succs[1] = true;
|
||||
// Unwinding instructions successors are always executable.
|
||||
if (TI.isExceptional()) {
|
||||
Succs.assign(TI.getNumSuccessors(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -605,8 +605,8 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
|
||||
return BI->getSuccessor(CI->isZero()) == To;
|
||||
}
|
||||
|
||||
// Invoke instructions successors are always executable.
|
||||
if (isa<InvokeInst>(TI))
|
||||
// Unwinding instructions successors are always executable.
|
||||
if (TI->isExceptional())
|
||||
return true;
|
||||
|
||||
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
|
||||
|
@ -117,8 +117,9 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT,
|
||||
|
||||
// Don't break self-loops.
|
||||
if (PredBB == BB) return false;
|
||||
// Don't break invokes.
|
||||
if (isa<InvokeInst>(PredBB->getTerminator())) return false;
|
||||
// Don't break unwinding instructions.
|
||||
if (PredBB->getTerminator()->isExceptional())
|
||||
return false;
|
||||
|
||||
succ_iterator SI(succ_begin(PredBB)), SE(succ_end(PredBB));
|
||||
BasicBlock *OnlySucc = BB;
|
||||
@ -283,7 +284,7 @@ llvm::SplitAllCriticalEdges(Function &F,
|
||||
BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
|
||||
DominatorTree *DT, LoopInfo *LI) {
|
||||
BasicBlock::iterator SplitIt = SplitPt;
|
||||
while (isa<PHINode>(SplitIt) || isa<LandingPadInst>(SplitIt))
|
||||
while (isa<PHINode>(SplitIt) || SplitIt->isEHPad())
|
||||
++SplitIt;
|
||||
BasicBlock *New = Old->splitBasicBlock(SplitIt, Old->getName()+".split");
|
||||
|
||||
@ -474,6 +475,10 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
|
||||
ArrayRef<BasicBlock *> Preds,
|
||||
const char *Suffix, DominatorTree *DT,
|
||||
LoopInfo *LI, bool PreserveLCSSA) {
|
||||
// Do not attempt to split that which cannot be split.
|
||||
if (!BB->canSplitPredecessors())
|
||||
return nullptr;
|
||||
|
||||
// For the landingpads we need to act a bit differently.
|
||||
// Delegate this work to the SplitLandingPadPredecessors.
|
||||
if (BB->isLandingPad()) {
|
||||
|
@ -63,8 +63,8 @@ bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// A class for recording information about inlining through an invoke.
|
||||
class InvokeInliningInfo {
|
||||
/// A class for recording information about inlining a landing pad.
|
||||
class LandingPadInliningInfo {
|
||||
BasicBlock *OuterResumeDest; ///< Destination of the invoke's unwind.
|
||||
BasicBlock *InnerResumeDest; ///< Destination for the callee's resume.
|
||||
LandingPadInst *CallerLPad; ///< LandingPadInst associated with the invoke.
|
||||
@ -72,7 +72,7 @@ namespace {
|
||||
SmallVector<Value*, 8> UnwindDestPHIValues;
|
||||
|
||||
public:
|
||||
InvokeInliningInfo(InvokeInst *II)
|
||||
LandingPadInliningInfo(InvokeInst *II)
|
||||
: OuterResumeDest(II->getUnwindDest()), InnerResumeDest(nullptr),
|
||||
CallerLPad(nullptr), InnerEHValuesPHI(nullptr) {
|
||||
// If there are PHI nodes in the unwind destination block, we need to keep
|
||||
@ -124,7 +124,7 @@ namespace {
|
||||
}
|
||||
|
||||
/// Get or create a target for the branch from ResumeInsts.
|
||||
BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
|
||||
BasicBlock *LandingPadInliningInfo::getInnerResumeDest() {
|
||||
if (InnerResumeDest) return InnerResumeDest;
|
||||
|
||||
// Split the landing pad.
|
||||
@ -162,8 +162,8 @@ BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
|
||||
/// When the landing pad block has only one predecessor, this is a simple
|
||||
/// branch. When there is more than one predecessor, we need to split the
|
||||
/// landing pad block after the landingpad instruction and jump to there.
|
||||
void InvokeInliningInfo::forwardResume(ResumeInst *RI,
|
||||
SmallPtrSetImpl<LandingPadInst*> &InlinedLPads) {
|
||||
void LandingPadInliningInfo::forwardResume(
|
||||
ResumeInst *RI, SmallPtrSetImpl<LandingPadInst *> &InlinedLPads) {
|
||||
BasicBlock *Dest = getInnerResumeDest();
|
||||
BasicBlock *Src = RI->getParent();
|
||||
|
||||
@ -182,8 +182,8 @@ void InvokeInliningInfo::forwardResume(ResumeInst *RI,
|
||||
/// This function analyze BB to see if there are any calls, and if so,
|
||||
/// it rewrites them to be invokes that jump to InvokeDest and fills in the PHI
|
||||
/// nodes in that block with the values specified in InvokeDestPHIValues.
|
||||
static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
|
||||
InvokeInliningInfo &Invoke) {
|
||||
static BasicBlock *
|
||||
HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, BasicBlock *UnwindEdge) {
|
||||
for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
|
||||
Instruction *I = BBI++;
|
||||
|
||||
@ -206,8 +206,7 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
|
||||
// Create the new invoke instruction.
|
||||
ImmutableCallSite CS(CI);
|
||||
SmallVector<Value*, 8> InvokeArgs(CS.arg_begin(), CS.arg_end());
|
||||
InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split,
|
||||
Invoke.getOuterResumeDest(),
|
||||
InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split, UnwindEdge,
|
||||
InvokeArgs, CI->getName(), BB);
|
||||
II->setDebugLoc(CI->getDebugLoc());
|
||||
II->setCallingConv(CI->getCallingConv());
|
||||
@ -219,12 +218,9 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
|
||||
|
||||
// Delete the original call
|
||||
Split->getInstList().pop_front();
|
||||
|
||||
// Update any PHI nodes in the exceptional block to indicate that there is
|
||||
// now a new entry in them.
|
||||
Invoke.addIncomingPHIValuesFor(BB);
|
||||
return;
|
||||
return BB;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If we inlined an invoke site, we need to convert calls
|
||||
@ -233,8 +229,8 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
|
||||
/// II is the invoke instruction being inlined. FirstNewBlock is the first
|
||||
/// block of the inlined code (the last block is the end of the function),
|
||||
/// and InlineCodeInfo is information about the code that got inlined.
|
||||
static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
ClonedCodeInfo &InlinedCodeInfo) {
|
||||
static void HandleInlinedLandingPad(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
ClonedCodeInfo &InlinedCodeInfo) {
|
||||
BasicBlock *InvokeDest = II->getUnwindDest();
|
||||
|
||||
Function *Caller = FirstNewBlock->getParent();
|
||||
@ -242,7 +238,7 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
// The inlined code is currently at the end of the function, scan from the
|
||||
// start of the inlined code to its end, checking for stuff we need to
|
||||
// rewrite.
|
||||
InvokeInliningInfo Invoke(II);
|
||||
LandingPadInliningInfo Invoke(II);
|
||||
|
||||
// Get all of the inlined landing pad instructions.
|
||||
SmallPtrSet<LandingPadInst*, 16> InlinedLPads;
|
||||
@ -264,7 +260,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
|
||||
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB){
|
||||
if (InlinedCodeInfo.ContainsCalls)
|
||||
HandleCallsInBlockInlinedThroughInvoke(BB, Invoke);
|
||||
if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
|
||||
BB, Invoke.getOuterResumeDest()))
|
||||
// Update any PHI nodes in the exceptional block to indicate that there
|
||||
// is now a new entry in them.
|
||||
Invoke.addIncomingPHIValuesFor(NewBB);
|
||||
|
||||
// Forward any resumes that are remaining here.
|
||||
if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator()))
|
||||
@ -278,6 +278,102 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
InvokeDest->removePredecessor(II->getParent());
|
||||
}
|
||||
|
||||
/// If we inlined an invoke site, we need to convert calls
|
||||
/// in the body of the inlined function into invokes.
|
||||
///
|
||||
/// II is the invoke instruction being inlined. FirstNewBlock is the first
|
||||
/// block of the inlined code (the last block is the end of the function),
|
||||
/// and InlineCodeInfo is information about the code that got inlined.
|
||||
static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
ClonedCodeInfo &InlinedCodeInfo) {
|
||||
BasicBlock *UnwindDest = II->getUnwindDest();
|
||||
Function *Caller = FirstNewBlock->getParent();
|
||||
|
||||
assert(UnwindDest->getFirstNonPHI()->isEHPad() && "unexpected BasicBlock!");
|
||||
|
||||
// If there are PHI nodes in the unwind destination block, we need to keep
|
||||
// track of which values came into them from the invoke before removing the
|
||||
// edge from this block.
|
||||
SmallVector<Value *, 8> UnwindDestPHIValues;
|
||||
llvm::BasicBlock *InvokeBB = II->getParent();
|
||||
for (Instruction &I : *UnwindDest) {
|
||||
// Save the value to use for this edge.
|
||||
PHINode *PHI = dyn_cast<PHINode>(&I);
|
||||
if (!PHI)
|
||||
break;
|
||||
UnwindDestPHIValues.push_back(PHI->getIncomingValueForBlock(InvokeBB));
|
||||
}
|
||||
|
||||
// Add incoming-PHI values to the unwind destination block for the given basic
|
||||
// block, using the values for the original invoke's source block.
|
||||
auto UpdatePHINodes = [&](BasicBlock *Src) {
|
||||
BasicBlock::iterator I = UnwindDest->begin();
|
||||
for (Value *V : UnwindDestPHIValues) {
|
||||
PHINode *PHI = cast<PHINode>(I);
|
||||
PHI->addIncoming(V, Src);
|
||||
++I;
|
||||
}
|
||||
};
|
||||
|
||||
// Forward EH terminator instructions to the caller's invoke destination.
|
||||
// This is as simple as connect all the instructions which 'unwind to caller'
|
||||
// to the invoke destination.
|
||||
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
|
||||
++BB) {
|
||||
Instruction *I = BB->getFirstNonPHI();
|
||||
if (I->isEHPad()) {
|
||||
if (auto *CEPI = dyn_cast<CatchEndPadInst>(I)) {
|
||||
if (CEPI->unwindsToCaller()) {
|
||||
CatchEndPadInst::Create(CEPI->getContext(), UnwindDest, CEPI);
|
||||
CEPI->eraseFromParent();
|
||||
UpdatePHINodes(BB);
|
||||
}
|
||||
} else if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
|
||||
if (TPI->unwindsToCaller()) {
|
||||
SmallVector<Value *, 3> TerminatePadArgs;
|
||||
for (Value *Operand : TPI->operands())
|
||||
TerminatePadArgs.push_back(Operand);
|
||||
TerminatePadInst::Create(TPI->getContext(), UnwindDest, TPI);
|
||||
TPI->eraseFromParent();
|
||||
UpdatePHINodes(BB);
|
||||
}
|
||||
} else if (auto *CPI = dyn_cast<CleanupPadInst>(I)) {
|
||||
if (CPI->getNumOperands() == 0) {
|
||||
CleanupPadInst::Create(CPI->getType(), {UnwindDest}, CPI->getName(),
|
||||
CPI);
|
||||
CPI->eraseFromParent();
|
||||
}
|
||||
} else {
|
||||
assert(isa<CatchPadInst>(I));
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) {
|
||||
if (CRI->unwindsToCaller()) {
|
||||
CleanupReturnInst::Create(CRI->getContext(), CRI->getReturnValue(),
|
||||
UnwindDest, CRI);
|
||||
CRI->eraseFromParent();
|
||||
UpdatePHINodes(BB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (InlinedCodeInfo.ContainsCalls)
|
||||
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
|
||||
++BB)
|
||||
if (BasicBlock *NewBB =
|
||||
HandleCallsInBlockInlinedThroughInvoke(BB, UnwindDest))
|
||||
// Update any PHI nodes in the exceptional block to indicate that there
|
||||
// is now a new entry in them.
|
||||
UpdatePHINodes(NewBB);
|
||||
|
||||
// Now that everything is happy, we have one final detail. The PHI nodes in
|
||||
// the exception destination block still have entries due to the original
|
||||
// invoke instruction. Eliminate these entries (which might even delete the
|
||||
// PHI node) now.
|
||||
UnwindDest->removePredecessor(InvokeBB);
|
||||
}
|
||||
|
||||
/// When inlining a function that contains noalias scope metadata,
|
||||
/// this metadata needs to be cloned so that the inlined blocks
|
||||
/// have different "unqiue scopes" at every call site. Were this not done, then
|
||||
@ -1204,8 +1300,15 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
|
||||
// If we are inlining for an invoke instruction, we must make sure to rewrite
|
||||
// any call instructions into invoke instructions.
|
||||
if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall))
|
||||
HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo);
|
||||
if (auto *II = dyn_cast<InvokeInst>(TheCall)) {
|
||||
BasicBlock *UnwindDest = II->getUnwindDest();
|
||||
Instruction *FirstNonPHI = UnwindDest->getFirstNonPHI();
|
||||
if (isa<LandingPadInst>(FirstNonPHI)) {
|
||||
HandleInlinedLandingPad(II, FirstNewBlock, InlinedFunctionInfo);
|
||||
} else {
|
||||
HandleInlinedEHPad(II, FirstNewBlock, InlinedFunctionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle any inlined musttail call sites. In order for a new call site to be
|
||||
// musttail, the source of the clone and the inlined call site must have been
|
||||
|
@ -283,8 +283,9 @@ bool llvm::isInstructionTriviallyDead(Instruction *I,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (!I->use_empty() || isa<TerminatorInst>(I)) return false;
|
||||
|
||||
// We don't want the landingpad instruction removed by anything this general.
|
||||
if (isa<LandingPadInst>(I))
|
||||
// We don't want the landingpad-like instructions removed by anything this
|
||||
// general.
|
||||
if (I->isEHPad())
|
||||
return false;
|
||||
|
||||
// We don't want debug info removed by anything this general, unless
|
||||
|
@ -142,6 +142,8 @@ BasicBlock *llvm::InsertPreheaderForLoop(Loop *L, Pass *PP) {
|
||||
BasicBlock *PreheaderBB;
|
||||
PreheaderBB = SplitBlockPredecessors(Header, OutsideBlocks, ".preheader", DT,
|
||||
LI, PreserveLCSSA);
|
||||
if (!PreheaderBB)
|
||||
return nullptr;
|
||||
|
||||
DEBUG(dbgs() << "LoopSimplify: Creating pre-header "
|
||||
<< PreheaderBB->getName() << "\n");
|
||||
@ -178,6 +180,8 @@ static BasicBlock *rewriteLoopExitBlock(Loop *L, BasicBlock *Exit,
|
||||
|
||||
NewExitBB = SplitBlockPredecessors(Exit, LoopBlocks, ".loopexit", DT, LI,
|
||||
PreserveLCSSA);
|
||||
if (!NewExitBB)
|
||||
return nullptr;
|
||||
|
||||
DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "
|
||||
<< NewExitBB->getName() << "\n");
|
||||
@ -256,8 +260,10 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
|
||||
return nullptr;
|
||||
|
||||
// The header is not a landing pad; preheader insertion should ensure this.
|
||||
assert(!L->getHeader()->isLandingPad() &&
|
||||
"Can't insert backedge to landing pad");
|
||||
BasicBlock *Header = L->getHeader();
|
||||
assert(!Header->isLandingPad() && "Can't insert backedge to landing pad");
|
||||
if (!Header->canSplitPredecessors())
|
||||
return nullptr;
|
||||
|
||||
PHINode *PN = findPHIToPartitionLoops(L, DT, AC);
|
||||
if (!PN) return nullptr; // No known way to partition.
|
||||
@ -285,7 +291,6 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
|
||||
|
||||
bool PreserveLCSSA = PP->mustPreserveAnalysisID(LCSSAID);
|
||||
|
||||
BasicBlock *Header = L->getHeader();
|
||||
BasicBlock *NewBB = SplitBlockPredecessors(Header, OuterLoopPreds, ".outer",
|
||||
DT, LI, PreserveLCSSA);
|
||||
|
||||
|
@ -25,3 +25,74 @@ lpad: ; preds = %entry
|
||||
declare void @_Z3quxv() optsize
|
||||
|
||||
declare i32 @__gxx_personality_v0(...)
|
||||
|
||||
define void @cleanupret0() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
br label %bb
|
||||
bb:
|
||||
cleanuppad void [i7 4]
|
||||
cleanupret i8 0 unwind label %bb
|
||||
}
|
||||
|
||||
define void @cleanupret1() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
br label %bb
|
||||
bb:
|
||||
cleanuppad void [i7 4]
|
||||
cleanupret void unwind label %bb
|
||||
}
|
||||
|
||||
define void @cleanupret2() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
cleanupret i8 0 unwind to caller
|
||||
}
|
||||
|
||||
define void @cleanupret3() personality i32 (...)* @__gxx_personality_v0 {
|
||||
cleanupret void unwind to caller
|
||||
}
|
||||
|
||||
define void @catchret() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
br label %bb
|
||||
bb:
|
||||
catchret label %bb
|
||||
}
|
||||
|
||||
define i8 @catchpad() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
br label %bb2
|
||||
bb:
|
||||
ret i8 %cbv
|
||||
bb2:
|
||||
%cbv = catchpad i8 [i7 4] to label %bb unwind label %bb2
|
||||
}
|
||||
|
||||
define void @terminatepad0() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
br label %bb
|
||||
bb:
|
||||
terminatepad [i7 4] unwind label %bb
|
||||
}
|
||||
|
||||
define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
terminatepad [i7 4] unwind to caller
|
||||
}
|
||||
|
||||
define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
cleanuppad void [i7 4]
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @catchendpad0() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
br label %bb
|
||||
bb:
|
||||
catchendpad unwind label %bb
|
||||
}
|
||||
|
||||
define void @catchendpad1() personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
catchendpad unwind to caller
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
; PR1042
|
||||
define i32 @foo() {
|
||||
; CHECK: The unwind destination does not have a landingpad instruction
|
||||
; CHECK: The unwind destination does not have an exception handling instruction
|
||||
%A = invoke i32 @foo( )
|
||||
to label %L unwind label %L ; <i32> [#uses=1]
|
||||
L: ; preds = %0, %0
|
||||
@ -18,7 +18,7 @@ L1: ; preds = %0
|
||||
L2: ; preds = %0
|
||||
br label %L
|
||||
L: ; preds = %L2, %L1, %L1
|
||||
; CHECK: The unwind destination does not have a landingpad instruction
|
||||
; CHECK: The unwind destination does not have an exception handling instruction
|
||||
ret i32 %A
|
||||
}
|
||||
|
||||
|
@ -241,6 +241,11 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHENDPAD)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_TERMINATEPAD)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_PHI)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
|
||||
|
Loading…
x
Reference in New Issue
Block a user