mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +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
|
||||
they must be the first non-phi instruction of a basic block that may be the
|
||||
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
|
||||
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
|
||||
C++ object with a destructor, invokes should unwind to a ``cleanuppad``. The
|
||||
``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.
|
||||
C++ object with a destructor, invokes should unwind to a ``cleanuppad``.
|
||||
|
||||
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
|
||||
@ -634,9 +630,9 @@ by normal execution executes a ``cleanupret`` instruction, which is a terminator
|
||||
indicating where the active exception will unwind to next.
|
||||
|
||||
Each of these new EH pad instructions has a way to identify which action should
|
||||
be considered after this action. The ``catchswitch`` and ``terminatepad``
|
||||
instructions are terminators, and have a unwind destination operand analogous
|
||||
to the unwind destination of an invoke. The ``cleanuppad`` instruction is not
|
||||
be considered after this action. The ``catchswitch`` instruction is a terminator
|
||||
and has an unwind destination operand analogous to the unwind destination of an
|
||||
invoke. The ``cleanuppad`` instruction is not
|
||||
a terminator, so the unwind destination is stored on the ``cleanupret``
|
||||
instruction instead. Successfully executing a catch handler should resume
|
||||
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
|
||||
|
||||
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
|
||||
@ -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``
|
||||
instructions. This ensures that every catch handler modelled by a ``catchpad``
|
||||
belongs to exactly one ``catchswitch``, which models the dispatch point after a
|
||||
C++ try. The ``terminatepad`` instruction cannot contain lexically nested
|
||||
funclets inside the termination action, so it does not produce a token.
|
||||
C++ try.
|
||||
|
||||
Here is an example of what this nesting looks like using some hypothetical
|
||||
C++ code:
|
||||
|
@ -5004,7 +5004,6 @@ The terminator instructions are: ':ref:`ret <i_ret>`',
|
||||
':ref:`resume <i_resume>`', ':ref:`catchswitch <i_catchswitch>`',
|
||||
':ref:`catchret <i_catchret>`',
|
||||
':ref:`cleanupret <i_cleanupret>`',
|
||||
':ref:`terminatepad <i_terminatepad>`',
|
||||
and ':ref:`unreachable <i_unreachable>`'.
|
||||
|
||||
.. _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``.
|
||||
|
||||
The ``default`` argument is the label of another basic block beginning with a
|
||||
"pad" instruction, one of ``cleanuppad``, ``terminatepad``, or
|
||||
``catchswitch``.
|
||||
"pad" instruction, one of ``cleanuppad`` or ``catchswitch``.
|
||||
|
||||
The ``handlers`` are a list of successor blocks that each begin with a
|
||||
: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
|
||||
exited.
|
||||
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
|
||||
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
|
||||
@ -5589,62 +5587,6 @@ Example:
|
||||
cleanupret from %cleanup unwind to caller
|
||||
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:
|
||||
|
||||
'``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
|
||||
exited.
|
||||
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
|
||||
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
|
||||
|
@ -252,9 +252,8 @@ typedef enum {
|
||||
LLVMCleanupRet = 61,
|
||||
LLVMCatchRet = 62,
|
||||
LLVMCatchPad = 63,
|
||||
LLVMTerminatePad = 64,
|
||||
LLVMCleanupPad = 65,
|
||||
LLVMCatchSwitch = 66
|
||||
LLVMCleanupPad = 64,
|
||||
LLVMCatchSwitch = 65
|
||||
} LLVMOpcode;
|
||||
|
||||
typedef enum {
|
||||
@ -1224,7 +1223,6 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(ResumeInst) \
|
||||
macro(CleanupReturnInst) \
|
||||
macro(CatchReturnInst) \
|
||||
macro(TerminatePadInst) \
|
||||
macro(FuncletPadInst) \
|
||||
macro(CatchPadInst) \
|
||||
macro(CleanupPadInst) \
|
||||
|
@ -421,9 +421,9 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
|
||||
FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [val] or [val,bb#]
|
||||
FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [val,bb#]
|
||||
FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [bb#,bb#,num,args...]
|
||||
FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...]
|
||||
FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...]
|
||||
FUNC_CODE_INST_CATCHSWITCH = 53, // CATCHSWITCH: [num,args...] or [num,args...,bb]
|
||||
FUNC_CODE_INST_CLEANUPPAD = 51, // CLEANUPPAD: [num,args...]
|
||||
FUNC_CODE_INST_CATCHSWITCH = 52, // CATCHSWITCH: [num,args...] or [num,args...,bb]
|
||||
// 53 is unused.
|
||||
// 54 is unused.
|
||||
FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
|
||||
};
|
||||
|
@ -720,13 +720,6 @@ public:
|
||||
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,
|
||||
ArrayRef<Value *> Args = None,
|
||||
const Twine &Name = "") {
|
||||
|
@ -172,7 +172,6 @@ public:
|
||||
RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst); }
|
||||
RetTy visitCatchSwitchInst(CatchSwitchInst &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);}
|
||||
|
@ -87,7 +87,6 @@ public:
|
||||
case Instruction::CleanupRet:
|
||||
case Instruction::Invoke:
|
||||
case Instruction::Resume:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -117,85 +117,84 @@ HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst)
|
||||
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
|
||||
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
|
||||
HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst)
|
||||
HANDLE_TERM_INST (11, TerminatePad , TerminatePadInst)
|
||||
LAST_TERM_INST (11)
|
||||
LAST_TERM_INST (10)
|
||||
|
||||
// Standard binary operators...
|
||||
FIRST_BINARY_INST(12)
|
||||
HANDLE_BINARY_INST(12, Add , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, FAdd , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, FSub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(17, FMul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(18, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(19, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(20, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(21, URem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(22, SRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(23, FRem , BinaryOperator)
|
||||
FIRST_BINARY_INST(11)
|
||||
HANDLE_BINARY_INST(11, Add , BinaryOperator)
|
||||
HANDLE_BINARY_INST(12, FAdd , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, FSub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, FMul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(17, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(18, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(19, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(20, URem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(21, SRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(22, FRem , BinaryOperator)
|
||||
|
||||
// Logical operators (integer operands)
|
||||
HANDLE_BINARY_INST(24, Shl , BinaryOperator) // Shift left (logical)
|
||||
HANDLE_BINARY_INST(25, LShr , BinaryOperator) // Shift right (logical)
|
||||
HANDLE_BINARY_INST(26, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||
HANDLE_BINARY_INST(27, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(28, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(29, Xor , BinaryOperator)
|
||||
LAST_BINARY_INST(29)
|
||||
HANDLE_BINARY_INST(23, Shl , BinaryOperator) // Shift left (logical)
|
||||
HANDLE_BINARY_INST(24, LShr , BinaryOperator) // Shift right (logical)
|
||||
HANDLE_BINARY_INST(25, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||
HANDLE_BINARY_INST(26, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(27, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(28, Xor , BinaryOperator)
|
||||
LAST_BINARY_INST(28)
|
||||
|
||||
// Memory operators...
|
||||
FIRST_MEMORY_INST(30)
|
||||
HANDLE_MEMORY_INST(30, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(31, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(32, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(33, GetElementPtr, GetElementPtrInst)
|
||||
HANDLE_MEMORY_INST(34, Fence , FenceInst )
|
||||
HANDLE_MEMORY_INST(35, AtomicCmpXchg , AtomicCmpXchgInst )
|
||||
HANDLE_MEMORY_INST(36, AtomicRMW , AtomicRMWInst )
|
||||
LAST_MEMORY_INST(36)
|
||||
FIRST_MEMORY_INST(29)
|
||||
HANDLE_MEMORY_INST(29, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(30, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(31, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(32, GetElementPtr, GetElementPtrInst)
|
||||
HANDLE_MEMORY_INST(33, Fence , FenceInst )
|
||||
HANDLE_MEMORY_INST(34, AtomicCmpXchg , AtomicCmpXchgInst )
|
||||
HANDLE_MEMORY_INST(35, AtomicRMW , AtomicRMWInst )
|
||||
LAST_MEMORY_INST(35)
|
||||
|
||||
// Cast operators ...
|
||||
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
||||
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
||||
FIRST_CAST_INST(37)
|
||||
HANDLE_CAST_INST(37, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(38, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(39, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(40, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(41, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(42, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(43, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(44, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(45, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(46, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(47, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(48, BitCast , BitCastInst ) // Type cast
|
||||
HANDLE_CAST_INST(49, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
|
||||
LAST_CAST_INST(49)
|
||||
FIRST_CAST_INST(36)
|
||||
HANDLE_CAST_INST(36, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(37, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(38, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(39, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(40, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(41, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(42, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(43, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(44, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(45, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(46, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(47, BitCast , BitCastInst ) // Type cast
|
||||
HANDLE_CAST_INST(48, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
|
||||
LAST_CAST_INST(48)
|
||||
|
||||
FIRST_FUNCLETPAD_INST(50)
|
||||
HANDLE_FUNCLETPAD_INST(50, CleanupPad, CleanupPadInst)
|
||||
HANDLE_FUNCLETPAD_INST(51, CatchPad , CatchPadInst)
|
||||
LAST_FUNCLETPAD_INST(51)
|
||||
FIRST_FUNCLETPAD_INST(49)
|
||||
HANDLE_FUNCLETPAD_INST(49, CleanupPad, CleanupPadInst)
|
||||
HANDLE_FUNCLETPAD_INST(50, CatchPad , CatchPadInst)
|
||||
LAST_FUNCLETPAD_INST(50)
|
||||
|
||||
// Other operators...
|
||||
FIRST_OTHER_INST(52)
|
||||
HANDLE_OTHER_INST(52, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(53, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(54, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(55, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(56, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(57, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(58, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(59, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(60, ExtractElement, ExtractElementInst)// extract from vector
|
||||
HANDLE_OTHER_INST(61, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(62, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
HANDLE_OTHER_INST(63, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||
HANDLE_OTHER_INST(64, InsertValue, InsertValueInst) // insert into aggregate
|
||||
HANDLE_OTHER_INST(65, LandingPad, LandingPadInst) // Landing pad instruction.
|
||||
LAST_OTHER_INST(65)
|
||||
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.
|
||||
LAST_OTHER_INST(64)
|
||||
|
||||
#undef FIRST_TERM_INST
|
||||
#undef HANDLE_TERM_INST
|
||||
|
@ -396,7 +396,6 @@ public:
|
||||
case Instruction::CatchPad:
|
||||
case Instruction::CleanupPad:
|
||||
case Instruction::LandingPad:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -3991,143 +3991,6 @@ struct OperandTraits<CatchSwitchInst> : public HungoffOperandTraits<2> {};
|
||||
|
||||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -289,8 +289,8 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
|
||||
DIBuilder &Builder, bool Deref, int Offset = 0);
|
||||
|
||||
/// Replace 'BB's terminator with one that does not have an unwind successor
|
||||
/// block. Rewrites `invoke` to `call`, `terminatepad unwind label %foo` to
|
||||
/// `terminatepad unwind to caller`, etc. Updates any PHIs in unwind successor.
|
||||
/// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
|
||||
/// successor.
|
||||
///
|
||||
/// \param BB Block whose terminator will be replaced. Its terminator must
|
||||
/// 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
|
||||
// a nested funclet).
|
||||
//
|
||||
// Note: Despite not being funclets in the truest sense, terminatepad and
|
||||
// catchswitch are considered to belong to their own funclet for the purposes
|
||||
// of coloring.
|
||||
// Note: Despite not being a funclet in the truest sense, a catchswitch is
|
||||
// considered to belong to its own funclet for the purposes of coloring.
|
||||
|
||||
DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
|
||||
<< F.getName() << "\n");
|
||||
|
@ -98,8 +98,6 @@ static BasicBlock::iterator findInsertPointAfter(Instruction *I,
|
||||
while (IP->isEHPad()) {
|
||||
if (isa<FuncletPadInst>(IP) || isa<LandingPadInst>(IP)) {
|
||||
++IP;
|
||||
} else if (auto *TPI = dyn_cast<TerminatePadInst>(IP)) {
|
||||
IP = TPI->getUnwindDest()->getFirstNonPHI()->getIterator();
|
||||
} else if (isa<CatchSwitchInst>(IP)) {
|
||||
IP = MustDominate->getFirstInsertionPt();
|
||||
} else {
|
||||
|
@ -3436,7 +3436,6 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::CleanupPad:
|
||||
case Instruction::CleanupRet:
|
||||
case Instruction::TerminatePad:
|
||||
return false; // Misc instructions which have effects
|
||||
}
|
||||
}
|
||||
|
@ -763,7 +763,6 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
INSTKEYWORD(catchret, CatchRet);
|
||||
INSTKEYWORD(catchswitch, CatchSwitch);
|
||||
INSTKEYWORD(catchpad, CatchPad);
|
||||
INSTKEYWORD(terminatepad, TerminatePad);
|
||||
INSTKEYWORD(cleanuppad, CleanupPad);
|
||||
#undef INSTKEYWORD
|
||||
|
||||
|
@ -4723,7 +4723,6 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
|
||||
case lltok::kw_catchswitch: return ParseCatchSwitch(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);
|
||||
// Binary Operators.
|
||||
case lltok::kw_add:
|
||||
@ -5285,43 +5284,6 @@ bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
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
|
||||
/// ::= 'cleanuppad' within Parent ParamList
|
||||
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
|
@ -465,7 +465,6 @@ namespace llvm {
|
||||
bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
|
||||
|
||||
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_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_getelementptr,
|
||||
|
@ -4484,40 +4484,6 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
|
||||
InstructionList.push_back(I);
|
||||
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_CLEANUPPAD: { // [tok,num,(ty,val)*]
|
||||
// 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()));
|
||||
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:
|
||||
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
|
||||
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
|
||||
/// 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.
|
||||
/// This function skips over imaginary basic blocks that hold catchswitch or
|
||||
/// terminatepad instructions, and finds all the "real" machine
|
||||
/// This function skips over imaginary basic blocks that hold catchswitch
|
||||
/// instructions, and finds all the "real" machine
|
||||
/// basic block destinations. As those destinations may not be successors of
|
||||
/// EHPadBB, here we also calculate the edge probability to those destinations.
|
||||
/// The passed-in Prob is the edge probability to EHPadBB.
|
||||
@ -1300,10 +1300,6 @@ void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
|
||||
DAG.setRoot(Ret);
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
|
||||
report_fatal_error("visitTerminatePad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchSwitch(const CatchSwitchInst &CSI) {
|
||||
report_fatal_error("visitCatchSwitch not yet implemented!");
|
||||
}
|
||||
|
@ -740,7 +740,6 @@ private:
|
||||
void visitCatchSwitch(const CatchSwitchInst &I);
|
||||
void visitCatchRet(const CatchReturnInst &I);
|
||||
void visitCatchPad(const CatchPadInst &I);
|
||||
void visitTerminatePad(const TerminatePadInst &TPI);
|
||||
void visitCleanupPad(const CleanupPadInst &CPI);
|
||||
|
||||
BranchProbability getEdgeProbability(const MachineBasicBlock *Src,
|
||||
|
@ -1574,7 +1574,6 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
|
||||
case CatchRet: return 0;
|
||||
case CatchPad: return 0;
|
||||
case CatchSwitch: return 0;
|
||||
case TerminatePad: return 0;
|
||||
case CleanupPad: return 0;
|
||||
case Add: return ISD::ADD;
|
||||
case FAdd: return ISD::FADD;
|
||||
|
@ -70,7 +70,6 @@ private:
|
||||
void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
|
||||
DenseMap<BasicBlock *, Value *> &Loads, Function &F);
|
||||
bool prepareExplicitEH(Function &F);
|
||||
void replaceTerminatePadWithCleanup(Function &F);
|
||||
void colorFunclets(Function &F);
|
||||
|
||||
void demotePHIsOnFunclets(Function &F);
|
||||
@ -523,45 +522,6 @@ void llvm::calculateClrEHStateNumbers(const Function *Fn,
|
||||
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) {
|
||||
BlockColors = colorEHFunclets(F);
|
||||
|
||||
@ -885,8 +845,6 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
|
||||
// not.
|
||||
removeUnreachableBlocks(F);
|
||||
|
||||
replaceTerminatePadWithCleanup(F);
|
||||
|
||||
// Determine which blocks are reachable from which funclet entries.
|
||||
colorFunclets(F);
|
||||
|
||||
|
@ -2917,21 +2917,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||
writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
|
||||
}
|
||||
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) {
|
||||
Out << " void";
|
||||
} else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
|
||||
|
@ -206,7 +206,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
||||
case CatchRet: return "catchret";
|
||||
case CatchPad: return "catchpad";
|
||||
case CatchSwitch: return "catchswitch";
|
||||
case TerminatePad: return "terminatepad";
|
||||
|
||||
// Standard binary operators...
|
||||
case Add: return "add";
|
||||
@ -421,7 +420,6 @@ bool Instruction::mayReadFromMemory() const {
|
||||
case Instruction::AtomicRMW:
|
||||
case Instruction::CatchPad:
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
case Instruction::Call:
|
||||
return !cast<CallInst>(this)->doesNotAccessMemory();
|
||||
@ -444,7 +442,6 @@ bool Instruction::mayWriteToMemory() const {
|
||||
case Instruction::AtomicRMW:
|
||||
case Instruction::CatchPad:
|
||||
case Instruction::CatchRet:
|
||||
case Instruction::TerminatePad:
|
||||
return true;
|
||||
case Instruction::Call:
|
||||
return !cast<CallInst>(this)->onlyReadsMemory();
|
||||
@ -477,8 +474,6 @@ bool Instruction::mayThrow() const {
|
||||
return CRI->unwindsToCaller();
|
||||
if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(this))
|
||||
return CatchSwitch->unwindsToCaller();
|
||||
if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
|
||||
return TPI->unwindsToCaller();
|
||||
return isa<ResumeInst>(this);
|
||||
}
|
||||
|
||||
|
@ -980,60 +980,6 @@ FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
|
||||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -4025,10 +3971,6 @@ FuncletPadInst *FuncletPadInst::cloneImpl() const {
|
||||
return new (getNumOperands()) FuncletPadInst(*this);
|
||||
}
|
||||
|
||||
TerminatePadInst *TerminatePadInst::cloneImpl() const {
|
||||
return new (getNumOperands()) TerminatePadInst(*this);
|
||||
}
|
||||
|
||||
UnreachableInst *UnreachableInst::cloneImpl() const {
|
||||
LLVMContext &Context = getContext();
|
||||
return new UnreachableInst(Context);
|
||||
|
@ -403,7 +403,6 @@ private:
|
||||
void visitCleanupPadInst(CleanupPadInst &CPI);
|
||||
void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch);
|
||||
void visitCleanupReturnInst(CleanupReturnInst &CRI);
|
||||
void visitTerminatePadInst(TerminatePadInst &TPI);
|
||||
|
||||
void VerifyCallSite(CallSite CS);
|
||||
void verifyMustTailCall(CallInst &CI);
|
||||
@ -2899,8 +2898,7 @@ void Verifier::visitEHPadPredecessors(Instruction &I) {
|
||||
if (auto *II = dyn_cast<InvokeInst>(TI)) {
|
||||
Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,
|
||||
"EH pad must be jumped to via an unwind edge", &I, II);
|
||||
} else if (!isa<CleanupReturnInst>(TI) && !isa<TerminatePadInst>(TI) &&
|
||||
!isa<CatchSwitchInst>(TI)) {
|
||||
} else if (!isa<CleanupReturnInst>(TI) && !isa<CatchSwitchInst>(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;
|
||||
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
|
||||
UnwindDest = CRI->getUnwindDest();
|
||||
} else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U) ||
|
||||
isa<TerminatePadInst>(U)) {
|
||||
} else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
|
||||
continue;
|
||||
} else {
|
||||
Assert(false, "bogus cleanuppad use", &CPI);
|
||||
@ -3072,37 +3069,6 @@ void Verifier::visitCleanupReturnInst(CleanupReturnInst &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) {
|
||||
Instruction *Op = cast<Instruction>(I.getOperand(i));
|
||||
// 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());
|
||||
}
|
||||
|
||||
void visitTerminatePad(TerminatePadInst &I) {
|
||||
DEBUG(dbgs() << "TerminatePad: " << I << "\n");
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
void visitGetElementPtrInst(GetElementPtrInst &I) {
|
||||
handleShadowOr(I);
|
||||
}
|
||||
|
@ -343,15 +343,7 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
|
||||
continue;
|
||||
|
||||
Instruction *Replacement = nullptr;
|
||||
if (auto *TPI = dyn_cast<TerminatePadInst>(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 (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
||||
if (CatchSwitch->unwindsToCaller()) {
|
||||
auto *NewCatchSwitch = CatchSwitchInst::Create(
|
||||
CatchSwitch->getParentPad(), UnwindDest,
|
||||
@ -1441,10 +1433,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
if (!I->isEHPad())
|
||||
continue;
|
||||
|
||||
if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
|
||||
if (isa<ConstantTokenNone>(TPI->getParentPad()))
|
||||
TPI->setParentPad(CallSiteEHPad);
|
||||
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
||||
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
|
||||
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
|
||||
CatchSwitch->setParentPad(CallSiteEHPad);
|
||||
} else {
|
||||
|
@ -1338,13 +1338,6 @@ void llvm::removeUnwindEdge(BasicBlock *BB) {
|
||||
if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
|
||||
NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI);
|
||||
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)) {
|
||||
auto *NewCatchSwitch = CatchSwitchInst::Create(
|
||||
CatchSwitch->getParentPad(), nullptr, CatchSwitch->getNumHandlers(),
|
||||
|
@ -3498,7 +3498,7 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
|
||||
}
|
||||
} else if ((isa<InvokeInst>(TI) &&
|
||||
cast<InvokeInst>(TI)->getUnwindDest() == BB) ||
|
||||
isa<TerminatePadInst>(TI) || isa<CatchSwitchInst>(TI)) {
|
||||
isa<CatchSwitchInst>(TI)) {
|
||||
removeUnwindEdge(TI->getParent());
|
||||
Changed = true;
|
||||
} else if (isa<CleanupReturnInst>(TI)) {
|
||||
|
@ -774,7 +774,7 @@ entry:
|
||||
invoke void @f.ccc() to label %normal unwind label %catchswitch3
|
||||
|
||||
catchswitch1:
|
||||
%cs1 = catchswitch within none [label %catchpad1] unwind label %terminate.1
|
||||
%cs1 = catchswitch within none [label %catchpad1] unwind to caller
|
||||
|
||||
catchpad1:
|
||||
catchpad within %cs1 []
|
||||
@ -802,20 +802,9 @@ catchpad3:
|
||||
|
||||
cleanuppad1:
|
||||
%clean.1 = cleanuppad within none []
|
||||
unreachable
|
||||
; CHECK: %clean.1 = cleanuppad within none []
|
||||
invoke void @f.ccc() to label %normal unwind label %terminate.2
|
||||
|
||||
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
|
||||
; CHECK-NEXT: unreachable
|
||||
|
||||
normal:
|
||||
ret i32 0
|
||||
@ -852,8 +841,10 @@ return:
|
||||
ret i32 0
|
||||
|
||||
terminate:
|
||||
terminatepad within %cs [] unwind to caller
|
||||
; CHECK: terminatepad within %cs [] unwind to caller
|
||||
cleanuppad within %cs []
|
||||
unreachable
|
||||
; CHECK: cleanuppad within %cs []
|
||||
; CHECK-NEXT: unreachable
|
||||
|
||||
continue:
|
||||
ret i32 0
|
||||
|
@ -93,22 +93,6 @@ exit:
|
||||
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(
|
||||
define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 {
|
||||
entry:
|
||||
|
@ -123,28 +123,6 @@ exit:
|
||||
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 {
|
||||
entry:
|
||||
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
|
||||
%phi2 = phi i8* [ %tmp96, %throw ]
|
||||
terminatepad within none [] unwind label %blah
|
||||
|
||||
blah:
|
||||
%cs = catchswitch within none [label %unreachable] unwind label %blah2
|
||||
|
||||
unreachable:
|
||||
|
@ -63,14 +63,6 @@ lpad:
|
||||
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 {
|
||||
; CHECK-LABEL: @invoke_with_same_range()
|
||||
; CHECK: tail call i8 @invoke_with_range()
|
||||
@ -84,6 +76,14 @@ lpad:
|
||||
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();
|
||||
|
@ -219,61 +219,6 @@ ehcleanup:
|
||||
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
|
||||
; a PHI node.
|
||||
;
|
||||
|
@ -65,21 +65,6 @@ unreachable.unwind:
|
||||
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()
|
||||
define void @test5() personality i8* bitcast (void ()* @Personality to i8*) {
|
||||
entry:
|
||||
|
@ -259,7 +259,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
|
||||
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
|
||||
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…
Reference in New Issue
Block a user