mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[IR] Remove terminatepad
It turns out that terminatepad gives little benefit over a cleanuppad which calls the termination function. This is not sufficient to implement fully generic filters but MSVC doesn't support them which makes terminatepad a little over-designed. Depends on D15478. Differential Revision: http://reviews.llvm.org/D15479 llvm-svn: 255522
This commit is contained in:
parent
252af42f99
commit
49dcd13916
@ -615,15 +615,11 @@ purposes.
|
|||||||
The following new instructions are considered "exception handling pads", in that
|
The following new instructions are considered "exception handling pads", in that
|
||||||
they must be the first non-phi instruction of a basic block that may be the
|
they must be the first non-phi instruction of a basic block that may be the
|
||||||
unwind destination of an EH flow edge:
|
unwind destination of an EH flow edge:
|
||||||
``catchswitch``, ``catchpad``, ``cleanuppad``, and ``terminatepad``.
|
``catchswitch``, ``catchpad``, and ``cleanuppad``.
|
||||||
As with landingpads, when entering a try scope, if the
|
As with landingpads, when entering a try scope, if the
|
||||||
frontend encounters a call site that may throw an exception, it should emit an
|
frontend encounters a call site that may throw an exception, it should emit an
|
||||||
invoke that unwinds to a ``catchswitch`` block. Similarly, inside the scope of a
|
invoke that unwinds to a ``catchswitch`` block. Similarly, inside the scope of a
|
||||||
C++ object with a destructor, invokes should unwind to a ``cleanuppad``. The
|
C++ object with a destructor, invokes should unwind to a ``cleanuppad``.
|
||||||
``terminatepad`` instruction exists to represent ``noexcept`` and throw
|
|
||||||
specifications with one combined instruction. All potentially throwing calls in
|
|
||||||
a ``noexcept`` function should transitively unwind to a terminateblock. Throw
|
|
||||||
specifications are not implemented by MSVC, and are not yet supported.
|
|
||||||
|
|
||||||
New instructions are also used to mark the points where control is transferred
|
New instructions are also used to mark the points where control is transferred
|
||||||
out of a catch/cleanup handler (which will correspond to exits from the
|
out of a catch/cleanup handler (which will correspond to exits from the
|
||||||
@ -634,9 +630,9 @@ by normal execution executes a ``cleanupret`` instruction, which is a terminator
|
|||||||
indicating where the active exception will unwind to next.
|
indicating where the active exception will unwind to next.
|
||||||
|
|
||||||
Each of these new EH pad instructions has a way to identify which action should
|
Each of these new EH pad instructions has a way to identify which action should
|
||||||
be considered after this action. The ``catchswitch`` and ``terminatepad``
|
be considered after this action. The ``catchswitch`` instruction is a terminator
|
||||||
instructions are terminators, and have a unwind destination operand analogous
|
and has an unwind destination operand analogous to the unwind destination of an
|
||||||
to the unwind destination of an invoke. The ``cleanuppad`` instruction is not
|
invoke. The ``cleanuppad`` instruction is not
|
||||||
a terminator, so the unwind destination is stored on the ``cleanupret``
|
a terminator, so the unwind destination is stored on the ``cleanupret``
|
||||||
instruction instead. Successfully executing a catch handler should resume
|
instruction instead. Successfully executing a catch handler should resume
|
||||||
normal control flow, so neither ``catchpad`` nor ``catchret`` instructions can
|
normal control flow, so neither ``catchpad`` nor ``catchret`` instructions can
|
||||||
@ -707,7 +703,9 @@ all of the new IR instructions:
|
|||||||
catchret from %catch to label %return
|
catchret from %catch to label %return
|
||||||
|
|
||||||
lpad.terminate: ; preds = %catch.body, %lpad.catch
|
lpad.terminate: ; preds = %catch.body, %lpad.catch
|
||||||
terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
|
cleanuppad within none []
|
||||||
|
call void @"\01?terminate@@YAXXZ"
|
||||||
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
Funclet parent tokens
|
Funclet parent tokens
|
||||||
@ -725,8 +723,7 @@ The ``catchswitch`` instruction does not create a funclet, but it produces a
|
|||||||
token that is always consumed by its immediate successor ``catchpad``
|
token that is always consumed by its immediate successor ``catchpad``
|
||||||
instructions. This ensures that every catch handler modelled by a ``catchpad``
|
instructions. This ensures that every catch handler modelled by a ``catchpad``
|
||||||
belongs to exactly one ``catchswitch``, which models the dispatch point after a
|
belongs to exactly one ``catchswitch``, which models the dispatch point after a
|
||||||
C++ try. The ``terminatepad`` instruction cannot contain lexically nested
|
C++ try.
|
||||||
funclets inside the termination action, so it does not produce a token.
|
|
||||||
|
|
||||||
Here is an example of what this nesting looks like using some hypothetical
|
Here is an example of what this nesting looks like using some hypothetical
|
||||||
C++ code:
|
C++ code:
|
||||||
|
@ -5004,7 +5004,6 @@ The terminator instructions are: ':ref:`ret <i_ret>`',
|
|||||||
':ref:`resume <i_resume>`', ':ref:`catchswitch <i_catchswitch>`',
|
':ref:`resume <i_resume>`', ':ref:`catchswitch <i_catchswitch>`',
|
||||||
':ref:`catchret <i_catchret>`',
|
':ref:`catchret <i_catchret>`',
|
||||||
':ref:`cleanupret <i_cleanupret>`',
|
':ref:`cleanupret <i_cleanupret>`',
|
||||||
':ref:`terminatepad <i_terminatepad>`',
|
|
||||||
and ':ref:`unreachable <i_unreachable>`'.
|
and ':ref:`unreachable <i_unreachable>`'.
|
||||||
|
|
||||||
.. _i_ret:
|
.. _i_ret:
|
||||||
@ -5388,8 +5387,7 @@ The ``parent`` argument is the token of the funclet that contains the
|
|||||||
this operand may be the token ``none``.
|
this operand may be the token ``none``.
|
||||||
|
|
||||||
The ``default`` argument is the label of another basic block beginning with a
|
The ``default`` argument is the label of another basic block beginning with a
|
||||||
"pad" instruction, one of ``cleanuppad``, ``terminatepad``, or
|
"pad" instruction, one of ``cleanuppad`` or ``catchswitch``.
|
||||||
``catchswitch``.
|
|
||||||
|
|
||||||
The ``handlers`` are a list of successor blocks that each begin with a
|
The ``handlers`` are a list of successor blocks that each begin with a
|
||||||
:ref:`catchpad <i_catchpad>` instruction.
|
:ref:`catchpad <i_catchpad>` instruction.
|
||||||
@ -5473,7 +5471,7 @@ The pad may then be "exited" in one of three ways:
|
|||||||
is undefined behavior if any descendant pads have been entered but not yet
|
is undefined behavior if any descendant pads have been entered but not yet
|
||||||
exited.
|
exited.
|
||||||
2) implicitly via a call (which unwinds all the way to the current function's caller),
|
2) implicitly via a call (which unwinds all the way to the current function's caller),
|
||||||
or via a ``catchswitch``, ``cleanupret``, or ``terminatepad`` that unwinds to caller.
|
or via a ``catchswitch`` or a ``cleanupret`` that unwinds to caller.
|
||||||
3) implicitly via an unwind edge whose destination EH pad isn't a descendant of
|
3) implicitly via an unwind edge whose destination EH pad isn't a descendant of
|
||||||
the ``catchpad``. When the ``catchpad`` is exited in this manner, it is
|
the ``catchpad``. When the ``catchpad`` is exited in this manner, it is
|
||||||
undefined behavior if the destination EH pad has a parent which is not an
|
undefined behavior if the destination EH pad has a parent which is not an
|
||||||
@ -5589,62 +5587,6 @@ Example:
|
|||||||
cleanupret from %cleanup unwind to caller
|
cleanupret from %cleanup unwind to caller
|
||||||
cleanupret from %cleanup unwind label %continue
|
cleanupret from %cleanup unwind label %continue
|
||||||
|
|
||||||
.. _i_terminatepad:
|
|
||||||
|
|
||||||
'``terminatepad``' Instruction
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Syntax:
|
|
||||||
"""""""
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
terminatepad within <token> [<args>*] unwind label <exception label>
|
|
||||||
terminatepad within <token> [<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 is both a terminator and a "pad" instruction,
|
|
||||||
meaning that is always the only non-phi instruction in the basic block.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
""""""""
|
|
||||||
|
|
||||||
.. code-block:: llvm
|
|
||||||
|
|
||||||
;; A terminate block which only permits integers.
|
|
||||||
terminatepad within none [i8** @_ZTIi] unwind label %continue
|
|
||||||
|
|
||||||
.. _i_unreachable:
|
.. _i_unreachable:
|
||||||
|
|
||||||
'``unreachable``' Instruction
|
'``unreachable``' Instruction
|
||||||
@ -8686,7 +8628,7 @@ The pad may then be "exited" in one of three ways:
|
|||||||
is undefined behavior if any descendant pads have been entered but not yet
|
is undefined behavior if any descendant pads have been entered but not yet
|
||||||
exited.
|
exited.
|
||||||
2) implicitly via a call (which unwinds all the way to the current function's caller),
|
2) implicitly via a call (which unwinds all the way to the current function's caller),
|
||||||
or via a ``catchswitch``, ``cleanupret``, or ``terminatepad`` that unwinds to caller.
|
or via a ``catchswitch`` or a ``cleanupret`` that unwinds to caller.
|
||||||
3) implicitly via an unwind edge whose destination EH pad isn't a descendant of
|
3) implicitly via an unwind edge whose destination EH pad isn't a descendant of
|
||||||
the ``cleanuppad``. When the ``cleanuppad`` is exited in this manner, it is
|
the ``cleanuppad``. When the ``cleanuppad`` is exited in this manner, it is
|
||||||
undefined behavior if the destination EH pad has a parent which is not an
|
undefined behavior if the destination EH pad has a parent which is not an
|
||||||
|
@ -252,9 +252,8 @@ typedef enum {
|
|||||||
LLVMCleanupRet = 61,
|
LLVMCleanupRet = 61,
|
||||||
LLVMCatchRet = 62,
|
LLVMCatchRet = 62,
|
||||||
LLVMCatchPad = 63,
|
LLVMCatchPad = 63,
|
||||||
LLVMTerminatePad = 64,
|
LLVMCleanupPad = 64,
|
||||||
LLVMCleanupPad = 65,
|
LLVMCatchSwitch = 65
|
||||||
LLVMCatchSwitch = 66
|
|
||||||
} LLVMOpcode;
|
} LLVMOpcode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -1224,7 +1223,6 @@ LLVMTypeRef LLVMX86MMXType(void);
|
|||||||
macro(ResumeInst) \
|
macro(ResumeInst) \
|
||||||
macro(CleanupReturnInst) \
|
macro(CleanupReturnInst) \
|
||||||
macro(CatchReturnInst) \
|
macro(CatchReturnInst) \
|
||||||
macro(TerminatePadInst) \
|
|
||||||
macro(FuncletPadInst) \
|
macro(FuncletPadInst) \
|
||||||
macro(CatchPadInst) \
|
macro(CatchPadInst) \
|
||||||
macro(CleanupPadInst) \
|
macro(CleanupPadInst) \
|
||||||
|
@ -421,9 +421,9 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
|
|||||||
FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [val] or [val,bb#]
|
FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [val] or [val,bb#]
|
||||||
FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [val,bb#]
|
FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [val,bb#]
|
||||||
FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [bb#,bb#,num,args...]
|
FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [bb#,bb#,num,args...]
|
||||||
FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...]
|
FUNC_CODE_INST_CLEANUPPAD = 51, // CLEANUPPAD: [num,args...]
|
||||||
FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...]
|
FUNC_CODE_INST_CATCHSWITCH = 52, // CATCHSWITCH: [num,args...] or [num,args...,bb]
|
||||||
FUNC_CODE_INST_CATCHSWITCH = 53, // CATCHSWITCH: [num,args...] or [num,args...,bb]
|
// 53 is unused.
|
||||||
// 54 is unused.
|
// 54 is unused.
|
||||||
FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
|
FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
|
||||||
};
|
};
|
||||||
|
@ -720,13 +720,6 @@ public:
|
|||||||
return Insert(CatchPadInst::Create(ParentPad, Args), Name);
|
return Insert(CatchPadInst::Create(ParentPad, Args), Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminatePadInst *CreateTerminatePad(Value *ParentPad,
|
|
||||||
BasicBlock *UnwindBB = nullptr,
|
|
||||||
ArrayRef<Value *> Args = None,
|
|
||||||
const Twine &Name = "") {
|
|
||||||
return Insert(TerminatePadInst::Create(ParentPad, UnwindBB, Args), Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
CleanupPadInst *CreateCleanupPad(Value *ParentPad,
|
CleanupPadInst *CreateCleanupPad(Value *ParentPad,
|
||||||
ArrayRef<Value *> Args = None,
|
ArrayRef<Value *> Args = None,
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
|
@ -172,7 +172,6 @@ public:
|
|||||||
RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst); }
|
RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst); }
|
||||||
RetTy visitCatchSwitchInst(CatchSwitchInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitCatchSwitchInst(CatchSwitchInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);}
|
|
||||||
RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);}
|
RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);}
|
||||||
RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);}
|
RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);}
|
||||||
RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);}
|
RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);}
|
||||||
|
@ -87,7 +87,6 @@ public:
|
|||||||
case Instruction::CleanupRet:
|
case Instruction::CleanupRet:
|
||||||
case Instruction::Invoke:
|
case Instruction::Invoke:
|
||||||
case Instruction::Resume:
|
case Instruction::Resume:
|
||||||
case Instruction::TerminatePad:
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -117,85 +117,84 @@ HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst)
|
|||||||
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
|
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
|
||||||
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
|
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
|
||||||
HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst)
|
HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst)
|
||||||
HANDLE_TERM_INST (11, TerminatePad , TerminatePadInst)
|
LAST_TERM_INST (10)
|
||||||
LAST_TERM_INST (11)
|
|
||||||
|
|
||||||
// Standard binary operators...
|
// Standard binary operators...
|
||||||
FIRST_BINARY_INST(12)
|
FIRST_BINARY_INST(11)
|
||||||
HANDLE_BINARY_INST(12, Add , BinaryOperator)
|
HANDLE_BINARY_INST(11, Add , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(13, FAdd , BinaryOperator)
|
HANDLE_BINARY_INST(12, FAdd , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(14, Sub , BinaryOperator)
|
HANDLE_BINARY_INST(13, Sub , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(15, FSub , BinaryOperator)
|
HANDLE_BINARY_INST(14, FSub , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(16, Mul , BinaryOperator)
|
HANDLE_BINARY_INST(15, Mul , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(17, FMul , BinaryOperator)
|
HANDLE_BINARY_INST(16, FMul , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(18, UDiv , BinaryOperator)
|
HANDLE_BINARY_INST(17, UDiv , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(19, SDiv , BinaryOperator)
|
HANDLE_BINARY_INST(18, SDiv , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(20, FDiv , BinaryOperator)
|
HANDLE_BINARY_INST(19, FDiv , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(21, URem , BinaryOperator)
|
HANDLE_BINARY_INST(20, URem , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(22, SRem , BinaryOperator)
|
HANDLE_BINARY_INST(21, SRem , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(23, FRem , BinaryOperator)
|
HANDLE_BINARY_INST(22, FRem , BinaryOperator)
|
||||||
|
|
||||||
// Logical operators (integer operands)
|
// Logical operators (integer operands)
|
||||||
HANDLE_BINARY_INST(24, Shl , BinaryOperator) // Shift left (logical)
|
HANDLE_BINARY_INST(23, Shl , BinaryOperator) // Shift left (logical)
|
||||||
HANDLE_BINARY_INST(25, LShr , BinaryOperator) // Shift right (logical)
|
HANDLE_BINARY_INST(24, LShr , BinaryOperator) // Shift right (logical)
|
||||||
HANDLE_BINARY_INST(26, AShr , BinaryOperator) // Shift right (arithmetic)
|
HANDLE_BINARY_INST(25, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||||
HANDLE_BINARY_INST(27, And , BinaryOperator)
|
HANDLE_BINARY_INST(26, And , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(28, Or , BinaryOperator)
|
HANDLE_BINARY_INST(27, Or , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(29, Xor , BinaryOperator)
|
HANDLE_BINARY_INST(28, Xor , BinaryOperator)
|
||||||
LAST_BINARY_INST(29)
|
LAST_BINARY_INST(28)
|
||||||
|
|
||||||
// Memory operators...
|
// Memory operators...
|
||||||
FIRST_MEMORY_INST(30)
|
FIRST_MEMORY_INST(29)
|
||||||
HANDLE_MEMORY_INST(30, Alloca, AllocaInst) // Stack management
|
HANDLE_MEMORY_INST(29, Alloca, AllocaInst) // Stack management
|
||||||
HANDLE_MEMORY_INST(31, Load , LoadInst ) // Memory manipulation instrs
|
HANDLE_MEMORY_INST(30, Load , LoadInst ) // Memory manipulation instrs
|
||||||
HANDLE_MEMORY_INST(32, Store , StoreInst )
|
HANDLE_MEMORY_INST(31, Store , StoreInst )
|
||||||
HANDLE_MEMORY_INST(33, GetElementPtr, GetElementPtrInst)
|
HANDLE_MEMORY_INST(32, GetElementPtr, GetElementPtrInst)
|
||||||
HANDLE_MEMORY_INST(34, Fence , FenceInst )
|
HANDLE_MEMORY_INST(33, Fence , FenceInst )
|
||||||
HANDLE_MEMORY_INST(35, AtomicCmpXchg , AtomicCmpXchgInst )
|
HANDLE_MEMORY_INST(34, AtomicCmpXchg , AtomicCmpXchgInst )
|
||||||
HANDLE_MEMORY_INST(36, AtomicRMW , AtomicRMWInst )
|
HANDLE_MEMORY_INST(35, AtomicRMW , AtomicRMWInst )
|
||||||
LAST_MEMORY_INST(36)
|
LAST_MEMORY_INST(35)
|
||||||
|
|
||||||
// Cast operators ...
|
// Cast operators ...
|
||||||
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
||||||
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
||||||
FIRST_CAST_INST(37)
|
FIRST_CAST_INST(36)
|
||||||
HANDLE_CAST_INST(37, Trunc , TruncInst ) // Truncate integers
|
HANDLE_CAST_INST(36, Trunc , TruncInst ) // Truncate integers
|
||||||
HANDLE_CAST_INST(38, ZExt , ZExtInst ) // Zero extend integers
|
HANDLE_CAST_INST(37, ZExt , ZExtInst ) // Zero extend integers
|
||||||
HANDLE_CAST_INST(39, SExt , SExtInst ) // Sign extend integers
|
HANDLE_CAST_INST(38, SExt , SExtInst ) // Sign extend integers
|
||||||
HANDLE_CAST_INST(40, FPToUI , FPToUIInst ) // floating point -> UInt
|
HANDLE_CAST_INST(39, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||||
HANDLE_CAST_INST(41, FPToSI , FPToSIInst ) // floating point -> SInt
|
HANDLE_CAST_INST(40, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||||
HANDLE_CAST_INST(42, UIToFP , UIToFPInst ) // UInt -> floating point
|
HANDLE_CAST_INST(41, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||||
HANDLE_CAST_INST(43, SIToFP , SIToFPInst ) // SInt -> floating point
|
HANDLE_CAST_INST(42, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||||
HANDLE_CAST_INST(44, FPTrunc , FPTruncInst ) // Truncate floating point
|
HANDLE_CAST_INST(43, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||||
HANDLE_CAST_INST(45, FPExt , FPExtInst ) // Extend floating point
|
HANDLE_CAST_INST(44, FPExt , FPExtInst ) // Extend floating point
|
||||||
HANDLE_CAST_INST(46, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
HANDLE_CAST_INST(45, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||||
HANDLE_CAST_INST(47, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
HANDLE_CAST_INST(46, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||||
HANDLE_CAST_INST(48, BitCast , BitCastInst ) // Type cast
|
HANDLE_CAST_INST(47, BitCast , BitCastInst ) // Type cast
|
||||||
HANDLE_CAST_INST(49, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
|
HANDLE_CAST_INST(48, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
|
||||||
LAST_CAST_INST(49)
|
LAST_CAST_INST(48)
|
||||||
|
|
||||||
FIRST_FUNCLETPAD_INST(50)
|
FIRST_FUNCLETPAD_INST(49)
|
||||||
HANDLE_FUNCLETPAD_INST(50, CleanupPad, CleanupPadInst)
|
HANDLE_FUNCLETPAD_INST(49, CleanupPad, CleanupPadInst)
|
||||||
HANDLE_FUNCLETPAD_INST(51, CatchPad , CatchPadInst)
|
HANDLE_FUNCLETPAD_INST(50, CatchPad , CatchPadInst)
|
||||||
LAST_FUNCLETPAD_INST(51)
|
LAST_FUNCLETPAD_INST(50)
|
||||||
|
|
||||||
// Other operators...
|
// Other operators...
|
||||||
FIRST_OTHER_INST(52)
|
FIRST_OTHER_INST(51)
|
||||||
HANDLE_OTHER_INST(52, ICmp , ICmpInst ) // Integer comparison instruction
|
HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction
|
||||||
HANDLE_OTHER_INST(53, FCmp , FCmpInst ) // Floating point comparison instr.
|
HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||||
HANDLE_OTHER_INST(54, PHI , PHINode ) // PHI node instruction
|
HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction
|
||||||
HANDLE_OTHER_INST(55, Call , CallInst ) // Call a function
|
HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function
|
||||||
HANDLE_OTHER_INST(56, Select , SelectInst ) // select instruction
|
HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction
|
||||||
HANDLE_OTHER_INST(57, UserOp1, Instruction) // May be used internally in a pass
|
HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass
|
||||||
HANDLE_OTHER_INST(58, UserOp2, Instruction) // Internal to passes only
|
HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only
|
||||||
HANDLE_OTHER_INST(59, VAArg , VAArgInst ) // vaarg instruction
|
HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction
|
||||||
HANDLE_OTHER_INST(60, ExtractElement, ExtractElementInst)// extract from vector
|
HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
|
||||||
HANDLE_OTHER_INST(61, InsertElement, InsertElementInst) // insert into vector
|
HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector
|
||||||
HANDLE_OTHER_INST(62, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||||
HANDLE_OTHER_INST(63, ExtractValue, ExtractValueInst)// extract from aggregate
|
HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||||
HANDLE_OTHER_INST(64, InsertValue, InsertValueInst) // insert into aggregate
|
HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate
|
||||||
HANDLE_OTHER_INST(65, LandingPad, LandingPadInst) // Landing pad instruction.
|
HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction.
|
||||||
LAST_OTHER_INST(65)
|
LAST_OTHER_INST(64)
|
||||||
|
|
||||||
#undef FIRST_TERM_INST
|
#undef FIRST_TERM_INST
|
||||||
#undef HANDLE_TERM_INST
|
#undef HANDLE_TERM_INST
|
||||||
|
@ -396,7 +396,6 @@ public:
|
|||||||
case Instruction::CatchPad:
|
case Instruction::CatchPad:
|
||||||
case Instruction::CleanupPad:
|
case Instruction::CleanupPad:
|
||||||
case Instruction::LandingPad:
|
case Instruction::LandingPad:
|
||||||
case Instruction::TerminatePad:
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -3991,143 +3991,6 @@ struct OperandTraits<CatchSwitchInst> : public HungoffOperandTraits<2> {};
|
|||||||
|
|
||||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value)
|
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value)
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// TerminatePadInst Class
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class TerminatePadInst : public TerminatorInst {
|
|
||||||
private:
|
|
||||||
void init(Value *ParentPad, BasicBlock *BB, ArrayRef<Value *> Args);
|
|
||||||
|
|
||||||
TerminatePadInst(const TerminatePadInst &TPI);
|
|
||||||
|
|
||||||
explicit TerminatePadInst(Value *ParentPad, BasicBlock *BB,
|
|
||||||
ArrayRef<Value *> Args, unsigned Values,
|
|
||||||
Instruction *InsertBefore);
|
|
||||||
explicit TerminatePadInst(Value *ParentPad, BasicBlock *BB,
|
|
||||||
ArrayRef<Value *> Args, unsigned Values,
|
|
||||||
BasicBlock *InsertAtEnd);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
|
||||||
friend class Instruction;
|
|
||||||
TerminatePadInst *cloneImpl() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static TerminatePadInst *Create(Value *ParentPad, BasicBlock *BB = nullptr,
|
|
||||||
ArrayRef<Value *> Args = None,
|
|
||||||
Instruction *InsertBefore = nullptr) {
|
|
||||||
unsigned Values = unsigned(Args.size()) + 1;
|
|
||||||
if (BB)
|
|
||||||
++Values;
|
|
||||||
return new (Values)
|
|
||||||
TerminatePadInst(ParentPad, BB, Args, Values, InsertBefore);
|
|
||||||
}
|
|
||||||
static TerminatePadInst *Create(Value *ParentPad, BasicBlock *BB,
|
|
||||||
ArrayRef<Value *> Args,
|
|
||||||
BasicBlock *InsertAtEnd) {
|
|
||||||
unsigned Values = unsigned(Args.size()) + 1;
|
|
||||||
if (BB)
|
|
||||||
++Values;
|
|
||||||
return new (Values)
|
|
||||||
TerminatePadInst(ParentPad, BB, Args, Values, 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 - 2;
|
|
||||||
return NumOperands - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience accessors
|
|
||||||
Value *getParentPad() const { return Op<-1>(); }
|
|
||||||
void setParentPad(Value *ParentPad) {
|
|
||||||
assert(ParentPad);
|
|
||||||
Op<-1>() = ParentPad;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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_begin() const { return op_begin(); }
|
|
||||||
op_iterator arg_begin() { return op_begin(); }
|
|
||||||
|
|
||||||
const_op_iterator arg_end() const {
|
|
||||||
if (hasUnwindDest())
|
|
||||||
return op_end() - 2;
|
|
||||||
return op_end() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
op_iterator arg_end() {
|
|
||||||
if (hasUnwindDest())
|
|
||||||
return op_end() - 2;
|
|
||||||
return op_end() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// arg_operands - iteration adapter for range-for loops.
|
|
||||||
iterator_range<op_iterator> arg_operands() {
|
|
||||||
return make_range(arg_begin(), arg_end());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// arg_operands - iteration adapter for range-for loops.
|
|
||||||
iterator_range<const_op_iterator> arg_operands() const {
|
|
||||||
return make_range(arg_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<-2>());
|
|
||||||
}
|
|
||||||
void setUnwindDest(BasicBlock *B) {
|
|
||||||
assert(B && hasUnwindDest());
|
|
||||||
Op<-2>() = 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
|
// CleanupPadInst Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -289,8 +289,8 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
|
|||||||
DIBuilder &Builder, bool Deref, int Offset = 0);
|
DIBuilder &Builder, bool Deref, int Offset = 0);
|
||||||
|
|
||||||
/// Replace 'BB's terminator with one that does not have an unwind successor
|
/// Replace 'BB's terminator with one that does not have an unwind successor
|
||||||
/// block. Rewrites `invoke` to `call`, `terminatepad unwind label %foo` to
|
/// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
|
||||||
/// `terminatepad unwind to caller`, etc. Updates any PHIs in unwind successor.
|
/// successor.
|
||||||
///
|
///
|
||||||
/// \param BB Block whose terminator will be replaced. Its terminator must
|
/// \param BB Block whose terminator will be replaced. Its terminator must
|
||||||
/// have an unwind successor.
|
/// have an unwind successor.
|
||||||
|
@ -57,9 +57,8 @@ DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
|
|||||||
// contain" is used to distinguish from being "transitively contained" in
|
// contain" is used to distinguish from being "transitively contained" in
|
||||||
// a nested funclet).
|
// a nested funclet).
|
||||||
//
|
//
|
||||||
// Note: Despite not being funclets in the truest sense, terminatepad and
|
// Note: Despite not being a funclet in the truest sense, a catchswitch is
|
||||||
// catchswitch are considered to belong to their own funclet for the purposes
|
// considered to belong to its own funclet for the purposes of coloring.
|
||||||
// of coloring.
|
|
||||||
|
|
||||||
DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
|
DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
|
||||||
<< F.getName() << "\n");
|
<< F.getName() << "\n");
|
||||||
|
@ -98,8 +98,6 @@ static BasicBlock::iterator findInsertPointAfter(Instruction *I,
|
|||||||
while (IP->isEHPad()) {
|
while (IP->isEHPad()) {
|
||||||
if (isa<FuncletPadInst>(IP) || isa<LandingPadInst>(IP)) {
|
if (isa<FuncletPadInst>(IP) || isa<LandingPadInst>(IP)) {
|
||||||
++IP;
|
++IP;
|
||||||
} else if (auto *TPI = dyn_cast<TerminatePadInst>(IP)) {
|
|
||||||
IP = TPI->getUnwindDest()->getFirstNonPHI()->getIterator();
|
|
||||||
} else if (isa<CatchSwitchInst>(IP)) {
|
} else if (isa<CatchSwitchInst>(IP)) {
|
||||||
IP = MustDominate->getFirstInsertionPt();
|
IP = MustDominate->getFirstInsertionPt();
|
||||||
} else {
|
} else {
|
||||||
|
@ -3436,7 +3436,6 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
|
|||||||
case Instruction::CatchRet:
|
case Instruction::CatchRet:
|
||||||
case Instruction::CleanupPad:
|
case Instruction::CleanupPad:
|
||||||
case Instruction::CleanupRet:
|
case Instruction::CleanupRet:
|
||||||
case Instruction::TerminatePad:
|
|
||||||
return false; // Misc instructions which have effects
|
return false; // Misc instructions which have effects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -763,7 +763,6 @@ lltok::Kind LLLexer::LexIdentifier() {
|
|||||||
INSTKEYWORD(catchret, CatchRet);
|
INSTKEYWORD(catchret, CatchRet);
|
||||||
INSTKEYWORD(catchswitch, CatchSwitch);
|
INSTKEYWORD(catchswitch, CatchSwitch);
|
||||||
INSTKEYWORD(catchpad, CatchPad);
|
INSTKEYWORD(catchpad, CatchPad);
|
||||||
INSTKEYWORD(terminatepad, TerminatePad);
|
|
||||||
INSTKEYWORD(cleanuppad, CleanupPad);
|
INSTKEYWORD(cleanuppad, CleanupPad);
|
||||||
#undef INSTKEYWORD
|
#undef INSTKEYWORD
|
||||||
|
|
||||||
|
@ -4723,7 +4723,6 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
|||||||
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
|
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
|
||||||
case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS);
|
case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS);
|
||||||
case lltok::kw_catchpad: return ParseCatchPad(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_cleanuppad: return ParseCleanupPad(Inst, PFS);
|
||||||
// Binary Operators.
|
// Binary Operators.
|
||||||
case lltok::kw_add:
|
case lltok::kw_add:
|
||||||
@ -5285,43 +5284,6 @@ bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseTerminatePad
|
|
||||||
/// ::= 'terminatepad' within Parent ParamList 'to' TypeAndValue
|
|
||||||
bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
|
|
||||||
Value *ParentPad = nullptr;
|
|
||||||
|
|
||||||
if (ParseToken(lltok::kw_within, "expected 'within' after terminatepad"))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
|
|
||||||
Lex.getKind() != lltok::LocalVarID)
|
|
||||||
return TokError("expected scope value for terminatepad");
|
|
||||||
|
|
||||||
if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
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(ParentPad, UnwindBB, Args);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ParseCleanupPad
|
/// ParseCleanupPad
|
||||||
/// ::= 'cleanuppad' within Parent ParamList
|
/// ::= 'cleanuppad' within Parent ParamList
|
||||||
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
|
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||||
|
@ -465,7 +465,6 @@ namespace llvm {
|
|||||||
bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
bool ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
|
|
||||||
bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
|
|
||||||
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
|
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
|
||||||
|
@ -185,7 +185,7 @@ namespace lltok {
|
|||||||
|
|
||||||
kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
|
kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
|
||||||
kw_unreachable, kw_cleanupret, kw_catchswitch, kw_catchret, kw_catchpad,
|
kw_unreachable, kw_cleanupret, kw_catchswitch, kw_catchret, kw_catchpad,
|
||||||
kw_terminatepad, kw_cleanuppad,
|
kw_cleanuppad,
|
||||||
|
|
||||||
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
|
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
|
||||||
kw_getelementptr,
|
kw_getelementptr,
|
||||||
|
@ -4484,40 +4484,6 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
|
|||||||
InstructionList.push_back(I);
|
InstructionList.push_back(I);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [tok,bb#,num,(ty,val)*]
|
|
||||||
// We must have, at minimum, the outer scope and the number of arguments.
|
|
||||||
if (Record.size() < 2)
|
|
||||||
return error("Invalid record");
|
|
||||||
|
|
||||||
unsigned Idx = 0;
|
|
||||||
|
|
||||||
Value *ParentPad =
|
|
||||||
getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicBlock *UnwindDest = nullptr;
|
|
||||||
if (Idx + 1 == Record.size()) {
|
|
||||||
UnwindDest = getBasicBlock(Record[Idx++]);
|
|
||||||
if (!UnwindDest)
|
|
||||||
return error("Invalid record");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Record.size() != Idx)
|
|
||||||
return error("Invalid record");
|
|
||||||
|
|
||||||
I = TerminatePadInst::Create(ParentPad, UnwindDest, Args);
|
|
||||||
InstructionList.push_back(I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case bitc::FUNC_CODE_INST_CATCHPAD:
|
case bitc::FUNC_CODE_INST_CATCHPAD:
|
||||||
case bitc::FUNC_CODE_INST_CLEANUPPAD: { // [tok,num,(ty,val)*]
|
case bitc::FUNC_CODE_INST_CLEANUPPAD: { // [tok,num,(ty,val)*]
|
||||||
// We must have, at minimum, the outer scope and the number of arguments.
|
// We must have, at minimum, the outer scope and the number of arguments.
|
||||||
|
@ -2025,21 +2025,6 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
|
|||||||
Vals.push_back(VE.getValueID(CatchSwitch.getUnwindDest()));
|
Vals.push_back(VE.getValueID(CatchSwitch.getUnwindDest()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::TerminatePad: {
|
|
||||||
Code = bitc::FUNC_CODE_INST_TERMINATEPAD;
|
|
||||||
const auto &TPI = cast<TerminatePadInst>(I);
|
|
||||||
|
|
||||||
pushValue(TPI.getParentPad(), InstID, Vals, VE);
|
|
||||||
|
|
||||||
unsigned NumArgOperands = TPI.getNumArgOperands();
|
|
||||||
Vals.push_back(NumArgOperands);
|
|
||||||
for (unsigned Op = 0; Op != NumArgOperands; ++Op)
|
|
||||||
PushValueAndType(TPI.getArgOperand(Op), InstID, Vals, VE);
|
|
||||||
|
|
||||||
if (TPI.hasUnwindDest())
|
|
||||||
Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::Unreachable:
|
case Instruction::Unreachable:
|
||||||
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
|
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
|
||||||
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
|
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
|
||||||
|
@ -1230,8 +1230,8 @@ void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
|
|||||||
/// When an invoke or a cleanupret unwinds to the next EH pad, there are
|
/// When an invoke or a cleanupret unwinds to the next EH pad, there are
|
||||||
/// many places it could ultimately go. In the IR, we have a single unwind
|
/// many places it could ultimately go. In the IR, we have a single unwind
|
||||||
/// destination, but in the machine CFG, we enumerate all the possible blocks.
|
/// destination, but in the machine CFG, we enumerate all the possible blocks.
|
||||||
/// This function skips over imaginary basic blocks that hold catchswitch or
|
/// This function skips over imaginary basic blocks that hold catchswitch
|
||||||
/// terminatepad instructions, and finds all the "real" machine
|
/// instructions, and finds all the "real" machine
|
||||||
/// basic block destinations. As those destinations may not be successors of
|
/// basic block destinations. As those destinations may not be successors of
|
||||||
/// EHPadBB, here we also calculate the edge probability to those destinations.
|
/// EHPadBB, here we also calculate the edge probability to those destinations.
|
||||||
/// The passed-in Prob is the edge probability to EHPadBB.
|
/// The passed-in Prob is the edge probability to EHPadBB.
|
||||||
@ -1300,10 +1300,6 @@ void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
|
|||||||
DAG.setRoot(Ret);
|
DAG.setRoot(Ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
|
|
||||||
report_fatal_error("visitTerminatePad not yet implemented!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SelectionDAGBuilder::visitCatchSwitch(const CatchSwitchInst &CSI) {
|
void SelectionDAGBuilder::visitCatchSwitch(const CatchSwitchInst &CSI) {
|
||||||
report_fatal_error("visitCatchSwitch not yet implemented!");
|
report_fatal_error("visitCatchSwitch not yet implemented!");
|
||||||
}
|
}
|
||||||
|
@ -740,7 +740,6 @@ private:
|
|||||||
void visitCatchSwitch(const CatchSwitchInst &I);
|
void visitCatchSwitch(const CatchSwitchInst &I);
|
||||||
void visitCatchRet(const CatchReturnInst &I);
|
void visitCatchRet(const CatchReturnInst &I);
|
||||||
void visitCatchPad(const CatchPadInst &I);
|
void visitCatchPad(const CatchPadInst &I);
|
||||||
void visitTerminatePad(const TerminatePadInst &TPI);
|
|
||||||
void visitCleanupPad(const CleanupPadInst &CPI);
|
void visitCleanupPad(const CleanupPadInst &CPI);
|
||||||
|
|
||||||
BranchProbability getEdgeProbability(const MachineBasicBlock *Src,
|
BranchProbability getEdgeProbability(const MachineBasicBlock *Src,
|
||||||
|
@ -1574,7 +1574,6 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
|
|||||||
case CatchRet: return 0;
|
case CatchRet: return 0;
|
||||||
case CatchPad: return 0;
|
case CatchPad: return 0;
|
||||||
case CatchSwitch: return 0;
|
case CatchSwitch: return 0;
|
||||||
case TerminatePad: return 0;
|
|
||||||
case CleanupPad: return 0;
|
case CleanupPad: return 0;
|
||||||
case Add: return ISD::ADD;
|
case Add: return ISD::ADD;
|
||||||
case FAdd: return ISD::FADD;
|
case FAdd: return ISD::FADD;
|
||||||
|
@ -70,7 +70,6 @@ private:
|
|||||||
void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
|
void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
|
||||||
DenseMap<BasicBlock *, Value *> &Loads, Function &F);
|
DenseMap<BasicBlock *, Value *> &Loads, Function &F);
|
||||||
bool prepareExplicitEH(Function &F);
|
bool prepareExplicitEH(Function &F);
|
||||||
void replaceTerminatePadWithCleanup(Function &F);
|
|
||||||
void colorFunclets(Function &F);
|
void colorFunclets(Function &F);
|
||||||
|
|
||||||
void demotePHIsOnFunclets(Function &F);
|
void demotePHIsOnFunclets(Function &F);
|
||||||
@ -523,45 +522,6 @@ void llvm::calculateClrEHStateNumbers(const Function *Fn,
|
|||||||
calculateStateNumbersForInvokes(Fn, FuncInfo);
|
calculateStateNumbersForInvokes(Fn, FuncInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) {
|
|
||||||
if (Personality != EHPersonality::MSVC_CXX)
|
|
||||||
return;
|
|
||||||
for (BasicBlock &BB : F) {
|
|
||||||
Instruction *First = BB.getFirstNonPHI();
|
|
||||||
auto *TPI = dyn_cast<TerminatePadInst>(First);
|
|
||||||
if (!TPI)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (TPI->getNumArgOperands() != 1)
|
|
||||||
report_fatal_error(
|
|
||||||
"Expected a unary terminatepad for MSVC C++ personalities!");
|
|
||||||
|
|
||||||
auto *TerminateFn = dyn_cast<Function>(TPI->getArgOperand(0));
|
|
||||||
if (!TerminateFn)
|
|
||||||
report_fatal_error("Function operand expected in terminatepad for MSVC "
|
|
||||||
"C++ personalities!");
|
|
||||||
|
|
||||||
// Insert the cleanuppad instruction.
|
|
||||||
auto *CPI =
|
|
||||||
CleanupPadInst::Create(TPI->getParentPad(), {},
|
|
||||||
Twine("terminatepad.for.", BB.getName()), &BB);
|
|
||||||
|
|
||||||
// Insert the call to the terminate instruction.
|
|
||||||
auto *CallTerminate = CallInst::Create(TerminateFn, {}, &BB);
|
|
||||||
CallTerminate->setDoesNotThrow();
|
|
||||||
CallTerminate->setDoesNotReturn();
|
|
||||||
CallTerminate->setCallingConv(TerminateFn->getCallingConv());
|
|
||||||
|
|
||||||
// Insert a new terminator for the cleanuppad using the same successor as
|
|
||||||
// the terminatepad.
|
|
||||||
CleanupReturnInst::Create(CPI, TPI->getUnwindDest(), &BB);
|
|
||||||
|
|
||||||
// Let's remove the terminatepad now that we've inserted the new
|
|
||||||
// instructions.
|
|
||||||
TPI->eraseFromParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WinEHPrepare::colorFunclets(Function &F) {
|
void WinEHPrepare::colorFunclets(Function &F) {
|
||||||
BlockColors = colorEHFunclets(F);
|
BlockColors = colorEHFunclets(F);
|
||||||
|
|
||||||
@ -885,8 +845,6 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
|
|||||||
// not.
|
// not.
|
||||||
removeUnreachableBlocks(F);
|
removeUnreachableBlocks(F);
|
||||||
|
|
||||||
replaceTerminatePadWithCleanup(F);
|
|
||||||
|
|
||||||
// Determine which blocks are reachable from which funclet entries.
|
// Determine which blocks are reachable from which funclet entries.
|
||||||
colorFunclets(F);
|
colorFunclets(F);
|
||||||
|
|
||||||
|
@ -2917,21 +2917,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
|||||||
writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
|
writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
|
||||||
}
|
}
|
||||||
Out << ']';
|
Out << ']';
|
||||||
} else if (const auto *TPI = dyn_cast<TerminatePadInst>(&I)) {
|
|
||||||
Out << " within ";
|
|
||||||
writeOperand(TPI->getParentPad(), /*PrintType=*/false);
|
|
||||||
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 (isa<ReturnInst>(I) && !Operand) {
|
} else if (isa<ReturnInst>(I) && !Operand) {
|
||||||
Out << " void";
|
Out << " void";
|
||||||
} else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
|
} else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
|
||||||
|
@ -206,7 +206,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
|||||||
case CatchRet: return "catchret";
|
case CatchRet: return "catchret";
|
||||||
case CatchPad: return "catchpad";
|
case CatchPad: return "catchpad";
|
||||||
case CatchSwitch: return "catchswitch";
|
case CatchSwitch: return "catchswitch";
|
||||||
case TerminatePad: return "terminatepad";
|
|
||||||
|
|
||||||
// Standard binary operators...
|
// Standard binary operators...
|
||||||
case Add: return "add";
|
case Add: return "add";
|
||||||
@ -421,7 +420,6 @@ bool Instruction::mayReadFromMemory() const {
|
|||||||
case Instruction::AtomicRMW:
|
case Instruction::AtomicRMW:
|
||||||
case Instruction::CatchPad:
|
case Instruction::CatchPad:
|
||||||
case Instruction::CatchRet:
|
case Instruction::CatchRet:
|
||||||
case Instruction::TerminatePad:
|
|
||||||
return true;
|
return true;
|
||||||
case Instruction::Call:
|
case Instruction::Call:
|
||||||
return !cast<CallInst>(this)->doesNotAccessMemory();
|
return !cast<CallInst>(this)->doesNotAccessMemory();
|
||||||
@ -444,7 +442,6 @@ bool Instruction::mayWriteToMemory() const {
|
|||||||
case Instruction::AtomicRMW:
|
case Instruction::AtomicRMW:
|
||||||
case Instruction::CatchPad:
|
case Instruction::CatchPad:
|
||||||
case Instruction::CatchRet:
|
case Instruction::CatchRet:
|
||||||
case Instruction::TerminatePad:
|
|
||||||
return true;
|
return true;
|
||||||
case Instruction::Call:
|
case Instruction::Call:
|
||||||
return !cast<CallInst>(this)->onlyReadsMemory();
|
return !cast<CallInst>(this)->onlyReadsMemory();
|
||||||
@ -477,8 +474,6 @@ bool Instruction::mayThrow() const {
|
|||||||
return CRI->unwindsToCaller();
|
return CRI->unwindsToCaller();
|
||||||
if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(this))
|
if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(this))
|
||||||
return CatchSwitch->unwindsToCaller();
|
return CatchSwitch->unwindsToCaller();
|
||||||
if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
|
|
||||||
return TPI->unwindsToCaller();
|
|
||||||
return isa<ResumeInst>(this);
|
return isa<ResumeInst>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,60 +980,6 @@ FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
|
|||||||
init(ParentPad, Args, NameStr);
|
init(ParentPad, Args, NameStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// TerminatePadInst Implementation
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
void TerminatePadInst::init(Value *ParentPad, BasicBlock *BB,
|
|
||||||
ArrayRef<Value *> Args) {
|
|
||||||
if (BB) {
|
|
||||||
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
|
|
||||||
setUnwindDest(BB);
|
|
||||||
}
|
|
||||||
std::copy(Args.begin(), Args.end(), arg_begin());
|
|
||||||
setParentPad(ParentPad);
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI)
|
|
||||||
: TerminatorInst(TPI.getType(), Instruction::TerminatePad,
|
|
||||||
OperandTraits<TerminatePadInst>::op_end(this) -
|
|
||||||
TPI.getNumOperands(),
|
|
||||||
TPI.getNumOperands()) {
|
|
||||||
setInstructionSubclassData(TPI.getSubclassDataFromInstruction());
|
|
||||||
std::copy(TPI.op_begin(), TPI.op_end(), op_begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminatePadInst::TerminatePadInst(Value *ParentPad, BasicBlock *BB,
|
|
||||||
ArrayRef<Value *> Args, unsigned Values,
|
|
||||||
Instruction *InsertBefore)
|
|
||||||
: TerminatorInst(Type::getVoidTy(ParentPad->getContext()),
|
|
||||||
Instruction::TerminatePad,
|
|
||||||
OperandTraits<TerminatePadInst>::op_end(this) - Values,
|
|
||||||
Values, InsertBefore) {
|
|
||||||
init(ParentPad, BB, Args);
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminatePadInst::TerminatePadInst(Value *ParentPad, BasicBlock *BB,
|
|
||||||
ArrayRef<Value *> Args, unsigned Values,
|
|
||||||
BasicBlock *InsertAtEnd)
|
|
||||||
: TerminatorInst(Type::getVoidTy(ParentPad->getContext()),
|
|
||||||
Instruction::TerminatePad,
|
|
||||||
OperandTraits<TerminatePadInst>::op_end(this) - Values,
|
|
||||||
Values, InsertAtEnd) {
|
|
||||||
init(ParentPad, BB, Args);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// UnreachableInst Implementation
|
// UnreachableInst Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -4025,10 +3971,6 @@ FuncletPadInst *FuncletPadInst::cloneImpl() const {
|
|||||||
return new (getNumOperands()) FuncletPadInst(*this);
|
return new (getNumOperands()) FuncletPadInst(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminatePadInst *TerminatePadInst::cloneImpl() const {
|
|
||||||
return new (getNumOperands()) TerminatePadInst(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
UnreachableInst *UnreachableInst::cloneImpl() const {
|
UnreachableInst *UnreachableInst::cloneImpl() const {
|
||||||
LLVMContext &Context = getContext();
|
LLVMContext &Context = getContext();
|
||||||
return new UnreachableInst(Context);
|
return new UnreachableInst(Context);
|
||||||
|
@ -403,7 +403,6 @@ private:
|
|||||||
void visitCleanupPadInst(CleanupPadInst &CPI);
|
void visitCleanupPadInst(CleanupPadInst &CPI);
|
||||||
void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch);
|
void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch);
|
||||||
void visitCleanupReturnInst(CleanupReturnInst &CRI);
|
void visitCleanupReturnInst(CleanupReturnInst &CRI);
|
||||||
void visitTerminatePadInst(TerminatePadInst &TPI);
|
|
||||||
|
|
||||||
void VerifyCallSite(CallSite CS);
|
void VerifyCallSite(CallSite CS);
|
||||||
void verifyMustTailCall(CallInst &CI);
|
void verifyMustTailCall(CallInst &CI);
|
||||||
@ -2899,8 +2898,7 @@ void Verifier::visitEHPadPredecessors(Instruction &I) {
|
|||||||
if (auto *II = dyn_cast<InvokeInst>(TI)) {
|
if (auto *II = dyn_cast<InvokeInst>(TI)) {
|
||||||
Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,
|
Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,
|
||||||
"EH pad must be jumped to via an unwind edge", &I, II);
|
"EH pad must be jumped to via an unwind edge", &I, II);
|
||||||
} else if (!isa<CleanupReturnInst>(TI) && !isa<TerminatePadInst>(TI) &&
|
} else if (!isa<CleanupReturnInst>(TI) && !isa<CatchSwitchInst>(TI)) {
|
||||||
!isa<CatchSwitchInst>(TI)) {
|
|
||||||
Assert(false, "EH pad must be jumped to via an unwind edge", &I, TI);
|
Assert(false, "EH pad must be jumped to via an unwind edge", &I, TI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3002,8 +3000,7 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
|
|||||||
BasicBlock *UnwindDest;
|
BasicBlock *UnwindDest;
|
||||||
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
|
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
|
||||||
UnwindDest = CRI->getUnwindDest();
|
UnwindDest = CRI->getUnwindDest();
|
||||||
} else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U) ||
|
} else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
|
||||||
isa<TerminatePadInst>(U)) {
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
Assert(false, "bogus cleanuppad use", &CPI);
|
Assert(false, "bogus cleanuppad use", &CPI);
|
||||||
@ -3072,37 +3069,6 @@ void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
|
|||||||
visitTerminatorInst(CRI);
|
visitTerminatorInst(CRI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Verifier::visitTerminatePadInst(TerminatePadInst &TPI) {
|
|
||||||
visitEHPadPredecessors(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *ParentPad = TPI.getParentPad();
|
|
||||||
Assert(isa<CatchSwitchInst>(ParentPad) || isa<ConstantTokenNone>(ParentPad) ||
|
|
||||||
isa<CleanupPadInst>(ParentPad) || isa<CatchPadInst>(ParentPad),
|
|
||||||
"TerminatePadInst has an invalid parent.", ParentPad);
|
|
||||||
|
|
||||||
visitTerminatorInst(TPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
|
void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
|
||||||
Instruction *Op = cast<Instruction>(I.getOperand(i));
|
Instruction *Op = cast<Instruction>(I.getOperand(i));
|
||||||
// If the we have an invalid invoke, don't try to compute the dominance.
|
// If the we have an invalid invoke, don't try to compute the dominance.
|
||||||
|
@ -2695,11 +2695,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
setOrigin(&I, getCleanOrigin());
|
setOrigin(&I, getCleanOrigin());
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitTerminatePad(TerminatePadInst &I) {
|
|
||||||
DEBUG(dbgs() << "TerminatePad: " << I << "\n");
|
|
||||||
// Nothing to do here.
|
|
||||||
}
|
|
||||||
|
|
||||||
void visitGetElementPtrInst(GetElementPtrInst &I) {
|
void visitGetElementPtrInst(GetElementPtrInst &I) {
|
||||||
handleShadowOr(I);
|
handleShadowOr(I);
|
||||||
}
|
}
|
||||||
|
@ -343,15 +343,7 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Instruction *Replacement = nullptr;
|
Instruction *Replacement = nullptr;
|
||||||
if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
|
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
||||||
if (TPI->unwindsToCaller()) {
|
|
||||||
SmallVector<Value *, 3> TerminatePadArgs;
|
|
||||||
for (Value *ArgOperand : TPI->arg_operands())
|
|
||||||
TerminatePadArgs.push_back(ArgOperand);
|
|
||||||
Replacement = TerminatePadInst::Create(TPI->getParentPad(), UnwindDest,
|
|
||||||
TerminatePadArgs, TPI);
|
|
||||||
}
|
|
||||||
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
|
||||||
if (CatchSwitch->unwindsToCaller()) {
|
if (CatchSwitch->unwindsToCaller()) {
|
||||||
auto *NewCatchSwitch = CatchSwitchInst::Create(
|
auto *NewCatchSwitch = CatchSwitchInst::Create(
|
||||||
CatchSwitch->getParentPad(), UnwindDest,
|
CatchSwitch->getParentPad(), UnwindDest,
|
||||||
@ -1441,10 +1433,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
|||||||
if (!I->isEHPad())
|
if (!I->isEHPad())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
|
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
||||||
if (isa<ConstantTokenNone>(TPI->getParentPad()))
|
|
||||||
TPI->setParentPad(CallSiteEHPad);
|
|
||||||
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
|
||||||
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
|
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
|
||||||
CatchSwitch->setParentPad(CallSiteEHPad);
|
CatchSwitch->setParentPad(CallSiteEHPad);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1338,13 +1338,6 @@ void llvm::removeUnwindEdge(BasicBlock *BB) {
|
|||||||
if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
|
if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
|
||||||
NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI);
|
NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI);
|
||||||
UnwindDest = CRI->getUnwindDest();
|
UnwindDest = CRI->getUnwindDest();
|
||||||
} else if (auto *TPI = dyn_cast<TerminatePadInst>(TI)) {
|
|
||||||
SmallVector<Value *, 3> TerminatePadArgs;
|
|
||||||
for (Value *Operand : TPI->arg_operands())
|
|
||||||
TerminatePadArgs.push_back(Operand);
|
|
||||||
NewTI = TerminatePadInst::Create(TPI->getParentPad(), nullptr,
|
|
||||||
TerminatePadArgs, TPI);
|
|
||||||
UnwindDest = TPI->getUnwindDest();
|
|
||||||
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
|
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
|
||||||
auto *NewCatchSwitch = CatchSwitchInst::Create(
|
auto *NewCatchSwitch = CatchSwitchInst::Create(
|
||||||
CatchSwitch->getParentPad(), nullptr, CatchSwitch->getNumHandlers(),
|
CatchSwitch->getParentPad(), nullptr, CatchSwitch->getNumHandlers(),
|
||||||
|
@ -3498,7 +3498,7 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
|
|||||||
}
|
}
|
||||||
} else if ((isa<InvokeInst>(TI) &&
|
} else if ((isa<InvokeInst>(TI) &&
|
||||||
cast<InvokeInst>(TI)->getUnwindDest() == BB) ||
|
cast<InvokeInst>(TI)->getUnwindDest() == BB) ||
|
||||||
isa<TerminatePadInst>(TI) || isa<CatchSwitchInst>(TI)) {
|
isa<CatchSwitchInst>(TI)) {
|
||||||
removeUnwindEdge(TI->getParent());
|
removeUnwindEdge(TI->getParent());
|
||||||
Changed = true;
|
Changed = true;
|
||||||
} else if (isa<CleanupReturnInst>(TI)) {
|
} else if (isa<CleanupReturnInst>(TI)) {
|
||||||
|
@ -774,7 +774,7 @@ entry:
|
|||||||
invoke void @f.ccc() to label %normal unwind label %catchswitch3
|
invoke void @f.ccc() to label %normal unwind label %catchswitch3
|
||||||
|
|
||||||
catchswitch1:
|
catchswitch1:
|
||||||
%cs1 = catchswitch within none [label %catchpad1] unwind label %terminate.1
|
%cs1 = catchswitch within none [label %catchpad1] unwind to caller
|
||||||
|
|
||||||
catchpad1:
|
catchpad1:
|
||||||
catchpad within %cs1 []
|
catchpad within %cs1 []
|
||||||
@ -802,20 +802,9 @@ catchpad3:
|
|||||||
|
|
||||||
cleanuppad1:
|
cleanuppad1:
|
||||||
%clean.1 = cleanuppad within none []
|
%clean.1 = cleanuppad within none []
|
||||||
|
unreachable
|
||||||
; CHECK: %clean.1 = cleanuppad within none []
|
; CHECK: %clean.1 = cleanuppad within none []
|
||||||
invoke void @f.ccc() to label %normal unwind label %terminate.2
|
; CHECK-NEXT: unreachable
|
||||||
|
|
||||||
terminate.1:
|
|
||||||
terminatepad within none [] unwind to caller
|
|
||||||
; CHECK: terminatepad within none [] unwind to caller
|
|
||||||
|
|
||||||
terminate.2:
|
|
||||||
terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre
|
|
||||||
; CHECK: terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre
|
|
||||||
|
|
||||||
normal.pre:
|
|
||||||
terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller
|
|
||||||
; CHECK: terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller
|
|
||||||
|
|
||||||
normal:
|
normal:
|
||||||
ret i32 0
|
ret i32 0
|
||||||
@ -852,8 +841,10 @@ return:
|
|||||||
ret i32 0
|
ret i32 0
|
||||||
|
|
||||||
terminate:
|
terminate:
|
||||||
terminatepad within %cs [] unwind to caller
|
cleanuppad within %cs []
|
||||||
; CHECK: terminatepad within %cs [] unwind to caller
|
unreachable
|
||||||
|
; CHECK: cleanuppad within %cs []
|
||||||
|
; CHECK-NEXT: unreachable
|
||||||
|
|
||||||
continue:
|
continue:
|
||||||
ret i32 0
|
ret i32 0
|
||||||
|
@ -93,22 +93,6 @@ exit:
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: @test3(
|
|
||||||
define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
|
|
||||||
entry:
|
|
||||||
invoke void @f()
|
|
||||||
to label %invoke.cont unwind label %terminate
|
|
||||||
|
|
||||||
invoke.cont:
|
|
||||||
ret void
|
|
||||||
|
|
||||||
terminate:
|
|
||||||
; CHECK: cleanuppad within none []
|
|
||||||
; CHECK: call void @__std_terminate()
|
|
||||||
; CHECK: unreachable
|
|
||||||
terminatepad within none [void ()* @__std_terminate] unwind to caller
|
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK-LABEL: @test4(
|
; CHECK-LABEL: @test4(
|
||||||
define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 {
|
define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
entry:
|
entry:
|
||||||
|
@ -123,28 +123,6 @@ exit:
|
|||||||
ret i8 0
|
ret i8 0
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @terminatepad0() personality i32 (...)* @__gxx_personality_v0 {
|
|
||||||
entry:
|
|
||||||
br label %try.cont
|
|
||||||
|
|
||||||
try.cont:
|
|
||||||
invoke void @_Z3quxv() optsize
|
|
||||||
to label %try.cont unwind label %bb
|
|
||||||
bb:
|
|
||||||
terminatepad within none [i7 4] unwind label %bb
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 {
|
|
||||||
entry:
|
|
||||||
br label %try.cont
|
|
||||||
|
|
||||||
try.cont:
|
|
||||||
invoke void @_Z3quxv() optsize
|
|
||||||
to label %try.cont unwind label %bb
|
|
||||||
bb:
|
|
||||||
terminatepad within none [i7 4] unwind to caller
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 {
|
define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 {
|
||||||
entry:
|
entry:
|
||||||
br label %try.cont
|
br label %try.cont
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
; RUN: opt < %s -inline -S | FileCheck %s
|
|
||||||
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
|
|
||||||
target triple = "x86_64-pc-windows-msvc18.0.0"
|
|
||||||
|
|
||||||
define void @f() personality i32 (...)* @__CxxFrameHandler3 {
|
|
||||||
entry:
|
|
||||||
invoke void @g()
|
|
||||||
to label %try.cont unwind label %catch.dispatch
|
|
||||||
|
|
||||||
catch.dispatch: ; preds = %entry
|
|
||||||
%cs1 = catchswitch within none [label %catch] unwind to caller
|
|
||||||
|
|
||||||
catch: ; preds = %catch.dispatch
|
|
||||||
%0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
|
|
||||||
invoke void @dtor()
|
|
||||||
to label %invoke.cont.1 unwind label %ehcleanup
|
|
||||||
|
|
||||||
invoke.cont.1: ; preds = %catch
|
|
||||||
catchret from %0 to label %try.cont
|
|
||||||
|
|
||||||
try.cont: ; preds = %entry, %invoke.cont.1
|
|
||||||
ret void
|
|
||||||
|
|
||||||
ehcleanup:
|
|
||||||
%cp2 = cleanuppad within none []
|
|
||||||
call void @g()
|
|
||||||
cleanupret from %cp2 unwind to caller
|
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK-LABEL: define void @f(
|
|
||||||
|
|
||||||
; CHECK: invoke void @g()
|
|
||||||
; CHECK: to label %dtor.exit unwind label %terminate.i
|
|
||||||
|
|
||||||
; CHECK: terminate.i:
|
|
||||||
; CHECK-NEXT: terminatepad within %0 [void ()* @terminate] unwind label %ehcleanup
|
|
||||||
|
|
||||||
declare i32 @__CxxFrameHandler3(...)
|
|
||||||
|
|
||||||
define internal void @dtor() personality i32 (...)* @__CxxFrameHandler3 {
|
|
||||||
entry:
|
|
||||||
invoke void @g()
|
|
||||||
to label %invoke.cont unwind label %terminate
|
|
||||||
|
|
||||||
invoke.cont: ; preds = %entry
|
|
||||||
ret void
|
|
||||||
|
|
||||||
terminate: ; preds = %entry
|
|
||||||
terminatepad within none [void ()* @terminate] unwind to caller
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @g()
|
|
||||||
declare void @terminate()
|
|
@ -20,9 +20,6 @@ throw: ; preds = %throw, %entry
|
|||||||
|
|
||||||
pad: ; preds = %throw
|
pad: ; preds = %throw
|
||||||
%phi2 = phi i8* [ %tmp96, %throw ]
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
||||||
terminatepad within none [] unwind label %blah
|
|
||||||
|
|
||||||
blah:
|
|
||||||
%cs = catchswitch within none [label %unreachable] unwind label %blah2
|
%cs = catchswitch within none [label %unreachable] unwind label %blah2
|
||||||
|
|
||||||
unreachable:
|
unreachable:
|
||||||
|
@ -63,14 +63,6 @@ lpad:
|
|||||||
resume { i8*, i32 } zeroinitializer
|
resume { i8*, i32 } zeroinitializer
|
||||||
}
|
}
|
||||||
|
|
||||||
define i8 @call_with_same_range() {
|
|
||||||
; CHECK-LABEL: @call_with_same_range
|
|
||||||
; CHECK: tail call i8 @call_with_range
|
|
||||||
bitcast i8 0 to i8
|
|
||||||
%out = call i8 @dummy(), !range !0
|
|
||||||
ret i8 %out
|
|
||||||
}
|
|
||||||
|
|
||||||
define i8 @invoke_with_same_range() personality i8* undef {
|
define i8 @invoke_with_same_range() personality i8* undef {
|
||||||
; CHECK-LABEL: @invoke_with_same_range()
|
; CHECK-LABEL: @invoke_with_same_range()
|
||||||
; CHECK: tail call i8 @invoke_with_range()
|
; CHECK: tail call i8 @invoke_with_range()
|
||||||
@ -84,6 +76,14 @@ lpad:
|
|||||||
resume { i8*, i32 } zeroinitializer
|
resume { i8*, i32 } zeroinitializer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i8 @call_with_same_range() {
|
||||||
|
; CHECK-LABEL: @call_with_same_range
|
||||||
|
; CHECK: tail call i8 @call_with_range
|
||||||
|
bitcast i8 0 to i8
|
||||||
|
%out = call i8 @dummy(), !range !0
|
||||||
|
ret i8 %out
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
declare i8 @dummy();
|
declare i8 @dummy();
|
||||||
|
@ -219,61 +219,6 @@ ehcleanup:
|
|||||||
cleanupret from %cp2 unwind to caller
|
cleanupret from %cp2 unwind to caller
|
||||||
}
|
}
|
||||||
|
|
||||||
; This tests the case where a terminatepad unwinds to a cleanuppad.
|
|
||||||
; I'm not sure how this case would arise, but it seems to be syntactically
|
|
||||||
; legal so I'm testing it.
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: define void @f5()
|
|
||||||
; CHECK: entry:
|
|
||||||
; CHECK: invoke void @g()
|
|
||||||
; CHECK: to label %try.cont unwind label %terminate
|
|
||||||
; CHECK: terminate:
|
|
||||||
; CHECK: terminatepad within none [i7 4] unwind to caller
|
|
||||||
; CHECK-NOT: cleanuppad
|
|
||||||
; CHECK: try.cont:
|
|
||||||
; CHECK: invoke void @g()
|
|
||||||
; CHECK: to label %try.cont.1 unwind label %terminate.1
|
|
||||||
; CHECK: terminate.1:
|
|
||||||
; CHECK: terminatepad within none [i7 4] unwind label %ehcleanup.2
|
|
||||||
; CHECK-NOT: ehcleanup.1:
|
|
||||||
; CHECK: ehcleanup.2:
|
|
||||||
; CHECK: [[TMP:\%.+]] = cleanuppad
|
|
||||||
; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
|
|
||||||
; CHECK: cleanupret from [[TMP]] unwind to caller
|
|
||||||
; CHECK: }
|
|
||||||
define void @f5() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
|
||||||
entry:
|
|
||||||
%a = alloca %struct.S2, align 1
|
|
||||||
invoke void @g()
|
|
||||||
to label %try.cont unwind label %terminate
|
|
||||||
|
|
||||||
terminate: ; preds = %entry
|
|
||||||
terminatepad within none [i7 4] unwind label %ehcleanup
|
|
||||||
|
|
||||||
ehcleanup: ; preds = %terminate
|
|
||||||
%0 = cleanuppad within none []
|
|
||||||
cleanupret from %0 unwind to caller
|
|
||||||
|
|
||||||
try.cont: ; preds = %entry
|
|
||||||
invoke void @g()
|
|
||||||
to label %try.cont.1 unwind label %terminate.1
|
|
||||||
|
|
||||||
terminate.1: ; preds = %try.cont
|
|
||||||
terminatepad within none [i7 4] unwind label %ehcleanup.1
|
|
||||||
|
|
||||||
ehcleanup.1: ; preds = %terminate.1
|
|
||||||
%1 = cleanuppad within none []
|
|
||||||
cleanupret from %1 unwind label %ehcleanup.2
|
|
||||||
|
|
||||||
ehcleanup.2: ; preds = %ehcleanup.1
|
|
||||||
%2 = cleanuppad within none []
|
|
||||||
call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
|
|
||||||
cleanupret from %2 unwind to caller
|
|
||||||
|
|
||||||
try.cont.1: ; preds = %try.cont
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; This case tests simplification of an otherwise empty cleanup pad that contains
|
; This case tests simplification of an otherwise empty cleanup pad that contains
|
||||||
; a PHI node.
|
; a PHI node.
|
||||||
;
|
;
|
||||||
|
@ -65,21 +65,6 @@ unreachable.unwind:
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: define void @test4()
|
|
||||||
define void @test4() personality i8* bitcast (void ()* @Personality to i8*) {
|
|
||||||
entry:
|
|
||||||
invoke void @f()
|
|
||||||
to label %exit unwind label %terminate.pad
|
|
||||||
terminate.pad:
|
|
||||||
; CHECK: terminatepad within none [] unwind to caller
|
|
||||||
terminatepad within none [] unwind label %unreachable.unwind
|
|
||||||
exit:
|
|
||||||
ret void
|
|
||||||
unreachable.unwind:
|
|
||||||
cleanuppad within none []
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK-LABEL: define void @test5()
|
; CHECK-LABEL: define void @test5()
|
||||||
define void @test5() personality i8* bitcast (void ()* @Personality to i8*) {
|
define void @test5() personality i8* bitcast (void ()* @Personality to i8*) {
|
||||||
entry:
|
entry:
|
||||||
|
@ -259,7 +259,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
|||||||
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
|
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
|
||||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
|
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
|
||||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
|
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
|
||||||
STRINGIFY_CODE(FUNC_CODE, INST_TERMINATEPAD)
|
|
||||||
STRINGIFY_CODE(FUNC_CODE, INST_PHI)
|
STRINGIFY_CODE(FUNC_CODE, INST_PHI)
|
||||||
STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
|
STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
|
||||||
STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
|
STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
|
||||||
|
Loading…
Reference in New Issue
Block a user