[llvm] r325778 - Syndicate duplicate code between CallInst and InvokeInst
Serge Guelton via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 22 05:30:32 PST 2018
Author: serge_sans_paille
Date: Thu Feb 22 05:30:32 2018
New Revision: 325778
URL: http://llvm.org/viewvc/llvm-project?rev=325778&view=rev
Log:
Syndicate duplicate code between CallInst and InvokeInst
NFC intended, syndicate common code to a parametric base class. Part of the original problem is that InvokeInst is a TerminatorInst, unlike CallInst. the problem is solved by introducing a parametrized class paramtertized by its base.
Differential Revision: https://reviews.llvm.org/D40727
Modified:
llvm/trunk/include/llvm/IR/Instructions.h
llvm/trunk/lib/IR/Instructions.cpp
Modified: llvm/trunk/include/llvm/IR/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=325778&r1=325777&r2=325778&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instructions.h (original)
+++ llvm/trunk/include/llvm/IR/Instructions.h Thu Feb 22 05:30:32 2018
@@ -1346,224 +1346,71 @@ public:
}
};
-//===----------------------------------------------------------------------===//
-/// 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<CallInst, User::op_iterator> {
- friend class OperandBundleUser<CallInst, User::op_iterator>;
-
- AttributeList Attrs; ///< parameter attributes for call
- FunctionType *FTy;
-
- 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<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
- Instruction *InsertBefore);
-
- inline CallInst(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
- Instruction *InsertBefore)
- : CallInst(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, Bundles, NameStr, InsertBefore) {}
-
- inline CallInst(Value *Func, ArrayRef<Value *> 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<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
- BasicBlock *InsertAtEnd);
-
- explicit CallInst(Value *F, const Twine &NameStr,
- Instruction *InsertBefore);
-
- CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd);
+class CallInst;
+class InvokeInst;
- void init(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
- init(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, Bundles, NameStr);
- }
- void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr);
- void init(Value *Func, const Twine &NameStr);
+template <class T> struct CallBaseParent { using type = Instruction; };
- bool hasDescriptor() const { return HasDescriptor; }
+template <> struct CallBaseParent<InvokeInst> { 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 InstTy>
+class CallBase : public CallBaseParent<InstTy>::type,
+ public OperandBundleUser<InstTy, User::op_iterator> {
protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
+ AttributeList Attrs; ///< parameter attributes for callable
+ FunctionType *FTy;
+ using BaseInstTy = typename CallBaseParent<InstTy>::type;
- CallInst *cloneImpl() const;
+ template <class... ArgsTy>
+ CallBase(AttributeList const &A, FunctionType *FT, ArgsTy &&... Args)
+ : BaseInstTy(std::forward<ArgsTy>(Args)...), Attrs(A), FTy(FT) {}
+ bool hasDescriptor() const { return Value::HasDescriptor; }
+
+ using BaseInstTy::BaseInstTy;
+
+ using OperandBundleUser<InstTy,
+ User::op_iterator>::isFnAttrDisallowedByOpBundle;
+ using OperandBundleUser<InstTy, User::op_iterator>::getNumTotalBundleOperands;
+ using OperandBundleUser<InstTy, User::op_iterator>::bundleOperandHasAttr;
+ using Instruction::getSubclassDataFromInstruction;
+ using Instruction::setInstructionSubclassData;
public:
- static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles = None,
- const Twine &NameStr = "",
- Instruction *InsertBefore = nullptr) {
- return Create(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, Bundles, NameStr, InsertBefore);
- }
-
- static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
- const Twine &NameStr,
- Instruction *InsertBefore = nullptr) {
- return Create(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, None, NameStr, InsertBefore);
- }
-
- static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> 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<Value *> Args,
- ArrayRef<OperandBundleDef> 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<Value *> Args,
- ArrayRef<OperandBundleDef> 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<Value *> Args,
- const Twine &NameStr, BasicBlock *InsertAtEnd) {
- return new (unsigned(Args.size() + 1))
- CallInst(Func, Args, None, NameStr, InsertAtEnd);
- }
+ using Instruction::getContext;
+ using OperandBundleUser<InstTy, User::op_iterator>::hasOperandBundles;
+ using OperandBundleUser<InstTy,
+ User::op_iterator>::getBundleOperandsStartIndex;
- 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);
+ static bool classof(const Instruction *I) {
+ llvm_unreachable(
+ "CallBase 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<OperandBundleDef> 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<OperandBundleDef> Bundles = None,
- Function* MallocF = nullptr,
- const Twine &Name = "");
- static Instruction *CreateMalloc(BasicBlock *InsertAtEnd,
- Type *IntPtrTy, Type *AllocTy,
- Value *AllocSize, Value *ArraySize = nullptr,
- ArrayRef<OperandBundleDef> 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<OperandBundleDef> Bundles,
- Instruction *InsertBefore);
- static Instruction *CreateFree(Value *Source,
- ArrayRef<OperandBundleDef> 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 @@ public:
}
/// 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<op_iterator> arg_operands() {
+ iterator_range<User::op_iterator> 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<const_op_iterator> arg_operands() const {
+ iterator_range<User::const_op_iterator> 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<CallBase>::op_begin(this);
+ }
+
+ User::const_op_iterator op_begin() const {
+ return OperandTraits<CallBase>::op_begin(const_cast<CallBase *>(this));
+ }
+
+ User::op_iterator op_end() { return OperandTraits<CallBase>::op_end(this); }
+
+ User::const_op_iterator op_end() const {
+ return OperandTraits<CallBase>::op_end(const_cast<CallBase *>(this));
+ }
+
+ Value *getOperand(unsigned i_nocapture) const {
+ assert(i_nocapture < OperandTraits<CallBase>::operands(this) &&
+ "getOperand() out of range!");
+ return cast_or_null<Value>(OperandTraits<CallBase>::op_begin(
+ const_cast<CallBase *>(this))[i_nocapture]
+ .get());
+ }
+
+ void setOperand(unsigned i_nocapture, Value *Val_nocapture) {
+ assert(i_nocapture < OperandTraits<CallBase>::operands(this) &&
+ "setOperand() out of range!");
+ OperandTraits<CallBase>::op_begin(this)[i_nocapture] = Val_nocapture;
+ }
+
+ unsigned getNumOperands() const {
+ return OperandTraits<CallBase>::operands(this);
+ }
+ template <int Idx_nocapture> Use &Op() {
+ return User::OpFrom<Idx_nocapture>(this);
+ }
+ template <int Idx_nocapture> const Use &Op() const {
+ return User::OpFrom<Idx_nocapture>(this);
+ }
+
+ /// Return the function called, or null if this is an
+ /// indirect function invocation.
+ ///
+ Function *getCalledFunction() const {
+ return dyn_cast<Function>(Op<-InstTy::ArgOffset>());
+ }
+
+ /// Determine whether this call has the given attribute.
+ bool hasFnAttr(Attribute::AttrKind Kind) const {
+ assert(Kind != Attribute::NoBuiltin &&
+ "Use CallBase::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 @@ public:
(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 @@ public:
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 @@ public:
/// \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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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<Function>(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 @@ public:
this->FTy = FTy;
assert(FTy == cast<FunctionType>(
cast<PointerType>(Fn->getType())->getElementType()));
- Op<-1>() = Fn;
- }
-
- /// Check if this call is an inline asm statement.
- bool isInlineAsm() const {
- return isa<InlineAsm>(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<Instruction>(V) && classof(cast<Instruction>(V));
- }
-
-private:
+protected:
template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
return true;
@@ -1920,7 +1863,227 @@ private:
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 CallBase<CallInst> {
+ friend class OperandBundleUser<CallInst, User::op_iterator>;
+
+ 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<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
+ Instruction *InsertBefore);
+
+ inline CallInst(Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : CallInst(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, Bundles, NameStr, InsertBefore) {}
+
+ inline CallInst(Value *Func, ArrayRef<Value *> 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<Value *> Args,
+ ArrayRef<OperandBundleDef> 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<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
+ init(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, Bundles, NameStr);
+ }
+ void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> 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<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ return Create(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, Bundles, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
+ const Twine &NameStr,
+ Instruction *InsertBefore = nullptr) {
+ return Create(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, None, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> 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<Value *> Args,
+ ArrayRef<OperandBundleDef> 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<Value *> Args,
+ ArrayRef<OperandBundleDef> 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<Value *> 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<OperandBundleDef> 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<OperandBundleDef> Bundles = None,
+ Function *MallocF = nullptr,
+ const Twine &Name = "");
+ static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy,
+ Type *AllocTy, Value *AllocSize,
+ Value *ArraySize = nullptr,
+ ArrayRef<OperandBundleDef> 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<OperandBundleDef> Bundles,
+ Instruction *InsertBefore);
+ static Instruction *CreateFree(Value *Source,
+ ArrayRef<OperandBundleDef> 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<InlineAsm>(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<Instruction>(V) && classof(cast<Instruction>(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 @@ private:
};
template <>
-struct OperandTraits<CallInst> : public VariadicOperandTraits<CallInst, 1> {
-};
+struct OperandTraits<CallBase<CallInst>>
+ : public VariadicOperandTraits<CallBase<CallInst>, 1> {};
CallInst::CallInst(Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
BasicBlock *InsertAtEnd)
- : Instruction(
- cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call, OperandTraits<CallInst>::op_end(this) -
- (Args.size() + CountBundleInputs(Bundles) + 1),
+ : CallBase<CallInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::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(Value *Func, ArrayRef
CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
Instruction *InsertBefore)
- : Instruction(Ty->getReturnType(), Instruction::Call,
- OperandTraits<CallInst>::op_end(this) -
- (Args.size() + CountBundleInputs(Bundles) + 1),
- unsigned(Args.size() + CountBundleInputs(Bundles) + 1),
- InsertBefore) {
+ : CallBase<CallInst>(Ty->getReturnType(), Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::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 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Ind
/// Invoke instruction. The SubclassData field is used to hold the
/// calling convention of the call.
///
-class InvokeInst : public TerminatorInst,
- public OperandBundleUser<InvokeInst, User::op_iterator> {
+class InvokeInst : public CallBase<InvokeInst> {
friend class OperandBundleUser<InvokeInst, User::op_iterator>;
- AttributeList Attrs;
- FunctionType *FTy;
-
InvokeInst(const InvokeInst &BI);
/// Construct an InvokeInst given a range of arguments.
@@ -3580,7 +3736,6 @@ class InvokeInst : public TerminatorInst
unsigned Values, const Twine &NameStr,
BasicBlock *InsertAtEnd);
- bool hasDescriptor() const { return HasDescriptor; }
void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles,
@@ -3601,6 +3756,7 @@ protected:
InvokeInst *cloneImpl() const;
public:
+ static constexpr int ArgOffset = 3;
static InvokeInst *Create(Value *Func, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
const Twine &NameStr,
@@ -3674,298 +3830,7 @@ public:
static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> 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<op_iterator> 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<const_op_iterator> 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<CallingConv::ID>(getSubclassDataFromInstruction());
- }
- void setCallingConv(CallingConv::ID CC) {
- auto ID = static_cast<unsigned>(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 @@ public:
}
private:
- template <typename AttrKind> 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 @@ private:
};
template <>
-struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> {
-};
+struct OperandTraits<CallBase<InvokeInst>>
+ : public VariadicOperandTraits<CallBase<InvokeInst>, 3> {};
InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, unsigned Values,
const Twine &NameStr, Instruction *InsertBefore)
- : TerminatorInst(Ty->getReturnType(), Instruction::Invoke,
- OperandTraits<InvokeInst>::op_end(this) - Values, Values,
- InsertBefore) {
+ : CallBase<InvokeInst>(Ty->getReturnType(), Instruction::Invoke,
+ OperandTraits<CallBase<InvokeInst>>::op_end(this) -
+ Values,
+ Values, InsertBefore) {
init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr);
}
@@ -4071,15 +3923,16 @@ InvokeInst::InvokeInst(Value *Func, Basi
BasicBlock *IfException, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, unsigned Values,
const Twine &NameStr, BasicBlock *InsertAtEnd)
- : TerminatorInst(
- cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Invoke, OperandTraits<InvokeInst>::op_end(this) - Values,
- Values, InsertAtEnd) {
+ : CallBase<InvokeInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Invoke,
+ OperandTraits<CallBase<InvokeInst>>::op_end(this) - Values, Values,
+ InsertAtEnd) {
init(Func, IfNormal, IfException, Args, Bundles, NameStr);
}
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value)
//===----------------------------------------------------------------------===//
// ResumeInst Class
Modified: llvm/trunk/lib/IR/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=325778&r1=325777&r2=325778&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Instructions.cpp (original)
+++ llvm/trunk/lib/IR/Instructions.cpp Thu Feb 22 05:30:32 2018
@@ -319,31 +319,32 @@ void CallInst::init(Value *Func, const T
setName(NameStr);
}
-CallInst::CallInst(Value *Func, const Twine &Name,
- Instruction *InsertBefore)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - 1,
- 1, InsertBefore) {
+CallInst::CallInst(Value *Func, const Twine &Name, Instruction *InsertBefore)
+ : CallBase<CallInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) - 1, 1,
+ InsertBefore) {
init(Func, Name);
}
-CallInst::CallInst(Value *Func, const Twine &Name,
- BasicBlock *InsertAtEnd)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - 1,
- 1, InsertAtEnd) {
+CallInst::CallInst(Value *Func, const Twine &Name, BasicBlock *InsertAtEnd)
+ : CallBase<CallInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) - 1, 1, InsertAtEnd) {
init(Func, Name);
}
CallInst::CallInst(const CallInst &CI)
- : Instruction(CI.getType(), Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
- CI.getNumOperands()),
- Attrs(CI.Attrs), FTy(CI.FTy) {
+ : CallBase<CallInst>(CI.Attrs, CI.FTy, CI.getType(), Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) -
+ CI.getNumOperands(),
+ CI.getNumOperands()) {
setTailCallKind(CI.getTailCallKind());
setCallingConv(CI.getCallingConv());
@@ -367,125 +368,14 @@ CallInst *CallInst::Create(CallInst *CI,
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 @@ void InvokeInst::init(FunctionType *FTy,
}
InvokeInst::InvokeInst(const InvokeInst &II)
- : TerminatorInst(II.getType(), Instruction::Invoke,
- OperandTraits<InvokeInst>::op_end(this) -
- II.getNumOperands(),
- II.getNumOperands()),
- Attrs(II.Attrs), FTy(II.FTy) {
+ : CallBase<InvokeInst>(II.Attrs, II.FTy, II.getType(), Instruction::Invoke,
+ OperandTraits<CallBase<InvokeInst>>::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 @@ InvokeInst *InvokeInst::Create(InvokeIns
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<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
More information about the llvm-commits
mailing list