Index: include/llvm/IR/InstVisitor.h =================================================================== --- include/llvm/IR/InstVisitor.h +++ include/llvm/IR/InstVisitor.h @@ -167,14 +167,14 @@ RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);} RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);} RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} - RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);} + RetTy visitResumeInst(ResumeInst &I) { DELEGATE(EHTerminatorInst);} RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} - RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);} - RetTy visitCleanupEndPadInst(CleanupEndPadInst &I) { DELEGATE(TerminatorInst); } - RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst); } - RetTy visitCatchPadInst(CatchPadInst &I) { DELEGATE(TerminatorInst);} - RetTy visitCatchEndPadInst(CatchEndPadInst &I) { DELEGATE(TerminatorInst); } - RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);} + RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(EHTerminatorInst);} + RetTy visitCleanupEndPadInst(CleanupEndPadInst &I) { DELEGATE(EHTerminatorInst); } + RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(EHTerminatorInst); } + RetTy visitCatchPadInst(CatchPadInst &I) { DELEGATE(EHTerminatorInst);} + RetTy visitCatchEndPadInst(CatchEndPadInst &I) { DELEGATE(EHTerminatorInst); } + RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(EHTerminatorInst);} RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);} @@ -235,11 +235,12 @@ // instruction type, they can overload one of these to get the whole class // of instructions... // - RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);} - RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);} - RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction);} - RetTy visitUnaryInstruction(UnaryInstruction &I){ DELEGATE(Instruction);} + RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);} + RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);} + RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);} + RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction);} + RetTy visitEHTerminatorInst(EHTerminatorInst &I) { DELEGATE(TerminatorInst); } + RetTy visitUnaryInstruction(UnaryInstruction &I) { DELEGATE(Instruction);} // Provide a special visitor for a 'callsite' that visits both calls and // invokes. When unimplemented, properly delegates to either the terminator or Index: include/llvm/IR/InstrTypes.h =================================================================== --- include/llvm/IR/InstrTypes.h +++ include/llvm/IR/InstrTypes.h @@ -76,23 +76,6 @@ return isa(V) && classof(cast(V)); } - // \brief Returns true if this terminator relates to exception handling. - bool isExceptional() const { - switch (getOpcode()) { - case Instruction::CatchPad: - case Instruction::CatchEndPad: - case Instruction::CatchRet: - case Instruction::CleanupEndPad: - case Instruction::CleanupRet: - case Instruction::Invoke: - case Instruction::Resume: - case Instruction::TerminatePad: - return true; - default: - return false; - } - } - //===--------------------------------------------------------------------===// // succ_iterator definition //===--------------------------------------------------------------------===// @@ -272,6 +255,51 @@ }; //===----------------------------------------------------------------------===// +// EHTerminatorInst Class +//===----------------------------------------------------------------------===// + +/// Subclasses of this class are terminators that relate to exception +/// propagation. They may have an unwind successor block which exception +/// edges target. +/// +class EHTerminatorInst : public TerminatorInst { +protected: + EHTerminatorInst(Type *Ty, Instruction::EHTermOps iType, Use *Ops, + unsigned NumOps, Instruction *InsertBefore = nullptr) + : TerminatorInst(Ty, static_cast(iType), Ops, + NumOps, InsertBefore) {} + + EHTerminatorInst(Type *Ty, Instruction::EHTermOps iType, Use *Ops, + unsigned NumOps, BasicBlock *InsertAtEnd) + : TerminatorInst(Ty, static_cast(iType), Ops, + NumOps, InsertAtEnd) {} + + // Out of line virtual method, so the vtable, etc has a home. + ~EHTerminatorInst() override; + + /// Virtual methods - Terminators should overload these and provide inline + /// overrides of non-V methods. + virtual BasicBlock *getUnwindDestV() const = 0; + virtual void setUnwindDestV(BasicBlock *B) = 0; + +public: + /// Return the unwind successor. May be null if this instruction unwinds + /// to caller. + BasicBlock *getUnwindDest() const { return getUnwindDestV(); } + + /// Update the unwind successor to point at the provided block. + void setUnwindDest(BasicBlock *B) { setUnwindDestV(B); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->isEHTerminator(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// // UnaryInstruction Class //===----------------------------------------------------------------------===// Index: include/llvm/IR/Instruction.h =================================================================== --- include/llvm/IR/Instruction.h +++ include/llvm/IR/Instruction.h @@ -113,6 +113,7 @@ const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } bool isTerminator() const { return isTerminator(getOpcode()); } + bool isEHTerminator() const { return isEHTerminator(getOpcode()); } bool isBinaryOp() const { return isBinaryOp(getOpcode()); } bool isShift() { return isShift(getOpcode()); } bool isCast() const { return isCast(getOpcode()); } @@ -123,6 +124,10 @@ return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; } + static inline bool isEHTerminator(unsigned OpCode) { + return OpCode >= EHTermOpsBegin && OpCode < EHTermOpsEnd; + } + static inline bool isBinaryOp(unsigned Opcode) { return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; } @@ -464,6 +469,13 @@ #include "llvm/IR/Instruction.def" }; + enum EHTermOps { +#define FIRST_EH_TERM_INST(N) EHTermOpsBegin = N, +#define HANDLE_EH_TERM_INST(N, OPC, CLASS) EH_##OPC = N, +#define LAST_EH_TERM_INST(N) EHTermOpsEnd = N + 1 +#include "llvm/IR/Instruction.def" + }; + enum BinaryOps { #define FIRST_BINARY_INST(N) BinaryOpsBegin = N, #define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, Index: include/llvm/IR/Instruction.def =================================================================== --- include/llvm/IR/Instruction.def +++ include/llvm/IR/Instruction.def @@ -32,6 +32,16 @@ #define LAST_TERM_INST(num) #endif +#ifndef FIRST_EH_TERM_INST +#define FIRST_EH_TERM_INST(num) +#endif +#ifndef HANDLE_EH_TERM_INST +#define HANDLE_EH_TERM_INST(num, opcode, Class) HANDLE_TERM_INST(num, opcode, Class) +#endif +#ifndef LAST_EH_TERM_INST +#define LAST_EH_TERM_INST(num) +#endif + #ifndef FIRST_BINARY_INST #define FIRST_BINARY_INST(num) #endif @@ -92,21 +102,23 @@ // block of the program. Every basic block must end with one of these // instructions for it to be a well formed basic block. // - FIRST_TERM_INST ( 1) -HANDLE_TERM_INST ( 1, Ret , ReturnInst) -HANDLE_TERM_INST ( 2, Br , BranchInst) -HANDLE_TERM_INST ( 3, Switch , SwitchInst) -HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) -HANDLE_TERM_INST ( 5, Invoke , InvokeInst) -HANDLE_TERM_INST ( 6, Resume , ResumeInst) -HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst) -HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst) -HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst) -HANDLE_TERM_INST (10, CatchPad , CatchPadInst) -HANDLE_TERM_INST (11, TerminatePad , TerminatePadInst) -HANDLE_TERM_INST (12, CatchEndPad , CatchEndPadInst) -HANDLE_TERM_INST (13, CleanupEndPad , CleanupEndPadInst) - LAST_TERM_INST (13) + FIRST_TERM_INST ( 1) + HANDLE_TERM_INST ( 1, Ret , ReturnInst) + HANDLE_TERM_INST ( 2, Br , BranchInst) + HANDLE_TERM_INST ( 3, Switch , SwitchInst) + HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) + HANDLE_TERM_INST ( 5, Unreachable , UnreachableInst) + FIRST_EH_TERM_INST ( 6) +HANDLE_EH_TERM_INST ( 6, Invoke , InvokeInst) +HANDLE_EH_TERM_INST ( 7, Resume , ResumeInst) +HANDLE_EH_TERM_INST ( 8, CleanupRet , CleanupReturnInst) +HANDLE_EH_TERM_INST ( 9, CatchRet , CatchReturnInst) +HANDLE_EH_TERM_INST (10, CatchPad , CatchPadInst) +HANDLE_EH_TERM_INST (11, TerminatePad , TerminatePadInst) +HANDLE_EH_TERM_INST (12, CatchEndPad , CatchEndPadInst) +HANDLE_EH_TERM_INST (13, CleanupEndPad , CleanupEndPadInst) + LAST_EH_TERM_INST (13) + LAST_TERM_INST (13) // Standard binary operators... FIRST_BINARY_INST(14) @@ -185,6 +197,10 @@ #undef HANDLE_TERM_INST #undef LAST_TERM_INST +#undef FIRST_EH_TERM_INST +#undef HANDLE_EH_TERM_INST +#undef LAST_EH_TERM_INST + #undef FIRST_BINARY_INST #undef HANDLE_BINARY_INST #undef LAST_BINARY_INST Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -3260,7 +3260,7 @@ /// InvokeInst - Invoke instruction. The SubclassData field is used to hold the /// calling convention of the call. /// -class InvokeInst : public TerminatorInst, +class InvokeInst : public EHTerminatorInst, public OperandBundleUser { AttributeSet AttributeList; FunctionType *FTy; @@ -3611,6 +3611,8 @@ BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; bool hasFnAttrImpl(Attribute::AttrKind A) const; @@ -3629,20 +3631,21 @@ BasicBlock *IfException, ArrayRef Args, ArrayRef Bundles, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) - : TerminatorInst(Ty->getReturnType(), Instruction::Invoke, - OperandTraits::op_end(this) - Values, Values, - InsertBefore) { + : EHTerminatorInst(Ty->getReturnType(), Instruction::EH_Invoke, + OperandTraits::op_end(this) - Values, Values, + InsertBefore) { init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr); } InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, ArrayRef Bundles, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) - : TerminatorInst( - cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Invoke, OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { + : EHTerminatorInst(cast( + cast(Func->getType())->getElementType()) + ->getReturnType(), + Instruction::EH_Invoke, + OperandTraits::op_end(this) - Values, Values, + InsertAtEnd) { init(Func, IfNormal, IfException, Args, Bundles, NameStr); } @@ -3655,7 +3658,7 @@ //===--------------------------------------------------------------------------- /// ResumeInst - Resume the propagation of an exception. /// -class ResumeInst : public TerminatorInst { +class ResumeInst : public EHTerminatorInst { ResumeInst(const ResumeInst &RI); explicit ResumeInst(Value *Exn, Instruction *InsertBefore=nullptr); @@ -3694,6 +3697,8 @@ BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; }; template <> @@ -3707,7 +3712,7 @@ // CatchEndPadInst Class //===----------------------------------------------------------------------===// -class CatchEndPadInst : public TerminatorInst { +class CatchEndPadInst : public EHTerminatorInst { private: CatchEndPadInst(const CatchEndPadInst &RI); @@ -3763,6 +3768,8 @@ BasicBlock *getSuccessorV(unsigned Idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned Idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -3781,7 +3788,7 @@ // CatchPadInst Class //===----------------------------------------------------------------------===// -class CatchPadInst : public TerminatorInst { +class CatchPadInst : public EHTerminatorInst { private: void init(BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, const Twine &NameStr); @@ -3872,6 +3879,8 @@ BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; }; template <> @@ -3884,7 +3893,7 @@ // TerminatePadInst Class //===----------------------------------------------------------------------===// -class TerminatePadInst : public TerminatorInst { +class TerminatePadInst : public EHTerminatorInst { private: void init(BasicBlock *BB, ArrayRef Args); @@ -3991,6 +4000,8 @@ BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -4058,7 +4069,7 @@ // CatchReturnInst Class //===----------------------------------------------------------------------===// -class CatchReturnInst : public TerminatorInst { +class CatchReturnInst : public EHTerminatorInst { CatchReturnInst(const CatchReturnInst &RI); void init(CatchPadInst *CatchPad, BasicBlock *BB); @@ -4115,6 +4126,8 @@ BasicBlock *getSuccessorV(unsigned Idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned Idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; }; template <> @@ -4127,7 +4140,7 @@ // CleanupEndPadInst Class //===----------------------------------------------------------------------===// -class CleanupEndPadInst : public TerminatorInst { +class CleanupEndPadInst : public EHTerminatorInst { private: CleanupEndPadInst(const CleanupEndPadInst &CEPI); @@ -4196,6 +4209,8 @@ BasicBlock *getSuccessorV(unsigned Idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned Idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -4214,7 +4229,7 @@ // CleanupReturnInst Class //===----------------------------------------------------------------------===// -class CleanupReturnInst : public TerminatorInst { +class CleanupReturnInst : public EHTerminatorInst { private: CleanupReturnInst(const CleanupReturnInst &RI); @@ -4289,6 +4304,8 @@ BasicBlock *getSuccessorV(unsigned Idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned Idx, BasicBlock *B) override; + BasicBlock *getUnwindDestV() const override; + void setUnwindDestV(BasicBlock *B) override; // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -46,6 +46,14 @@ } //===----------------------------------------------------------------------===// +// EHTerminatorInst Class +//===----------------------------------------------------------------------===// + +// Out of line virtual method, so the vtable, etc has a home. +EHTerminatorInst::~EHTerminatorInst() { +} + +//===----------------------------------------------------------------------===// // UnaryInstruction Class //===----------------------------------------------------------------------===// @@ -538,10 +546,10 @@ } InvokeInst::InvokeInst(const InvokeInst &II) - : TerminatorInst(II.getType(), Instruction::Invoke, - OperandTraits::op_end(this) - - II.getNumOperands(), - II.getNumOperands()), + : EHTerminatorInst(II.getType(), Instruction::EH_Invoke, + OperandTraits::op_end(this) - + II.getNumOperands(), + II.getNumOperands()), AttributeList(II.AttributeList), FTy(II.FTy) { setCallingConv(II.getCallingConv()); std::copy(II.op_begin(), II.op_end(), op_begin()); @@ -559,6 +567,8 @@ void InvokeInst::setSuccessorV(unsigned idx, BasicBlock *B) { return setSuccessor(idx, B); } +BasicBlock *InvokeInst::getUnwindDestV() const { return getUnwindDest(); } +void InvokeInst::setUnwindDestV(BasicBlock *B) { return setUnwindDest(B); } bool InvokeInst::hasFnAttrImpl(Attribute::AttrKind A) const { if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) @@ -661,20 +671,22 @@ //===----------------------------------------------------------------------===// ResumeInst::ResumeInst(const ResumeInst &RI) - : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Resume, - OperandTraits::op_begin(this), 1) { + : EHTerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::EH_Resume, + OperandTraits::op_begin(this), 1) { Op<0>() = RI.Op<0>(); } ResumeInst::ResumeInst(Value *Exn, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume, - OperandTraits::op_begin(this), 1, InsertBefore) { + : EHTerminatorInst( + Type::getVoidTy(Exn->getContext()), Instruction::EH_Resume, + OperandTraits::op_begin(this), 1, InsertBefore) { Op<0>() = Exn; } ResumeInst::ResumeInst(Value *Exn, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume, - OperandTraits::op_begin(this), 1, InsertAtEnd) { + : EHTerminatorInst( + Type::getVoidTy(Exn->getContext()), Instruction::EH_Resume, + OperandTraits::op_begin(this), 1, InsertAtEnd) { Op<0>() = Exn; } @@ -690,15 +702,22 @@ llvm_unreachable("ResumeInst has no successors!"); } +BasicBlock *ResumeInst::getUnwindDestV() const { + llvm_unreachable("ResumeInst has no successors!"); +} +void ResumeInst::setUnwindDestV(BasicBlock *B) { + llvm_unreachable("ResumeInst has no successors!"); +} + //===----------------------------------------------------------------------===// // CleanupEndPadInst Implementation //===----------------------------------------------------------------------===// CleanupEndPadInst::CleanupEndPadInst(const CleanupEndPadInst &CEPI) - : TerminatorInst(CEPI.getType(), Instruction::CleanupEndPad, - OperandTraits::op_end(this) - - CEPI.getNumOperands(), - CEPI.getNumOperands()) { + : EHTerminatorInst(CEPI.getType(), Instruction::EH_CleanupEndPad, + OperandTraits::op_end(this) - + CEPI.getNumOperands(), + CEPI.getNumOperands()) { setInstructionSubclassData(CEPI.getSubclassDataFromInstruction()); setCleanupPad(CEPI.getCleanupPad()); if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) @@ -716,20 +735,20 @@ CleanupEndPadInst::CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, unsigned Values, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), - Instruction::CleanupEndPad, - OperandTraits::op_end(this) - Values, - Values, InsertBefore) { + : EHTerminatorInst(Type::getVoidTy(CleanupPad->getContext()), + Instruction::EH_CleanupEndPad, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { init(CleanupPad, UnwindBB); } CleanupEndPadInst::CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, unsigned Values, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), - Instruction::CleanupEndPad, - OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { + : EHTerminatorInst(Type::getVoidTy(CleanupPad->getContext()), + Instruction::EH_CleanupEndPad, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { init(CleanupPad, UnwindBB); } @@ -744,16 +763,22 @@ assert(Idx == 0); setUnwindDest(B); } +BasicBlock *CleanupEndPadInst::getUnwindDestV() const { + return getUnwindDest(); +} +void CleanupEndPadInst::setUnwindDestV(BasicBlock *B) { + return setUnwindDest(B); +} //===----------------------------------------------------------------------===// // CleanupReturnInst Implementation //===----------------------------------------------------------------------===// CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI) - : TerminatorInst(CRI.getType(), Instruction::CleanupRet, - OperandTraits::op_end(this) - - CRI.getNumOperands(), - CRI.getNumOperands()) { + : EHTerminatorInst(CRI.getType(), Instruction::EH_CleanupRet, + OperandTraits::op_end(this) - + CRI.getNumOperands(), + CRI.getNumOperands()) { setInstructionSubclassData(CRI.getSubclassDataFromInstruction()); Op<-1>() = CRI.Op<-1>(); if (CRI.hasUnwindDest()) @@ -772,20 +797,20 @@ CleanupReturnInst::CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, unsigned Values, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), - Instruction::CleanupRet, - OperandTraits::op_end(this) - Values, - Values, InsertBefore) { + : EHTerminatorInst(Type::getVoidTy(CleanupPad->getContext()), + Instruction::EH_CleanupRet, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { init(CleanupPad, UnwindBB); } CleanupReturnInst::CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, unsigned Values, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), - Instruction::CleanupRet, - OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { + : EHTerminatorInst(Type::getVoidTy(CleanupPad->getContext()), + Instruction::EH_CleanupRet, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { init(CleanupPad, UnwindBB); } @@ -800,16 +825,22 @@ assert(Idx == 0); setUnwindDest(B); } +BasicBlock *CleanupReturnInst::getUnwindDestV() const { + return getUnwindDest(); +} +void CleanupReturnInst::setUnwindDestV(BasicBlock *B) { + return setUnwindDest(B); +} //===----------------------------------------------------------------------===// // CatchEndPadInst Implementation //===----------------------------------------------------------------------===// CatchEndPadInst::CatchEndPadInst(const CatchEndPadInst &CRI) - : TerminatorInst(CRI.getType(), Instruction::CatchEndPad, - OperandTraits::op_end(this) - - CRI.getNumOperands(), - CRI.getNumOperands()) { + : EHTerminatorInst(CRI.getType(), Instruction::EH_CatchEndPad, + OperandTraits::op_end(this) - + CRI.getNumOperands(), + CRI.getNumOperands()) { setInstructionSubclassData(CRI.getSubclassDataFromInstruction()); if (BasicBlock *UnwindDest = CRI.getUnwindDest()) setUnwindDest(UnwindDest); @@ -824,17 +855,17 @@ CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad, - OperandTraits::op_end(this) - Values, - Values, InsertBefore) { + : EHTerminatorInst(Type::getVoidTy(C), Instruction::EH_CatchEndPad, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { init(UnwindBB); } CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad, - OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { + : EHTerminatorInst(Type::getVoidTy(C), Instruction::EH_CatchEndPad, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { init(UnwindBB); } @@ -849,6 +880,8 @@ assert(Idx == 0); setUnwindDest(B); } +BasicBlock *CatchEndPadInst::getUnwindDestV() const { return getUnwindDest(); } +void CatchEndPadInst::setUnwindDestV(BasicBlock *B) { return setUnwindDest(B); } //===----------------------------------------------------------------------===// // CatchReturnInst Implementation @@ -859,25 +892,26 @@ } CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI) - : TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet, - OperandTraits::op_begin(this), 2) { + : EHTerminatorInst(Type::getVoidTy(CRI.getContext()), + Instruction::EH_CatchRet, + OperandTraits::op_begin(this), 2) { Op<0>() = CRI.Op<0>(); Op<1>() = CRI.Op<1>(); } CatchReturnInst::CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, - OperandTraits::op_begin(this), 2, - InsertBefore) { + : EHTerminatorInst( + Type::getVoidTy(BB->getContext()), Instruction::EH_CatchRet, + OperandTraits::op_begin(this), 2, InsertBefore) { init(CatchPad, BB); } CatchReturnInst::CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, - OperandTraits::op_begin(this), 2, - InsertAtEnd) { + : EHTerminatorInst( + Type::getVoidTy(BB->getContext()), Instruction::EH_CatchRet, + OperandTraits::op_begin(this), 2, InsertAtEnd) { init(CatchPad, BB); } @@ -892,6 +926,12 @@ assert(Idx < getNumSuccessors() && "Successor # out of range for catchret!"); setSuccessor(B); } +BasicBlock *CatchReturnInst::getUnwindDestV() const { + llvm_unreachable("CatchReturnInst does not have an unwind dest!"); +} +void CatchReturnInst::setUnwindDestV(BasicBlock *B) { + llvm_unreachable("CatchReturnInst does not have an unwind dest!"); +} //===----------------------------------------------------------------------===// // CatchPadInst Implementation @@ -906,30 +946,30 @@ } CatchPadInst::CatchPadInst(const CatchPadInst &CPI) - : TerminatorInst(CPI.getType(), Instruction::CatchPad, - OperandTraits::op_end(this) - - CPI.getNumOperands(), - CPI.getNumOperands()) { + : EHTerminatorInst(CPI.getType(), Instruction::EH_CatchPad, + OperandTraits::op_end(this) - + CPI.getNumOperands(), + CPI.getNumOperands()) { std::copy(CPI.op_begin(), CPI.op_end(), op_begin()); } 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) { + : EHTerminatorInst(Type::getTokenTy(IfNormal->getContext()), + Instruction::EH_CatchPad, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { init(IfNormal, IfException, Args, NameStr); } 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) { + : EHTerminatorInst(Type::getTokenTy(IfNormal->getContext()), + Instruction::EH_CatchPad, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { init(IfNormal, IfException, Args, NameStr); } @@ -942,6 +982,8 @@ void CatchPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) { return setSuccessor(Idx, B); } +BasicBlock *CatchPadInst::getUnwindDestV() const { return getUnwindDest(); } +void CatchPadInst::setUnwindDestV(BasicBlock *B) { return setUnwindDest(B); } //===----------------------------------------------------------------------===// // TerminatePadInst Implementation @@ -955,10 +997,10 @@ } TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI) - : TerminatorInst(TPI.getType(), Instruction::TerminatePad, - OperandTraits::op_end(this) - - TPI.getNumOperands(), - TPI.getNumOperands()) { + : EHTerminatorInst(TPI.getType(), Instruction::EH_TerminatePad, + OperandTraits::op_end(this) - + TPI.getNumOperands(), + TPI.getNumOperands()) { setInstructionSubclassData(TPI.getSubclassDataFromInstruction()); std::copy(TPI.op_begin(), TPI.op_end(), op_begin()); } @@ -966,18 +1008,18 @@ TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB, ArrayRef Args, unsigned Values, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad, - OperandTraits::op_end(this) - Values, - Values, InsertBefore) { + : EHTerminatorInst(Type::getVoidTy(C), Instruction::EH_TerminatePad, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { init(BB, Args); } TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB, ArrayRef Args, unsigned Values, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad, - OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { + : EHTerminatorInst(Type::getVoidTy(C), Instruction::EH_TerminatePad, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { init(BB, Args); } @@ -992,6 +1034,10 @@ assert(Idx == 0); return setUnwindDest(B); } +BasicBlock *TerminatePadInst::getUnwindDestV() const { return getUnwindDest(); } +void TerminatePadInst::setUnwindDestV(BasicBlock *B) { + return setUnwindDest(B); +} //===----------------------------------------------------------------------===// // CleanupPadInst Implementation Index: lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- lib/Transforms/Scalar/JumpThreading.cpp +++ lib/Transforms/Scalar/JumpThreading.cpp @@ -677,7 +677,7 @@ // predecessors of our predecessor block. if (BasicBlock *SinglePred = BB->getSinglePredecessor()) { const TerminatorInst *TI = SinglePred->getTerminator(); - if (!TI->isExceptional() && TI->getNumSuccessors() == 1 && + if (!isa(TI) && TI->getNumSuccessors() == 1 && SinglePred != BB && !hasAddressTakenAndUsed(BB)) { // If SinglePred was a loop header, BB becomes one. if (LoopHeaders.erase(SinglePred)) Index: lib/Transforms/Scalar/SCCP.cpp =================================================================== --- lib/Transforms/Scalar/SCCP.cpp +++ lib/Transforms/Scalar/SCCP.cpp @@ -546,7 +546,7 @@ } // Unwinding instructions successors are always executable. - if (TI.isExceptional()) { + if (isa(&TI)) { Succs.assign(TI.getNumSuccessors(), true); return; } @@ -612,7 +612,7 @@ } // Unwinding instructions successors are always executable. - if (TI->isExceptional()) + if (isa(TI)) return true; if (SwitchInst *SI = dyn_cast(TI)) { Index: lib/Transforms/Utils/BasicBlockUtils.cpp =================================================================== --- lib/Transforms/Utils/BasicBlockUtils.cpp +++ lib/Transforms/Utils/BasicBlockUtils.cpp @@ -118,7 +118,7 @@ // Don't break self-loops. if (PredBB == BB) return false; // Don't break unwinding instructions. - if (PredBB->getTerminator()->isExceptional()) + if (isa(PredBB->getTerminator())) return false; succ_iterator SI(succ_begin(PredBB)), SE(succ_end(PredBB)); Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -3034,20 +3034,8 @@ if (UnwindDest == nullptr) { removeUnwindEdge(PredBB); } else { - // If the predecessor did not terminate with an invoke instruction, it - // must be some variety of EH pad. TerminatorInst *TI = PredBB->getTerminator(); - // FIXME: Introducing an EH terminator base class would simplify this. - if (auto *II = dyn_cast(TI)) - II->setUnwindDest(UnwindDest); - else if (auto *CRI = dyn_cast(TI)) - CRI->setUnwindDest(UnwindDest); - else if (auto *CEP = dyn_cast(TI)) - CEP->setUnwindDest(UnwindDest); - else if (auto *TPI = dyn_cast(TI)) - TPI->setUnwindDest(UnwindDest); - else - llvm_unreachable("Unexpected predecessor to cleanup pad."); + cast(TI)->setUnwindDest(UnwindDest); } }