1
0
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:
David Majnemer 2015-12-14 18:34:23 +00:00
parent 252af42f99
commit 49dcd13916
41 changed files with 109 additions and 770 deletions

View File

@ -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:

View File

@ -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

View File

@ -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) \

View File

@ -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...]
}; };

View File

@ -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 = "") {

View File

@ -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);}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -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.

View File

@ -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");

View File

@ -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 {

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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) {

View File

@ -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,

View File

@ -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,

View File

@ -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.

View File

@ -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;

View File

@ -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!");
} }

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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)) {

View File

@ -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);
} }

View File

@ -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);

View File

@ -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.

View File

@ -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);
} }

View File

@ -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 {

View File

@ -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(),

View File

@ -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)) {

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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()

View File

@ -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:

View File

@ -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();

View File

@ -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.
; ;

View File

@ -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:

View File

@ -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)