summaryrefslogtreecommitdiff
path: root/include/llvm/IR/IntrinsicInst.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/IntrinsicInst.h')
-rw-r--r--include/llvm/IR/IntrinsicInst.h533
1 files changed, 289 insertions, 244 deletions
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index f55d17ec72c8a..2ca0a24cbae13 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -71,11 +71,35 @@ namespace llvm {
/// variable's value or its address.
Value *getVariableLocation(bool AllowNullOp = true) const;
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// Does this describe the address of a local variable. True for dbg.addr
+ /// and dbg.declare, but not dbg.value, which describes its value.
+ bool isAddressOfVariable() const {
+ return getIntrinsicID() != Intrinsic::dbg_value;
+ }
+
+ DILocalVariable *getVariable() const {
+ return cast<DILocalVariable>(getRawVariable());
+ }
+
+ DIExpression *getExpression() const {
+ return cast<DIExpression>(getRawExpression());
+ }
+
+ Metadata *getRawVariable() const {
+ return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();
+ }
+
+ Metadata *getRawExpression() const {
+ return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
+ }
+
+ /// \name Casting methods
+ /// @{
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_addr:
return true;
default: return false;
}
@@ -83,6 +107,7 @@ namespace llvm {
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
+ /// @}
};
/// This represents the llvm.dbg.declare instruction.
@@ -90,25 +115,26 @@ namespace llvm {
public:
Value *getAddress() const { return getVariableLocation(); }
- DILocalVariable *getVariable() const {
- return cast<DILocalVariable>(getRawVariable());
- }
-
- DIExpression *getExpression() const {
- return cast<DIExpression>(getRawExpression());
+ /// \name Casting methods
+ /// @{
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::dbg_declare;
}
-
- Metadata *getRawVariable() const {
- return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
+ /// @}
+ };
- Metadata *getRawExpression() const {
- return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
- }
+ /// This represents the llvm.dbg.addr instruction.
+ class DbgAddrIntrinsic : public DbgInfoIntrinsic {
+ public:
+ Value *getAddress() const { return getVariableLocation(); }
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// \name Casting methods
+ /// @{
static bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::dbg_declare;
+ return I->getIntrinsicID() == Intrinsic::dbg_addr;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
@@ -122,34 +148,15 @@ namespace llvm {
return getVariableLocation(/* AllowNullOp = */ false);
}
- uint64_t getOffset() const {
- return cast<ConstantInt>(
- const_cast<Value*>(getArgOperand(1)))->getZExtValue();
- }
-
- DILocalVariable *getVariable() const {
- return cast<DILocalVariable>(getRawVariable());
- }
-
- DIExpression *getExpression() const {
- return cast<DIExpression>(getRawExpression());
- }
-
- Metadata *getRawVariable() const {
- return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
- }
-
- Metadata *getRawExpression() const {
- return cast<MetadataAsValue>(getArgOperand(3))->getMetadata();
- }
-
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// \name Casting methods
+ /// @{
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_value;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
+ /// @}
};
/// This is the common base class for constrained floating point intrinsics.
@@ -172,6 +179,7 @@ namespace llvm {
};
bool isUnaryOp() const;
+ bool isTernaryOp() const;
RoundingMode getRoundingMode() const;
ExceptionBehavior getExceptionBehavior() const;
@@ -183,6 +191,7 @@ namespace llvm {
case Intrinsic::experimental_constrained_fmul:
case Intrinsic::experimental_constrained_fdiv:
case Intrinsic::experimental_constrained_frem:
+ case Intrinsic::experimental_constrained_fma:
case Intrinsic::experimental_constrained_sqrt:
case Intrinsic::experimental_constrained_pow:
case Intrinsic::experimental_constrained_powi:
@@ -204,12 +213,13 @@ namespace llvm {
}
};
- /// This class represents atomic memcpy intrinsic
- /// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is
- /// C&P of all methods from that hierarchy
- class ElementUnorderedAtomicMemCpyInst : public IntrinsicInst {
+ /// Common base class for all memory intrinsics. Simply provides
+ /// common methods.
+ /// Written as CRTP to avoid a common base class amongst the
+ /// three atomicity hierarchies.
+ template <typename Derived> class MemIntrinsicBase : public IntrinsicInst {
private:
- enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
+ enum { ARG_DEST = 0, ARG_LENGTH = 2 };
public:
Value *getRawDest() const {
@@ -218,51 +228,21 @@ namespace llvm {
const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
- /// Return the arguments to the instruction.
- Value *getRawSource() const {
- return const_cast<Value *>(getArgOperand(ARG_SOURCE));
- }
- const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
- Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
-
Value *getLength() const {
return const_cast<Value *>(getArgOperand(ARG_LENGTH));
}
const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
- bool isVolatile() const { return false; }
-
- Value *getRawElementSizeInBytes() const {
- return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
- }
-
- ConstantInt *getElementSizeInBytesCst() const {
- return cast<ConstantInt>(getRawElementSizeInBytes());
- }
-
- uint32_t getElementSizeInBytes() const {
- return getElementSizeInBytesCst()->getZExtValue();
- }
-
/// This is just like getRawDest, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
+ /// instructions (including addrspacecast) that feed it, giving the
+ /// original input. The returned value is guaranteed to be a pointer.
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
- /// This is just like getRawSource, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getSource() const { return getRawSource()->stripPointerCasts(); }
-
unsigned getDestAddressSpace() const {
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
}
- unsigned getSourceAddressSpace() const {
- return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
- }
-
/// Set the specified arguments of the instruction.
void setDest(Value *Ptr) {
assert(getRawDest()->getType() == Ptr->getType() &&
@@ -270,58 +250,20 @@ namespace llvm {
setArgOperand(ARG_DEST, Ptr);
}
- void setSource(Value *Ptr) {
- assert(getRawSource()->getType() == Ptr->getType() &&
- "setSource called with pointer of wrong type!");
- setArgOperand(ARG_SOURCE, Ptr);
- }
-
void setLength(Value *L) {
assert(getLength()->getType() == L->getType() &&
"setLength called with value of wrong type!");
setArgOperand(ARG_LENGTH, L);
}
-
- void setElementSizeInBytes(Constant *V) {
- assert(V->getType() == Type::getInt8Ty(getContext()) &&
- "setElementSizeInBytes called with value of wrong type!");
- setArgOperand(ARG_ELEMENTSIZE, V);
- }
-
- static bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
- }
- static bool classof(const Value *V) {
- return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
- }
};
- class ElementUnorderedAtomicMemMoveInst : public IntrinsicInst {
+ // The common base class for the atomic memset/memmove/memcpy intrinsics
+ // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
+ class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> {
private:
- enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
+ enum { ARG_ELEMENTSIZE = 3 };
public:
- Value *getRawDest() const {
- return const_cast<Value *>(getArgOperand(ARG_DEST));
- }
- const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
- Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
-
- /// Return the arguments to the instruction.
- Value *getRawSource() const {
- return const_cast<Value *>(getArgOperand(ARG_SOURCE));
- }
- const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
- Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
-
- Value *getLength() const {
- return const_cast<Value *>(getArgOperand(ARG_LENGTH));
- }
- const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
- Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
-
- bool isVolatile() const { return false; }
-
Value *getRawElementSizeInBytes() const {
return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
}
@@ -334,150 +276,129 @@ namespace llvm {
return getElementSizeInBytesCst()->getZExtValue();
}
- /// This is just like getRawDest, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getDest() const { return getRawDest()->stripPointerCasts(); }
-
- /// This is just like getRawSource, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getSource() const { return getRawSource()->stripPointerCasts(); }
-
- unsigned getDestAddressSpace() const {
- return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
- }
-
- unsigned getSourceAddressSpace() const {
- return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
- }
-
- /// Set the specified arguments of the instruction.
- void setDest(Value *Ptr) {
- assert(getRawDest()->getType() == Ptr->getType() &&
- "setDest called with pointer of wrong type!");
- setArgOperand(ARG_DEST, Ptr);
- }
-
- void setSource(Value *Ptr) {
- assert(getRawSource()->getType() == Ptr->getType() &&
- "setSource called with pointer of wrong type!");
- setArgOperand(ARG_SOURCE, Ptr);
- }
-
- void setLength(Value *L) {
- assert(getLength()->getType() == L->getType() &&
- "setLength called with value of wrong type!");
- setArgOperand(ARG_LENGTH, L);
- }
-
void setElementSizeInBytes(Constant *V) {
assert(V->getType() == Type::getInt8Ty(getContext()) &&
"setElementSizeInBytes called with value of wrong type!");
setArgOperand(ARG_ELEMENTSIZE, V);
}
- static inline bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memcpy_element_unordered_atomic:
+ case Intrinsic::memmove_element_unordered_atomic:
+ case Intrinsic::memset_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
}
- static inline bool classof(const Value *V) {
+ static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
};
/// This class represents atomic memset intrinsic
- /// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is
- /// C&P of all methods from that hierarchy
- class ElementUnorderedAtomicMemSetInst : public IntrinsicInst {
+ // i.e. llvm.element.unordered.atomic.memset
+ class AtomicMemSetInst : public AtomicMemIntrinsic {
private:
- enum { ARG_DEST = 0, ARG_VALUE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
+ enum { ARG_VALUE = 1 };
public:
- Value *getRawDest() const {
- return const_cast<Value *>(getArgOperand(ARG_DEST));
+ Value *getValue() const {
+ return const_cast<Value *>(getArgOperand(ARG_VALUE));
}
- const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
- Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
-
- Value *getValue() const { return const_cast<Value*>(getArgOperand(ARG_VALUE)); }
const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
- Value *getLength() const {
- return const_cast<Value *>(getArgOperand(ARG_LENGTH));
+ void setValue(Value *Val) {
+ assert(getValue()->getType() == Val->getType() &&
+ "setValue called with value of wrong type!");
+ setArgOperand(ARG_VALUE, Val);
}
- const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
- Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
-
- bool isVolatile() const { return false; }
- Value *getRawElementSizeInBytes() const {
- return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
}
-
- ConstantInt *getElementSizeInBytesCst() const {
- return cast<ConstantInt>(getRawElementSizeInBytes());
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
+ };
- uint32_t getElementSizeInBytes() const {
- return getElementSizeInBytesCst()->getZExtValue();
+ // This class wraps the atomic memcpy/memmove intrinsics
+ // i.e. llvm.element.unordered.atomic.memcpy/memmove
+ class AtomicMemTransferInst : public AtomicMemIntrinsic {
+ private:
+ enum { ARG_SOURCE = 1 };
+
+ public:
+ /// Return the arguments to the instruction.
+ Value *getRawSource() const {
+ return const_cast<Value *>(getArgOperand(ARG_SOURCE));
}
+ const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
+ Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
- /// This is just like getRawDest, but it strips off any cast
+ /// This is just like getRawSource, but it strips off any cast
/// instructions that feed it, giving the original input. The returned
/// value is guaranteed to be a pointer.
- Value *getDest() const { return getRawDest()->stripPointerCasts(); }
+ Value *getSource() const { return getRawSource()->stripPointerCasts(); }
- unsigned getDestAddressSpace() const {
- return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
+ unsigned getSourceAddressSpace() const {
+ return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
}
- /// Set the specified arguments of the instruction.
- void setDest(Value *Ptr) {
- assert(getRawDest()->getType() == Ptr->getType() &&
- "setDest called with pointer of wrong type!");
- setArgOperand(ARG_DEST, Ptr);
+ void setSource(Value *Ptr) {
+ assert(getRawSource()->getType() == Ptr->getType() &&
+ "setSource called with pointer of wrong type!");
+ setArgOperand(ARG_SOURCE, Ptr);
}
- void setValue(Value *Val) {
- assert(getValue()->getType() == Val->getType() &&
- "setValue called with value of wrong type!");
- setArgOperand(ARG_VALUE, Val);
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memcpy_element_unordered_atomic:
+ case Intrinsic::memmove_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
}
-
- void setLength(Value *L) {
- assert(getLength()->getType() == L->getType() &&
- "setLength called with value of wrong type!");
- setArgOperand(ARG_LENGTH, L);
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
+ };
- void setElementSizeInBytes(Constant *V) {
- assert(V->getType() == Type::getInt8Ty(getContext()) &&
- "setElementSizeInBytes called with value of wrong type!");
- setArgOperand(ARG_ELEMENTSIZE, V);
+ /// This class represents the atomic memcpy intrinsic
+ /// i.e. llvm.element.unordered.atomic.memcpy
+ class AtomicMemCpyInst : public AtomicMemTransferInst {
+ public:
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
+ };
- static inline bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
+ /// This class represents the atomic memmove intrinsic
+ /// i.e. llvm.element.unordered.atomic.memmove
+ class AtomicMemMoveInst : public AtomicMemTransferInst {
+ public:
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;
}
- static inline bool classof(const Value *V) {
+ static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
};
/// This is the common base class for memset/memcpy/memmove.
- class MemIntrinsic : public IntrinsicInst {
- public:
- Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); }
- const Use &getRawDestUse() const { return getArgOperandUse(0); }
- Use &getRawDestUse() { return getArgOperandUse(0); }
-
- Value *getLength() const { return const_cast<Value*>(getArgOperand(2)); }
- const Use &getLengthUse() const { return getArgOperandUse(2); }
- Use &getLengthUse() { return getArgOperandUse(2); }
+ class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> {
+ private:
+ enum { ARG_ALIGN = 3, ARG_VOLATILE = 4 };
+ public:
ConstantInt *getAlignmentCst() const {
- return cast<ConstantInt>(const_cast<Value*>(getArgOperand(3)));
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_ALIGN)));
}
unsigned getAlignment() const {
@@ -485,45 +406,20 @@ namespace llvm {
}
ConstantInt *getVolatileCst() const {
- return cast<ConstantInt>(const_cast<Value*>(getArgOperand(4)));
+ return cast<ConstantInt>(
+ const_cast<Value *>(getArgOperand(ARG_VOLATILE)));
}
bool isVolatile() const {
return !getVolatileCst()->isZero();
}
- unsigned getDestAddressSpace() const {
- return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
- }
-
- /// This is just like getRawDest, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getDest() const { return getRawDest()->stripPointerCasts(); }
-
- /// Set the specified arguments of the instruction.
- void setDest(Value *Ptr) {
- assert(getRawDest()->getType() == Ptr->getType() &&
- "setDest called with pointer of wrong type!");
- setArgOperand(0, Ptr);
- }
-
- void setLength(Value *L) {
- assert(getLength()->getType() == L->getType() &&
- "setLength called with value of wrong type!");
- setArgOperand(2, L);
- }
-
- void setAlignment(Constant* A) {
- setArgOperand(3, A);
- }
+ void setAlignment(Constant *A) { setArgOperand(ARG_ALIGN, A); }
- void setVolatile(Constant* V) {
- setArgOperand(4, V);
- }
+ void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); }
Type *getAlignmentType() const {
- return getArgOperand(3)->getType();
+ return getArgOperand(ARG_ALIGN)->getType();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -621,6 +517,155 @@ namespace llvm {
}
};
+ // The common base class for any memset/memmove/memcpy intrinsics;
+ // whether they be atomic or non-atomic.
+ // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
+ // and llvm.memset/memcpy/memmove
+ class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> {
+ public:
+ bool isVolatile() const {
+ // Only the non-atomic intrinsics can be volatile
+ if (auto *MI = dyn_cast<MemIntrinsic>(this))
+ return MI->isVolatile();
+ return false;
+ }
+
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memcpy:
+ case Intrinsic::memmove:
+ case Intrinsic::memset:
+ case Intrinsic::memcpy_element_unordered_atomic:
+ case Intrinsic::memmove_element_unordered_atomic:
+ case Intrinsic::memset_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
+ /// This class represents any memset intrinsic
+ // i.e. llvm.element.unordered.atomic.memset
+ // and llvm.memset
+ class AnyMemSetInst : public AnyMemIntrinsic {
+ private:
+ enum { ARG_VALUE = 1 };
+
+ public:
+ Value *getValue() const {
+ return const_cast<Value *>(getArgOperand(ARG_VALUE));
+ }
+ const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
+ Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
+
+ void setValue(Value *Val) {
+ assert(getValue()->getType() == Val->getType() &&
+ "setValue called with value of wrong type!");
+ setArgOperand(ARG_VALUE, Val);
+ }
+
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memset:
+ case Intrinsic::memset_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
+ // This class wraps any memcpy/memmove intrinsics
+ // i.e. llvm.element.unordered.atomic.memcpy/memmove
+ // and llvm.memcpy/memmove
+ class AnyMemTransferInst : public AnyMemIntrinsic {
+ private:
+ enum { ARG_SOURCE = 1 };
+
+ public:
+ /// Return the arguments to the instruction.
+ Value *getRawSource() const {
+ return const_cast<Value *>(getArgOperand(ARG_SOURCE));
+ }
+ const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
+ Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
+
+ /// This is just like getRawSource, but it strips off any cast
+ /// instructions that feed it, giving the original input. The returned
+ /// value is guaranteed to be a pointer.
+ Value *getSource() const { return getRawSource()->stripPointerCasts(); }
+
+ unsigned getSourceAddressSpace() const {
+ return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
+ }
+
+ void setSource(Value *Ptr) {
+ assert(getRawSource()->getType() == Ptr->getType() &&
+ "setSource called with pointer of wrong type!");
+ setArgOperand(ARG_SOURCE, Ptr);
+ }
+
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memcpy:
+ case Intrinsic::memmove:
+ case Intrinsic::memcpy_element_unordered_atomic:
+ case Intrinsic::memmove_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
+ /// This class represents any memcpy intrinsic
+ /// i.e. llvm.element.unordered.atomic.memcpy
+ /// and llvm.memcpy
+ class AnyMemCpyInst : public AnyMemTransferInst {
+ public:
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memcpy:
+ case Intrinsic::memcpy_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
+ /// This class represents any memmove intrinsic
+ /// i.e. llvm.element.unordered.atomic.memmove
+ /// and llvm.memmove
+ class AnyMemMoveInst : public AnyMemTransferInst {
+ public:
+ static bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::memmove:
+ case Intrinsic::memmove_element_unordered_atomic:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
/// This represents the llvm.va_start intrinsic.
class VAStartInst : public IntrinsicInst {
public: