Changeset View
Changeset View
Standalone View
Standalone View
include/llvm/IR/Instructions.h
Show First 20 Lines • Show All 1,340 Lines • ▼ Show 20 Lines | public: | ||||
static bool classof(const Instruction *I) { | static bool classof(const Instruction *I) { | ||||
return I->getOpcode() == Instruction::FCmp; | return I->getOpcode() == Instruction::FCmp; | ||||
} | } | ||||
static bool classof(const Value *V) { | static bool classof(const Value *V) { | ||||
return isa<Instruction>(V) && classof(cast<Instruction>(V)); | return isa<Instruction>(V) && classof(cast<Instruction>(V)); | ||||
} | } | ||||
}; | }; | ||||
template <class T> class CallableInst { | |||||
protected: | |||||
AttributeList Attrs; ///< parameter attributes for call | |||||
FunctionType *FTy; | |||||
public: | |||||
CallableInst() = default; | |||||
CallableInst(AttributeList Attrs, FunctionType *FTy) | |||||
: Attrs(Attrs), FTy(FTy) {} | |||||
FunctionType *getFunctionType() const { return FTy; } | |||||
void mutateFunctionType(FunctionType *FTy) { | |||||
static_cast<T *>(this)->mutateType(FTy->getReturnType()); | |||||
this->FTy = FTy; | |||||
} | |||||
/// 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) { | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.addAttribute(static_cast<T *>(this)->getContext(), i, Kind); | |||||
setAttributes(PAL); | |||||
} | |||||
/// adds the attribute to the list of attributes. | |||||
void addAttribute(unsigned i, Attribute Attr) { | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.addAttribute(static_cast<T *>(this)->getContext(), i, Attr); | |||||
setAttributes(PAL); | |||||
} | |||||
/// Adds the attribute to the indicated argument | |||||
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { | |||||
assert(ArgNo < static_cast<T *>(this)->getNumArgOperands() && | |||||
"Out of bounds"); | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.addParamAttribute(static_cast<T *>(this)->getContext(), ArgNo, | |||||
Kind); | |||||
setAttributes(PAL); | |||||
} | |||||
/// Adds the attribute to the indicated argument | |||||
void addParamAttr(unsigned ArgNo, Attribute Attr) { | |||||
assert(ArgNo < static_cast<T *>(this)->getNumArgOperands() && | |||||
"Out of bounds"); | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.addParamAttribute(static_cast<T *>(this)->getContext(), ArgNo, | |||||
Attr); | |||||
setAttributes(PAL); | |||||
} | |||||
/// removes the attribute from the list of attributes. | |||||
void removeAttribute(unsigned i, Attribute::AttrKind Kind) { | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.removeAttribute(static_cast<T *>(this)->getContext(), i, Kind); | |||||
setAttributes(PAL); | |||||
} | |||||
/// removes the attribute from the list of attributes. | |||||
void removeAttribute(unsigned i, StringRef Kind) { | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.removeAttribute(static_cast<T *>(this)->getContext(), i, Kind); | |||||
setAttributes(PAL); | |||||
} | |||||
/// Removes the attribute from the given argument | |||||
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { | |||||
assert(ArgNo < static_cast<T *>(this)->getNumArgOperands() && | |||||
"Out of bounds"); | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.removeParamAttribute(static_cast<T *>(this)->getContext(), ArgNo, | |||||
Kind); | |||||
setAttributes(PAL); | |||||
} | |||||
/// adds the dereferenceable attribute to the list of attributes. | |||||
void addDereferenceableAttr(unsigned i, uint64_t Bytes) { | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.addDereferenceableAttr(static_cast<T *>(this)->getContext(), i, | |||||
Bytes); | |||||
setAttributes(PAL); | |||||
} | |||||
/// adds the dereferenceable_or_null attribute to the list of | |||||
/// attributes. | |||||
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { | |||||
AttributeList PAL = getAttributes(); | |||||
PAL = PAL.addDereferenceableAttr(static_cast<T *>(this)->getContext(), i, | |||||
Bytes); | |||||
setAttributes(PAL); | |||||
} | |||||
/// 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 { | |||||
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 { | |||||
assert(ArgNo < static_cast<T const *>(this)->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 ArgNo, Attribute::AttrKind Kind) const { | |||||
return getAttributes().getAttribute(ArgNo, Kind); | |||||
} | |||||
/// Get the attribute of a given kind at a position. | |||||
Attribute getAttribute(unsigned ArgNo, StringRef Kind) const { | |||||
return getAttributes().getAttribute(ArgNo, Kind); | |||||
} | |||||
/// 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); | |||||
} | |||||
/// 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. | |||||
/// | |||||
Function *getCalledFunction() const { | |||||
return dyn_cast<Function>( | |||||
static_cast<T const *>(this)->template Op<T::CalledFunctionOffset>()); | |||||
} | |||||
/// Get a pointer to the function that is invoked by this | |||||
/// instruction | |||||
const Value *getCalledValue() const { | |||||
return static_cast<T const *>(this)->template Op<T::CalledFunctionOffset>(); | |||||
} | |||||
Value *getCalledValue() { | |||||
return static_cast<T *>(this)->template Op<T::CalledFunctionOffset>(); | |||||
} | |||||
/// Set the function called. | |||||
void setCalledFunction(Value *Fn) { | |||||
setCalledFunction( | |||||
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), | |||||
Fn); | |||||
} | |||||
void setCalledFunction(FunctionType *FTy, Value *Fn) { | |||||
this->FTy = FTy; | |||||
assert(FTy == cast<FunctionType>( | |||||
cast<PointerType>(Fn->getType())->getElementType())); | |||||
static_cast<T *>(this)->template Op<T::CalledFunctionOffset>() = Fn; | |||||
} | |||||
protected: | |||||
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 call instruction. | |||||
if (static_cast<T const *>(this)->isFnAttrDisallowedByOpBundle(Kind)) | |||||
return false; | |||||
if (const Function *F = getCalledFunction()) | |||||
return F->getAttributes().hasAttribute(AttributeList::FunctionIndex, | |||||
Kind); | |||||
return false; | |||||
} | |||||
}; | |||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
/// This class represents a function call, abstracting a target | /// This class represents a function call, abstracting a target | ||||
/// machine's calling convention. This class uses low bit of the SubClassData | /// 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 | /// field to indicate whether or not this is a tail call. The rest of the bits | ||||
/// hold the calling convention of the call. | /// hold the calling convention of the call. | ||||
/// | /// | ||||
class CallInst : public Instruction, | class CallInst : public Instruction, | ||||
public CallableInst<CallInst>, | |||||
public OperandBundleUser<CallInst, User::op_iterator> { | public OperandBundleUser<CallInst, User::op_iterator> { | ||||
friend class OperandBundleUser<CallInst, User::op_iterator>; | friend class OperandBundleUser<CallInst, User::op_iterator>; | ||||
AttributeList Attrs; ///< parameter attributes for call | |||||
FunctionType *FTy; | |||||
CallInst(const CallInst &CI); | CallInst(const CallInst &CI); | ||||
/// Construct a CallInst given a range of arguments. | /// Construct a CallInst given a range of arguments. | ||||
/// Construct a CallInst from a range of arguments | /// Construct a CallInst from a range of arguments | ||||
inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, | inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, | ||||
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, | ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, | ||||
Instruction *InsertBefore); | Instruction *InsertBefore); | ||||
Show All 27 Lines | class CallInst : public Instruction, | ||||
} | } | ||||
void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, | void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, | ||||
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr); | ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr); | ||||
void init(Value *Func, const Twine &NameStr); | void init(Value *Func, const Twine &NameStr); | ||||
bool hasDescriptor() const { return HasDescriptor; } | bool hasDescriptor() const { return HasDescriptor; } | ||||
protected: | protected: | ||||
// Note: Instruction needs to be a friend here to call cloneImpl. | // Note: Instruction needs to be a friend here to call cloneImpl. | ||||
vsk: nit: ", actually" -> "(InvokeInst and CallInst)." | |||||
friend class Instruction; | friend class Instruction; | ||||
template <class T> friend class ::llvm::CallableInst; | |||||
CallInst *cloneImpl() const; | CallInst *cloneImpl() const; | ||||
public: | public: | ||||
static int constexpr CalledFunctionOffset = -1; | |||||
static CallInst *Create(Value *Func, ArrayRef<Value *> Args, | static CallInst *Create(Value *Func, ArrayRef<Value *> Args, | ||||
ArrayRef<OperandBundleDef> Bundles = None, | ArrayRef<OperandBundleDef> Bundles = None, | ||||
const Twine &NameStr = "", | const Twine &NameStr = "", | ||||
Instruction *InsertBefore = nullptr) { | Instruction *InsertBefore = nullptr) { | ||||
return Create(cast<FunctionType>( | return Create(cast<FunctionType>( | ||||
cast<PointerType>(Func->getType())->getElementType()), | cast<PointerType>(Func->getType())->getElementType()), | ||||
Func, Args, Bundles, NameStr, InsertBefore); | Func, Args, Bundles, NameStr, InsertBefore); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | static Instruction *CreateFree(Value *Source, | ||||
BasicBlock *InsertAtEnd); | BasicBlock *InsertAtEnd); | ||||
static Instruction *CreateFree(Value *Source, | static Instruction *CreateFree(Value *Source, | ||||
ArrayRef<OperandBundleDef> Bundles, | ArrayRef<OperandBundleDef> Bundles, | ||||
Instruction *InsertBefore); | Instruction *InsertBefore); | ||||
static Instruction *CreateFree(Value *Source, | static Instruction *CreateFree(Value *Source, | ||||
ArrayRef<OperandBundleDef> Bundles, | ArrayRef<OperandBundleDef> Bundles, | ||||
BasicBlock *InsertAtEnd); | BasicBlock *InsertAtEnd); | ||||
FunctionType *getFunctionType() const { return FTy; } | |||||
void mutateFunctionType(FunctionType *FTy) { | |||||
mutateType(FTy->getReturnType()); | |||||
this->FTy = FTy; | |||||
} | |||||
// Note that 'musttail' implies 'tail'. | // Note that 'musttail' implies 'tail'. | ||||
enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2, | enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2, | ||||
TCK_NoTail = 3 }; | TCK_NoTail = 3 }; | ||||
TailCallKind getTailCallKind() const { | TailCallKind getTailCallKind() const { | ||||
return TailCallKind(getSubclassDataFromInstruction() & 3); | return TailCallKind(getSubclassDataFromInstruction() & 3); | ||||
} | } | ||||
bool isTailCall() const { | bool isTailCall() const { | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | public: | ||||
} | } | ||||
void setCallingConv(CallingConv::ID CC) { | void setCallingConv(CallingConv::ID CC) { | ||||
auto ID = static_cast<unsigned>(CC); | auto ID = static_cast<unsigned>(CC); | ||||
assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); | assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); | ||||
setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | | setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | | ||||
(ID << 2)); | (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); | |||||
/// 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); | |||||
/// Adds the attribute to the indicated argument | |||||
void addParamAttr(unsigned ArgNo, Attribute Attr); | |||||
/// 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); | |||||
/// Removes the attribute from the given argument | |||||
void removeParamAttr(unsigned ArgNo, StringRef 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); | |||||
} | |||||
/// Get the attribute of a given kind from a given arg | /// Get the attribute of a given kind from a given arg | ||||
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { | Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { | ||||
assert(ArgNo < getNumArgOperands() && "Out of bounds"); | assert(ArgNo < getNumArgOperands() && "Out of bounds"); | ||||
return getAttributes().getParamAttr(ArgNo, Kind); | return getAttributes().getParamAttr(ArgNo, Kind); | ||||
} | } | ||||
/// Get the attribute of a given kind from a given arg | /// Get the attribute of a given kind from a given arg | ||||
Show All 12 Lines | public: | ||||
/// The index \p i is interpreted as | /// The index \p i is interpreted as | ||||
/// | /// | ||||
/// \p i == Attribute::ReturnIndex -> the return value | /// \p i == Attribute::ReturnIndex -> the return value | ||||
/// \p i in [1, arg_size + 1) -> argument number (\p i - 1) | /// \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 in [arg_size + 1, data_operand_size + 1) -> bundle operand at index | ||||
/// (\p i - 1) in the operand list. | /// (\p i - 1) in the operand list. | ||||
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const; | 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 | /// Return true if the call should not be treated as a call to a | ||||
/// builtin. | /// builtin. | ||||
bool isNoBuiltin() const { | bool isNoBuiltin() const { | ||||
return hasFnAttrImpl(Attribute::NoBuiltin) && | return hasFnAttrImpl(Attribute::NoBuiltin) && | ||||
!hasFnAttrImpl(Attribute::Builtin); | !hasFnAttrImpl(Attribute::Builtin); | ||||
} | } | ||||
/// Determine if the call requires strict floating point semantics. | /// Determine if the call requires strict floating point semantics. | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | public: | ||||
bool hasStructRetAttr() const { | bool hasStructRetAttr() const { | ||||
if (getNumArgOperands() == 0) | if (getNumArgOperands() == 0) | ||||
return false; | return false; | ||||
// Be friendly and also check the callee. | // Be friendly and also check the callee. | ||||
return paramHasAttr(0, Attribute::StructRet); | 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. | |||||
/// | |||||
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>(); } | |||||
/// Set the function called. | |||||
void setCalledFunction(Value* Fn) { | |||||
setCalledFunction( | |||||
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), | |||||
Fn); | |||||
} | |||||
void setCalledFunction(FunctionType *FTy, Value *Fn) { | |||||
this->FTy = FTy; | |||||
assert(FTy == cast<FunctionType>( | |||||
cast<PointerType>(Fn->getType())->getElementType())); | |||||
Op<-1>() = Fn; | |||||
} | |||||
/// Check if this call is an inline asm statement. | /// Check if this call is an inline asm statement. | ||||
bool isInlineAsm() const { | bool isInlineAsm() const { | ||||
return isa<InlineAsm>(Op<-1>()); | return isa<InlineAsm>(Op<CalledFunctionOffset>()); | ||||
} | } | ||||
// Methods for support type inquiry through isa, cast, and dyn_cast: | // Methods for support type inquiry through isa, cast, and dyn_cast: | ||||
static bool classof(const Instruction *I) { | static bool classof(const Instruction *I) { | ||||
return I->getOpcode() == Instruction::Call; | return I->getOpcode() == Instruction::Call; | ||||
} | } | ||||
static bool classof(const Value *V) { | static bool classof(const Value *V) { | ||||
return isa<Instruction>(V) && classof(cast<Instruction>(V)); | return isa<Instruction>(V) && classof(cast<Instruction>(V)); | ||||
} | } | ||||
private: | 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 call 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 | // Shadow Instruction::setInstructionSubclassData with a private forwarding | ||||
// method so that subclasses cannot accidentally use it. | // method so that subclasses cannot accidentally use it. | ||||
void setInstructionSubclassData(unsigned short D) { | void setInstructionSubclassData(unsigned short D) { | ||||
Instruction::setInstructionSubclassData(D); | Instruction::setInstructionSubclassData(D); | ||||
} | } | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 1,612 Lines • ▼ Show 20 Lines | |||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// InvokeInst Class | // InvokeInst Class | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
/// Invoke instruction. The SubclassData field is used to hold the | /// Invoke instruction. The SubclassData field is used to hold the | ||||
/// calling convention of the call. | /// calling convention of the call. | ||||
/// | /// | ||||
class InvokeInst : public TerminatorInst, | class InvokeInst : public TerminatorInst, | ||||
public CallableInst<InvokeInst>, | |||||
public OperandBundleUser<InvokeInst, User::op_iterator> { | public OperandBundleUser<InvokeInst, User::op_iterator> { | ||||
friend class OperandBundleUser<InvokeInst, User::op_iterator>; | friend class OperandBundleUser<InvokeInst, User::op_iterator>; | ||||
template <class T> friend class ::llvm::CallableInst; | |||||
AttributeList Attrs; | |||||
FunctionType *FTy; | |||||
InvokeInst(const InvokeInst &BI); | InvokeInst(const InvokeInst &BI); | ||||
/// Construct an InvokeInst given a range of arguments. | /// Construct an InvokeInst given a range of arguments. | ||||
/// | /// | ||||
/// Construct an InvokeInst from a range of arguments | /// Construct an InvokeInst from a range of arguments | ||||
inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, | inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, | ||||
ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, | ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, | ||||
Show All 32 Lines | |||||
protected: | protected: | ||||
// Note: Instruction needs to be a friend here to call cloneImpl. | // Note: Instruction needs to be a friend here to call cloneImpl. | ||||
friend class Instruction; | friend class Instruction; | ||||
InvokeInst *cloneImpl() const; | InvokeInst *cloneImpl() const; | ||||
public: | public: | ||||
static int constexpr CalledFunctionOffset = -3; | |||||
static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, | static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, | ||||
BasicBlock *IfException, ArrayRef<Value *> Args, | BasicBlock *IfException, ArrayRef<Value *> Args, | ||||
const Twine &NameStr, | const Twine &NameStr, | ||||
Instruction *InsertBefore = nullptr) { | Instruction *InsertBefore = nullptr) { | ||||
return Create(cast<FunctionType>( | return Create(cast<FunctionType>( | ||||
cast<PointerType>(Func->getType())->getElementType()), | cast<PointerType>(Func->getType())->getElementType()), | ||||
Func, IfNormal, IfException, Args, None, NameStr, | Func, IfNormal, IfException, Args, None, NameStr, | ||||
InsertBefore); | InsertBefore); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | public: | ||||
/// that the operand bundles for the new instruction are set to the operand | /// that the operand bundles for the new instruction are set to the operand | ||||
/// bundles in \p Bundles. | /// bundles in \p Bundles. | ||||
static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> Bundles, | static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> Bundles, | ||||
Instruction *InsertPt = nullptr); | Instruction *InsertPt = nullptr); | ||||
/// Provide fast operand accessors | /// Provide fast operand accessors | ||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); | 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. | /// Return the number of invoke arguments. | ||||
/// | /// | ||||
unsigned getNumArgOperands() const { | unsigned getNumArgOperands() const { | ||||
return getNumOperands() - getNumTotalBundleOperands() - 3; | return getNumOperands() - getNumTotalBundleOperands() - 3; | ||||
} | } | ||||
/// getArgOperand/setArgOperand - Return/set the i-th invoke argument. | /// getArgOperand/setArgOperand - Return/set the i-th invoke argument. | ||||
/// | /// | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | CallingConv::ID getCallingConv() const { | ||||
return static_cast<CallingConv::ID>(getSubclassDataFromInstruction()); | return static_cast<CallingConv::ID>(getSubclassDataFromInstruction()); | ||||
} | } | ||||
void setCallingConv(CallingConv::ID CC) { | void setCallingConv(CallingConv::ID CC) { | ||||
auto ID = static_cast<unsigned>(CC); | auto ID = static_cast<unsigned>(CC); | ||||
assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); | assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); | ||||
setInstructionSubclassData(ID); | 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 | /// Return true if the data operand at index \p i has the attribute \p | ||||
/// A. | /// A. | ||||
/// | /// | ||||
/// Data operands include invoke arguments and values used in operand bundles, | /// Data operands include invoke arguments and values used in operand bundles, | ||||
/// but does not include the invokee operand, or the two successor blocks. | /// but does not include the invokee operand, or the two successor blocks. | ||||
/// This routine dispatches to the underlying AttributeList or the | /// This routine dispatches to the underlying AttributeList or the | ||||
/// OperandBundleUser as appropriate. | /// OperandBundleUser as appropriate. | ||||
/// | /// | ||||
/// The index \p i is interpreted as | /// The index \p i is interpreted as | ||||
/// | /// | ||||
/// \p i == Attribute::ReturnIndex -> the return value | /// \p i == Attribute::ReturnIndex -> the return value | ||||
/// \p i in [1, arg_size + 1) -> argument number (\p i - 1) | /// \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 in [arg_size + 1, data_operand_size + 1) -> bundle operand at index | ||||
/// (\p i - 1) in the operand list. | /// (\p i - 1) in the operand list. | ||||
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const; | 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 | /// Return true if the call should not be treated as a call to a | ||||
/// builtin. | /// builtin. | ||||
bool isNoBuiltin() const { | bool isNoBuiltin() const { | ||||
// We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have | // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have | ||||
// to check it by hand. | // to check it by hand. | ||||
return hasFnAttrImpl(Attribute::NoBuiltin) && | return hasFnAttrImpl(Attribute::NoBuiltin) && | ||||
!hasFnAttrImpl(Attribute::Builtin); | !hasFnAttrImpl(Attribute::Builtin); | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | public: | ||||
bool hasStructRetAttr() const { | bool hasStructRetAttr() const { | ||||
if (getNumArgOperands() == 0) | if (getNumArgOperands() == 0) | ||||
return false; | return false; | ||||
// Be friendly and also check the callee. | // Be friendly and also check the callee. | ||||
return paramHasAttr(0, Attribute::StructRet); | 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. | |||||
/// | |||||
Function *getCalledFunction() const { | |||||
return dyn_cast<Function>(Op<-3>()); | |||||
} | |||||
/// Get a pointer to the function that is invoked by this | |||||
/// instruction | |||||
const Value *getCalledValue() const { return Op<-3>(); } | |||||
Value *getCalledValue() { return Op<-3>(); } | |||||
/// Set the function called. | |||||
void setCalledFunction(Value* Fn) { | |||||
setCalledFunction( | |||||
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), | |||||
Fn); | |||||
} | |||||
void setCalledFunction(FunctionType *FTy, Value *Fn) { | |||||
this->FTy = FTy; | |||||
assert(FTy == cast<FunctionType>( | |||||
cast<PointerType>(Fn->getType())->getElementType())); | |||||
Op<-3>() = Fn; | |||||
} | |||||
// get*Dest - Return the destination basic blocks... | // get*Dest - Return the destination basic blocks... | ||||
BasicBlock *getNormalDest() const { | BasicBlock *getNormalDest() const { | ||||
return cast<BasicBlock>(Op<-2>()); | return cast<BasicBlock>(Op<-2>()); | ||||
} | } | ||||
BasicBlock *getUnwindDest() const { | BasicBlock *getUnwindDest() const { | ||||
return cast<BasicBlock>(Op<-1>()); | return cast<BasicBlock>(Op<-1>()); | ||||
} | } | ||||
Show All 24 Lines | public: | ||||
static bool classof(const Instruction *I) { | static bool classof(const Instruction *I) { | ||||
return (I->getOpcode() == Instruction::Invoke); | return (I->getOpcode() == Instruction::Invoke); | ||||
} | } | ||||
static bool classof(const Value *V) { | static bool classof(const Value *V) { | ||||
return isa<Instruction>(V) && classof(cast<Instruction>(V)); | return isa<Instruction>(V) && classof(cast<Instruction>(V)); | ||||
} | } | ||||
private: | 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 | // Shadow Instruction::setInstructionSubclassData with a private forwarding | ||||
// method so that subclasses cannot accidentally use it. | // method so that subclasses cannot accidentally use it. | ||||
void setInstructionSubclassData(unsigned short D) { | void setInstructionSubclassData(unsigned short D) { | ||||
Instruction::setInstructionSubclassData(D); | Instruction::setInstructionSubclassData(D); | ||||
} | } | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 1,140 Lines • Show Last 20 Lines |
nit: ", actually" -> "(InvokeInst and CallInst)."