X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FIR%2FInstructions.h;h=cc6c25974cd5422ed48a6691a033783ea3fab7aa;hp=825f4cace8850ebe0bd8c91ccaa8b54468bed01a;hb=53395c948459c88257c8ae57b65831fab51e4646;hpb=d4cdf1962b2242fb155ee2203199dd043725e7e1 diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 825f4cace88..cc6c25974cd 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" @@ -158,6 +159,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -166,7 +168,6 @@ private: } }; - //===----------------------------------------------------------------------===// // LoadInst Class //===----------------------------------------------------------------------===// @@ -176,6 +177,7 @@ private: /// class LoadInst : public UnaryInstruction { void AssertOK(); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -226,6 +228,14 @@ public: LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, BasicBlock *InsertAtEnd); + bool getHasSubsequentAcqlRMW() { + return hasSubsequentAcqlRMW_; + } + + void setHasSubsequentAcqlRMW(bool val) { + hasSubsequentAcqlRMW_ = val; + } + /// isVolatile - Return true if this is a load from a volatile memory /// location. /// @@ -290,7 +300,6 @@ public: return getPointerOperand()->getType()->getPointerAddressSpace(); } - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Load; @@ -298,14 +307,16 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { Instruction::setInstructionSubclassData(D); } -}; + bool hasSubsequentAcqlRMW_; +}; //===----------------------------------------------------------------------===// // StoreInst Class @@ -316,6 +327,7 @@ private: class StoreInst : public Instruction { void *operator new(size_t, unsigned) = delete; void AssertOK(); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -344,7 +356,6 @@ public: SynchronizationScope SynchScope, BasicBlock *InsertAtEnd); - /// isVolatile - Return true if this is a store to a volatile memory /// location. /// @@ -422,6 +433,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -445,6 +457,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) class FenceInst : public Instruction { void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -496,6 +509,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -517,6 +531,7 @@ class AtomicCmpXchgInst : public Instruction { void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -648,6 +663,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -673,6 +689,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// class AtomicRMWInst : public Instruction { void *operator new(size_t, unsigned) = delete; + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -795,6 +812,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: void Init(BinOp Operation, Value *Ptr, Value *Val, AtomicOrdering Ordering, SynchronizationScope SynchScope); @@ -831,6 +849,8 @@ class GetElementPtrInst : public Instruction { Type *SourceElementType; Type *ResultElementType; + void anchor() override; + GetElementPtrInst(const GetElementPtrInst &GEPI); void init(Value *Ptr, ArrayRef IdxList, const Twine &NameStr); @@ -1078,10 +1098,8 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, init(Ptr, IdxList, NameStr); } - DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) - //===----------------------------------------------------------------------===// // ICmpInst Class //===----------------------------------------------------------------------===// @@ -1091,6 +1109,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) /// must be identical types. /// \brief Represent an integer comparison operator. class ICmpInst: public CmpInst { + void anchor() override; + void AssertOK() { assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE && getPredicate() <= CmpInst::LAST_ICMP_PREDICATE && @@ -1226,7 +1246,6 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } - }; //===----------------------------------------------------------------------===// @@ -1350,62 +1369,102 @@ public: /// field to indicate whether or not this is a tail call. The rest of the bits /// hold the calling convention of the call. /// -class CallInst : public Instruction { +class CallInst : public Instruction, + public OperandBundleUser { AttributeSet AttributeList; ///< parameter attributes for call FunctionType *FTy; CallInst(const CallInst &CI); - void init(Value *Func, ArrayRef Args, const Twine &NameStr) { + void init(Value *Func, ArrayRef Args, + ArrayRef Bundles, const Twine &NameStr) { init(cast( cast(Func->getType())->getElementType()), - Func, Args, NameStr); + Func, Args, Bundles, NameStr); } void init(FunctionType *FTy, Value *Func, ArrayRef Args, - const Twine &NameStr); + ArrayRef Bundles, const Twine &NameStr); void init(Value *Func, const Twine &NameStr); /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr, Instruction *InsertBefore); - inline CallInst(Value *Func, ArrayRef Args, const Twine &NameStr, + ArrayRef Bundles, const Twine &NameStr, + Instruction *InsertBefore); + inline CallInst(Value *Func, ArrayRef Args, + ArrayRef Bundles, const Twine &NameStr, Instruction *InsertBefore) : CallInst(cast( cast(Func->getType())->getElementType()), - Func, Args, NameStr, InsertBefore) {} + Func, Args, Bundles, NameStr, InsertBefore) {} + + inline CallInst(Value *Func, ArrayRef Args, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(Func, Args, None, NameStr, InsertBefore) {} /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments inline CallInst(Value *Func, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd); + ArrayRef Bundles, const Twine &NameStr, + BasicBlock *InsertAtEnd); explicit CallInst(Value *F, const Twine &NameStr, Instruction *InsertBefore); CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); + + friend class OperandBundleUser; + bool hasDescriptor() const { return HasDescriptor; } + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; CallInst *cloneImpl() const; public: - static CallInst *Create(Value *Func, - ArrayRef Args, + static CallInst *Create(Value *Func, ArrayRef Args, + ArrayRef Bundles = None, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { return Create(cast( cast(Func->getType())->getElementType()), - Func, Args, NameStr, InsertBefore); + Func, Args, Bundles, NameStr, InsertBefore); + } + static CallInst *Create(Value *Func, ArrayRef Args, + const Twine &NameStr, + Instruction *InsertBefore = nullptr) { + return Create(cast( + cast(Func->getType())->getElementType()), + Func, Args, None, NameStr, InsertBefore); } static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr = "", + const Twine &NameStr, Instruction *InsertBefore = nullptr) { return new (unsigned(Args.size() + 1)) - CallInst(Ty, Func, Args, NameStr, InsertBefore); + CallInst(Ty, Func, Args, None, NameStr, InsertBefore); + } + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, + ArrayRef Bundles = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + const unsigned TotalOps = + unsigned(Args.size()) + CountBundleInputs(Bundles) + 1; + const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (TotalOps, DescriptorBytes) + CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore); } - static CallInst *Create(Value *Func, - ArrayRef Args, + static CallInst *Create(Value *Func, ArrayRef Args, + ArrayRef Bundles, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertAtEnd); + const unsigned TotalOps = + unsigned(Args.size()) + CountBundleInputs(Bundles) + 1; + const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (TotalOps, DescriptorBytes) + CallInst(Func, Args, Bundles, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *Func, ArrayRef Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new (unsigned(Args.size() + 1)) + CallInst(Func, Args, None, NameStr, InsertAtEnd); } static CallInst *Create(Value *F, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { @@ -1415,6 +1474,16 @@ public: BasicBlock *InsertAtEnd) { return new(1) CallInst(F, NameStr, InsertAtEnd); } + + /// \brief Create a clone of \p CI with a different set of operand bundles and + /// insert it before \p InsertPt. + /// + /// The returned call instruction is identical \p CI in every way except that + /// the operand bundles for the new instruction are set to the operand bundles + /// in \p Bundles. + static CallInst *Create(CallInst *CI, ArrayRef Bundles, + Instruction *InsertPt = nullptr); + /// CreateMalloc - Generate the IR for a call to malloc: /// 1. Compute the malloc call's argument as the specified type's size, /// possibly multiplied by the array size if the array size is not @@ -1445,16 +1514,21 @@ public: } // Note that 'musttail' implies 'tail'. - enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; + enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2, + TCK_NoTail = 3 }; TailCallKind getTailCallKind() const { return TailCallKind(getSubclassDataFromInstruction() & 3); } bool isTailCall() const { - return (getSubclassDataFromInstruction() & 3) != TCK_None; + unsigned Kind = getSubclassDataFromInstruction() & 3; + return Kind == TCK_Tail || Kind == TCK_MustTail; } bool isMustTailCall() const { return (getSubclassDataFromInstruction() & 3) == TCK_MustTail; } + bool isNoTailCall() const { + return (getSubclassDataFromInstruction() & 3) == TCK_NoTail; + } void setTailCall(bool isTC = true) { setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | unsigned(isTC ? TCK_Tail : TCK_None)); @@ -1469,7 +1543,9 @@ public: /// getNumArgOperands - Return the number of call arguments. /// - unsigned getNumArgOperands() const { return getNumOperands() - 1; } + unsigned getNumArgOperands() const { + return getNumOperands() - getNumTotalBundleOperands() - 1; + } /// getArgOperand/setArgOperand - Return/set the i-th call argument. /// @@ -1482,16 +1558,32 @@ public: setOperand(i, v); } - /// arg_operands - iteration adapter for range-for loops. + /// \brief Return the iterator pointing to the beginning of the argument list. + op_iterator arg_begin() { return op_begin(); } + + /// \brief Return the iterator pointing to the end of the argument list. + op_iterator arg_end() { + // [ call args ], [ operand bundles ], callee + return op_end() - getNumTotalBundleOperands() - 1; + }; + + /// \brief Iteration adapter for range-for loops. iterator_range arg_operands() { - // The last operand in the op list is the callee - it's not one of the args - // so we don't want to iterate over it. - return iterator_range(op_begin(), op_end() - 1); + return make_range(arg_begin(), arg_end()); } - /// arg_operands - iteration adapter for range-for loops. + /// \brief Return the iterator pointing to the beginning of the argument list. + const_op_iterator arg_begin() const { return op_begin(); } + + /// \brief Return the iterator pointing to the end of the argument list. + const_op_iterator arg_end() const { + // [ call args ], [ operand bundles ], callee + return op_end() - getNumTotalBundleOperands() - 1; + }; + + /// \brief Iteration adapter for range-for loops. iterator_range arg_operands() const { - return iterator_range(op_begin(), op_end() - 1); + return make_range(arg_begin(), arg_end()); } /// \brief Wrappers for getting the \c Use of a call argument. @@ -1510,8 +1602,10 @@ public: return static_cast(getSubclassDataFromInstruction() >> 2); } void setCallingConv(CallingConv::ID CC) { + auto ID = static_cast(CC); + assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | - (static_cast(CC) << 2)); + (ID << 2)); } /// getAttributes - Return the parameter attributes for this call. @@ -1553,6 +1647,21 @@ public: /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; + /// \brief Return true if the data operand at index \p i has the attribute \p + /// A. + /// + /// Data operands include call arguments and values used in operand bundles, + /// but does not include the callee operand. This routine dispatches to the + /// underlying AttributeList or the OperandBundleUser as appropriate. + /// + /// The index \p i is interpreted as + /// + /// \p i == Attribute::ReturnIndex -> the return value + /// \p i in [1, arg_size + 1) -> argument number (\p i - 1) + /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index + /// (\p i - 1) in the operand list. + bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const; + /// \brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeList.getParamAlignment(i); @@ -1569,7 +1678,14 @@ public: uint64_t getDereferenceableOrNullBytes(unsigned i) const { return AttributeList.getDereferenceableOrNullBytes(i); } - + + /// @brief Determine if the parameter or return value is marked with NoAlias + /// attribute. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + return AttributeList.hasAttribute(n, Attribute::NoAlias); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -1643,6 +1759,9 @@ public: /// \brief Determine if the call returns a structure through first /// pointer argument. bool hasStructRetAttr() const { + if (getNumArgOperands() == 0) + return false; + // Be friendly and also check the callee. return paramHasAttr(1, Attribute::StructRet); } @@ -1694,6 +1813,12 @@ private: template bool hasFnAttrImpl(AttrKind A) const { if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) return true; + + // Operand bundles override attributes on the called function, but don't + // override attributes directly present on the call instruction. + if (isFnAttrDisallowedByOpBundle(A)) + return false; + if (const Function *F = getCalledFunction()) return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, A); return false; @@ -1711,24 +1836,28 @@ struct OperandTraits : public VariadicOperandTraits { }; CallInst::CallInst(Value *Func, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits::op_end(this) - (Args.size() + 1), - unsigned(Args.size() + 1), InsertAtEnd) { - init(Func, Args, NameStr); + ArrayRef Bundles, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction( + cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, OperandTraits::op_end(this) - + (Args.size() + CountBundleInputs(Bundles) + 1), + unsigned(Args.size() + CountBundleInputs(Bundles) + 1), InsertAtEnd) { + init(Func, Args, Bundles, NameStr); } CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr, Instruction *InsertBefore) + ArrayRef Bundles, const Twine &NameStr, + Instruction *InsertBefore) : Instruction(Ty->getReturnType(), Instruction::Call, - OperandTraits::op_end(this) - (Args.size() + 1), - unsigned(Args.size() + 1), InsertBefore) { - init(Ty, Func, Args, NameStr); + OperandTraits::op_end(this) - + (Args.size() + CountBundleInputs(Bundles) + 1), + unsigned(Args.size() + CountBundleInputs(Bundles) + 1), + InsertBefore) { + init(Ty, Func, Args, Bundles, NameStr); } - // Note: if you get compile errors about private methods then // please update your code to use the high-level operand // interfaces. See line 943 above. @@ -1762,6 +1891,7 @@ class SelectInst : public Instruction { init(C, S1, S2); setName(NameStr); } + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -1862,6 +1992,7 @@ class ExtractElementInst : public Instruction { Instruction *InsertBefore = nullptr); ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -1892,7 +2023,6 @@ public: return cast(getVectorOperand()->getType()); } - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2038,7 +2168,6 @@ public: return Mask; } - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ShuffleVector; @@ -2113,7 +2242,7 @@ public: inline idx_iterator idx_begin() const { return Indices.begin(); } inline idx_iterator idx_end() const { return Indices.end(); } inline iterator_range indices() const { - return iterator_range(idx_begin(), idx_end()); + return make_range(idx_begin(), idx_end()); } Value *getAggregateOperand() { @@ -2164,7 +2293,6 @@ ExtractValueInst::ExtractValueInst(Value *Agg, init(Idxs, NameStr); } - //===----------------------------------------------------------------------===// // InsertValueInst Class //===----------------------------------------------------------------------===// @@ -2231,7 +2359,7 @@ public: inline idx_iterator idx_begin() const { return Indices.begin(); } inline idx_iterator idx_end() const { return Indices.end(); } inline iterator_range indices() const { - return iterator_range(idx_begin(), idx_end()); + return make_range(idx_begin(), idx_end()); } Value *getAggregateOperand() { @@ -2312,6 +2440,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { + void anchor() override; + void *operator new(size_t, unsigned) = delete; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. @@ -2337,6 +2467,7 @@ class PHINode : public Instruction { setName(NameStr); allocHungoffUses(ReservedSpace); } + protected: // allocHungoffUses - this is more complicated than the generic // User::allocHungoffUses, because we have to allocate Uses for the incoming @@ -2391,6 +2522,14 @@ public: return block_begin() + getNumOperands(); } + iterator_range blocks() { + return make_range(block_begin(), block_end()); + } + + iterator_range blocks() const { + return make_range(block_begin(), block_end()); + } + op_range incoming_values() { return operands(); } const_op_range incoming_values() const { return operands(); } @@ -2497,7 +2636,8 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } - private: + +private: void growOperands(); }; @@ -2524,8 +2664,10 @@ class LandingPadInst : public Instruction { /// the number actually in use. unsigned ReservedSpace; LandingPadInst(const LandingPadInst &LP); + public: enum ClauseType { Catch, Filter }; + private: void *operator new(size_t, unsigned) = delete; // Allocate space for exactly zero operands. @@ -2636,6 +2778,7 @@ private: Instruction *InsertBefore = nullptr); ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -2672,7 +2815,8 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } - private: + +private: BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned idx, BasicBlock *B) override; @@ -2711,6 +2855,7 @@ class BranchInst : public TerminatorInst { BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, BasicBlock *InsertAtEnd); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -2775,6 +2920,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; @@ -2821,25 +2967,23 @@ class SwitchInst : public TerminatorInst { /// constructor also autoinserts at the end of the specified BasicBlock. SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, BasicBlock *InsertAtEnd); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; SwitchInst *cloneImpl() const; public: - // -2 static const unsigned DefaultPseudoIndex = static_cast(~0L-1); template class CaseIteratorT { protected: - SwitchInstTy *SI; unsigned Index; public: - typedef CaseIteratorT Self; /// Initializes case iterator for given SwitchInst and for given @@ -3000,12 +3144,12 @@ public: /// cases - iteration adapter for range-for loops. iterator_range cases() { - return iterator_range(case_begin(), case_end()); + return make_range(case_begin(), case_end()); } /// cases - iteration adapter for range-for loops. iterator_range cases() const { - return iterator_range(case_begin(), case_end()); + return make_range(case_begin(), case_end()); } /// Returns an iterator that points to the default case. @@ -3083,6 +3227,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; @@ -3095,7 +3240,6 @@ struct OperandTraits : public HungoffOperandTraits<2> { DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) - //===----------------------------------------------------------------------===// // IndirectBrInst Class //===----------------------------------------------------------------------===// @@ -3128,6 +3272,7 @@ class IndirectBrInst : public TerminatorInst { /// here to make memory allocation more efficient. This constructor also /// autoinserts at the end of the specified BasicBlock. IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -3151,7 +3296,6 @@ public: const Value *getAddress() const { return getOperand(0); } void setAddress(Value *V) { setOperand(0, V); } - /// getNumDestinations - return the number of possible destinations in this /// indirectbr instruction. unsigned getNumDestinations() const { return getNumOperands()-1; } @@ -3183,6 +3327,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; @@ -3195,7 +3340,6 @@ struct OperandTraits : public HungoffOperandTraits<1> { DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) - //===----------------------------------------------------------------------===// // InvokeInst Class //===----------------------------------------------------------------------===// @@ -3203,72 +3347,123 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// InvokeInst - Invoke instruction. The SubclassData field is used to hold the /// calling convention of the call. /// -class InvokeInst : public TerminatorInst { +class InvokeInst : public TerminatorInst, + public OperandBundleUser { AttributeSet AttributeList; FunctionType *FTy; InvokeInst(const InvokeInst &BI); void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, const Twine &NameStr) { + ArrayRef Args, ArrayRef Bundles, + const Twine &NameStr) { init(cast( cast(Func->getType())->getElementType()), - Func, IfNormal, IfException, Args, NameStr); + Func, IfNormal, IfException, Args, Bundles, NameStr); } void init(FunctionType *FTy, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, - const Twine &NameStr); + ArrayRef Bundles, const Twine &NameStr); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore) + ArrayRef Args, ArrayRef Bundles, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore) : InvokeInst(cast( cast(Func->getType())->getElementType()), - Func, IfNormal, IfException, Args, Values, NameStr, + Func, IfNormal, IfException, Args, Bundles, Values, NameStr, InsertBefore) {} inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore); + ArrayRef Bundles, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, unsigned Values, - const Twine &NameStr, BasicBlock *InsertAtEnd); + ArrayRef Args, ArrayRef Bundles, + unsigned Values, const Twine &NameStr, + BasicBlock *InsertAtEnd); + + friend class OperandBundleUser; + bool hasDescriptor() const { return HasDescriptor; } + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; InvokeInst *cloneImpl() const; public: - static InvokeInst *Create(Value *Func, - BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, const Twine &NameStr = "", + static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + const Twine &NameStr, Instruction *InsertBefore = nullptr) { return Create(cast( cast(Func->getType())->getElementType()), - Func, IfNormal, IfException, Args, NameStr, InsertBefore); + Func, IfNormal, IfException, Args, None, NameStr, + InsertBefore); } - static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, + ArrayRef Bundles = None, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { + return Create(cast( + cast(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, Bundles, NameStr, + InsertBefore); + } + static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + const Twine &NameStr, + Instruction *InsertBefore = nullptr) { unsigned Values = unsigned(Args.size()) + 3; - return new (Values) InvokeInst(Ty, Func, IfNormal, IfException, Args, + return new (Values) InvokeInst(Ty, Func, IfNormal, IfException, Args, None, Values, NameStr, InsertBefore); } + static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + ArrayRef Bundles = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + unsigned Values = unsigned(Args.size()) + CountBundleInputs(Bundles) + 3; + unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (Values, DescriptorBytes) + InvokeInst(Ty, Func, IfNormal, IfException, Args, Bundles, Values, + NameStr, InsertBefore); + } static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values = unsigned(Args.size()) + 3; - return new(Values) InvokeInst(Func, IfNormal, IfException, Args, - Values, NameStr, InsertAtEnd); + return new (Values) InvokeInst(Func, IfNormal, IfException, Args, None, + Values, NameStr, InsertAtEnd); + } + static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + ArrayRef Bundles, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + unsigned Values = unsigned(Args.size()) + CountBundleInputs(Bundles) + 3; + unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (Values, DescriptorBytes) + InvokeInst(Func, IfNormal, IfException, Args, Bundles, Values, NameStr, + InsertAtEnd); } + /// \brief Create a clone of \p II with a different set of operand bundles and + /// insert it before \p InsertPt. + /// + /// The returned invoke instruction is identical to \p II in every way except + /// that the operand bundles for the new instruction are set to the operand + /// bundles in \p Bundles. + static InvokeInst *Create(InvokeInst *II, ArrayRef Bundles, + Instruction *InsertPt = nullptr); + /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -3281,7 +3476,9 @@ public: /// getNumArgOperands - Return the number of invoke arguments. /// - unsigned getNumArgOperands() const { return getNumOperands() - 3; } + unsigned getNumArgOperands() const { + return getNumOperands() - getNumTotalBundleOperands() - 3; + } /// getArgOperand/setArgOperand - Return/set the i-th invoke argument. /// @@ -3294,14 +3491,32 @@ public: setOperand(i, v); } - /// arg_operands - iteration adapter for range-for loops. + /// \brief Return the iterator pointing to the beginning of the argument list. + op_iterator arg_begin() { return op_begin(); } + + /// \brief Return the iterator pointing to the end of the argument list. + op_iterator arg_end() { + // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee + return op_end() - getNumTotalBundleOperands() - 3; + }; + + /// \brief Iteration adapter for range-for loops. iterator_range arg_operands() { - return iterator_range(op_begin(), op_end() - 3); + return make_range(arg_begin(), arg_end()); } - /// arg_operands - iteration adapter for range-for loops. + /// \brief Return the iterator pointing to the beginning of the argument list. + const_op_iterator arg_begin() const { return op_begin(); } + + /// \brief Return the iterator pointing to the end of the argument list. + const_op_iterator arg_end() const { + // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee + return op_end() - getNumTotalBundleOperands() - 3; + }; + + /// \brief Iteration adapter for range-for loops. iterator_range arg_operands() const { - return iterator_range(op_begin(), op_end() - 3); + return make_range(arg_begin(), arg_end()); } /// \brief Wrappers for getting the \c Use of a invoke argument. @@ -3320,7 +3535,9 @@ public: return static_cast(getSubclassDataFromInstruction()); } void setCallingConv(CallingConv::ID CC) { - setInstructionSubclassData(static_cast(CC)); + auto ID = static_cast(CC); + assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); + setInstructionSubclassData(ID); } /// getAttributes - Return the parameter attributes for this invoke. @@ -3351,9 +3568,30 @@ public: return hasFnAttrImpl(A); } + /// \brief Determine whether this call has the given attribute. + bool hasFnAttr(StringRef A) const { + return hasFnAttrImpl(A); + } + /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; + /// \brief Return true if the data operand at index \p i has the attribute \p + /// A. + /// + /// Data operands include invoke arguments and values used in operand bundles, + /// but does not include the invokee operand, or the two successor blocks. + /// This routine dispatches to the underlying AttributeList or the + /// OperandBundleUser as appropriate. + /// + /// The index \p i is interpreted as + /// + /// \p i == Attribute::ReturnIndex -> the return value + /// \p i in [1, arg_size + 1) -> argument number (\p i - 1) + /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index + /// (\p i - 1) in the operand list. + bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const; + /// \brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeList.getParamAlignment(i); @@ -3364,13 +3602,20 @@ public: uint64_t getDereferenceableBytes(unsigned i) const { return AttributeList.getDereferenceableBytes(i); } - + /// \brief Extract the number of dereferenceable_or_null bytes for a call or /// parameter (0=unknown). uint64_t getDereferenceableOrNullBytes(unsigned i) const { return AttributeList.getDereferenceableOrNullBytes(i); } + /// @brief Determine if the parameter or return value is marked with NoAlias + /// attribute. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + return AttributeList.hasAttribute(n, Attribute::NoAlias); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -3432,6 +3677,9 @@ public: /// \brief Determine if the call returns a structure through first /// pointer argument. bool hasStructRetAttr() const { + if (getNumArgOperands() == 0) + return false; + // Be friendly and also check the callee. return paramHasAttr(1, Attribute::StructRet); } @@ -3509,7 +3757,19 @@ private: unsigned getNumSuccessorsV() const override; void setSuccessorV(unsigned idx, BasicBlock *B) override; - bool hasFnAttrImpl(Attribute::AttrKind A) const; + template bool hasFnAttrImpl(AttrKind A) const { + if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) + return true; + + // Operand bundles override attributes on the called function, but don't + // override attributes directly present on the invoke instruction. + if (isFnAttrDisallowedByOpBundle(A)) + return false; + + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, A); + return false; + } // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -3524,23 +3784,23 @@ struct OperandTraits : public VariadicOperandTraits { InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore) + ArrayRef Bundles, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore) : TerminatorInst(Ty->getReturnType(), Instruction::Invoke, OperandTraits::op_end(this) - Values, Values, InsertBefore) { - init(Ty, Func, IfNormal, IfException, Args, NameStr); + init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr); } -InvokeInst::InvokeInst(Value *Func, - BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, unsigned Values, +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) { - init(Func, IfNormal, IfException, Args, NameStr); + : TerminatorInst( + cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { + init(Func, IfNormal, IfException, Args, Bundles, NameStr); } DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) @@ -3557,6 +3817,7 @@ class ResumeInst : public TerminatorInst { explicit ResumeInst(Value *Exn, Instruction *InsertBefore=nullptr); ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -3585,6 +3846,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override; @@ -3599,356 +3861,268 @@ struct OperandTraits : DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) //===----------------------------------------------------------------------===// -// CatchEndPadInst Class +// CatchSwitchInst Class //===----------------------------------------------------------------------===// +class CatchSwitchInst : public TerminatorInst { + void *operator new(size_t, unsigned) = delete; + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + // Operand[0] = Outer scope + // Operand[1] = Unwind block destination + // Operand[n] = BasicBlock to go to on match + CatchSwitchInst(const CatchSwitchInst &CSI); + void init(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumReserved); + void growOperands(unsigned Size); + // allocate space for exactly zero operands + void *operator new(size_t s) { return User::operator new(s); } + /// CatchSwitchInst ctor - Create a new switch instruction, specifying a + /// default destination. The number of additional handlers can be specified + /// here to make memory allocation more efficient. + /// This constructor can also autoinsert before another instruction. + CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, + unsigned NumHandlers, const Twine &NameStr, + Instruction *InsertBefore); -class CatchEndPadInst : public TerminatorInst { -private: - CatchEndPadInst(const CatchEndPadInst &RI); - - void init(BasicBlock *UnwindBB); - CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values, - Instruction *InsertBefore = nullptr); - CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values, + /// CatchSwitchInst ctor - Create a new switch instruction, specifying a + /// default destination. The number of additional handlers can be specified + /// here to make memory allocation more efficient. + /// This constructor also autoinserts at the end of the specified BasicBlock. + CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, + unsigned NumHandlers, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; - CatchEndPadInst *cloneImpl() const; + CatchSwitchInst *cloneImpl() const; public: - static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB = nullptr, + static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest, + unsigned NumHandlers, + const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - unsigned Values = UnwindBB ? 1 : 0; - return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertBefore); + return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr, + InsertBefore); } - static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB, + static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest, + unsigned NumHandlers, const Twine &NameStr, BasicBlock *InsertAtEnd) { - unsigned Values = UnwindBB ? 1 : 0; - return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertAtEnd); + return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr, + InsertAtEnd); } /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + // Accessor Methods for CatchSwitch stmt + Value *getParentPad() const { return getOperand(0); } + void setParentPad(Value *ParentPad) { setOperand(0, ParentPad); } + + // Accessor Methods for CatchSwitch stmt bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; } bool unwindsToCaller() const { return !hasUnwindDest(); } - - /// Convenience accessor. Returns null if there is no return value. - unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } - BasicBlock *getUnwindDest() const { - return hasUnwindDest() ? cast(Op<-1>()) : nullptr; + if (hasUnwindDest()) + return cast(getOperand(1)); + return nullptr; } - void setUnwindDest(BasicBlock *NewDest) { - assert(NewDest); - Op<-1>() = NewDest; + void setUnwindDest(BasicBlock *UnwindDest) { + assert(UnwindDest); + assert(hasUnwindDest()); + setOperand(1, UnwindDest); } - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::CatchEndPad); - } - static inline bool classof(const Value *V) { - return isa(V) && classof(cast(V)); + /// getNumHandlers - return the number of 'handlers' in this catchswitch + /// instruction, except the default handler + unsigned getNumHandlers() const { + if (hasUnwindDest()) + return getNumOperands() - 2; + return getNumOperands() - 1; } 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); + static BasicBlock *handler_helper(Value *V) { return cast(V); } + static const BasicBlock *handler_helper(const Value *V) { + return cast(V); } -}; -template <> -struct OperandTraits - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchEndPadInst, Value) - -//===----------------------------------------------------------------------===// -// CatchPadInst Class -//===----------------------------------------------------------------------===// - -class CatchPadInst : public TerminatorInst { -private: - void init(BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, const Twine &NameStr); - - CatchPadInst(const CatchPadInst &CPI); +public: + typedef std::pointer_to_unary_function DerefFnTy; + typedef mapped_iterator handler_iterator; + typedef iterator_range handler_range; - 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. - friend class Instruction; - CatchPadInst *cloneImpl() const; + typedef std::pointer_to_unary_function + ConstDerefFnTy; + typedef mapped_iterator const_handler_iterator; + typedef iterator_range const_handler_range; -public: - 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(IfNormal, IfException, Args, Values, - NameStr, InsertBefore); - } - static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - unsigned Values = unsigned(Args.size()) + 2; - return new (Values) - CatchPadInst(IfNormal, IfException, Args, Values, NameStr, InsertAtEnd); + /// Returns an iterator that points to the first handler in CatchSwitchInst. + handler_iterator handler_begin() { + op_iterator It = op_begin() + 1; + if (hasUnwindDest()) + ++It; + return handler_iterator(It, DerefFnTy(handler_helper)); + } + /// Returns an iterator that points to the first handler in the + /// CatchSwitchInst. + const_handler_iterator handler_begin() const { + const_op_iterator It = op_begin() + 1; + if (hasUnwindDest()) + ++It; + return const_handler_iterator(It, ConstDerefFnTy(handler_helper)); } - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - /// getNumArgOperands - Return the number of catchpad arguments. - /// - unsigned getNumArgOperands() const { return getNumOperands() - 2; } - - /// getArgOperand/setArgOperand - Return/set the i-th catchpad argument. - /// - Value *getArgOperand(unsigned i) const { return getOperand(i); } - void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + /// Returns a read-only iterator that points one past the last + /// handler in the CatchSwitchInst. + handler_iterator handler_end() { + return handler_iterator(op_end(), DerefFnTy(handler_helper)); + } + /// Returns an iterator that points one past the last handler in the + /// CatchSwitchInst. + const_handler_iterator handler_end() const { + return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper)); + } - /// arg_operands - iteration adapter for range-for loops. - iterator_range arg_operands() { - return iterator_range(op_begin(), op_end() - 2); + /// handlers - iteration adapter for range-for loops. + handler_range handlers() { + return make_range(handler_begin(), handler_end()); } - /// arg_operands - iteration adapter for range-for loops. - iterator_range arg_operands() const { - return iterator_range(op_begin(), op_end() - 2); + /// handlers - iteration adapter for range-for loops. + const_handler_range handlers() const { + return make_range(handler_begin(), handler_end()); } - /// \brief Wrappers for getting the \c Use of a catchpad argument. - const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); } - Use &getArgOperandUse(unsigned i) { return getOperandUse(i); } + /// addHandler - Add an entry to the switch instruction... + /// Note: + /// This action invalidates handler_end(). Old handler_end() iterator will + /// point to the added handler. + void addHandler(BasicBlock *Dest); - // get*Dest - Return the destination basic blocks... - BasicBlock *getNormalDest() const { return cast(Op<-2>()); } - BasicBlock *getUnwindDest() const { return cast(Op<-1>()); } - void setNormalDest(BasicBlock *B) { Op<-2>() = B; } - void setUnwindDest(BasicBlock *B) { Op<-1>() = B; } + void removeHandler(handler_iterator HI); - BasicBlock *getSuccessor(unsigned i) const { - assert(i < 2 && "Successor # out of range for catchpad!"); - return i == 0 ? getNormalDest() : getUnwindDest(); + unsigned getNumSuccessors() const { return getNumOperands() - 1; } + BasicBlock *getSuccessor(unsigned Idx) const { + assert(Idx < getNumSuccessors() && + "Successor # out of range for catchswitch!"); + return cast(getOperand(Idx + 1)); } - - void setSuccessor(unsigned idx, BasicBlock *NewSucc) { - assert(idx < 2 && "Successor # out of range for catchpad!"); - *(&Op<-2>() + idx) = NewSucc; + void setSuccessor(unsigned Idx, BasicBlock *NewSucc) { + assert(Idx < getNumSuccessors() && + "Successor # out of range for catchswitch!"); + setOperand(Idx + 1, NewSucc); } - unsigned getNumSuccessors() const { return 2; } - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::CatchPad; + return I->getOpcode() == Instruction::CatchSwitch; } static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } private: - BasicBlock *getSuccessorV(unsigned idx) const override; + BasicBlock *getSuccessorV(unsigned Idx) const override; unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + void setSuccessorV(unsigned Idx, BasicBlock *B) override; }; template <> -struct OperandTraits - : public VariadicOperandTraits {}; +struct OperandTraits : public HungoffOperandTraits<2> {}; -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchPadInst, Value) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value) //===----------------------------------------------------------------------===// -// TerminatePadInst Class +// CleanupPadInst Class //===----------------------------------------------------------------------===// - -class TerminatePadInst : public TerminatorInst { +class CleanupPadInst : public FuncletPadInst { private: - void init(BasicBlock *BB, ArrayRef Args); - - TerminatePadInst(const TerminatePadInst &TPI); - - explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB, - ArrayRef Args, unsigned Values, - Instruction *InsertBefore); - explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB, - ArrayRef Args, unsigned Values, - BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - TerminatePadInst *cloneImpl() const; + explicit CleanupPadInst(Value *ParentPad, ArrayRef Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore) + : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values, + NameStr, InsertBefore) {} + explicit CleanupPadInst(Value *ParentPad, ArrayRef Args, + unsigned Values, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values, + NameStr, InsertAtEnd) {} public: - static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB = nullptr, - ArrayRef Args = None, - Instruction *InsertBefore = nullptr) { - unsigned Values = unsigned(Args.size()); - if (BB) - ++Values; - return new (Values) TerminatePadInst(C, BB, Args, Values, InsertBefore); - } - static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB, - ArrayRef Args, - BasicBlock *InsertAtEnd) { - unsigned Values = unsigned(Args.size()); - if (BB) - ++Values; - return new (Values) TerminatePadInst(C, BB, Args, Values, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; } - bool unwindsToCaller() const { return !hasUnwindDest(); } - - /// getNumArgOperands - Return the number of terminatepad arguments. - /// - unsigned getNumArgOperands() const { - unsigned NumOperands = getNumOperands(); - if (hasUnwindDest()) - return NumOperands - 1; - return NumOperands; - } - - /// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument. - /// - Value *getArgOperand(unsigned i) const { return getOperand(i); } - void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } - - const_op_iterator arg_end() const { - if (hasUnwindDest()) - return op_end() - 1; - return op_end(); - } - - op_iterator arg_end() { - if (hasUnwindDest()) - return op_end() - 1; - return op_end(); - } - - /// arg_operands - iteration adapter for range-for loops. - iterator_range arg_operands() { - return iterator_range(op_begin(), arg_end()); - } - - /// arg_operands - iteration adapter for range-for loops. - iterator_range arg_operands() const { - return iterator_range(op_begin(), arg_end()); - } - - /// \brief Wrappers for getting the \c Use of a terminatepad argument. - const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); } - Use &getArgOperandUse(unsigned i) { return getOperandUse(i); } - - // get*Dest - Return the destination basic blocks... - BasicBlock *getUnwindDest() const { - if (!hasUnwindDest()) - return nullptr; - return cast(Op<-1>()); + static CleanupPadInst *Create(Value *ParentPad, ArrayRef Args = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + unsigned Values = 1 + Args.size(); + return new (Values) + CleanupPadInst(ParentPad, Args, Values, NameStr, InsertBefore); } - void setUnwindDest(BasicBlock *B) { - assert(B && hasUnwindDest()); - Op<-1>() = B; + static CleanupPadInst *Create(Value *ParentPad, ArrayRef Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + unsigned Values = 1 + Args.size(); + return new (Values) + CleanupPadInst(ParentPad, Args, Values, NameStr, InsertAtEnd); } - unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::TerminatePad; + return I->getOpcode() == Instruction::CleanupPad; } static inline bool classof(const Value *V) { return isa(V) && classof(cast(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 - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value) - //===----------------------------------------------------------------------===// -// CleanupPadInst Class +// CatchPadInst Class //===----------------------------------------------------------------------===// - -class CleanupPadInst : public Instruction { +class CatchPadInst : public FuncletPadInst { private: - void init(ArrayRef Args, const Twine &NameStr); - - CleanupPadInst(const CleanupPadInst &CPI); - - explicit CleanupPadInst(LLVMContext &C, ArrayRef Args, - const Twine &NameStr, Instruction *InsertBefore); - explicit CleanupPadInst(LLVMContext &C, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - CleanupPadInst *cloneImpl() const; + explicit CatchPadInst(Value *CatchSwitch, ArrayRef Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore) + : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values, + NameStr, InsertBefore) {} + explicit CatchPadInst(Value *CatchSwitch, ArrayRef Args, + unsigned Values, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values, + NameStr, InsertAtEnd) {} public: - static CleanupPadInst *Create(LLVMContext &C, ArrayRef Args, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertBefore); + static CatchPadInst *Create(Value *CatchSwitch, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + unsigned Values = 1 + Args.size(); + return new (Values) + CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertBefore); } - static CleanupPadInst *Create(LLVMContext &C, ArrayRef Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertAtEnd); + static CatchPadInst *Create(Value *CatchSwitch, ArrayRef Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + unsigned Values = 1 + Args.size(); + return new (Values) + CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertAtEnd); } - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + /// Convenience accessors + CatchSwitchInst *getCatchSwitch() const { + return cast(Op<-1>()); + } + void setCatchSwitch(Value *CatchSwitch) { + assert(CatchSwitch); + Op<-1>() = CatchSwitch; + } - // Methods for support type inquiry through isa, cast, and dyn_cast: + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::CleanupPad; + return I->getOpcode() == Instruction::CatchPad; } static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } }; -template <> -struct OperandTraits - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value) - //===----------------------------------------------------------------------===// // CatchReturnInst Class //===----------------------------------------------------------------------===// @@ -3956,11 +4130,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value) class CatchReturnInst : public TerminatorInst { CatchReturnInst(const CatchReturnInst &RI); - void init(CatchPadInst *CatchPad, BasicBlock *BB); - CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB, - Instruction *InsertBefore); - CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB, - BasicBlock *InsertAtEnd); + void init(Value *CatchPad, BasicBlock *BB); + CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore); + CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd); protected: // Note: Instruction needs to be a friend here to call cloneImpl. @@ -3968,13 +4140,13 @@ protected: CatchReturnInst *cloneImpl() const; public: - static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB, + static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore = nullptr) { assert(CatchPad); assert(BB); return new (2) CatchReturnInst(CatchPad, BB, InsertBefore); } - static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB, + static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd) { assert(CatchPad); assert(BB); @@ -3998,6 +4170,10 @@ public: } unsigned getNumSuccessors() const { return 1; } + Value *getParentPad() const { + return getCatchPad()->getCatchSwitch()->getParentPad(); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::CatchRet); @@ -4018,93 +4194,6 @@ struct OperandTraits DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value) -//===----------------------------------------------------------------------===// -// CleanupEndPadInst Class -//===----------------------------------------------------------------------===// - -class CleanupEndPadInst : public TerminatorInst { -private: - CleanupEndPadInst(const CleanupEndPadInst &CEPI); - - void init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB); - CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, - unsigned Values, Instruction *InsertBefore = nullptr); - CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, - unsigned Values, BasicBlock *InsertAtEnd); - -protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - CleanupEndPadInst *cloneImpl() const; - -public: - static CleanupEndPadInst *Create(CleanupPadInst *CleanupPad, - BasicBlock *UnwindBB = nullptr, - Instruction *InsertBefore = nullptr) { - unsigned Values = UnwindBB ? 2 : 1; - return new (Values) - CleanupEndPadInst(CleanupPad, UnwindBB, Values, InsertBefore); - } - static CleanupEndPadInst *Create(CleanupPadInst *CleanupPad, - BasicBlock *UnwindBB, - BasicBlock *InsertAtEnd) { - unsigned Values = UnwindBB ? 2 : 1; - return new (Values) - CleanupEndPadInst(CleanupPad, UnwindBB, Values, InsertAtEnd); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; } - bool unwindsToCaller() const { return !hasUnwindDest(); } - - unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } - - /// Convenience accessors - CleanupPadInst *getCleanupPad() const { - return cast(Op<-1>()); - } - void setCleanupPad(CleanupPadInst *CleanupPad) { - assert(CleanupPad); - Op<-1>() = CleanupPad; - } - - BasicBlock *getUnwindDest() const { - return hasUnwindDest() ? cast(Op<-2>()) : nullptr; - } - void setUnwindDest(BasicBlock *NewDest) { - assert(hasUnwindDest()); - assert(NewDest); - 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::CleanupEndPad); - } - static inline bool classof(const Value *V) { - return isa(V) && classof(cast(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 - : public VariadicOperandTraits {}; - -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupEndPadInst, Value) - //===----------------------------------------------------------------------===// // CleanupReturnInst Class //===----------------------------------------------------------------------===// @@ -4113,11 +4202,11 @@ class CleanupReturnInst : public TerminatorInst { private: CleanupReturnInst(const CleanupReturnInst &RI); - 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); + void init(Value *CleanupPad, BasicBlock *UnwindBB); + CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, + Instruction *InsertBefore = nullptr); + CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, + BasicBlock *InsertAtEnd); protected: // Note: Instruction needs to be a friend here to call cloneImpl. @@ -4125,7 +4214,7 @@ protected: CleanupReturnInst *cloneImpl() const; public: - static CleanupReturnInst *Create(CleanupPadInst *CleanupPad, + static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB = nullptr, Instruction *InsertBefore = nullptr) { assert(CleanupPad); @@ -4135,8 +4224,7 @@ public: return new (Values) CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertBefore); } - static CleanupReturnInst *Create(CleanupPadInst *CleanupPad, - BasicBlock *UnwindBB, + static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB, BasicBlock *InsertAtEnd) { assert(CleanupPad); unsigned Values = 1; @@ -4154,22 +4242,22 @@ public: /// Convenience accessor. CleanupPadInst *getCleanupPad() const { - return cast(Op<-1>()); + return cast(Op<0>()); } void setCleanupPad(CleanupPadInst *CleanupPad) { assert(CleanupPad); - Op<-1>() = CleanupPad; + Op<0>() = CleanupPad; } unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } BasicBlock *getUnwindDest() const { - return hasUnwindDest() ? cast(Op<-2>()) : nullptr; + return hasUnwindDest() ? cast(Op<1>()) : nullptr; } void setUnwindDest(BasicBlock *NewDest) { assert(NewDest); assert(hasUnwindDest()); - Op<-2>() = NewDest; + Op<1>() = NewDest; } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -4209,6 +4297,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value) /// class UnreachableInst : public TerminatorInst { void *operator new(size_t, unsigned) = delete; + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -4231,6 +4320,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + private: BasicBlock *getSuccessorV(unsigned idx) const override; unsigned getNumSuccessorsV() const override;