summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/ExceptionHandling.rst31
-rw-r--r--llvm/docs/LangRef.rst94
-rw-r--r--llvm/include/llvm/Bitcode/LLVMBitCodes.h6
-rw-r--r--llvm/include/llvm/IR/IRBuilder.h21
-rw-r--r--llvm/include/llvm/IR/Instructions.h301
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp2
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp184
-rw-r--r--llvm/lib/AsmParser/LLParser.h25
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp154
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp10
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp7
-rw-r--r--llvm/lib/IR/AsmWriter.cpp22
-rw-r--r--llvm/lib/IR/Instruction.cpp2
-rw-r--r--llvm/lib/IR/Instructions.cpp102
-rw-r--r--llvm/lib/IR/Verifier.cpp47
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp12
-rw-r--r--llvm/lib/Transforms/Utils/InlineFunction.cpp3
-rw-r--r--llvm/test/Assembler/invalid-OperatorConstraint.ll59
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-demotion.ll80
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-statenumbering.ll6
-rw-r--r--llvm/test/Feature/exception.ll102
21 files changed, 738 insertions, 532 deletions
diff --git a/llvm/docs/ExceptionHandling.rst b/llvm/docs/ExceptionHandling.rst
index 87465343dfe..fce875b9b8a 100644
--- a/llvm/docs/ExceptionHandling.rst
+++ b/llvm/docs/ExceptionHandling.rst
@@ -614,20 +614,19 @@ 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.
-Each of these new EH pad instructions has a label operand that indicates which
+Each of these new EH pad instructions has a way to identify which
action should be considered after this action. The ``catchpad`` and
-``terminatepad`` instructions are terminators, and this label is considered to
-be an unwind destination analogous to the unwind destination of an invoke. The
+``terminatepad`` instructions are terminators, and have a label operand considered
+to be an unwind destination analogous to the unwind destination of an invoke. The
``cleanuppad`` instruction is different from the other two in that it is not a
-terminator, and this label operand is not an edge in the CFG. The code inside a
-cleanuppad runs before transferring control to the next action, so the
-``cleanupret`` instruction is the instruction that unwinds to the next EH pad.
-All of these "unwind edges" may refer to a basic block that contains an EH pad
-instruction, or they may simply unwind to the caller. Unwinding to the caller
-has roughly the same semantics as the ``resume`` instruction in the
-``landingpad`` model. When inlining through an invoke, instructions that unwind
-to the caller are hooked up to unwind to the unwind destination of the call
-site.
+terminator. The code inside a cleanuppad runs before transferring control to the
+next action, so the ``cleanupret`` instruction is the instruction that holds a
+label operand and unwinds to the next EH pad. All of these "unwind edges" may
+refer to a basic block that contains an EH pad instruction, or they may simply
+unwind to the caller. Unwinding to the caller has roughly the same semantics as
+the ``resume`` instruction in the ``landingpad`` model. When inlining through an
+invoke, instructions that unwind to the caller are hooked up to unwind to the
+unwind destination of the call site.
Putting things together, here is a hypothetical lowering of some C++ that uses
all of the new IR instructions:
@@ -674,17 +673,17 @@ all of the new IR instructions:
; EH scope code, ordered innermost to outermost:
lpad.cleanup: ; preds = %invoke.cont
- cleanuppad [label %lpad.catch]
+ %cleanup = cleanuppad []
call void @"\01??_DCleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) nounwind
- cleanupret unwind label %lpad.catch
+ cleanupret %cleanup unwind label %lpad.catch
lpad.catch: ; preds = %entry, %lpad.cleanup
- catchpad void [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e]
+ %catch = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e]
to label %catch unwind label %lpad.terminate
catch: ; preds = %lpad.catch
%9 = load i32, i32* %e, align 4
- catchret label %return
+ catchret %catch label %return
lpad.terminate:
terminatepad [void ()* @"\01?terminate@@YAXXZ"]
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8a9ea13de08..9041c0cb206 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -5138,7 +5138,7 @@ Syntax:
::
- <resultval> = catchpad <resultty> [<args>*]
+ <resultval> = catchpad [<args>*]
to label <normal label> unwind label <exception label>
Overview:
@@ -5153,9 +5153,9 @@ routine requires to know if this is an appropriate place to catch the
exception. Control is tranfered to the ``exception`` label if the
``catchpad`` is not an appropriate handler for the in-flight exception.
The ``normal`` label should contain the code found in the ``catch``
-portion of a ``try``/``catch`` sequence. It defines values supplied by
-the :ref:`personality function <personalityfn>` upon re-entry to the
-function. The ``resultval`` has the type ``resultty``.
+portion of a ``try``/``catch`` sequence. The ``resultval`` has the type
+:ref:`token <t_token>` and is used to match the ``catchpad`` to
+corresponding :ref:`catchrets <i_catchret>`.
Arguments:
""""""""""
@@ -5170,15 +5170,11 @@ label to transfer control to if it doesn't.
Semantics:
""""""""""
-The '``catchpad``' instruction defines the values which are set by the
-:ref:`personality function <personalityfn>` upon re-entry to the function, and
-therefore the "result type" of the ``catchpad`` instruction. As with
-calling conventions, how the personality function results are
-represented in LLVM IR is target specific.
-
When the call stack is being unwound due to an exception being thrown,
the exception is compared against the ``args``. If it doesn't match,
then control is transfered to the ``exception`` basic block.
+As with calling conventions, how the personality function results are
+represented in LLVM IR is target specific.
The ``catchpad`` instruction has several restrictions:
@@ -5192,11 +5188,14 @@ The ``catchpad`` instruction has several restrictions:
catch block.
- A basic block that is not a catch block may not include a
'``catchpad``' instruction.
+- A catch block which has another catch block as a predecessor may not have
+ any other predecessors.
- It is undefined behavior for control to transfer from a ``catchpad`` to a
- ``cleanupret`` without first executing a ``catchret`` and a subsequent
- ``cleanuppad``.
-- It is undefined behavior for control to transfer from a ``catchpad`` to a
- ``ret`` without first executing a ``catchret``.
+ ``ret`` without first executing a ``catchret`` that consumes the
+ ``catchpad`` or unwinding through its ``catchendpad``.
+- It is undefined behavior for control to transfer from a ``catchpad`` to
+ itself without first executing a ``catchret`` that consumes the
+ ``catchpad`` or unwinding through its ``catchendpad``.
Example:
""""""""
@@ -5204,7 +5203,7 @@ Example:
.. code-block:: llvm
;; A catch block which can catch an integer.
- %res = catchpad { i8*, i32 } [i8** @_ZTIi]
+ %tok = catchpad [i8** @_ZTIi]
to label %int.handler unwind label %terminate
.. _i_catchendpad:
@@ -5264,7 +5263,8 @@ The ``catchendpad`` instruction has several restrictions:
'``catchendpad``' instruction.
- Exactly one catch block may unwind to a ``catchendpad``.
- The unwind target of invokes between a ``catchpad`` and a
- corresponding ``catchret`` must be its ``catchendpad``.
+ corresponding ``catchret`` must be its ``catchendpad`` or
+ an inner EH pad.
Example:
""""""""
@@ -5284,7 +5284,7 @@ Syntax:
::
- catchret <type> <value> to label <normal>
+ catchret <value> to label <normal>
Overview:
"""""""""
@@ -5296,8 +5296,10 @@ single successor.
Arguments:
""""""""""
-The '``catchret``' instruction requires one argument which specifies
-where control will transfer to next.
+The first argument to a '``catchret``' indicates which ``catchpad`` it
+exits. It must be a :ref:`catchpad <i_catchpad>`.
+The second argument to a '``catchret``' specifies where control will
+transfer to next.
Semantics:
""""""""""
@@ -5309,13 +5311,21 @@ The :ref:`personality function <personalityfn>` gets a chance to execute
arbitrary code to, for example, run a C++ destructor.
Control then transfers to ``normal``.
It may be passed an optional, personality specific, value.
+It is undefined behavior to execute a ``catchret`` whose ``catchpad`` has
+not been executed.
+It is undefined behavior to execute a ``catchret`` if any ``catchpad`` or
+``cleanuppad`` has been executed, without subsequently executing a
+corresponding ``catchret``/``cleanupret`` or unwinding out of the inner
+pad, following the most recent execution of the ``catchret``'s corresponding
+``catchpad``.
+
Example:
""""""""
.. code-block:: llvm
- catchret label %continue
+ catchret %catch label %continue
.. _i_cleanupret:
@@ -5327,8 +5337,8 @@ Syntax:
::
- cleanupret <type> <value> unwind label <continue>
- cleanupret <type> <value> unwind to caller
+ cleanupret <value> unwind label <continue>
+ cleanupret <value> unwind to caller
Overview:
"""""""""
@@ -5340,9 +5350,9 @@ an optional successor.
Arguments:
""""""""""
-The '``cleanupret``' instruction requires one argument, which must have the
-same type as the result of any '``cleanuppad``' instruction in the same
-function. It also has an optional successor, ``continue``.
+The '``cleanupret``' instruction requires one argument, which indicates
+which ``cleanuppad`` it exits, and must be a :ref:`cleanuppad <i_cleanuppad>`.
+It also has an optional successor, ``continue``.
Semantics:
""""""""""
@@ -5351,14 +5361,21 @@ The '``cleanupret``' instruction indicates to the
:ref:`personality function <personalityfn>` that one
:ref:`cleanuppad <i_cleanuppad>` it transferred control to has ended.
It transfers control to ``continue`` or unwinds out of the function.
+It is undefined behavior to execute a ``cleanupret`` whose ``cleanuppad`` has
+not been executed.
+It is undefined behavior to execute a ``cleanupret`` if any ``catchpad`` or
+``cleanuppad`` has been executed, without subsequently executing a
+corresponding ``catchret``/``cleanupret`` or unwinding out of the inner pad,
+following the most recent execution of the ``cleanupret``'s corresponding
+``cleanuppad``.
Example:
""""""""
.. code-block:: llvm
- cleanupret void unwind to caller
- cleanupret { i8*, i32 } %exn unwind label %continue
+ cleanupret %cleanup unwind to caller
+ cleanupret %cleanup unwind label %continue
.. _i_terminatepad:
@@ -8391,7 +8408,7 @@ Syntax:
::
- <resultval> = cleanuppad <resultty> [<args>*]
+ <resultval> = cleanuppad [<args>*]
Overview:
"""""""""
@@ -8403,7 +8420,8 @@ transfer control to run cleanup actions.
The ``args`` correspond to whatever additional
information the :ref:`personality function <personalityfn>` requires to
execute the cleanup.
-The ``resultval`` has the type ``resultty``.
+The ``resultval`` has the type :ref:`token <t_token>` and is used to
+match the ``cleanuppad`` to corresponding :ref:`cleanuprets <i_cleanupret>`.
Arguments:
""""""""""
@@ -8415,9 +8433,8 @@ Semantics:
""""""""""
The '``cleanuppad``' instruction defines the values which are set by the
-:ref:`personality function <personalityfn>` upon re-entry to the function, and
-therefore the "result type" of the ``cleanuppad`` instruction. As with
-calling conventions, how the personality function results are
+:ref:`personality function <personalityfn>` upon re-entry to the function.
+As with calling conventions, how the personality function results are
represented in LLVM IR is target specific.
When the call stack is being unwound due to an exception being thrown,
@@ -8434,18 +8451,21 @@ The ``cleanuppad`` instruction has several restrictions:
cleanup block.
- A basic block that is not a cleanup block may not include a
'``cleanuppad``' instruction.
+- All ``cleanupret``s which exit a cleanuppad must have the same
+ exceptional successor.
- It is undefined behavior for control to transfer from a ``cleanuppad`` to a
- ``catchret`` without first executing a ``cleanupret`` and a subsequent
- ``catchpad``.
-- It is undefined behavior for control to transfer from a ``cleanuppad`` to a
- ``ret`` without first executing a ``cleanupret``.
+ ``ret`` without first executing a ``cleanupret`` that consumes the
+ ``cleanuppad`` or unwinding out of the ``cleanuppad``.
+- It is undefined behavior for control to transfer from a ``cleanuppad`` to
+ itself without first executing a ``cleanupret`` that consumes the
+ ``cleanuppad`` or unwinding out of the ``cleanuppad``.
Example:
""""""""
.. code-block:: llvm
- %res = cleanuppad { i8*, i32 } [label %nextaction]
+ %tok = cleanuppad []
.. _intrinsics:
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index a8302e230f3..66bc5d21f37 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -356,9 +356,9 @@ namespace bitc {
FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align,
// vol,ordering,synchscope]
FUNC_CODE_INST_LANDINGPAD = 47, // LANDINGPAD: [ty,val,num,id0,val0...]
- FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [] or [val] or [bb#] or [val,bb#]
- FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [bb#]
- FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [ty,val,val,num,args...]
+ FUNC_CODE_INST_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_CATCHENDPAD = 53, // CATCHENDPAD: [] or [bb#]
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 265ef7a4a2c..5c66e848325 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -671,15 +671,14 @@ public:
return Insert(ResumeInst::Create(Exn));
}
- CleanupReturnInst *CreateCleanupRet(BasicBlock *UnwindBB = nullptr,
- Value *RetVal = nullptr) {
- return Insert(CleanupReturnInst::Create(Context, RetVal, UnwindBB));
+ CleanupReturnInst *CreateCleanupRet(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB = nullptr) {
+ return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB));
}
- CatchPadInst *CreateCatchPad(Type *Ty, BasicBlock *NormalDest,
- BasicBlock *UnwindDest, ArrayRef<Value *> Args,
- const Twine &Name = "") {
- return Insert(CatchPadInst::Create(Ty, NormalDest, UnwindDest, Args), Name);
+ CatchPadInst *CreateCatchPad(BasicBlock *NormalDest, BasicBlock *UnwindDest,
+ ArrayRef<Value *> Args, const Twine &Name = "") {
+ return Insert(CatchPadInst::Create(NormalDest, UnwindDest, Args), Name);
}
CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) {
@@ -692,13 +691,13 @@ public:
return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name);
}
- CleanupPadInst *CreateCleanupPad(Type *Ty, ArrayRef<Value *> Args,
+ CleanupPadInst *CreateCleanupPad(ArrayRef<Value *> Args,
const Twine &Name = "") {
- return Insert(CleanupPadInst::Create(Ty, Args), Name);
+ return Insert(CleanupPadInst::Create(Context, Args), Name);
}
- CatchReturnInst *CreateCatchRet(BasicBlock *BB, Value *RetVal = nullptr) {
- return Insert(CatchReturnInst::Create(BB, RetVal));
+ CatchReturnInst *CreateCatchRet(CatchPadInst *CatchPad, BasicBlock *BB) {
+ return Insert(CatchReturnInst::Create(CatchPad, BB));
}
UnreachableInst *CreateUnreachable() {
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index a4d9f7ba9e2..f29639f95dc 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -2740,7 +2740,7 @@ public:
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
assert(idx < getNumSuccessors() && "Successor # out of range for Branch!");
- *(&Op<-1>() - idx) = (Value*)NewSucc;
+ *(&Op<-1>() - idx) = NewSucc;
}
/// \brief Swap the successors of this branch instruction.
@@ -3056,7 +3056,7 @@ public:
}
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
assert(idx < getNumSuccessors() && "Successor # out of range for switch!");
- setOperand(idx*2+1, (Value*)NewSucc);
+ setOperand(idx * 2 + 1, NewSucc);
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -3156,7 +3156,7 @@ public:
return cast<BasicBlock>(getOperand(i+1));
}
void setSuccessor(unsigned i, BasicBlock *NewSucc) {
- setOperand(i+1, (Value*)NewSucc);
+ setOperand(i + 1, NewSucc);
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -3570,111 +3570,6 @@ struct OperandTraits<ResumeInst> :
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
//===----------------------------------------------------------------------===//
-// CleanupReturnInst Class
-//===----------------------------------------------------------------------===//
-
-class CleanupReturnInst : public TerminatorInst {
- CleanupReturnInst(const CleanupReturnInst &RI);
-
-private:
- void init(Value *RetVal, BasicBlock *UnwindBB);
- CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB,
- unsigned Values, Instruction *InsertBefore = nullptr);
- CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB,
- unsigned Values, BasicBlock *InsertAtEnd);
-
- int getUnwindLabelOpIdx() const {
- assert(hasUnwindDest());
- return 0;
- }
-
- int getRetValOpIdx() const {
- assert(hasReturnValue());
- if (hasUnwindDest())
- return 1;
- return 0;
- }
-
-protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
- CleanupReturnInst *cloneImpl() const;
-
-public:
- static CleanupReturnInst *Create(LLVMContext &C,
- Value *RetVal = nullptr,
- BasicBlock *UnwindBB = nullptr,
- Instruction *InsertBefore = nullptr) {
- unsigned Values = 0;
- if (RetVal)
- ++Values;
- if (UnwindBB)
- ++Values;
- return new (Values)
- CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertBefore);
- }
- static CleanupReturnInst *Create(LLVMContext &C, Value *RetVal,
- BasicBlock *UnwindBB,
- BasicBlock *InsertAtEnd) {
- unsigned Values = 0;
- if (RetVal)
- ++Values;
- if (UnwindBB)
- ++Values;
- return new (Values)
- CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertAtEnd);
- }
-
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
- bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
- bool unwindsToCaller() const { return !hasUnwindDest(); }
- bool hasReturnValue() const { return getSubclassDataFromInstruction() & 2; }
-
- /// Convenience accessor. Returns null if there is no return value.
- Value *getReturnValue() const {
- if (!hasReturnValue())
- return nullptr;
- return getOperand(getRetValOpIdx());
- }
- void setReturnValue(Value *RetVal) {
- assert(hasReturnValue());
- setOperand(getRetValOpIdx(), RetVal);
- }
-
- unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
-
- BasicBlock *getUnwindDest() const;
- void setUnwindDest(BasicBlock *NewDest);
-
- // Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Instruction *I) {
- return (I->getOpcode() == Instruction::CleanupRet);
- }
- static inline bool classof(const Value *V) {
- return isa<Instruction>(V) && classof(cast<Instruction>(V));
- }
-
-private:
- BasicBlock *getSuccessorV(unsigned Idx) const override;
- unsigned getNumSuccessorsV() const override;
- void setSuccessorV(unsigned Idx, BasicBlock *B) override;
-
- // Shadow Instruction::setInstructionSubclassData with a private forwarding
- // method so that subclasses cannot accidentally use it.
- void setInstructionSubclassData(unsigned short D) {
- Instruction::setInstructionSubclassData(D);
- }
-};
-
-template <>
-struct OperandTraits<CleanupReturnInst>
- : public VariadicOperandTraits<CleanupReturnInst> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value)
-
-//===----------------------------------------------------------------------===//
// CatchEndPadInst Class
//===----------------------------------------------------------------------===//
@@ -3760,14 +3655,12 @@ private:
CatchPadInst(const CatchPadInst &CPI);
- explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
- BasicBlock *IfException, ArrayRef<Value *> Args,
- unsigned Values, const Twine &NameStr,
- Instruction *InsertBefore);
- explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
- BasicBlock *IfException, ArrayRef<Value *> Args,
- unsigned Values, const Twine &NameStr,
- BasicBlock *InsertAtEnd);
+ explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr, Instruction *InsertBefore);
+ explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr, BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
@@ -3775,20 +3668,19 @@ protected:
CatchPadInst *cloneImpl() const;
public:
- static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal,
- BasicBlock *IfException, ArrayRef<Value *> Args,
- const Twine &NameStr = "",
+ static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = unsigned(Args.size()) + 2;
- return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args, Values,
+ return new (Values) CatchPadInst(IfNormal, IfException, Args, Values,
NameStr, InsertBefore);
}
- static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal,
- BasicBlock *IfException, ArrayRef<Value *> Args,
- const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, const Twine &NameStr,
+ BasicBlock *InsertAtEnd) {
unsigned Values = unsigned(Args.size()) + 2;
- return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args, Values,
- NameStr, InsertAtEnd);
+ return new (Values)
+ CatchPadInst(IfNormal, IfException, Args, Values, NameStr, InsertAtEnd);
}
/// Provide fast operand accessors
@@ -3820,8 +3712,8 @@ public:
// get*Dest - Return the destination basic blocks...
BasicBlock *getNormalDest() const { return cast<BasicBlock>(Op<-2>()); }
BasicBlock *getUnwindDest() const { return cast<BasicBlock>(Op<-1>()); }
- void setNormalDest(BasicBlock *B) { Op<-2>() = reinterpret_cast<Value *>(B); }
- void setUnwindDest(BasicBlock *B) { Op<-1>() = reinterpret_cast<Value *>(B); }
+ void setNormalDest(BasicBlock *B) { Op<-2>() = B; }
+ void setUnwindDest(BasicBlock *B) { Op<-1>() = B; }
BasicBlock *getSuccessor(unsigned i) const {
assert(i < 2 && "Successor # out of range for catchpad!");
@@ -3830,7 +3722,7 @@ public:
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
assert(idx < 2 && "Successor # out of range for catchpad!");
- *(&Op<-2>() + idx) = reinterpret_cast<Value *>(NewSucc);
+ *(&Op<-2>() + idx) = NewSucc;
}
unsigned getNumSuccessors() const { return 2; }
@@ -3949,7 +3841,7 @@ public:
}
void setUnwindDest(BasicBlock *B) {
assert(B && hasUnwindDest());
- Op<-1>() = reinterpret_cast<Value *>(B);
+ Op<-1>() = B;
}
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
@@ -3990,9 +3882,9 @@ private:
CleanupPadInst(const CleanupPadInst &CPI);
- explicit CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
+ explicit CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore);
- explicit CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
+ explicit CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
const Twine &NameStr, BasicBlock *InsertAtEnd);
protected:
@@ -4001,14 +3893,14 @@ protected:
CleanupPadInst *cloneImpl() const;
public:
- static CleanupPadInst *Create(Type *RetTy, ArrayRef<Value *> Args,
+ static CleanupPadInst *Create(LLVMContext &C, ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
- return new (Args.size()) CleanupPadInst(RetTy, Args, NameStr, InsertBefore);
+ return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertBefore);
}
- static CleanupPadInst *Create(Type *RetTy, ArrayRef<Value *> Args,
+ static CleanupPadInst *Create(LLVMContext &C, ArrayRef<Value *> Args,
const Twine &NameStr, BasicBlock *InsertAtEnd) {
- return new (Args.size()) CleanupPadInst(RetTy, Args, NameStr, InsertAtEnd);
+ return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertAtEnd);
}
/// Provide fast operand accessors
@@ -4037,10 +3929,10 @@ class CatchReturnInst : public TerminatorInst {
CatchReturnInst(const CatchReturnInst &RI);
private:
- void init(BasicBlock *BB, Value *RetVal);
- CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values,
+ void init(CatchPadInst *CatchPad, BasicBlock *BB);
+ CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
Instruction *InsertBefore = nullptr);
- CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values,
+ CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
BasicBlock *InsertAtEnd);
protected:
@@ -4049,34 +3941,35 @@ protected:
CatchReturnInst *cloneImpl() const;
public:
- static CatchReturnInst *Create(BasicBlock *BB, Value *RetVal = nullptr,
+ static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB,
Instruction *InsertBefore = nullptr) {
+ assert(CatchPad);
assert(BB);
- unsigned Values = 1;
- if (RetVal)
- ++Values;
- return new (Values) CatchReturnInst(BB, RetVal, Values, InsertBefore);
+ return new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
}
- static CatchReturnInst *Create(BasicBlock *BB, Value *RetVal,
+ static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB,
BasicBlock *InsertAtEnd) {
+ assert(CatchPad);
assert(BB);
- unsigned Values = 1;
- if (RetVal)
- ++Values;
- return new (Values) CatchReturnInst(BB, RetVal, Values, InsertAtEnd);
+ return new (2) CatchReturnInst(CatchPad, BB, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// Convenience accessors.
- BasicBlock *getSuccessor() const { return cast<BasicBlock>(Op<-1>()); }
- void setSuccessor(BasicBlock *NewSucc) { Op<-1>() = (Value *)NewSucc; }
- unsigned getNumSuccessors() const { return 1; }
+ CatchPadInst *getCatchPad() const { return cast<CatchPadInst>(Op<0>()); }
+ void setCatchPad(CatchPadInst *CatchPad) {
+ assert(CatchPad);
+ Op<0>() = CatchPad;
+ }
- bool hasReturnValue() const { return getNumOperands() > 1; }
- Value *getReturnValue() const { return Op<-2>(); }
- void setReturnValue(Value *RetVal) { Op<-2>() = RetVal; }
+ BasicBlock *getSuccessor() const { return cast<BasicBlock>(Op<1>()); }
+ void setSuccessor(BasicBlock *NewSucc) {
+ assert(NewSucc);
+ Op<1>() = NewSucc;
+ }
+ unsigned getNumSuccessors() const { return 1; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
@@ -4094,11 +3987,109 @@ private:
template <>
struct OperandTraits<CatchReturnInst>
- : public VariadicOperandTraits<CatchReturnInst> {};
+ : public FixedNumOperandTraits<CatchReturnInst, 2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
//===----------------------------------------------------------------------===//
+// CleanupReturnInst Class
+//===----------------------------------------------------------------------===//
+
+class CleanupReturnInst : public TerminatorInst {
+ CleanupReturnInst(const CleanupReturnInst &RI);
+
+private:
+ void init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB);
+ CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
+ unsigned Values, Instruction *InsertBefore = nullptr);
+ CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
+ unsigned Values, BasicBlock *InsertAtEnd);
+
+ int getUnwindLabelOpIdx() const {
+ assert(hasUnwindDest());
+ return 0;
+ }
+
+protected:
+ // Note: Instruction needs to be a friend here to call cloneImpl.
+ friend class Instruction;
+ CleanupReturnInst *cloneImpl() const;
+
+public:
+ static CleanupReturnInst *Create(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB = nullptr,
+ Instruction *InsertBefore = nullptr) {
+ assert(CleanupPad);
+ unsigned Values = 1;
+ if (UnwindBB)
+ ++Values;
+ return new (Values)
+ CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertBefore);
+ }
+ static CleanupReturnInst *Create(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB,
+ BasicBlock *InsertAtEnd) {
+ assert(CleanupPad);
+ unsigned Values = 1;
+ if (UnwindBB)
+ ++Values;
+ return new (Values)
+ CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertAtEnd);
+ }
+
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
+ bool unwindsToCaller() const { return !hasUnwindDest(); }
+
+ /// Convenience accessor.
+ CleanupPadInst *getCleanupPad() const {
+ return cast<CleanupPadInst>(Op<-1>());
+ }
+ void setCleanupPad(CleanupPadInst *CleanupPad) {
+ assert(CleanupPad);
+ Op<-1>() = CleanupPad;
+ }
+
+ unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
+
+ BasicBlock *getUnwindDest() const {
+ return hasUnwindDest() ? cast<BasicBlock>(Op<-2>()) : nullptr;
+ }
+ void setUnwindDest(BasicBlock *NewDest) {
+ assert(NewDest);
+ assert(hasUnwindDest());
+ Op<-2>() = NewDest;
+ }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const Instruction *I) {
+ return (I->getOpcode() == Instruction::CleanupRet);
+ }
+ static inline bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+
+private:
+ BasicBlock *getSuccessorV(unsigned Idx) const override;
+ unsigned getNumSuccessorsV() const override;
+ void setSuccessorV(unsigned Idx, BasicBlock *B) override;
+
+ // Shadow Instruction::setInstructionSubclassData with a private forwarding
+ // method so that subclasses cannot accidentally use it.
+ void setInstructionSubclassData(unsigned short D) {
+ Instruction::setInstructionSubclassData(D);
+ }
+};
+
+template <>
+struct OperandTraits<CleanupReturnInst>
+ : public VariadicOperandTraits<CleanupReturnInst, /*MINARITY=*/1> {};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value)
+
+//===----------------------------------------------------------------------===//
// UnreachableInst Class
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index 40bfac56719..32dc50ae62c 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -913,7 +913,7 @@ bool CallAnalyzer::visitCleanupReturnInst(CleanupReturnInst &CRI) {
bool CallAnalyzer::visitCatchReturnInst(CatchReturnInst &CRI) {
// FIXME: It's not clear that a single instruction is an accurate model for
- // the inline cost of a cleanupret instruction.
+ // the inline cost of a catchret instruction.
return false;
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fc7fceb2a26..082637bf0b8 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2237,8 +2237,8 @@ bool LLParser::PerFunctionState::FinishFunction() {
/// GetVal - Get a value with the specified name or ID, creating a
/// forward reference record if needed. This can return null if the value
/// exists but does not have the right type.
-Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
- Type *Ty, LocTy Loc) {
+Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
+ LocTy Loc, OperatorConstraint OC) {
// Look this name up in the normal function symbol table.
Value *Val = F.getValueSymbolTable().lookup(Name);
@@ -2253,6 +2253,24 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
// If we have the value in the symbol table or fwd-ref table, return it.
if (Val) {
+ // Check operator constraints.
+ switch (OC) {
+ case OC_None:
+ // no constraint
+ break;
+ case OC_CatchPad:
+ if (!isa<CatchPadInst>(Val)) {
+ P.Error(Loc, "'%" + Name + "' is not a catchpad");
+ return nullptr;
+ }
+ break;
+ case OC_CleanupPad:
+ if (!isa<CleanupPadInst>(Val)) {
+ P.Error(Loc, "'%" + Name + "' is not a cleanuppad");
+ return nullptr;
+ }
+ break;
+ }
if (Val->getType() == Ty) return Val;
if (Ty->isLabelTy())
P.Error(Loc, "'%" + Name + "' is not a basic block");
@@ -2270,17 +2288,31 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
- if (Ty->isLabelTy())
+ if (Ty->isLabelTy()) {
+ assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), Name, &F);
- else
+ } else if (!OC) {
FwdVal = new Argument(Ty, Name);
+ } else {
+ switch (OC) {
+ case OC_CatchPad:
+ FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {},
+ Name);
+ break;
+ case OC_CleanupPad:
+ FwdVal = CleanupPadInst::Create(F.getContext(), {}, Name);
+ break;
+ default:
+ llvm_unreachable("unexpected constraint");
+ }
+ }
ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
return FwdVal;
}
-Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty,
- LocTy Loc) {
+Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
+ OperatorConstraint OC) {
// Look this name up in the normal function symbol table.
Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr;
@@ -2295,6 +2327,24 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty,
// If we have the value in the symbol table or fwd-ref table, return it.
if (Val) {
+ // Check operator constraint.
+ switch (OC) {
+ case OC_None:
+ // no constraint
+ break;
+ case OC_CatchPad:
+ if (!isa<CatchPadInst>(Val)) {
+ P.Error(Loc, "'%" + Twine(ID) + "' is not a catchpad");
+ return nullptr;
+ }
+ break;
+ case OC_CleanupPad:
+ if (!isa<CleanupPadInst>(Val)) {
+ P.Error(Loc, "'%" + Twine(ID) + "' is not a cleanuppad");
+ return nullptr;
+ }
+ break;
+ }
if (Val->getType() == Ty) return Val;
if (Ty->isLabelTy())
P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block");
@@ -2311,10 +2361,23 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty,
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
- if (Ty->isLabelTy())
+ if (Ty->isLabelTy()) {
+ assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), "", &F);
- else
+ } else if (!OC) {
FwdVal = new Argument(Ty);
+ } else {
+ switch (OC) {
+ case OC_CatchPad:
+ FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {});
+ break;
+ case OC_CleanupPad:
+ FwdVal = CleanupPadInst::Create(F.getContext(), {});
+ break;
+ default:
+ llvm_unreachable("unexpected constraint");
+ }
+ }
ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
return FwdVal;
@@ -2346,11 +2409,24 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
std::map<unsigned, std::pair<Value*, LocTy> >::iterator FI =
ForwardRefValIDs.find(NameID);
if (FI != ForwardRefValIDs.end()) {
- if (FI->second.first->getType() != Inst->getType())
+ Value *Sentinel = FI->second.first;
+ if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- FI->second.first->replaceAllUsesWith(Inst);
- delete FI->second.first;
+ // Check operator constraints. We only put cleanuppads or catchpads in
+ // the forward value map if the value is constrained to match.
+ if (isa<CatchPadInst>(Sentinel)) {
+ if (!isa<CatchPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + Twine(NameID) + "' is not a catchpad");
+ } else if (isa<CleanupPadInst>(Sentinel)) {
+ if (!isa<CleanupPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + Twine(NameID) + "' is not a cleanuppad");
+ }
+
+ Sentinel->replaceAllUsesWith(Inst);
+ delete Sentinel;
ForwardRefValIDs.erase(FI);
}
@@ -2362,11 +2438,24 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
std::map<std::string, std::pair<Value*, LocTy> >::iterator
FI = ForwardRefVals.find(NameStr);
if (FI != ForwardRefVals.end()) {
- if (FI->second.first->getType() != Inst->getType())
+ Value *Sentinel = FI->second.first;
+ if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- FI->second.first->replaceAllUsesWith(Inst);
- delete FI->second.first;
+ // Check operator constraints. We only put cleanuppads or catchpads in
+ // the forward value map if the value is constrained to match.
+ if (isa<CatchPadInst>(Sentinel)) {
+ if (!isa<CatchPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + NameStr + "' is not a catchpad");
+ } else if (isa<CleanupPadInst>(Sentinel)) {
+ if (!isa<CleanupPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + NameStr + "' is not a cleanuppad");
+ }
+
+ Sentinel->replaceAllUsesWith(Inst);
+ delete Sentinel;
ForwardRefVals.erase(FI);
}
@@ -4007,18 +4096,30 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
//===----------------------------------------------------------------------===//
bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
- PerFunctionState *PFS) {
+ PerFunctionState *PFS,
+ OperatorConstraint OC) {
if (Ty->isFunctionTy())
return Error(ID.Loc, "functions are not values, refer to them as pointers");
+ if (OC && ID.Kind != ValID::t_LocalID && ID.Kind != ValID::t_LocalName) {
+ switch (OC) {
+ case OC_CatchPad:
+ return Error(ID.Loc, "Catchpad value required in this position");
+ case OC_CleanupPad:
+ return Error(ID.Loc, "Cleanuppad value required in this position");
+ default:
+ llvm_unreachable("Unexpected constraint kind");
+ }
+ }
+
switch (ID.Kind) {
case ValID::t_LocalID:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
- V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc);
+ V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc, OC);
return V == nullptr;
case ValID::t_LocalName:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
- V = PFS->GetVal(ID.StrVal, Ty, ID.Loc);
+ V = PFS->GetVal(ID.StrVal, Ty, ID.Loc, OC);
return V == nullptr;
case ValID::t_InlineAsm: {
assert(ID.FTy);
@@ -4140,11 +4241,11 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
}
}
-bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
+bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
+ OperatorConstraint OC) {
V = nullptr;
ValID ID;
- return ParseValID(ID, PFS) ||
- ConvertValIDToValue(Ty, ID, V, PFS);
+ return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS, OC);
}
bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
@@ -4985,7 +5086,7 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) {
bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
PerFunctionState &PFS) {
- if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
+ if (ParseToken(lltok::lsquare, "expected '[' in catchpad/cleanuppad"))
return true;
while (Lex.getKind() != lltok::rsquare) {
@@ -5016,16 +5117,12 @@ bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
}
/// ParseCleanupRet
-/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
+/// ::= 'cleanupret' Value unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetTy = nullptr;
- Value *RetVal = nullptr;
- if (ParseType(RetTy, /*AllowVoid=*/true))
- return true;
+ Value *CleanupPad = nullptr;
- if (!RetTy->isVoidTy())
- if (ParseValue(RetTy, RetVal, PFS))
- return true;
+ if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+ return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
return true;
@@ -5041,39 +5138,32 @@ bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
}
}
- Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
+ Inst = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
return false;
}
/// ParseCatchRet
-/// ::= 'catchret' ('void' | TypeAndValue) 'to' TypeAndValue
+/// ::= 'catchret' Value 'to' TypeAndValue
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetTy = nullptr;
- Value *RetVal = nullptr;
+ Value *CatchPad = nullptr;
- if (ParseType(RetTy, /*AllowVoid=*/true))
+ if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS, OC_CatchPad))
return true;
- if (!RetTy->isVoidTy())
- if (ParseValue(RetTy, RetVal, PFS))
- return true;
-
BasicBlock *BB;
if (ParseToken(lltok::kw_to, "expected 'to' in catchret") ||
ParseTypeAndBasicBlock(BB, PFS))
return true;
- Inst = CatchReturnInst::Create(BB, RetVal);
+ Inst = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
return false;
}
/// ParseCatchPad
-/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetType = nullptr;
-
SmallVector<Value *, 8> Args;
- if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ if (ParseExceptionArgs(Args, PFS))
return true;
BasicBlock *NormalBB, *UnwindBB;
@@ -5083,7 +5173,7 @@ bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
- Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
+ Inst = CatchPadInst::Create(NormalBB, UnwindBB, Args);
return false;
}
@@ -5115,13 +5205,11 @@ bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
/// ParseCleanupPad
/// ::= 'cleanuppad' ParamList
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetType = nullptr;
-
SmallVector<Value *, 8> Args;
- if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ if (ParseExceptionArgs(Args, PFS))
return true;
- Inst = CleanupPadInst::Create(RetType, Args);
+ Inst = CleanupPadInst::Create(Context, Args);
return false;
}
diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index 96fb06a1f29..8b7e9560a69 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -108,6 +108,14 @@ namespace llvm {
unsigned MDKind, MDSlot;
};
+ /// Indicates which operator an operand allows (for the few operands that
+ /// may only reference a certain operator).
+ enum OperatorConstraint {
+ OC_None = 0, // No constraint
+ OC_CatchPad, // Must be CatchPadInst
+ OC_CleanupPad // Must be CleanupPadInst
+ };
+
SmallVector<Instruction*, 64> InstsWithTBAATag;
// Type resolution handling data structures. The location is set when we
@@ -329,8 +337,10 @@ namespace llvm {
/// GetVal - Get a value with the specified name or ID, creating a
/// forward reference record if needed. This can return null if the value
/// exists but does not have the right type.
- Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc);
- Value *GetVal(unsigned ID, Type *Ty, LocTy Loc);
+ Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc,
+ OperatorConstraint OC = OC_None);
+ Value *GetVal(unsigned ID, Type *Ty, LocTy Loc,
+ OperatorConstraint OC = OC_None);
/// SetInstName - After an instruction is parsed and inserted into its
/// basic block, this installs its name.
@@ -352,12 +362,15 @@ namespace llvm {
};
bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
- PerFunctionState *PFS);
+ PerFunctionState *PFS,
+ OperatorConstraint OC = OC_None);
bool parseConstantValue(Type *Ty, Constant *&C);
- bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS);
- bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS) {
- return ParseValue(Ty, V, &PFS);
+ bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
+ OperatorConstraint OC = OC_None);
+ bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS,
+ OperatorConstraint OC = OC_None) {
+ return ParseValue(Ty, V, &PFS, OC);
}
bool ParseValue(Type *Ty, Value *&V, LocTy &Loc,
PerFunctionState &PFS) {
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index b379e59236d..7ede794bc76 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -41,6 +41,14 @@ enum {
SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
};
+/// Indicates which operator an operand allows (for the few operands that may
+/// only reference a certain operator).
+enum OperatorConstraint {
+ OC_None = 0, // No constraint
+ OC_CatchPad, // Must be CatchPadInst
+ OC_CleanupPad // Must be CleanupPadInst
+};
+
class BitcodeReaderValueList {
std::vector<WeakVH> ValuePtrs;
@@ -84,9 +92,10 @@ public:
}
Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
- Value *getValueFwdRef(unsigned Idx, Type *Ty);
+ Value *getValueFwdRef(unsigned Idx, Type *Ty,
+ OperatorConstraint OC = OC_None);
- void assignValue(Value *V, unsigned Idx);
+ bool assignValue(Value *V, unsigned Idx);
/// Once all constants are read, this method bulk resolves any forward
/// references.
@@ -262,10 +271,11 @@ private:
StructType *createIdentifiedStructType(LLVMContext &Context);
Type *getTypeByID(unsigned ID);
- Value *getFnValueByID(unsigned ID, Type *Ty) {
+ Value *getFnValueByID(unsigned ID, Type *Ty,
+ OperatorConstraint OC = OC_None) {
if (Ty && Ty->isMetadataTy())
return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
- return ValueList.getValueFwdRef(ID, Ty);
+ return ValueList.getValueFwdRef(ID, Ty, OC);
}
Metadata *getFnMetadataByID(unsigned ID) {
return MDValueList.getValueFwdRef(ID);
@@ -308,8 +318,9 @@ private:
/// past the number of slots used by the value in the record. Return true if
/// there is an error.
bool popValue(SmallVectorImpl<uint64_t> &Record, unsigned &Slot,
- unsigned InstNum, Type *Ty, Value *&ResVal) {
- if (getValue(Record, Slot, InstNum, Ty, ResVal))
+ unsigned InstNum, Type *Ty, Value *&ResVal,
+ OperatorConstraint OC = OC_None) {
+ if (getValue(Record, Slot, InstNum, Ty, ResVal, OC))
return true;
// All values currently take a single record slot.
++Slot;
@@ -318,32 +329,34 @@ private:
/// Like popValue, but does not increment the Slot number.
bool getValue(SmallVectorImpl<uint64_t> &Record, unsigned Slot,
- unsigned InstNum, Type *Ty, Value *&ResVal) {
- ResVal = getValue(Record, Slot, InstNum, Ty);
+ unsigned InstNum, Type *Ty, Value *&ResVal,
+ OperatorConstraint OC = OC_None) {
+ ResVal = getValue(Record, Slot, InstNum, Ty, OC);
return ResVal == nullptr;
}
/// Version of getValue that returns ResVal directly, or 0 if there is an
/// error.
Value *getValue(SmallVectorImpl<uint64_t> &Record, unsigned Slot,
- unsigned InstNum, Type *Ty) {
+ unsigned InstNum, Type *Ty, OperatorConstraint OC = OC_None) {
if (Slot == Record.size()) return nullptr;
unsigned ValNo = (unsigned)Record[Slot];
// Adjust the ValNo, if it was encoded relative to the InstNum.
if (UseRelativeIDs)
ValNo = InstNum - ValNo;
- return getFnValueByID(ValNo, Ty);
+ return getFnValueByID(ValNo, Ty, OC);
}
/// Like getValue, but decodes signed VBRs.
Value *getValueSigned(SmallVectorImpl<uint64_t> &Record, unsigned Slot,
- unsigned InstNum, Type *Ty) {
+ unsigned InstNum, Type *Ty,
+ OperatorConstraint OC = OC_None) {
if (Slot == Record.size()) return nullptr;
unsigned ValNo = (unsigned)decodeSignRotatedValue(Record[Slot]);
// Adjust the ValNo, if it was encoded relative to the InstNum.
if (UseRelativeIDs)
ValNo = InstNum - ValNo;
- return getFnValueByID(ValNo, Ty);
+ return getFnValueByID(ValNo, Ty, OC);
}
/// Converts alignment exponent (i.e. power of two (or zero)) to the
@@ -753,10 +766,10 @@ struct OperandTraits<ConstantPlaceHolder> :
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
}
-void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
+bool BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
if (Idx == size()) {
push_back(V);
- return;
+ return false;
}
if (Idx >= size())
@@ -765,7 +778,7 @@ void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
WeakVH &OldV = ValuePtrs[Idx];
if (!OldV) {
OldV = V;
- return;
+ return false;
}
// Handle constants and non-constants (e.g. instrs) differently for
@@ -776,9 +789,26 @@ void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
} else {
// If there was a forward reference to this value, replace it.
Value *PrevVal = OldV;
+ // Check operator constraints. We only put cleanuppads or catchpads in
+ // the forward value map if the value is constrained to match.
+ if (CatchPadInst *CatchPad = dyn_cast<CatchPadInst>(PrevVal)) {
+ if (!isa<CatchPadInst>(V))
+ return true;
+ // Delete the dummy basic block that was created with the sentinel
+ // catchpad.
+ BasicBlock *DummyBlock = CatchPad->getUnwindDest();
+ assert(DummyBlock == CatchPad->getNormalDest());
+ CatchPad->dropAllReferences();
+ delete DummyBlock;
+ } else if (isa<CleanupPadInst>(PrevVal)) {
+ if (!isa<CleanupPadInst>(V))
+ return true;
+ }
OldV->replaceAllUsesWith(V);
delete PrevVal;
}
+
+ return false;
}
@@ -799,7 +829,8 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
return C;
}
-Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty,
+ OperatorConstraint OC) {
// Bail out for a clearly invalid value. This would make us call resize(0)
if (Idx == UINT_MAX)
return nullptr;
@@ -811,14 +842,39 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
// If the types don't match, it's invalid.
if (Ty && Ty != V->getType())
return nullptr;
- return V;
+ if (!OC)
+ return V;
+ // Use dyn_cast to enforce operator constraints
+ switch (OC) {
+ case OC_CatchPad:
+ return dyn_cast<CatchPadInst>(V);
+ case OC_CleanupPad:
+ return dyn_cast<CleanupPadInst>(V);
+ default:
+ llvm_unreachable("Unexpected operator constraint");
+ }
}
// No type specified, must be invalid reference.
if (!Ty) return nullptr;
// Create and return a placeholder, which will later be RAUW'd.
- Value *V = new Argument(Ty);
+ Value *V;
+ switch (OC) {
+ case OC_None:
+ V = new Argument(Ty);
+ break;
+ case OC_CatchPad: {
+ BasicBlock *BB = BasicBlock::Create(Context);
+ V = CatchPadInst::Create(BB, BB, {});
+ break;
+ }
+ default:
+ assert(OC == OC_CleanupPad && "unexpected operator constraint");
+ V = CleanupPadInst::Create(Context, {});
+ break;
+ }
+
ValuePtrs[Idx] = V;
return V;
}
@@ -2610,7 +2666,8 @@ std::error_code BitcodeReader::parseConstants() {
}
}
- ValueList.assignValue(V, NextCstNo);
+ if (ValueList.assignValue(V, NextCstNo))
+ return error("Invalid forward reference");
++NextCstNo;
}
}
@@ -3819,56 +3876,47 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
}
break;
}
- // CLEANUPRET: [] or [ty,val] or [bb#] or [ty,val,bb#]
+ // CLEANUPRET: [val] or [val,bb#]
case bitc::FUNC_CODE_INST_CLEANUPRET: {
- if (Record.size() < 2)
+ if (Record.size() != 1 && Record.size() != 2)
return error("Invalid record");
unsigned Idx = 0;
- bool HasReturnValue = !!Record[Idx++];
- bool HasUnwindDest = !!Record[Idx++];
- Value *RetVal = nullptr;
- BasicBlock *UnwindDest = nullptr;
-
- if (HasReturnValue && getValueTypePair(Record, Idx, NextValueNo, RetVal))
+ Value *CleanupPad = getValue(Record, Idx++, NextValueNo,
+ Type::getTokenTy(Context), OC_CleanupPad);
+ if (!CleanupPad)
return error("Invalid record");
- if (HasUnwindDest) {
- if (Idx == Record.size())
- return error("Invalid record");
+ BasicBlock *UnwindDest = nullptr;
+ if (Record.size() == 2) {
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
- if (Record.size() != Idx)
- return error("Invalid record");
-
- I = CleanupReturnInst::Create(Context, RetVal, UnwindDest);
+ I = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad),
+ UnwindDest);
InstructionList.push_back(I);
break;
}
- case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [bb#]
- if (Record.size() != 1 && Record.size() != 3)
+ case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [val,bb#]
+ if (Record.size() != 2)
return error("Invalid record");
unsigned Idx = 0;
+ Value *CatchPad = getValue(Record, Idx++, NextValueNo,
+ Type::getTokenTy(Context), OC_CatchPad);
+ if (!CatchPad)
+ return error("Invalid record");
BasicBlock *BB = getBasicBlock(Record[Idx++]);
if (!BB)
return error("Invalid record");
- Value *RetVal = nullptr;
- if (Record.size() == 3 &&
- getValueTypePair(Record, Idx, NextValueNo, RetVal))
- return error("Invalid record");
- I = CatchReturnInst::Create(BB, RetVal);
+ I = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
InstructionList.push_back(I);
break;
}
- case bitc::FUNC_CODE_INST_CATCHPAD: { // CATCHPAD: [ty,bb#,bb#,num,(ty,val)*]
- if (Record.size() < 4)
+ case bitc::FUNC_CODE_INST_CATCHPAD: { // CATCHPAD: [bb#,bb#,num,(ty,val)*]
+ if (Record.size() < 3)
return error("Invalid record");
unsigned Idx = 0;
- Type *Ty = getTypeByID(Record[Idx++]);
- if (!Ty)
- return error("Invalid record");
BasicBlock *NormalBB = getBasicBlock(Record[Idx++]);
if (!NormalBB)
return error("Invalid record");
@@ -3886,7 +3934,7 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
if (Record.size() != Idx)
return error("Invalid record");
- I = CatchPadInst::Create(Ty, NormalBB, UnwindBB, Args);
+ I = CatchPadInst::Create(NormalBB, UnwindBB, Args);
InstructionList.push_back(I);
break;
}
@@ -3918,13 +3966,10 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
InstructionList.push_back(I);
break;
}
- case bitc::FUNC_CODE_INST_CLEANUPPAD: { // CLEANUPPAD: [ty, num,(ty,val)*]
- if (Record.size() < 2)
+ case bitc::FUNC_CODE_INST_CLEANUPPAD: { // CLEANUPPAD: [num,(ty,val)*]
+ if (Record.size() < 1)
return error("Invalid record");
unsigned Idx = 0;
- Type *Ty = getTypeByID(Record[Idx++]);
- if (!Ty)
- return error("Invalid record");
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
@@ -3936,7 +3981,7 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
if (Record.size() != Idx)
return error("Invalid record");
- I = CleanupPadInst::Create(Ty, Args);
+ I = CleanupPadInst::Create(Context, Args);
InstructionList.push_back(I);
break;
}
@@ -4541,7 +4586,8 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
// Non-void values get registered in the value table for future use.
if (I && !I->getType()->isVoidTy())
- ValueList.assignValue(I, NextValueNo++);
+ if (ValueList.assignValue(I, NextValueNo++))
+ return error("Invalid forward reference");
}
OutOfRecordLoop:
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 87b02e3dca4..c0eb5d497bc 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1855,10 +1855,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::CleanupRet: {
Code = bitc::FUNC_CODE_INST_CLEANUPRET;
const auto &CRI = cast<CleanupReturnInst>(I);
- Vals.push_back(CRI.hasReturnValue());
- Vals.push_back(CRI.hasUnwindDest());
- if (CRI.hasReturnValue())
- PushValueAndType(CRI.getReturnValue(), InstID, Vals, VE);
+ pushValue(CRI.getCleanupPad(), InstID, Vals, VE);
if (CRI.hasUnwindDest())
Vals.push_back(VE.getValueID(CRI.getUnwindDest()));
break;
@@ -1866,15 +1863,13 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::CatchRet: {
Code = bitc::FUNC_CODE_INST_CATCHRET;
const auto &CRI = cast<CatchReturnInst>(I);
+ pushValue(CRI.getCatchPad(), InstID, Vals, VE);
Vals.push_back(VE.getValueID(CRI.getSuccessor()));
- if (CRI.hasReturnValue())
- PushValueAndType(CRI.getReturnValue(), InstID, Vals, VE);
break;
}
case Instruction::CatchPad: {
Code = bitc::FUNC_CODE_INST_CATCHPAD;
const auto &CPI = cast<CatchPadInst>(I);
- Vals.push_back(VE.getTypeID(CPI.getType()));
Vals.push_back(VE.getValueID(CPI.getNormalDest()));
Vals.push_back(VE.getValueID(CPI.getUnwindDest()));
unsigned NumArgOperands = CPI.getNumArgOperands();
@@ -1898,7 +1893,6 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::CleanupPad: {
Code = bitc::FUNC_CODE_INST_CLEANUPPAD;
const auto &CPI = cast<CleanupPadInst>(I);
- Vals.push_back(VE.getTypeID(CPI.getType()));
unsigned NumOperands = CPI.getNumOperands();
Vals.push_back(NumOperands);
for (unsigned Op = 0; Op != NumOperands; ++Op)
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index 68384f08b7c..3cc9c395c22 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -2956,8 +2956,7 @@ static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
if (isa<CatchPadInst>(TI) || isa<CatchEndPadInst>(TI) ||
isa<TerminatePadInst>(TI))
return BB;
- return cast<CleanupPadInst>(cast<CleanupReturnInst>(TI)->getReturnValue())
- ->getParent();
+ return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent();
}
static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
@@ -3242,11 +3241,11 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
// The token consumed by a CatchReturnInst must match the funclet token.
bool IsUnreachableCatchret = false;
if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
- IsUnreachableCatchret = CRI->getReturnValue() != CatchPad;
+ IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
// The token consumed by a CleanupPadInst must match the funclet token.
bool IsUnreachableCleanupret = false;
if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
- IsUnreachableCleanupret = CRI->getReturnValue() != CleanupPad;
+ IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) {
new UnreachableInst(BB->getContext(), TI);
TI->eraseFromParent();
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 5ec111869f0..ae9ab8d6187 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2860,9 +2860,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(LPI->getClause(i), true);
}
} else if (const auto *CPI = dyn_cast<CatchPadInst>(&I)) {
- Out << ' ';
- TypePrinter.print(I.getType(), Out);
-
Out << " [";
for (unsigned Op = 0, NumOps = CPI->getNumArgOperands(); Op < NumOps;
++Op) {
@@ -2888,9 +2885,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
else
Out << "to caller";
} else if (const auto *CPI = dyn_cast<CleanupPadInst>(&I)) {
- Out << ' ';
- TypePrinter.print(I.getType(), Out);
-
Out << " [";
for (unsigned Op = 0, NumOps = CPI->getNumOperands(); Op < NumOps; ++Op) {
if (Op > 0)
@@ -2901,22 +2895,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
- if (CRI->hasReturnValue()) {
- Out << ' ';
- writeOperand(CRI->getReturnValue(), /*PrintType=*/true);
- } else {
- Out << " void";
- }
+ Out << ' ';
+ writeOperand(CRI->getCatchPad(), /*PrintType=*/false);
Out << " to ";
writeOperand(CRI->getSuccessor(), /*PrintType=*/true);
} else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
- if (CRI->hasReturnValue()) {
- Out << ' ';
- writeOperand(CRI->getReturnValue(), /*PrintType=*/true);
- } else {
- Out << " void";
- }
+ Out << ' ';
+ writeOperand(CRI->getCleanupPad(), /*PrintType=*/false);
Out << " unwind ";
if (CRI->hasUnwindDest())
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 85173d96562..0dc8633ac2a 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -261,7 +261,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case ExtractValue: return "extractvalue";
case InsertValue: return "insertvalue";
case LandingPad: return "landingpad";
- case CleanupPad: return "cleanuppad";
+ case CleanupPad: return "cleanuppad";
default: return "<Invalid operator> ";
}
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 46c799ece2c..e79fa415ffb 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -684,51 +684,39 @@ CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI)
CRI.getNumOperands()) {
SubclassOptionalData = CRI.SubclassOptionalData;
setInstructionSubclassData(CRI.getSubclassDataFromInstruction());
- if (Value *RetVal = CRI.getReturnValue())
- setReturnValue(RetVal);
- if (BasicBlock *UnwindDest = CRI.getUnwindDest())
- setUnwindDest(UnwindDest);
+ Op<-1>() = CRI.Op<-1>();
+ if (CRI.hasUnwindDest())
+ Op<-2>() = CRI.Op<-2>();
}
-void CleanupReturnInst::init(Value *RetVal, BasicBlock *UnwindBB) {
+void CleanupReturnInst::init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB) {
SubclassOptionalData = 0;
if (UnwindBB)
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
- if (RetVal)
- setInstructionSubclassData(getSubclassDataFromInstruction() | 2);
+ Op<-1>() = CleanupPad;
if (UnwindBB)
- setUnwindDest(UnwindBB);
- if (RetVal)
- setReturnValue(RetVal);
+ Op<-2>() = UnwindBB;
}
-CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
+CleanupReturnInst::CleanupReturnInst(CleanupPadInst *CleanupPad,
BasicBlock *UnwindBB, unsigned Values,
Instruction *InsertBefore)
- : TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
+ : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
+ Instruction::CleanupRet,
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
Values, InsertBefore) {
- init(RetVal, UnwindBB);
+ init(CleanupPad, UnwindBB);
}
-CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
+CleanupReturnInst::CleanupReturnInst(CleanupPadInst *CleanupPad,
BasicBlock *UnwindBB, unsigned Values,
BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
+ : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
+ Instruction::CleanupRet,
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
Values, InsertAtEnd) {
- init(RetVal, UnwindBB);
-}
-
-BasicBlock *CleanupReturnInst::getUnwindDest() const {
- if (hasUnwindDest())
- return cast<BasicBlock>(getOperand(getUnwindLabelOpIdx()));
- return nullptr;
-}
-void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
- assert(NewDest);
- setOperand(getUnwindLabelOpIdx(), NewDest);
+ init(CleanupPad, UnwindBB);
}
BasicBlock *CleanupReturnInst::getSuccessorV(unsigned Idx) const {
@@ -797,38 +785,32 @@ void CatchEndPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
//===----------------------------------------------------------------------===//
// CatchReturnInst Implementation
//===----------------------------------------------------------------------===//
-void CatchReturnInst::init(BasicBlock *BB, Value *RetVal) {
- Op<-1>() = BB;
- if (RetVal)
- Op<-2>() = RetVal;
+void CatchReturnInst::init(CatchPadInst *CatchPad, BasicBlock *BB) {
+ Op<0>() = CatchPad;
+ Op<1>() = BB;
}
CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI)
: TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet,
- OperandTraits<CatchReturnInst>::op_end(this) -
- CRI.getNumOperands(),
- CRI.getNumOperands()) {
- Op<-1>() = CRI.Op<-1>();
- if (CRI.getNumOperands() != 1) {
- assert(CRI.getNumOperands() == 2);
- Op<-2>() = CRI.Op<-2>();
- }
+ OperandTraits<CatchReturnInst>::op_begin(this), 2) {
+ Op<0>() = CRI.Op<0>();
+ Op<1>() = CRI.Op<1>();
}
-CatchReturnInst::CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values,
+CatchReturnInst::CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
- OperandTraits<CatchReturnInst>::op_end(this) - Values,
- Values, InsertBefore) {
- init(BB, RetVal);
+ OperandTraits<CatchReturnInst>::op_begin(this), 2,
+ InsertBefore) {
+ init(CatchPad, BB);
}
-CatchReturnInst::CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values,
+CatchReturnInst::CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
- OperandTraits<CatchReturnInst>::op_end(this) - Values,
- Values, InsertAtEnd) {
- init(BB, RetVal);
+ OperandTraits<CatchReturnInst>::op_begin(this), 2,
+ InsertAtEnd) {
+ init(CatchPad, BB);
}
BasicBlock *CatchReturnInst::getSuccessorV(unsigned Idx) const {
@@ -863,21 +845,21 @@ CatchPadInst::CatchPadInst(const CatchPadInst &CPI)
std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
}
-CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
- BasicBlock *IfException, ArrayRef<Value *> Args,
- unsigned Values, const Twine &NameStr,
- Instruction *InsertBefore)
- : TerminatorInst(RetTy, Instruction::CatchPad,
+CatchPadInst::CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr, Instruction *InsertBefore)
+ : TerminatorInst(Type::getTokenTy(IfNormal->getContext()),
+ Instruction::CatchPad,
OperandTraits<CatchPadInst>::op_end(this) - Values, Values,
InsertBefore) {
init(IfNormal, IfException, Args, NameStr);
}
-CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
- BasicBlock *IfException, ArrayRef<Value *> Args,
- unsigned Values, const Twine &NameStr,
- BasicBlock *InsertAtEnd)
- : TerminatorInst(RetTy, Instruction::CatchPad,
+CatchPadInst::CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getTokenTy(IfNormal->getContext()),
+ Instruction::CatchPad,
OperandTraits<CatchPadInst>::op_end(this) - Values, Values,
InsertAtEnd) {
init(IfNormal, IfException, Args, NameStr);
@@ -962,17 +944,17 @@ CleanupPadInst::CleanupPadInst(const CleanupPadInst &CPI)
std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
}
-CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
+CleanupPadInst::CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore)
- : Instruction(RetTy, Instruction::CleanupPad,
+ : Instruction(Type::getTokenTy(C), Instruction::CleanupPad,
OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
Args.size(), InsertBefore) {
init(Args, NameStr);
}
-CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
+CleanupPadInst::CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
const Twine &NameStr, BasicBlock *InsertAtEnd)
- : Instruction(RetTy, Instruction::CleanupPad,
+ : Instruction(Type::getTokenTy(C), Instruction::CleanupPad,
OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
Args.size(), InsertAtEnd) {
init(Args, NameStr);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 813d06cf643..7e10e4e1cee 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -184,12 +184,6 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// \brief Track unresolved string-based type references.
SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs;
- /// \brief The result type for a catchpad.
- Type *CatchPadResultTy;
-
- /// \brief The result type for a cleanuppad.
- Type *CleanupPadResultTy;
-
/// \brief The result type for a landingpad.
Type *LandingPadResultTy;
@@ -203,8 +197,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
public:
explicit Verifier(raw_ostream &OS)
- : VerifierSupport(OS), Context(nullptr), CatchPadResultTy(nullptr),
- CleanupPadResultTy(nullptr), LandingPadResultTy(nullptr),
+ : VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr),
SawFrameEscape(false) {}
bool verify(const Function &F) {
@@ -239,8 +232,6 @@ public:
// FIXME: We strip const here because the inst visitor strips const.
visit(const_cast<Function &>(F));
InstsInThisBlock.clear();
- CatchPadResultTy = nullptr;
- CleanupPadResultTy = nullptr;
LandingPadResultTy = nullptr;
SawFrameEscape = false;
@@ -2877,14 +2868,6 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
visitEHPadPredecessors(CPI);
- if (!CatchPadResultTy)
- CatchPadResultTy = CPI.getType();
- else
- Assert(CatchPadResultTy == CPI.getType(),
- "The catchpad instruction should have a consistent result type "
- "inside a function.",
- &CPI);
-
BasicBlock *BB = CPI.getParent();
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
@@ -2896,6 +2879,14 @@ void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
"CatchPadInst not the first non-PHI instruction in the block.",
&CPI);
+ if (!BB->getSinglePredecessor())
+ for (BasicBlock *PredBB : predecessors(BB)) {
+ Assert(!isa<CatchPadInst>(PredBB->getTerminator()),
+ "CatchPadInst with CatchPadInst predecessor cannot have any other "
+ "predecessors.",
+ &CPI);
+ }
+
BasicBlock *UnwindDest = CPI.getUnwindDest();
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(
@@ -2946,14 +2937,6 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
BasicBlock *BB = CPI.getParent();
- if (!CleanupPadResultTy)
- CleanupPadResultTy = CPI.getType();
- else
- Assert(CleanupPadResultTy == CPI.getType(),
- "The cleanuppad instruction should have a consistent result type "
- "inside a function.",
- &CPI);
-
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"CleanupPadInst needs to be in a function with a personality.", &CPI);
@@ -2964,6 +2947,18 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
"CleanupPadInst not the first non-PHI instruction in the block.",
&CPI);
+ CleanupReturnInst *FirstCRI = nullptr;
+ for (User *U : CPI.users())
+ if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
+ if (!FirstCRI)
+ FirstCRI = CRI;
+ else
+ Assert(CRI->getUnwindDest() == FirstCRI->getUnwindDest(),
+ "Cleanuprets from same cleanuppad have different exceptional "
+ "successors.",
+ FirstCRI, CRI);
+ }
+
visitInstruction(CPI);
}
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 46593ca7233..e36637a4fd8 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2674,17 +2674,13 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
}
void visitCleanupPadInst(CleanupPadInst &I) {
- if (!I.getType()->isVoidTy()) {
- setShadow(&I, getCleanShadow(&I));
- setOrigin(&I, getCleanOrigin());
- }
+ setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
}
void visitCatchPad(CatchPadInst &I) {
- if (!I.getType()->isVoidTy()) {
- setShadow(&I, getCleanShadow(&I));
- setOrigin(&I, getCleanOrigin());
- }
+ setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
}
void visitTerminatePad(TerminatePadInst &I) {
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 83dd1826c22..22d86c4fdc0 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -344,8 +344,7 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) {
if (CRI->unwindsToCaller()) {
- CleanupReturnInst::Create(CRI->getContext(), CRI->getReturnValue(),
- UnwindDest, CRI);
+ CleanupReturnInst::Create(CRI->getCleanupPad(), UnwindDest, CRI);
CRI->eraseFromParent();
UpdatePHINodes(BB);
}
diff --git a/llvm/test/Assembler/invalid-OperatorConstraint.ll b/llvm/test/Assembler/invalid-OperatorConstraint.ll
new file mode 100644
index 00000000000..e21586a51bd
--- /dev/null
+++ b/llvm/test/Assembler/invalid-OperatorConstraint.ll
@@ -0,0 +1,59 @@
+; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s
+; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s
+; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s
+; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s
+; RUN: sed -e s/.T5:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK5 %s
+; RUN: sed -e s/.T6:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK6 %s
+
+;T1: define void @f() {
+;T1: entry:
+;T1: ; operator constraint requires an operator
+;T1: catchret undef to label %entry
+;T1: ; CHECK1: [[@LINE-1]]:15: error: Catchpad value required in this position
+;T1: }
+
+;T2: define void @f() {
+;T2: entry:
+;T2: %x = cleanuppad []
+;T2: ; catchret's first operand's operator must be catchpad
+;T2: catchret %x to label %entry
+;T2: ; CHECK2: [[@LINE-1]]:15: error: '%x' is not a catchpad
+;T2: }
+
+;T3: define void @f() {
+;T3: entry:
+;T3: ; catchret's first operand's operator must be catchpad
+;T3: ; (forward reference case)
+;T3: catchret %x to label %next
+;T3: ; CHECK3: [[@LINE-1]]:15: error: '%x' is not a catchpad
+;T3: next:
+;T3: %x = cleanuppad []
+;T3: ret void
+;T3: }
+
+;T4: define void @f() {
+;T4: entry:
+;T4: ; operator constraint requires an operator
+;T4: cleanupret undef unwind label %entry
+;T4: ; CHECK4: [[@LINE-1]]:17: error: Cleanuppad value required in this position
+;T4: }
+
+;T5: define void @f() {
+;T5: entry:
+;T5: %x = catchpad []
+;T5: to label %next unwind label %entry
+;T5: next:
+;T5: ; cleanupret first operand's operator must be cleanuppad
+;T5: cleanupret %x unwind to caller
+;T5: ; CHECK5: [[@LINE-1]]:17: error: '%x' is not a cleanuppad
+;T5: }
+
+;T6: define void @f() {
+;T6: entry:
+;T6: ; cleanupret's first operand's operator must be cleanuppad
+;T6: ; (forward reference case)
+;T6: cleanupret %x unwind label %next
+;T6: ; CHECK6: [[@LINE-1]]:17: error: '%x' is not a cleanuppad
+;T6: next:
+;T6: %x = catchpad [] to label %entry unwind label %next
+;T6: }
diff --git a/llvm/test/CodeGen/WinEH/wineh-demotion.ll b/llvm/test/CodeGen/WinEH/wineh-demotion.ll
index c44df6670d3..113d95015a0 100644
--- a/llvm/test/CodeGen/WinEH/wineh-demotion.ll
+++ b/llvm/test/CodeGen/WinEH/wineh-demotion.ll
@@ -36,14 +36,14 @@ merge:
; CHECK: merge:
; CHECK-NOT: = phi
%phi = phi i32 [ %x, %left ], [ %y, %right ]
- %cp = catchpad token [] to label %catch unwind label %catchend
+ %cp = catchpad [] to label %catch unwind label %catchend
catch:
; CHECK: catch:
; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
; CHECK-NEXT: call void @h(i32 [[Reload]])
call void @h(i32 %phi)
- catchret token %cp to label %exit
+ catchret %cp to label %exit
catchend:
catchendpad unwind to caller
@@ -75,9 +75,9 @@ right:
merge.inner:
; CHECK: merge.inner:
; CHECK-NOT: = phi
- ; CHECK: catchpad token
+ ; CHECK: catchpad []
%x = phi i32 [ 1, %left ], [ 2, %right ]
- %cpinner = catchpad token [] to label %catch.inner unwind label %catchend.inner
+ %cpinner = catchpad [] to label %catch.inner unwind label %catchend.inner
catch.inner:
; Need just one store here because only %y is affected
@@ -89,16 +89,16 @@ catch.inner:
to label %catchret.inner unwind label %merge.outer
catchret.inner:
- catchret token %cpinner to label %exit
+ catchret %cpinner to label %exit
catchend.inner:
catchendpad unwind label %merge.outer
merge.outer:
; CHECK: merge.outer:
; CHECK-NOT: = phi
- ; CHECK: [[CatchPad:%[^ ]+]] = catchpad token
+ ; CHECK: [[CatchPad:%[^ ]+]] = catchpad []
%y = phi i32 [ %x, %catchend.inner ], [ %z, %catch.inner ]
- %cpouter = catchpad token [] to label %catch.outer unwind label %catchend.outer
+ %cpouter = catchpad [] to label %catch.outer unwind label %catchend.outer
catchend.outer:
catchendpad unwind to caller
@@ -109,10 +109,10 @@ catch.outer:
; CHECK: catch.outer:
; CHECK-DAG: load i32, i32* [[Slot1]]
; CHECK-DAG: load i32, i32* [[Slot2]]
- ; CHECK: catchret token [[CatchPad]] to label
+ ; CHECK: catchret [[CatchPad]] to label
call void @h(i32 %x)
call void @h(i32 %y)
- catchret token %cpouter to label %exit
+ catchret %cpouter to label %exit
exit:
ret void
@@ -131,7 +131,7 @@ entry:
to label %exit unwind label %catchpad
catchpad:
- %cp = catchpad token [] to label %catch unwind label %catchend
+ %cp = catchpad [] to label %catch unwind label %catchend
catch:
; Need to reload %B here
@@ -152,7 +152,7 @@ merge:
; CHECK: %phi = phi i32 [ [[ReloadX]], %left ]
%phi = phi i32 [ %x, %left ], [ 42, %right ]
call void @h(i32 %phi)
- catchret token %cp to label %exit
+ catchret %cp to label %exit
catchend:
catchendpad unwind to caller
@@ -188,11 +188,11 @@ right:
to label %join unwind label %catchpad.inner
catchpad.inner:
; CHECK: catchpad.inner:
- ; CHECK-NEXT: catchpad token
+ ; CHECK-NEXT: catchpad []
%phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
- %cp1 = catchpad token [] to label %catch.inner unwind label %catchend.inner
+ %cp1 = catchpad [] to label %catch.inner unwind label %catchend.inner
catch.inner:
- catchret token %cp1 to label %join
+ catchret %cp1 to label %join
catchend.inner:
catchendpad unwind label %catchpad.outer
join:
@@ -205,15 +205,15 @@ join:
to label %exit unwind label %catchpad.outer
catchpad.outer:
; CHECK: catchpad.outer:
- ; CHECK-NEXT: catchpad token
+ ; CHECK-NEXT: catchpad []
%phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ]
- %cp2 = catchpad token [] to label %catch.outer unwind label %catchend.outer
+ %cp2 = catchpad [] to label %catch.outer unwind label %catchend.outer
catch.outer:
; CHECK: catch.outer:
; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
; CHECK: call void @h(i32 [[Reload]])
call void @h(i32 %phi.outer)
- catchret token %cp2 to label %exit
+ catchret %cp2 to label %exit
catchend.outer:
catchendpad unwind to caller
exit:
@@ -241,10 +241,10 @@ invoke.cont:
cleanup:
; cleanup phi can be loaded at cleanup entry
; CHECK: cleanup:
- ; CHECK-NEXT: cleanuppad token
+ ; CHECK-NEXT: cleanuppad []
; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
%phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
- %cp = cleanuppad token []
+ %cp = cleanuppad []
%b = call i1 @i()
br i1 %b, label %left, label %right
@@ -264,8 +264,8 @@ merge:
; need store for %phi.catch
; CHECK: merge:
; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
- ; CHECK-NEXT: cleanupret token
- cleanupret token %cp unwind label %catchpad
+ ; CHECK-NEXT: cleanupret
+ cleanupret %cp unwind label %catchpad
invoke.cont2:
; need store for %phi.catch
@@ -277,16 +277,16 @@ invoke.cont2:
catchpad:
; CHECK: catchpad:
- ; CHECK-NEXT: catchpad token
+ ; CHECK-NEXT: catchpad []
%phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
- %cp2 = catchpad token [] to label %catch unwind label %catchend
+ %cp2 = catchpad [] to label %catch unwind label %catchend
catch:
; CHECK: catch:
; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
; CHECK: call void @h(i32 [[CatchReload]]
call void @h(i32 %phi.catch)
- catchret token %cp2 to label %exit
+ catchret %cp2 to label %exit
catchend:
catchendpad unwind to caller
@@ -310,8 +310,8 @@ entry:
; CHECK: store i32 %x, i32* [[SpillSlot:%[^ ]+]]
; CHECK: br label %loop
to_caller:
- %cp1 = cleanuppad token []
- cleanupret token %cp1 unwind to caller
+ %cp1 = cleanuppad []
+ cleanupret %cp1 unwind to caller
loop:
invoke void @f()
to label %loop unwind label %cleanup
@@ -319,9 +319,9 @@ cleanup:
; CHECK: cleanup:
; CHECK: [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]]
; CHECK: call void @h(i32 [[Load]])
- %cp2 = cleanuppad token []
+ %cp2 = cleanuppad []
call void @h(i32 %x)
- cleanupret token %cp2 unwind to caller
+ cleanupret %cp2 unwind to caller
}
; CHECK-LABEL: @test7(
@@ -343,9 +343,9 @@ invoke.cont:
catchpad:
; %x phi should be eliminated
; CHECK: catchpad:
- ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad token
+ ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad []
%x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
- %cp = catchpad token [] to label %catch unwind label %catchend
+ %cp = catchpad [] to label %catch unwind label %catchend
catch:
%b = call i1 @i()
br i1 %b, label %left, label %right
@@ -353,8 +353,8 @@ left:
; Edge from %left to %join needs to be split so that
; the load of %x can be inserted *after* the catchret
; CHECK: left:
- ; CHECK-NEXT: catchret token %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
- catchret token %cp to label %join
+ ; CHECK-NEXT: catchret %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
+ catchret %cp to label %join
; CHECK: [[SplitLeft]]:
; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
; CHECK: br label %join
@@ -363,9 +363,9 @@ right:
; the load of %y can be inserted *after* the catchret
; CHECK: right:
; CHECK: store i32 %y, i32* [[SlotY:%[^ ]+]]
- ; CHECK: catchret token %[[CatchPad]] to label %[[SplitRight:[^ ]+]]
+ ; CHECK: catchret %[[CatchPad]] to label %[[SplitRight:[^ ]+]]
%y = call i32 @g()
- catchret token %cp to label %join
+ catchret %cp to label %join
; CHECK: [[SplitRight]]:
; CHECK: [[LoadY:%[^ ]+]] = load i32, i32* [[SlotY]]
; CHECK: br label %join
@@ -392,20 +392,20 @@ done:
ret void
cleanup1:
- ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad token
+ ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad []
; CHECK-NEXT: call void @f()
- ; CHECK-NEXT: cleanupret token [[CleanupPad1]]
- %cp0 = cleanuppad token []
+ ; CHECK-NEXT: cleanupret [[CleanupPad1]]
+ %cp0 = cleanuppad []
br label %cleanupexit
cleanup2:
- ; CHECK: cleanuppad token
+ ; CHECK: cleanuppad []
; CHECK-NEXT: call void @f()
; CHECK-NEXT: unreachable
- %cp1 = cleanuppad token []
+ %cp1 = cleanuppad []
br label %cleanupexit
cleanupexit:
call void @f()
- cleanupret token %cp0 unwind label %cleanup2
+ cleanupret %cp0 unwind label %cleanup2
}
diff --git a/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll b/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll
index 84b56fe6411..fcbb8bd2fc3 100644
--- a/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll
+++ b/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll
@@ -37,7 +37,7 @@ entry:
to label %unreachable.for.entry unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %1 = catchpad token [i8* null, i8* null] to label %catch unwind label %catchendblock
+ %1 = catchpad [i8* null, i8* null] to label %catch unwind label %catchendblock
catch: ; preds = %catch.dispatch
; CHECK: catch:
@@ -47,7 +47,7 @@ catch: ; preds = %catch.dispatch
to label %unreachable unwind label %catch.dispatch.1
catch.dispatch.1: ; preds = %catch
- %2 = catchpad token [i8* null, i8* null] to label %catch.3 unwind label %catchendblock.2
+ %2 = catchpad [i8* null, i8* null] to label %catch.3 unwind label %catchendblock.2
catch.3: ; preds = %catch.dispatch.1
; CHECK: catch.3:
@@ -57,7 +57,7 @@ catch.3: ; preds = %catch.dispatch.1
to label %invoke.cont unwind label %catchendblock.2
invoke.cont: ; preds = %catch.3
- catchret token %2 to label %try.cont
+ catchret %2 to label %try.cont
try.cont: ; preds = %invoke.cont
; CHECK: try.cont:
diff --git a/llvm/test/Feature/exception.ll b/llvm/test/Feature/exception.ll
index e2635c2de42..de458bb7e4e 100644
--- a/llvm/test/Feature/exception.ll
+++ b/llvm/test/Feature/exception.ll
@@ -28,60 +28,100 @@ declare i32 @__gxx_personality_v0(...)
define void @cleanupret0() personality i32 (...)* @__gxx_personality_v0 {
entry:
- br label %try.cont
-
-try.cont:
invoke void @_Z3quxv() optsize
- to label %try.cont unwind label %bb
-bb:
- cleanuppad void [i7 4]
- cleanupret i8 0 unwind label %bb
+ to label %exit unwind label %pad
+pad:
+ %cp = cleanuppad [i7 4]
+ cleanupret %cp unwind to caller
+exit:
+ ret void
}
+; forward ref by name
define void @cleanupret1() personality i32 (...)* @__gxx_personality_v0 {
entry:
- br label %try.cont
-
-try.cont:
invoke void @_Z3quxv() optsize
- to label %try.cont unwind label %bb
-bb:
- cleanuppad void [i7 4]
- cleanupret void unwind label %bb
+ to label %exit unwind label %pad
+cleanup:
+ cleanupret %cp unwind label %pad
+pad:
+ %cp = cleanuppad []
+ br label %cleanup
+exit:
+ ret void
}
+; forward ref by ID
define void @cleanupret2() personality i32 (...)* @__gxx_personality_v0 {
entry:
- cleanupret i8 0 unwind to caller
+ invoke void @_Z3quxv() optsize
+ to label %exit unwind label %pad
+cleanup:
+ cleanupret %0 unwind label %pad
+pad:
+ %0 = cleanuppad []
+ br label %cleanup
+exit:
+ ret void
}
-define void @cleanupret3() personality i32 (...)* @__gxx_personality_v0 {
- cleanupret void unwind to caller
+define void @catchret0() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+ invoke void @_Z3quxv() optsize
+ to label %exit unwind label %pad
+pad:
+ %cp = catchpad [i7 4]
+ to label %catch unwind label %endpad
+catch:
+ catchret %cp to label %exit
+endpad:
+ catchendpad unwind to caller
+exit:
+ ret void
}
-define void @catchret() personality i32 (...)* @__gxx_personality_v0 {
+; forward ref by name
+define void @catchret1() personality i32 (...)* @__gxx_personality_v0 {
entry:
- br label %bb
-bb:
- catchret void to label %bb
+ invoke void @_Z3quxv() optsize
+ to label %exit unwind label %pad
+catch:
+ catchret %cp to label %exit
+pad:
+ %cp = catchpad []
+ to label %catch unwind label %endpad
+endpad:
+ catchendpad unwind to caller
+exit:
+ ret void
}
-define i8 @catchpad() personality i32 (...)* @__gxx_personality_v0 {
+; forward ref by ID
+define void @catchret2() personality i32 (...)* @__gxx_personality_v0 {
entry:
- br label %try.cont
+ invoke void @_Z3quxv() optsize
+ to label %exit unwind label %pad
+catch:
+ catchret %0 to label %exit
+pad:
+ %0 = catchpad []
+ to label %catch unwind label %endpad
+endpad:
+ catchendpad unwind to caller
+exit:
+ ret void
+}
-try.cont:
+define i8 @catchpad() personality i32 (...)* @__gxx_personality_v0 {
+entry:
invoke void @_Z3quxv() optsize
to label %exit unwind label %bb2
-bb:
- catchret token %cbv to label %exit
-
-exit:
- ret i8 0
bb2:
- %cbv = catchpad token [i7 4] to label %bb unwind label %bb3
+ catchpad [i7 4] to label %exit unwind label %bb3
bb3:
catchendpad unwind to caller
+exit:
+ ret i8 0
}
define void @terminatepad0() personality i32 (...)* @__gxx_personality_v0 {
@@ -114,7 +154,7 @@ try.cont:
invoke void @_Z3quxv() optsize
to label %try.cont unwind label %bb
bb:
- cleanuppad void [i7 4]
+ cleanuppad [i7 4]
ret void
}
OpenPOWER on IntegriCloud