Index: docs/ExceptionHandling.rst =================================================================== --- docs/ExceptionHandling.rst +++ docs/ExceptionHandling.rst @@ -614,20 +614,19 @@ 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 @@ ; 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 void [%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"] Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -5138,7 +5138,7 @@ :: - = catchpad [*] + = catchpad [*] to label unwind label Overview: @@ -5153,9 +5153,9 @@ 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 ` 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 ` and is used to match the ``catchpad`` to +corresponding :ref:`catchrets `. Arguments: """""""""" @@ -5170,15 +5170,11 @@ Semantics: """""""""" -The '``catchpad``' instruction defines the values which are set by the -:ref:`personality function ` 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,15 @@ 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``'s value 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``'s value (counting instances in of the same ``catchpad`` in + different call frames as distinct). Example: """""""" @@ -5204,7 +5204,7 @@ .. 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 +5264,8 @@ '``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 +5285,7 @@ :: - catchret to label + catchret to label Overview: """"""""" @@ -5296,8 +5297,10 @@ 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 either ``undef`` or a :ref:`catchpad `. +The second argument to a '``catchret``' specifies where control will +transfer to next. Semantics: """""""""" @@ -5309,13 +5312,23 @@ 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`` +argument is ``undef``. +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 +5340,8 @@ :: - cleanupret unwind label - cleanupret unwind to caller + cleanupret unwind label + cleanupret unwind to caller Overview: """"""""" @@ -5340,9 +5353,10 @@ 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 either ``undef`` or a +:ref:`cleanuppad `. It also has an optional successor, +``continue``. Semantics: """""""""" @@ -5351,14 +5365,23 @@ :ref:`personality function ` that one :ref:`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`` +argument is ``undef``. +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 +8414,7 @@ :: - = cleanuppad [*] + = cleanuppad [*] Overview: """"""""" @@ -8403,7 +8426,8 @@ The ``args`` correspond to whatever additional information the :ref:`personality function ` requires to execute the cleanup. -The ``resultval`` has the type ``resultty``. +The ``resultval`` has the type :ref:`token ` and is used to +match the ``cleanuppad`` to corresponding :ref:`cleanuprets `. Arguments: """""""""" @@ -8415,9 +8439,8 @@ """""""""" The '``cleanuppad``' instruction defines the values which are set by the -:ref:`personality function ` 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 ` 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 +8457,22 @@ 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`` (counting instances in of the same ``cleanuppad`` in different + call frames as distinct). Example: """""""" .. code-block:: llvm - %res = cleanuppad { i8*, i32 } [label %nextaction] + %tok = cleanuppad [] .. _intrinsics: Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -356,9 +356,9 @@ 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#] Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -671,15 +671,14 @@ return Insert(ResumeInst::Create(Exn)); } - CleanupReturnInst *CreateCleanupRet(BasicBlock *UnwindBB = nullptr, - Value *RetVal = nullptr) { - return Insert(CleanupReturnInst::Create(Context, RetVal, UnwindBB)); + CleanupReturnInst *CreateCleanupRet(Value *CleanupPad, + BasicBlock *UnwindBB = nullptr) { + return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB)); } - CatchPadInst *CreateCatchPad(Type *Ty, BasicBlock *NormalDest, - BasicBlock *UnwindDest, ArrayRef Args, - const Twine &Name = "") { - return Insert(CatchPadInst::Create(Ty, NormalDest, UnwindDest, Args), Name); + CatchPadInst *CreateCatchPad(BasicBlock *NormalDest, BasicBlock *UnwindDest, + ArrayRef Args, const Twine &Name = "") { + return Insert(CatchPadInst::Create(NormalDest, UnwindDest, Args), Name); } CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) { @@ -692,13 +691,13 @@ return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name); } - CleanupPadInst *CreateCleanupPad(Type *Ty, ArrayRef Args, + CleanupPadInst *CreateCleanupPad(ArrayRef 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(Value *CatchPad, BasicBlock *BB) { + return Insert(CatchReturnInst::Create(CatchPad, BB)); } UnreachableInst *CreateUnreachable() { Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -3578,51 +3578,38 @@ 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); + CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, + Instruction *InsertBefore = nullptr); + CleanupReturnInst(Value *CleanupPad, 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, + static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB = nullptr, Instruction *InsertBefore = nullptr) { - unsigned Values = 0; - if (RetVal) - ++Values; + unsigned Values = 1; if (UnwindBB) ++Values; return new (Values) - CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertBefore); + CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertBefore); } - static CleanupReturnInst *Create(LLVMContext &C, Value *RetVal, - BasicBlock *UnwindBB, + static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB, BasicBlock *InsertAtEnd) { - unsigned Values = 0; - if (RetVal) - ++Values; + unsigned Values = 1; if (UnwindBB) ++Values; return new (Values) - CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertAtEnd); + CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertAtEnd); } /// Provide fast operand accessors @@ -3630,23 +3617,21 @@ 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); - } + /// Convenience accessor. + Value *getCleanupPad() const { return Op<-1>(); } + void setCleanupPad(Value *CleanupPad) { Op<-1>() = CleanupPad; } unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } - BasicBlock *getUnwindDest() const; - void setUnwindDest(BasicBlock *NewDest); + BasicBlock *getUnwindDest() const { + return hasUnwindDest() ? cast(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) { @@ -3670,7 +3655,7 @@ template <> struct OperandTraits - : public VariadicOperandTraits {}; + : public VariadicOperandTraits {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value) @@ -3760,14 +3745,12 @@ CatchPadInst(const CatchPadInst &CPI); - explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore); - explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd); + explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef Args, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef Args, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); protected: // Note: Instruction needs to be a friend here to call cloneImpl. @@ -3775,20 +3758,19 @@ CatchPadInst *cloneImpl() const; public: - static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - const Twine &NameStr = "", + static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef 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 Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { + static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef 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 @@ -3990,9 +3972,9 @@ CleanupPadInst(const CleanupPadInst &CPI); - explicit CleanupPadInst(Type *RetTy, ArrayRef Args, + explicit CleanupPadInst(LLVMContext &C, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore); - explicit CleanupPadInst(Type *RetTy, ArrayRef Args, + explicit CleanupPadInst(LLVMContext &C, ArrayRef Args, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: @@ -4001,14 +3983,14 @@ CleanupPadInst *cloneImpl() const; public: - static CleanupPadInst *Create(Type *RetTy, ArrayRef Args, + static CleanupPadInst *Create(LLVMContext &C, ArrayRef 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 Args, + static CleanupPadInst *Create(LLVMContext &C, ArrayRef 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,11 +4019,10 @@ CatchReturnInst(const CatchReturnInst &RI); private: - void init(BasicBlock *BB, Value *RetVal); - CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values, + void init(Value *CatchPad, BasicBlock *BB); + CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore = nullptr); - CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values, - BasicBlock *InsertAtEnd); + CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd); protected: // Note: Instruction needs to be a friend here to call cloneImpl. @@ -4049,34 +4030,27 @@ CatchReturnInst *cloneImpl() const; public: - static CatchReturnInst *Create(BasicBlock *BB, Value *RetVal = nullptr, + static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore = nullptr) { 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(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd) { 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(Op<-1>()); } - void setSuccessor(BasicBlock *NewSucc) { Op<-1>() = (Value *)NewSucc; } - unsigned getNumSuccessors() const { return 1; } + Value *getCatchPad() const { return Op<0>(); } + void setCatchPad(Value *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(Op<1>()); } + void setSuccessor(BasicBlock *NewSucc) { Op<1>() = (Value *)NewSucc; } + unsigned getNumSuccessors() const { return 1; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { @@ -4094,7 +4068,7 @@ template <> struct OperandTraits - : public VariadicOperandTraits {}; + : public FixedNumOperandTraits {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value) Index: lib/Analysis/InlineCost.cpp =================================================================== --- lib/Analysis/InlineCost.cpp +++ lib/Analysis/InlineCost.cpp @@ -913,7 +913,7 @@ 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; } Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4966,7 +4966,7 @@ bool LLParser::ParseExceptionArgs(SmallVectorImpl &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) { @@ -4997,16 +4997,12 @@ } /// 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)) + return true; if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret")) return true; @@ -5022,39 +5018,32 @@ } } - Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB); + Inst = CleanupReturnInst::Create(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)) 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(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 Args; - if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS)) + if (ParseExceptionArgs(Args, PFS)) return true; BasicBlock *NormalBB, *UnwindBB; @@ -5064,7 +5053,7 @@ ParseTypeAndBasicBlock(UnwindBB, PFS)) return true; - Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args); + Inst = CatchPadInst::Create(NormalBB, UnwindBB, Args); return false; } @@ -5096,13 +5085,11 @@ /// ParseCleanupPad /// ::= 'cleanuppad' ParamList bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) { - Type *RetType = nullptr; - SmallVector 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; } Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -3819,56 +3819,46 @@ } 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)); + 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(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)); + 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(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 +3876,7 @@ 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 +3908,10 @@ 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 Args; for (unsigned Op = 0; Op != NumArgOperands; ++Op) { @@ -3936,7 +3923,7 @@ if (Record.size() != Idx) return error("Invalid record"); - I = CleanupPadInst::Create(Ty, Args); + I = CleanupPadInst::Create(Context, Args); InstructionList.push_back(I); break; } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1855,10 +1855,7 @@ case Instruction::CleanupRet: { Code = bitc::FUNC_CODE_INST_CLEANUPRET; const auto &CRI = cast(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 @@ case Instruction::CatchRet: { Code = bitc::FUNC_CODE_INST_CATCHRET; const auto &CRI = cast(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(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 @@ case Instruction::CleanupPad: { Code = bitc::FUNC_CODE_INST_CLEANUPPAD; const auto &CPI = cast(I); - Vals.push_back(VE.getTypeID(CPI.getType())); unsigned NumOperands = CPI.getNumOperands(); Vals.push_back(NumOperands); for (unsigned Op = 0; Op != NumOperands; ++Op) Index: lib/CodeGen/WinEHPrepare.cpp =================================================================== --- lib/CodeGen/WinEHPrepare.cpp +++ lib/CodeGen/WinEHPrepare.cpp @@ -2956,7 +2956,7 @@ if (isa(TI) || isa(TI) || isa(TI)) return BB; - return cast(cast(TI)->getReturnValue()) + return cast(cast(TI)->getCleanupPad()) ->getParent(); } @@ -3242,11 +3242,11 @@ // The token consumed by a CatchReturnInst must match the funclet token. bool IsUnreachableCatchret = false; if (auto *CRI = dyn_cast(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(TI)) - IsUnreachableCleanupret = CRI->getReturnValue() != CleanupPad; + IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad; if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) { new UnreachableInst(BB->getContext(), TI); TI->eraseFromParent(); Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -2860,9 +2860,6 @@ writeOperand(LPI->getClause(i), true); } } else if (const auto *CPI = dyn_cast(&I)) { - Out << ' '; - TypePrinter.print(I.getType(), Out); - Out << " ["; for (unsigned Op = 0, NumOps = CPI->getNumArgOperands(); Op < NumOps; ++Op) { @@ -2888,9 +2885,6 @@ else Out << "to caller"; } else if (const auto *CPI = dyn_cast(&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 @@ } else if (isa(I) && !Operand) { Out << " void"; } else if (const auto *CRI = dyn_cast(&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(&I)) { - if (CRI->hasReturnValue()) { - Out << ' '; - writeOperand(CRI->getReturnValue(), /*PrintType=*/true); - } else { - Out << " void"; - } + Out << ' '; + writeOperand(CRI->getCleanupPad(), /*PrintType=*/false); Out << " unwind "; if (CRI->hasUnwindDest()) Index: lib/IR/Instruction.cpp =================================================================== --- lib/IR/Instruction.cpp +++ lib/IR/Instruction.cpp @@ -261,7 +261,7 @@ case ExtractValue: return "extractvalue"; case InsertValue: return "insertvalue"; case LandingPad: return "landingpad"; - case CleanupPad: return "cleanuppad"; + case CleanupPad: return "cleanuppad"; default: return " "; } Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -684,51 +684,37 @@ CRI.getNumOperands()) { SubclassOptionalData = CRI.SubclassOptionalData; setInstructionSubclassData(CRI.getSubclassDataFromInstruction()); - if (Value *RetVal = CRI.getReturnValue()) - setReturnValue(RetVal); + setCleanupPad(CRI.getCleanupPad()); if (BasicBlock *UnwindDest = CRI.getUnwindDest()) setUnwindDest(UnwindDest); } -void CleanupReturnInst::init(Value *RetVal, BasicBlock *UnwindBB) { +void CleanupReturnInst::init(Value *CleanupPad, BasicBlock *UnwindBB) { SubclassOptionalData = 0; if (UnwindBB) setInstructionSubclassData(getSubclassDataFromInstruction() | 1); - if (RetVal) - setInstructionSubclassData(getSubclassDataFromInstruction() | 2); + setCleanupPad(CleanupPad); if (UnwindBB) setUnwindDest(UnwindBB); - if (RetVal) - setReturnValue(RetVal); } -CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal, - BasicBlock *UnwindBB, unsigned Values, - Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet, +CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, + unsigned Values, Instruction *InsertBefore) + : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), + Instruction::CleanupRet, OperandTraits::op_end(this) - Values, Values, InsertBefore) { - init(RetVal, UnwindBB); + init(CleanupPad, UnwindBB); } -CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal, - BasicBlock *UnwindBB, unsigned Values, - BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet, +CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, + unsigned Values, BasicBlock *InsertAtEnd) + : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), + Instruction::CleanupRet, OperandTraits::op_end(this) - Values, Values, InsertAtEnd) { - init(RetVal, UnwindBB); -} - -BasicBlock *CleanupReturnInst::getUnwindDest() const { - if (hasUnwindDest()) - return cast(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 +783,32 @@ //===----------------------------------------------------------------------===// // CatchReturnInst Implementation //===----------------------------------------------------------------------===// -void CatchReturnInst::init(BasicBlock *BB, Value *RetVal) { - Op<-1>() = BB; - if (RetVal) - Op<-2>() = RetVal; +void CatchReturnInst::init(Value *CatchPad, BasicBlock *BB) { + Op<0>() = CatchPad; + Op<1>() = BB; } CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI) : TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet, - OperandTraits::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::op_begin(this), 2) { + Op<0>() = CRI.Op<0>(); + Op<1>() = CRI.Op<1>(); } -CatchReturnInst::CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values, +CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore) : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, - OperandTraits::op_end(this) - Values, - Values, InsertBefore) { - init(BB, RetVal); + OperandTraits::op_begin(this), 2, + InsertBefore) { + init(CatchPad, BB); } -CatchReturnInst::CatchReturnInst(BasicBlock *BB, Value *RetVal, unsigned Values, +CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd) : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, - OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { - init(BB, RetVal); + OperandTraits::op_begin(this), 2, + InsertAtEnd) { + init(CatchPad, BB); } BasicBlock *CatchReturnInst::getSuccessorV(unsigned Idx) const { @@ -863,21 +843,21 @@ std::copy(CPI.op_begin(), CPI.op_end(), op_begin()); } -CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore) - : TerminatorInst(RetTy, Instruction::CatchPad, +CatchPadInst::CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef Args, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore) + : TerminatorInst(Type::getTokenTy(IfNormal->getContext()), + Instruction::CatchPad, OperandTraits::op_end(this) - Values, Values, InsertBefore) { init(IfNormal, IfException, Args, NameStr); } -CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal, - BasicBlock *IfException, ArrayRef Args, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : TerminatorInst(RetTy, Instruction::CatchPad, +CatchPadInst::CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef Args, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : TerminatorInst(Type::getTokenTy(IfNormal->getContext()), + Instruction::CatchPad, OperandTraits::op_end(this) - Values, Values, InsertAtEnd) { init(IfNormal, IfException, Args, NameStr); @@ -962,17 +942,17 @@ std::copy(CPI.op_begin(), CPI.op_end(), op_begin()); } -CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef Args, +CleanupPadInst::CleanupPadInst(LLVMContext &C, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(RetTy, Instruction::CleanupPad, + : Instruction(Type::getTokenTy(C), Instruction::CleanupPad, OperandTraits::op_end(this) - Args.size(), Args.size(), InsertBefore) { init(Args, NameStr); } -CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef Args, +CleanupPadInst::CleanupPadInst(LLVMContext &C, ArrayRef Args, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(RetTy, Instruction::CleanupPad, + : Instruction(Type::getTokenTy(C), Instruction::CleanupPad, OperandTraits::op_end(this) - Args.size(), Args.size(), InsertAtEnd) { init(Args, NameStr); Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -184,12 +184,6 @@ /// \brief Track unresolved string-based type references. SmallDenseMap 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 @@ 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 @@ // FIXME: We strip const here because the inst visitor strips const. visit(const_cast(F)); InstsInThisBlock.clear(); - CatchPadResultTy = nullptr; - CleanupPadResultTy = nullptr; LandingPadResultTy = nullptr; SawFrameEscape = false; @@ -395,6 +386,7 @@ void visitEHPadPredecessors(Instruction &I); void visitLandingPadInst(LandingPadInst &LPI); void visitCatchPadInst(CatchPadInst &CPI); + void visitCatchReturnInst(CatchReturnInst &CRI); void visitCatchEndPadInst(CatchEndPadInst &CEPI); void visitCleanupPadInst(CleanupPadInst &CPI); void visitCleanupReturnInst(CleanupReturnInst &CRI); @@ -2877,14 +2869,6 @@ 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 +2880,14 @@ "CatchPadInst not the first non-PHI instruction in the block.", &CPI); + if (!BB->getSinglePredecessor()) + for (BasicBlock *PredBB : predecessors(BB)) { + Assert(!isa(PredBB->getTerminator()), + "CatchPadInst with CatchPadInst predecessor cannot have any other " + "predecessors.", + &CPI); + } + BasicBlock *UnwindDest = CPI.getUnwindDest(); Instruction *I = UnwindDest->getFirstNonPHI(); Assert( @@ -2906,6 +2898,14 @@ visitTerminatorInst(CPI); } +void Verifier::visitCatchReturnInst(CatchReturnInst &CRI) { + Value *CatchPad = CRI.getCatchPad(); + Assert(isa(CatchPad) || isa(CatchPad), + "CatchReturnInst may only consume a catchpad", &CRI); + + visitTerminatorInst(CRI); +} + void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) { visitEHPadPredecessors(CEPI); @@ -2946,14 +2946,6 @@ 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,10 +2956,26 @@ "CleanupPadInst not the first non-PHI instruction in the block.", &CPI); + CleanupReturnInst *FirstCRI = nullptr; + for (User *U : CPI.users()) { + if (CleanupReturnInst *CRI = dyn_cast(U)) + if (!FirstCRI) + FirstCRI = CRI; + else + Assert(CRI->getUnwindDest() == FirstCRI->getUnwindDest(), + "Cleanuprets from same cleanuppad have different exceptional " + "successors.", + FirstCRI, CRI); + } + visitInstruction(CPI); } void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { + Value *CleanupPad = CRI.getCleanupPad(); + Assert(isa(CleanupPad) || isa(CleanupPad), + "CleanupReturnInst may only consume a cleanuppad", &CRI); + if (BasicBlock *UnwindDest = CRI.getUnwindDest()) { Instruction *I = UnwindDest->getFirstNonPHI(); Assert(I->isEHPad() && !isa(I), Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2674,17 +2674,13 @@ } 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) { Index: lib/Transforms/Utils/InlineFunction.cpp =================================================================== --- lib/Transforms/Utils/InlineFunction.cpp +++ lib/Transforms/Utils/InlineFunction.cpp @@ -344,8 +344,7 @@ if (auto *CRI = dyn_cast(BB->getTerminator())) { if (CRI->unwindsToCaller()) { - CleanupReturnInst::Create(CRI->getContext(), CRI->getReturnValue(), - UnwindDest, CRI); + CleanupReturnInst::Create(CRI->getCleanupPad(), UnwindDest, CRI); CRI->eraseFromParent(); UpdatePHINodes(BB); } Index: test/CodeGen/WinEH/wineh-demotion.ll =================================================================== --- test/CodeGen/WinEH/wineh-demotion.ll +++ test/CodeGen/WinEH/wineh-demotion.ll @@ -36,14 +36,14 @@ ; 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 @@ 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 @@ 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 @@ ; 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 @@ 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 @@ ; 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 @@ 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 @@ 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 @@ 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 @@ ; 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 @@ 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 @@ ; 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 @@ ; 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 @@ 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 @@ ; 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 @@ ; 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 @@ 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 } Index: test/CodeGen/WinEH/wineh-statenumbering.ll =================================================================== --- test/CodeGen/WinEH/wineh-statenumbering.ll +++ test/CodeGen/WinEH/wineh-statenumbering.ll @@ -37,7 +37,7 @@ 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 @@ 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 @@ 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: Index: test/Feature/exception.ll =================================================================== --- test/Feature/exception.ll +++ test/Feature/exception.ll @@ -34,36 +34,20 @@ invoke void @_Z3quxv() optsize to label %try.cont unwind label %bb bb: - cleanuppad void [i7 4] - cleanupret i8 0 unwind label %bb + %cp = cleanuppad [i7 4] + cleanupret %cp unwind label %bb } 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 -} - -define void @cleanupret2() personality i32 (...)* @__gxx_personality_v0 { -entry: - cleanupret i8 0 unwind to caller -} - -define void @cleanupret3() personality i32 (...)* @__gxx_personality_v0 { - cleanupret void unwind to caller + cleanupret undef unwind to caller } define void @catchret() personality i32 (...)* @__gxx_personality_v0 { entry: br label %bb bb: - catchret void to label %bb + catchret undef to label %bb } define i8 @catchpad() personality i32 (...)* @__gxx_personality_v0 { @@ -74,12 +58,12 @@ invoke void @_Z3quxv() optsize to label %exit unwind label %bb2 bb: - catchret token %cbv to label %exit + catchret %cbv to label %exit exit: ret i8 0 bb2: - %cbv = catchpad token [i7 4] to label %bb unwind label %bb3 + %cbv = catchpad [i7 4] to label %bb unwind label %bb3 bb3: catchendpad unwind to caller } @@ -114,7 +98,7 @@ invoke void @_Z3quxv() optsize to label %try.cont unwind label %bb bb: - cleanuppad void [i7 4] + cleanuppad [i7 4] ret void }