Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -1346,224 +1346,71 @@ } }; -//===----------------------------------------------------------------------===// -/// This class represents a function call, abstracting a target -/// machine's calling convention. This class uses low bit of the SubClassData -/// 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, - public OperandBundleUser { - friend class OperandBundleUser; - - AttributeList Attrs; ///< parameter attributes for call - FunctionType *FTy; +class CallInst; +class InvokeInst; - CallInst(const CallInst &CI); - - /// Construct a CallInst given a range of arguments. - /// Construct a CallInst from a range of arguments - inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - Instruction *InsertBefore); +template struct CallableBase { using type = Instruction; }; - inline CallInst(Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - Instruction *InsertBefore) - : CallInst(cast( - cast(Func->getType())->getElementType()), - 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. - /// Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr, - BasicBlock *InsertAtEnd); - - explicit CallInst(Value *F, const Twine &NameStr, - Instruction *InsertBefore); - - CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr) { - init(cast( - cast(Func->getType())->getElementType()), - Func, Args, Bundles, NameStr); - } - void init(FunctionType *FTy, Value *Func, ArrayRef Args, - ArrayRef Bundles, const Twine &NameStr); - void init(Value *Func, const Twine &NameStr); - - bool hasDescriptor() const { return HasDescriptor; } +template <> struct CallableBase { using type = TerminatorInst; }; +//===----------------------------------------------------------------------===// +/// Base class for all callable instructions (InvokeInst and CallInst) +/// Holds everything related to calling a function, abstracting from the base +/// type @p BaseInstTy and the concrete instruction @p InstTy +/// +template +class Callable : public CallableBase::type, + public OperandBundleUser { 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, - ArrayRef Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return Create(cast( - cast(Func->getType())->getElementType()), - 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); - } + AttributeList Attrs; ///< parameter attributes for callable + FunctionType *FTy; + using BaseInstTy = typename CallableBase::type; - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return new (unsigned(Args.size() + 1)) - CallInst(Ty, Func, Args, None, NameStr, InsertBefore); - } + template + Callable(AttributeList const &A, FunctionType *FT, ArgsTy &&... Args) + : BaseInstTy(std::forward(Args)...), Attrs(A), FTy(FT) {} + bool hasDescriptor() const { return Value::HasDescriptor; } - 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); + using BaseInstTy::BaseInstTy; - return new (TotalOps, DescriptorBytes) - CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore); - } + using OperandBundleUser::isFnAttrDisallowedByOpBundle; + using OperandBundleUser::getNumTotalBundleOperands; + using OperandBundleUser::bundleOperandHasAttr; + using Instruction::getSubclassDataFromInstruction; + using Instruction::setInstructionSubclassData; - static CallInst *Create(Value *Func, ArrayRef Args, - ArrayRef Bundles, - const Twine &NameStr, BasicBlock *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) { - return new(1) CallInst(F, NameStr, InsertBefore); - } +public: + using Instruction::getContext; + using OperandBundleUser::hasOperandBundles; + using OperandBundleUser::getBundleOperandsStartIndex; - static CallInst *Create(Value *F, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new(1) CallInst(F, NameStr, InsertAtEnd); + static bool classof(const Instruction *I) { + llvm_unreachable( + "Callable is not meant to be used as part of the classof hierarchy"); } - /// Create a clone of \p CI with a different set of operand bundles and - /// insert it before \p InsertPt. +public: + /// Return the parameter attributes for this call. /// - /// 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); + AttributeList getAttributes() const { return Attrs; } - /// 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 - /// constant 1. - /// 2. Call malloc with that argument. - /// 3. Bitcast the result of the malloc call to the specified type. - static Instruction *CreateMalloc(Instruction *InsertBefore, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - Function* MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - Function* MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(Instruction *InsertBefore, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - ArrayRef Bundles = None, - Function* MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - ArrayRef Bundles = None, - Function* MallocF = nullptr, - const Twine &Name = ""); - /// Generate the IR for a call to the builtin free function. - static Instruction *CreateFree(Value *Source, - Instruction *InsertBefore); - static Instruction *CreateFree(Value *Source, - BasicBlock *InsertAtEnd); - static Instruction *CreateFree(Value *Source, - ArrayRef Bundles, - Instruction *InsertBefore); - static Instruction *CreateFree(Value *Source, - ArrayRef Bundles, - BasicBlock *InsertAtEnd); + /// Set the parameter attributes for this call. + /// + void setAttributes(AttributeList A) { Attrs = A; } FunctionType *getFunctionType() const { return FTy; } void mutateFunctionType(FunctionType *FTy) { - mutateType(FTy->getReturnType()); + Value::mutateType(FTy->getReturnType()); this->FTy = FTy; } - // Note that 'musttail' implies 'tail'. - enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2, - TCK_NoTail = 3 }; - TailCallKind getTailCallKind() const { - return TailCallKind(getSubclassDataFromInstruction() & 3); - } - - bool isTailCall() const { - 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)); - } - - void setTailCallKind(TailCallKind TCK) { - setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | - unsigned(TCK)); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// Return the number of call arguments. /// unsigned getNumArgOperands() const { - return getNumOperands() - getNumTotalBundleOperands() - 1; + return getNumOperands() - getNumTotalBundleOperands() - InstTy::ArgOffset; } /// getArgOperand/setArgOperand - Return/set the i-th call argument. @@ -1578,46 +1425,112 @@ } /// Return the iterator pointing to the beginning of the argument list. - op_iterator arg_begin() { return op_begin(); } + User::op_iterator arg_begin() { return op_begin(); } /// Return the iterator pointing to the end of the argument list. - op_iterator arg_end() { + User::op_iterator arg_end() { // [ call args ], [ operand bundles ], callee - return op_end() - getNumTotalBundleOperands() - 1; + return op_end() - getNumTotalBundleOperands() - InstTy::ArgOffset; } /// Iteration adapter for range-for loops. - iterator_range arg_operands() { + iterator_range arg_operands() { return make_range(arg_begin(), arg_end()); } /// Return the iterator pointing to the beginning of the argument list. - const_op_iterator arg_begin() const { return op_begin(); } + User::const_op_iterator arg_begin() const { return op_begin(); } /// Return the iterator pointing to the end of the argument list. - const_op_iterator arg_end() const { + User::const_op_iterator arg_end() const { // [ call args ], [ operand bundles ], callee - return op_end() - getNumTotalBundleOperands() - 1; + return op_end() - getNumTotalBundleOperands() - InstTy::ArgOffset; } /// Iteration adapter for range-for loops. - iterator_range arg_operands() const { + iterator_range arg_operands() const { return make_range(arg_begin(), arg_end()); } /// Wrappers for getting the \c Use of a call argument. const Use &getArgOperandUse(unsigned i) const { assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); + return User::getOperandUse(i); } Use &getArgOperandUse(unsigned i) { assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); + return User::getOperandUse(i); } /// If one of the arguments has the 'returned' attribute, return its /// operand value. Otherwise, return nullptr. - Value *getReturnedArgOperand() const; + Value *getReturnedArgOperand() const { + unsigned Index; + + if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) + return getArgOperand(Index - AttributeList::FirstArgIndex); + if (const Function *F = getCalledFunction()) + if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && + Index) + return getArgOperand(Index - AttributeList::FirstArgIndex); + + return nullptr; + } + + User::op_iterator op_begin() { + return OperandTraits::op_begin(this); + } + + User::const_op_iterator op_begin() const { + return OperandTraits::op_begin(const_cast(this)); + } + + User::op_iterator op_end() { return OperandTraits::op_end(this); } + + User::const_op_iterator op_end() const { + return OperandTraits::op_end(const_cast(this)); + } + + Value *getOperand(unsigned i_nocapture) const { + assert(i_nocapture < OperandTraits::operands(this) && + "getOperand() out of range!"); + return cast_or_null(OperandTraits::op_begin( + const_cast(this))[i_nocapture] + .get()); + } + + void setOperand(unsigned i_nocapture, Value *Val_nocapture) { + assert(i_nocapture < OperandTraits::operands(this) && + "setOperand() out of range!"); + OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; + } + + unsigned getNumOperands() const { + return OperandTraits::operands(this); + } + template Use &Op() { + return User::OpFrom(this); + } + template const Use &Op() const { + return User::OpFrom(this); + } + + /// Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast(Op<-InstTy::ArgOffset>()); + } + + /// Determine whether this call has the given attribute. + bool hasFnAttr(Attribute::AttrKind Kind) const { + assert(Kind != Attribute::NoBuiltin && + "Use Callable::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(Kind); + } + + /// Determine whether this call has the given attribute. + bool hasFnAttr(StringRef Kind) const { return hasFnAttrImpl(Kind); } /// getCallingConv/setCallingConv - Get or set the calling convention of this /// function call. @@ -1631,62 +1544,103 @@ (ID << 2)); } - /// Return the parameter attributes for this call. - /// - AttributeList getAttributes() const { return Attrs; } - - /// Set the parameter attributes for this call. - /// - void setAttributes(AttributeList A) { Attrs = A; } /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute::AttrKind Kind); + void addAttribute(unsigned i, Attribute::AttrKind Kind) { + AttributeList PAL = getAttributes(); + PAL = PAL.addAttribute(getContext(), i, Kind); + setAttributes(PAL); + } /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute Attr); + void addAttribute(unsigned i, Attribute Attr) { + AttributeList PAL = getAttributes(); + PAL = PAL.addAttribute(getContext(), i, Attr); + setAttributes(PAL); + } /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind); + setAttributes(PAL); + } /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute Attr); + void addParamAttr(unsigned ArgNo, Attribute Attr) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr); + setAttributes(PAL); + } /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attribute::AttrKind Kind); + void removeAttribute(unsigned i, Attribute::AttrKind Kind) { + AttributeList PAL = getAttributes(); + PAL = PAL.removeAttribute(getContext(), i, Kind); + setAttributes(PAL); + } /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, StringRef Kind); + void removeAttribute(unsigned i, StringRef Kind) { + AttributeList PAL = getAttributes(); + PAL = PAL.removeAttribute(getContext(), i, Kind); + setAttributes(PAL); + } /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); + setAttributes(PAL); + } /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, StringRef Kind); + void removeParamAttr(unsigned ArgNo, StringRef Kind) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); + setAttributes(PAL); + } /// adds the dereferenceable attribute to the list of attributes. - void addDereferenceableAttr(unsigned i, uint64_t Bytes); + void addDereferenceableAttr(unsigned i, uint64_t Bytes) { + AttributeList PAL = getAttributes(); + PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); + setAttributes(PAL); + } /// adds the dereferenceable_or_null attribute to the list of /// attributes. - void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); - - /// Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind Kind) const { - assert(Kind != Attribute::NoBuiltin && - "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); - return hasFnAttrImpl(Kind); - } - - /// Determine whether this call has the given attribute. - bool hasFnAttr(StringRef Kind) const { - return hasFnAttrImpl(Kind); + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { + AttributeList PAL = getAttributes(); + PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); + setAttributes(PAL); } /// Determine whether the return value has the given attribute. - bool hasRetAttr(Attribute::AttrKind Kind) const; + bool hasRetAttr(Attribute::AttrKind Kind) const { + if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind)) + return true; + + // Look at the callee, if available. + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind); + return false; + } /// Determine whether the argument or parameter has the given attribute. - bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; + bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { + assert(ArgNo < getNumArgOperands() && "Param index out of bounds!"); + + if (Attrs.hasParamAttribute(ArgNo, Kind)) + return true; + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasParamAttribute(ArgNo, Kind); + return false; + } /// Get the attribute of a given kind at a position. Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { @@ -1709,7 +1663,6 @@ assert(ArgNo < getNumArgOperands() && "Out of bounds"); return getAttributes().getParamAttr(ArgNo, Kind); } - /// Return true if the data operand at index \p i has the attribute \p /// A. /// @@ -1723,7 +1676,28 @@ /// \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 Kind) const; + bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const { + // There are getNumOperands() - (InstTy::ArgOffset - 1) data operands. + // The last operand is the callee. + assert(i < (getNumOperands() - InstTy::ArgOffset + 1) && + "Data operand index out of bounds!"); + + // The attribute A can either be directly specified, if the operand in + // question is a call argument; or be indirectly implied by the kind of its + // containing operand bundle, if the operand is a bundle operand. + + if (i == AttributeList::ReturnIndex) + return hasRetAttr(Kind); + + // FIXME: Avoid these i - 1 calculations and update the API to use + // zero-based indices. + if (i < (getNumArgOperands() + 1)) + return paramHasAttr(i - 1, Kind); + + assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) && + "Must be either a call argument or an operand bundle!"); + return bundleOperandHasAttr(i - 1, Kind); + } /// Extract the alignment of the return value. unsigned getRetAlignment() const { return Attrs.getRetAlignment(); } @@ -1765,15 +1739,6 @@ void setIsNoInline() { addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); } - - /// Return true if the call can return twice - bool canReturnTwice() const { - return hasFnAttr(Attribute::ReturnsTwice); - } - void setCanReturnTwice() { - addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice); - } - /// Determine if the call does not access memory. bool doesNotAccessMemory() const { return hasFnAttr(Attribute::ReadNone); @@ -1824,7 +1789,6 @@ void setOnlyAccessesInaccessibleMemOrArgMem() { addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly); } - /// Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { @@ -1837,13 +1801,13 @@ addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind); } - /// Determine if the call cannot be duplicated. + /// Determine if the invoke cannot be duplicated. bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } void setCannotDuplicate() { addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate); } - /// Determine if the call is convergent + /// Determine if the invoke is convergent bool isConvergent() const { return hasFnAttr(Attribute::Convergent); } void setConvergent() { addAttribute(AttributeList::FunctionIndex, Attribute::Convergent); @@ -1866,18 +1830,10 @@ bool hasByValArgument() const { return Attrs.hasAttrSomewhere(Attribute::ByVal); } - - /// Return the function called, or null if this is an - /// indirect function invocation. - /// - Function *getCalledFunction() const { - return dyn_cast(Op<-1>()); - } - /// Get a pointer to the function that is invoked by this /// instruction. - const Value *getCalledValue() const { return Op<-1>(); } - Value *getCalledValue() { return Op<-1>(); } + const Value *getCalledValue() const { return Op<-InstTy::ArgOffset>(); } + Value *getCalledValue() { return Op<-InstTy::ArgOffset>(); } /// Set the function called. void setCalledFunction(Value* Fn) { @@ -1889,23 +1845,10 @@ this->FTy = FTy; assert(FTy == cast( cast(Fn->getType())->getElementType())); - Op<-1>() = Fn; - } - - /// Check if this call is an inline asm statement. - bool isInlineAsm() const { - return isa(Op<-1>()); + Op<-InstTy::ArgOffset>() = Fn; } - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Call; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - -private: +protected: template bool hasFnAttrImpl(AttrKind Kind) const { if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind)) return true; @@ -1920,7 +1863,227 @@ Kind); return false; } +}; + +//===----------------------------------------------------------------------===// +/// This class represents a function call, abstracting a target +/// machine's calling convention. This class uses low bit of the SubClassData +/// 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 Callable { + friend class OperandBundleUser; + + CallInst(const CallInst &CI); + + /// Construct a CallInst given a range of arguments. + /// Construct a CallInst from a range of arguments + inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, + 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, 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. + /// Construct a CallInst from a range of arguments + inline CallInst(Value *Func, ArrayRef Args, + ArrayRef Bundles, const Twine &NameStr, + BasicBlock *InsertAtEnd); + + explicit CallInst(Value *F, const Twine &NameStr, Instruction *InsertBefore); + + CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); + + void init(Value *Func, ArrayRef Args, + ArrayRef Bundles, const Twine &NameStr) { + init(cast( + cast(Func->getType())->getElementType()), + Func, Args, Bundles, NameStr); + } + void init(FunctionType *FTy, Value *Func, ArrayRef Args, + ArrayRef Bundles, const Twine &NameStr); + void init(Value *Func, const Twine &NameStr); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + + CallInst *cloneImpl() const; + +public: + static constexpr int ArgOffset = 1; + + 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, 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, + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + 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, + ArrayRef Bundles, + const Twine &NameStr, BasicBlock *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) { + return new (1) CallInst(F, NameStr, InsertBefore); + } + + static CallInst *Create(Value *F, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new (1) CallInst(F, NameStr, InsertAtEnd); + } + + /// 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); + + /// 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 + /// constant 1. + /// 2. Call malloc with that argument. + /// 3. Bitcast the result of the malloc call to the specified type. + static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + Function *MallocF = nullptr, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + Function *MallocF = nullptr, + const Twine &Name = ""); + static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + ArrayRef Bundles = None, + Function *MallocF = nullptr, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + ArrayRef Bundles = None, + Function *MallocF = nullptr, + const Twine &Name = ""); + /// Generate the IR for a call to the builtin free function. + static Instruction *CreateFree(Value *Source, Instruction *InsertBefore); + static Instruction *CreateFree(Value *Source, BasicBlock *InsertAtEnd); + static Instruction *CreateFree(Value *Source, + ArrayRef Bundles, + Instruction *InsertBefore); + static Instruction *CreateFree(Value *Source, + ArrayRef Bundles, + BasicBlock *InsertAtEnd); + + // Note that 'musttail' implies 'tail'. + enum TailCallKind { + TCK_None = 0, + TCK_Tail = 1, + TCK_MustTail = 2, + TCK_NoTail = 3 + }; + TailCallKind getTailCallKind() const { + return TailCallKind(getSubclassDataFromInstruction() & 3); + } + + bool isTailCall() const { + 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)); + } + + void setTailCallKind(TailCallKind TCK) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(TCK)); + } + + /// Return true if the call can return twice + bool canReturnTwice() const { return hasFnAttr(Attribute::ReturnsTwice); } + void setCanReturnTwice() { + addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice); + } + + /// Check if this call is an inline asm statement. + bool isInlineAsm() const { return isa(Op<-1>()); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Call; + } + static 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) { @@ -1929,17 +2092,19 @@ }; template <> -struct OperandTraits : public VariadicOperandTraits { -}; +struct OperandTraits> + : public VariadicOperandTraits, 1> {}; CallInst::CallInst(Value *Func, ArrayRef Args, 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), + : Callable( + 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); } @@ -1947,19 +2112,14 @@ CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, ArrayRef Bundles, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(Ty->getReturnType(), Instruction::Call, - OperandTraits::op_end(this) - - (Args.size() + CountBundleInputs(Bundles) + 1), - unsigned(Args.size() + CountBundleInputs(Bundles) + 1), - InsertBefore) { + : Callable(Ty->getReturnType(), Instruction::Call, + 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. -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value) - //===----------------------------------------------------------------------===// // SelectInst Class //===----------------------------------------------------------------------===// @@ -3547,13 +3707,9 @@ /// Invoke instruction. The SubclassData field is used to hold the /// calling convention of the call. /// -class InvokeInst : public TerminatorInst, - public OperandBundleUser { +class InvokeInst : public Callable { friend class OperandBundleUser; - AttributeList Attrs; - FunctionType *FTy; - InvokeInst(const InvokeInst &BI); /// Construct an InvokeInst given a range of arguments. @@ -3580,7 +3736,6 @@ unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); - bool hasDescriptor() const { return HasDescriptor; } void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, ArrayRef Bundles, @@ -3601,6 +3756,7 @@ InvokeInst *cloneImpl() const; public: + static constexpr int ArgOffset = 3; static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, const Twine &NameStr, @@ -3674,298 +3830,7 @@ static InvokeInst *Create(InvokeInst *II, ArrayRef Bundles, Instruction *InsertPt = nullptr); - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - FunctionType *getFunctionType() const { return FTy; } - - void mutateFunctionType(FunctionType *FTy) { - mutateType(FTy->getReturnType()); - this->FTy = FTy; - } - - /// Return the number of invoke arguments. - /// - unsigned getNumArgOperands() const { - return getNumOperands() - getNumTotalBundleOperands() - 3; - } - - /// getArgOperand/setArgOperand - Return/set the i-th invoke argument. - /// - Value *getArgOperand(unsigned i) const { - assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperand(i); - } - void setArgOperand(unsigned i, Value *v) { - assert(i < getNumArgOperands() && "Out of bounds!"); - setOperand(i, v); - } - - /// Return the iterator pointing to the beginning of the argument list. - op_iterator arg_begin() { return op_begin(); } - - /// 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; - } - - /// Iteration adapter for range-for loops. - iterator_range arg_operands() { - return make_range(arg_begin(), arg_end()); - } - - /// Return the iterator pointing to the beginning of the argument list. - const_op_iterator arg_begin() const { return op_begin(); } - - /// 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; - } - - /// Iteration adapter for range-for loops. - iterator_range arg_operands() const { - return make_range(arg_begin(), arg_end()); - } - - /// Wrappers for getting the \c Use of a invoke argument. - const Use &getArgOperandUse(unsigned i) const { - assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); - } - Use &getArgOperandUse(unsigned i) { - assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); - } - - /// If one of the arguments has the 'returned' attribute, return its - /// operand value. Otherwise, return nullptr. - Value *getReturnedArgOperand() const; - - /// getCallingConv/setCallingConv - Get or set the calling convention of this - /// function call. - CallingConv::ID getCallingConv() const { - return static_cast(getSubclassDataFromInstruction()); - } - void setCallingConv(CallingConv::ID CC) { - auto ID = static_cast(CC); - assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); - setInstructionSubclassData(ID); - } - - /// Return the parameter attributes for this invoke. - /// - AttributeList getAttributes() const { return Attrs; } - - /// Set the parameter attributes for this invoke. - /// - void setAttributes(AttributeList A) { Attrs = A; } - - /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute::AttrKind Kind); - /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute Attr); - - /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - - /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attribute::AttrKind Kind); - - /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, StringRef Kind); - - /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - - /// adds the dereferenceable attribute to the list of attributes. - void addDereferenceableAttr(unsigned i, uint64_t Bytes); - - /// adds the dereferenceable_or_null attribute to the list of - /// attributes. - void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); - - /// Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind Kind) const { - assert(Kind != Attribute::NoBuiltin && - "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); - return hasFnAttrImpl(Kind); - } - - /// Determine whether this call has the given attribute. - bool hasFnAttr(StringRef Kind) const { - return hasFnAttrImpl(Kind); - } - - /// Determine whether the return value has the given attribute. - bool hasRetAttr(Attribute::AttrKind Kind) const; - - /// Determine whether the argument or parameter has the given attribute. - bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; - - /// Get the attribute of a given kind at a position. - Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { - return getAttributes().getAttribute(i, Kind); - } - - /// Get the attribute of a given kind at a position. - Attribute getAttribute(unsigned i, StringRef Kind) const { - return getAttributes().getAttribute(i, Kind); - } - - /// 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 Kind) const; - - /// Extract the alignment of the return value. - unsigned getRetAlignment() const { return Attrs.getRetAlignment(); } - - /// Extract the alignment for a call or parameter (0=unknown). - unsigned getParamAlignment(unsigned ArgNo) const { - return Attrs.getParamAlignment(ArgNo); - } - - /// Extract the number of dereferenceable bytes for a call or - /// parameter (0=unknown). - uint64_t getDereferenceableBytes(unsigned i) const { - return Attrs.getDereferenceableBytes(i); - } - - /// Extract the number of dereferenceable_or_null bytes for a call or - /// parameter (0=unknown). - uint64_t getDereferenceableOrNullBytes(unsigned i) const { - return Attrs.getDereferenceableOrNullBytes(i); - } - - /// @brief Determine if the return value is marked with NoAlias attribute. - bool returnDoesNotAlias() const { - return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); - } - - /// Return true if the call should not be treated as a call to a - /// builtin. - bool isNoBuiltin() const { - // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have - // to check it by hand. - return hasFnAttrImpl(Attribute::NoBuiltin) && - !hasFnAttrImpl(Attribute::Builtin); - } - - /// Determine if the call requires strict floating point semantics. - bool isStrictFP() const { return hasFnAttr(Attribute::StrictFP); } - - /// Return true if the call should not be inlined. - bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } - void setIsNoInline() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); - } - - /// Determine if the call does not access memory. - bool doesNotAccessMemory() const { - return hasFnAttr(Attribute::ReadNone); - } - void setDoesNotAccessMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); - } - - /// Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); - } - void setOnlyReadsMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly); - } - - /// Determine if the call does not access or only writes memory. - bool doesNotReadMemory() const { - return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly); - } - void setDoesNotReadMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly); - } - - /// @brief Determine if the call access memmory only using it's pointer - /// arguments. - bool onlyAccessesArgMemory() const { - return hasFnAttr(Attribute::ArgMemOnly); - } - void setOnlyAccessesArgMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly); - } - - /// @brief Determine if the function may only access memory that is - /// inaccessible from the IR. - bool onlyAccessesInaccessibleMemory() const { - return hasFnAttr(Attribute::InaccessibleMemOnly); - } - void setOnlyAccessesInaccessibleMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly); - } - - /// @brief Determine if the function may only access memory that is - /// either inaccessible from the IR or pointed to by its arguments. - bool onlyAccessesInaccessibleMemOrArgMem() const { - return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - void setOnlyAccessesInaccessibleMemOrArgMem() { - addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly); - } - - /// Determine if the call cannot return. - bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } - void setDoesNotReturn() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn); - } - - /// Determine if the call cannot unwind. - bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } - void setDoesNotThrow() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind); - } - - /// Determine if the invoke cannot be duplicated. - bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } - void setCannotDuplicate() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate); - } - - /// Determine if the invoke is convergent - bool isConvergent() const { return hasFnAttr(Attribute::Convergent); } - void setConvergent() { - addAttribute(AttributeList::FunctionIndex, Attribute::Convergent); - } - void setNotConvergent() { - removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent); - } - - /// 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(0, Attribute::StructRet); - } - - /// Determine if any call argument is an aggregate passed by value. - bool hasByValArgument() const { - return Attrs.hasAttrSomewhere(Attribute::ByVal); - } /// Return the function called, or null if this is an /// indirect function invocation. @@ -4031,20 +3896,6 @@ } private: - template bool hasFnAttrImpl(AttrKind Kind) const { - if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind)) - return true; - - // Operand bundles override attributes on the called function, but don't - // override attributes directly present on the invoke instruction. - if (isFnAttrDisallowedByOpBundle(Kind)) - return false; - - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasAttribute(AttributeList::FunctionIndex, - Kind); - return false; - } // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -4054,16 +3905,17 @@ }; template <> -struct OperandTraits : public VariadicOperandTraits { -}; +struct OperandTraits> + : public VariadicOperandTraits, 3> {}; InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, 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) { + : Callable(Ty->getReturnType(), Instruction::Invoke, + OperandTraits>::op_end(this) - + Values, + Values, InsertBefore) { init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr); } @@ -4071,15 +3923,16 @@ 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) { + : Callable( + 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) //===----------------------------------------------------------------------===// // ResumeInst Class Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -319,31 +319,32 @@ setName(NameStr); } -CallInst::CallInst(Value *Func, const Twine &Name, - Instruction *InsertBefore) - : Instruction(cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits::op_end(this) - 1, - 1, InsertBefore) { +CallInst::CallInst(Value *Func, const Twine &Name, Instruction *InsertBefore) + : Callable( + cast( + cast(Func->getType())->getElementType()) + ->getReturnType(), + Instruction::Call, + OperandTraits>::op_end(this) - 1, 1, + InsertBefore) { init(Func, Name); } -CallInst::CallInst(Value *Func, const Twine &Name, - BasicBlock *InsertAtEnd) - : Instruction(cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits::op_end(this) - 1, - 1, InsertAtEnd) { +CallInst::CallInst(Value *Func, const Twine &Name, BasicBlock *InsertAtEnd) + : Callable( + cast( + cast(Func->getType())->getElementType()) + ->getReturnType(), + Instruction::Call, + OperandTraits>::op_end(this) - 1, 1, InsertAtEnd) { init(Func, Name); } CallInst::CallInst(const CallInst &CI) - : Instruction(CI.getType(), Instruction::Call, - OperandTraits::op_end(this) - CI.getNumOperands(), - CI.getNumOperands()), - Attrs(CI.Attrs), FTy(CI.FTy) { + : Callable(CI.Attrs, CI.FTy, CI.getType(), Instruction::Call, + OperandTraits>::op_end(this) - + CI.getNumOperands(), + CI.getNumOperands()) { setTailCallKind(CI.getTailCallKind()); setCallingConv(CI.getCallingConv()); @@ -367,125 +368,14 @@ return NewCI; } -Value *CallInst::getReturnedArgOperand() const { - unsigned Index; - if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) - return getArgOperand(Index - AttributeList::FirstArgIndex); - if (const Function *F = getCalledFunction()) - if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && - Index) - return getArgOperand(Index - AttributeList::FirstArgIndex); - return nullptr; -} - -void CallInst::addAttribute(unsigned i, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttribute(getContext(), i, Kind); - setAttributes(PAL); -} - -void CallInst::addAttribute(unsigned i, Attribute Attr) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttribute(getContext(), i, Attr); - setAttributes(PAL); -} - -void CallInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - assert(ArgNo < getNumArgOperands() && "Out of bounds"); - AttributeList PAL = getAttributes(); - PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); -} - -void CallInst::addParamAttr(unsigned ArgNo, Attribute Attr) { - assert(ArgNo < getNumArgOperands() && "Out of bounds"); - AttributeList PAL = getAttributes(); - PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr); - setAttributes(PAL); -} - -void CallInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttribute(getContext(), i, Kind); - setAttributes(PAL); -} - -void CallInst::removeAttribute(unsigned i, StringRef Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttribute(getContext(), i, Kind); - setAttributes(PAL); -} - -void CallInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - assert(ArgNo < getNumArgOperands() && "Out of bounds"); - AttributeList PAL = getAttributes(); - PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); -} -void CallInst::removeParamAttr(unsigned ArgNo, StringRef Kind) { - assert(ArgNo < getNumArgOperands() && "Out of bounds"); - AttributeList PAL = getAttributes(); - PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); -} - -void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); - setAttributes(PAL); -} - -void CallInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); - setAttributes(PAL); -} -bool CallInst::hasRetAttr(Attribute::AttrKind Kind) const { - if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind)) - return true; - // Look at the callee, if available. - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind); - return false; -} -bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const { - assert(i < getNumArgOperands() && "Param index out of bounds!"); - if (Attrs.hasParamAttribute(i, Kind)) - return true; - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasParamAttribute(i, Kind); - return false; -} -bool CallInst::dataOperandHasImpliedAttr(unsigned i, - Attribute::AttrKind Kind) const { - // There are getNumOperands() - 1 data operands. The last operand is the - // callee. - assert(i < getNumOperands() && "Data operand index out of bounds!"); - - // The attribute A can either be directly specified, if the operand in - // question is a call argument; or be indirectly implied by the kind of its - // containing operand bundle, if the operand is a bundle operand. - - if (i == AttributeList::ReturnIndex) - return hasRetAttr(Kind); - - // FIXME: Avoid these i - 1 calculations and update the API to use zero-based - // indices. - if (i < (getNumArgOperands() + 1)) - return paramHasAttr(i - 1, Kind); - - assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) && - "Must be either a call argument or an operand bundle!"); - return bundleOperandHasAttr(i - 1, Kind); -} /// IsConstantOne - Return true only if val is constant int 1 static bool IsConstantOne(Value *val) { @@ -721,11 +611,10 @@ } InvokeInst::InvokeInst(const InvokeInst &II) - : TerminatorInst(II.getType(), Instruction::Invoke, - OperandTraits::op_end(this) - - II.getNumOperands(), - II.getNumOperands()), - Attrs(II.Attrs), FTy(II.FTy) { + : Callable(II.Attrs, II.FTy, II.getType(), Instruction::Invoke, + OperandTraits>::op_end(this) - + II.getNumOperands(), + II.getNumOperands()) { setCallingConv(II.getCallingConv()); std::copy(II.op_begin(), II.op_end(), op_begin()); std::copy(II.bundle_op_info_begin(), II.bundle_op_info_end(), @@ -747,109 +636,6 @@ return NewII; } -Value *InvokeInst::getReturnedArgOperand() const { - unsigned Index; - - if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) - return getArgOperand(Index - AttributeList::FirstArgIndex); - if (const Function *F = getCalledFunction()) - if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && - Index) - return getArgOperand(Index - AttributeList::FirstArgIndex); - - return nullptr; -} - -bool InvokeInst::hasRetAttr(Attribute::AttrKind Kind) const { - if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind)) - return true; - - // Look at the callee, if available. - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind); - return false; -} - -bool InvokeInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const { - assert(i < getNumArgOperands() && "Param index out of bounds!"); - - if (Attrs.hasParamAttribute(i, Kind)) - return true; - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasParamAttribute(i, Kind); - return false; -} - -bool InvokeInst::dataOperandHasImpliedAttr(unsigned i, - Attribute::AttrKind Kind) const { - // There are getNumOperands() - 3 data operands. The last three operands are - // the callee and the two successor basic blocks. - assert(i < (getNumOperands() - 2) && "Data operand index out of bounds!"); - - // The attribute A can either be directly specified, if the operand in - // question is an invoke argument; or be indirectly implied by the kind of its - // containing operand bundle, if the operand is a bundle operand. - - if (i == AttributeList::ReturnIndex) - return hasRetAttr(Kind); - - // FIXME: Avoid these i - 1 calculations and update the API to use zero-based - // indices. - if (i < (getNumArgOperands() + 1)) - return paramHasAttr(i - 1, Kind); - - assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) && - "Must be either an invoke argument or an operand bundle!"); - return bundleOperandHasAttr(i - 1, Kind); -} - -void InvokeInst::addAttribute(unsigned i, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttribute(getContext(), i, Kind); - setAttributes(PAL); -} - -void InvokeInst::addAttribute(unsigned i, Attribute Attr) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttribute(getContext(), i, Attr); - setAttributes(PAL); -} - -void InvokeInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); -} - -void InvokeInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttribute(getContext(), i, Kind); - setAttributes(PAL); -} - -void InvokeInst::removeAttribute(unsigned i, StringRef Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttribute(getContext(), i, Kind); - setAttributes(PAL); -} - -void InvokeInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); -} - -void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); - setAttributes(PAL); -} - -void InvokeInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); - setAttributes(PAL); -} LandingPadInst *InvokeInst::getLandingPadInst() const { return cast(getUnwindDest()->getFirstNonPHI());