• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines classes that make it really easy to deal with intrinsic
10 // functions with the isa/dyncast family of functions.  In particular, this
11 // allows you to do things like:
12 //
13 //     if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst))
14 //        ... MCI->getDest() ... MCI->getSource() ...
15 //
16 // All intrinsic function calls are instances of the call instruction, so these
17 // are all subclasses of the CallInst class.  Note that none of these classes
18 // has state or virtual methods, which is an important part of this gross/neat
19 // hack working.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 #ifndef LLVM_IR_INTRINSICINST_H
24 #define LLVM_IR_INTRINSICINST_H
25 
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/FPEnv.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/GlobalVariable.h"
31 #include "llvm/IR/Instructions.h"
32 #include "llvm/IR/Intrinsics.h"
33 #include "llvm/IR/Metadata.h"
34 #include "llvm/IR/Value.h"
35 #include "llvm/Support/Casting.h"
36 #include <cassert>
37 #include <cstdint>
38 
39 namespace llvm {
40 
41   /// A wrapper class for inspecting calls to intrinsic functions.
42   /// This allows the standard isa/dyncast/cast functionality to work with calls
43   /// to intrinsic functions.
44   class IntrinsicInst : public CallInst {
45   public:
46     IntrinsicInst() = delete;
47     IntrinsicInst(const IntrinsicInst &) = delete;
48     IntrinsicInst &operator=(const IntrinsicInst &) = delete;
49 
50     /// Return the intrinsic ID of this intrinsic.
getIntrinsicID()51     Intrinsic::ID getIntrinsicID() const {
52       return getCalledFunction()->getIntrinsicID();
53     }
54 
55     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const CallInst * I)56     static bool classof(const CallInst *I) {
57       if (const Function *CF = I->getCalledFunction())
58         return CF->isIntrinsic();
59       return false;
60     }
classof(const Value * V)61     static bool classof(const Value *V) {
62       return isa<CallInst>(V) && classof(cast<CallInst>(V));
63     }
64   };
65 
66   /// This is the common base class for debug info intrinsics.
67   class DbgInfoIntrinsic : public IntrinsicInst {
68   public:
69     /// \name Casting methods
70     /// @{
classof(const IntrinsicInst * I)71     static bool classof(const IntrinsicInst *I) {
72       switch (I->getIntrinsicID()) {
73       case Intrinsic::dbg_declare:
74       case Intrinsic::dbg_value:
75       case Intrinsic::dbg_addr:
76       case Intrinsic::dbg_label:
77         return true;
78       default: return false;
79       }
80     }
classof(const Value * V)81     static bool classof(const Value *V) {
82       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
83     }
84     /// @}
85   };
86 
87   /// This is the common base class for debug info intrinsics for variables.
88   class DbgVariableIntrinsic : public DbgInfoIntrinsic {
89   public:
90     /// Get the location corresponding to the variable referenced by the debug
91     /// info intrinsic.  Depending on the intrinsic, this could be the
92     /// variable's value or its address.
93     Value *getVariableLocation(bool AllowNullOp = true) const;
94 
95     /// Does this describe the address of a local variable. True for dbg.addr
96     /// and dbg.declare, but not dbg.value, which describes its value.
isAddressOfVariable()97     bool isAddressOfVariable() const {
98       return getIntrinsicID() != Intrinsic::dbg_value;
99     }
100 
getVariable()101     DILocalVariable *getVariable() const {
102       return cast<DILocalVariable>(getRawVariable());
103     }
104 
getExpression()105     DIExpression *getExpression() const {
106       return cast<DIExpression>(getRawExpression());
107     }
108 
getRawVariable()109     Metadata *getRawVariable() const {
110       return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();
111     }
112 
getRawExpression()113     Metadata *getRawExpression() const {
114       return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
115     }
116 
117     /// Get the size (in bits) of the variable, or fragment of the variable that
118     /// is described.
119     Optional<uint64_t> getFragmentSizeInBits() const;
120 
121     /// \name Casting methods
122     /// @{
classof(const IntrinsicInst * I)123     static bool classof(const IntrinsicInst *I) {
124       switch (I->getIntrinsicID()) {
125       case Intrinsic::dbg_declare:
126       case Intrinsic::dbg_value:
127       case Intrinsic::dbg_addr:
128         return true;
129       default: return false;
130       }
131     }
classof(const Value * V)132     static bool classof(const Value *V) {
133       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
134     }
135     /// @}
136   };
137 
138   /// This represents the llvm.dbg.declare instruction.
139   class DbgDeclareInst : public DbgVariableIntrinsic {
140   public:
getAddress()141     Value *getAddress() const { return getVariableLocation(); }
142 
143     /// \name Casting methods
144     /// @{
classof(const IntrinsicInst * I)145     static bool classof(const IntrinsicInst *I) {
146       return I->getIntrinsicID() == Intrinsic::dbg_declare;
147     }
classof(const Value * V)148     static bool classof(const Value *V) {
149       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
150     }
151     /// @}
152   };
153 
154   /// This represents the llvm.dbg.addr instruction.
155   class DbgAddrIntrinsic : public DbgVariableIntrinsic {
156   public:
getAddress()157     Value *getAddress() const { return getVariableLocation(); }
158 
159     /// \name Casting methods
160     /// @{
classof(const IntrinsicInst * I)161     static bool classof(const IntrinsicInst *I) {
162       return I->getIntrinsicID() == Intrinsic::dbg_addr;
163     }
classof(const Value * V)164     static bool classof(const Value *V) {
165       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
166     }
167   };
168 
169   /// This represents the llvm.dbg.value instruction.
170   class DbgValueInst : public DbgVariableIntrinsic {
171   public:
getValue()172     Value *getValue() const {
173       return getVariableLocation(/* AllowNullOp = */ false);
174     }
175 
176     /// \name Casting methods
177     /// @{
classof(const IntrinsicInst * I)178     static bool classof(const IntrinsicInst *I) {
179       return I->getIntrinsicID() == Intrinsic::dbg_value;
180     }
classof(const Value * V)181     static bool classof(const Value *V) {
182       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
183     }
184     /// @}
185   };
186 
187   /// This represents the llvm.dbg.label instruction.
188   class DbgLabelInst : public DbgInfoIntrinsic {
189   public:
getLabel()190     DILabel *getLabel() const {
191       return cast<DILabel>(getRawLabel());
192     }
193 
getRawLabel()194     Metadata *getRawLabel() const {
195       return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();
196     }
197 
198     /// Methods for support type inquiry through isa, cast, and dyn_cast:
199     /// @{
classof(const IntrinsicInst * I)200     static bool classof(const IntrinsicInst *I) {
201       return I->getIntrinsicID() == Intrinsic::dbg_label;
202     }
classof(const Value * V)203     static bool classof(const Value *V) {
204       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
205     }
206     /// @}
207   };
208 
209   /// This is the common base class for constrained floating point intrinsics.
210   class ConstrainedFPIntrinsic : public IntrinsicInst {
211   public:
212     bool isUnaryOp() const;
213     bool isTernaryOp() const;
214     Optional<fp::RoundingMode> getRoundingMode() const;
215     Optional<fp::ExceptionBehavior> getExceptionBehavior() const;
216 
217     // Methods for support type inquiry through isa, cast, and dyn_cast:
218     static bool classof(const IntrinsicInst *I);
classof(const Value * V)219     static bool classof(const Value *V) {
220       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
221     }
222   };
223 
224   /// Constrained floating point compare intrinsics.
225   class ConstrainedFPCmpIntrinsic : public ConstrainedFPIntrinsic {
226   public:
227     FCmpInst::Predicate getPredicate() const;
228 
229     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)230     static bool classof(const IntrinsicInst *I) {
231       switch (I->getIntrinsicID()) {
232       case Intrinsic::experimental_constrained_fcmp:
233       case Intrinsic::experimental_constrained_fcmps:
234         return true;
235       default: return false;
236       }
237     }
classof(const Value * V)238     static bool classof(const Value *V) {
239       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
240     }
241   };
242 
243   /// This class represents an intrinsic that is based on a binary operation.
244   /// This includes op.with.overflow and saturating add/sub intrinsics.
245   class BinaryOpIntrinsic : public IntrinsicInst {
246   public:
classof(const IntrinsicInst * I)247     static bool classof(const IntrinsicInst *I) {
248       switch (I->getIntrinsicID()) {
249       case Intrinsic::uadd_with_overflow:
250       case Intrinsic::sadd_with_overflow:
251       case Intrinsic::usub_with_overflow:
252       case Intrinsic::ssub_with_overflow:
253       case Intrinsic::umul_with_overflow:
254       case Intrinsic::smul_with_overflow:
255       case Intrinsic::uadd_sat:
256       case Intrinsic::sadd_sat:
257       case Intrinsic::usub_sat:
258       case Intrinsic::ssub_sat:
259         return true;
260       default:
261         return false;
262       }
263     }
classof(const Value * V)264     static bool classof(const Value *V) {
265       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
266     }
267 
getLHS()268     Value *getLHS() const { return const_cast<Value*>(getArgOperand(0)); }
getRHS()269     Value *getRHS() const { return const_cast<Value*>(getArgOperand(1)); }
270 
271     /// Returns the binary operation underlying the intrinsic.
272     Instruction::BinaryOps getBinaryOp() const;
273 
274     /// Whether the intrinsic is signed or unsigned.
275     bool isSigned() const;
276 
277     /// Returns one of OBO::NoSignedWrap or OBO::NoUnsignedWrap.
278     unsigned getNoWrapKind() const;
279   };
280 
281   /// Represents an op.with.overflow intrinsic.
282   class WithOverflowInst : public BinaryOpIntrinsic {
283   public:
classof(const IntrinsicInst * I)284     static bool classof(const IntrinsicInst *I) {
285       switch (I->getIntrinsicID()) {
286       case Intrinsic::uadd_with_overflow:
287       case Intrinsic::sadd_with_overflow:
288       case Intrinsic::usub_with_overflow:
289       case Intrinsic::ssub_with_overflow:
290       case Intrinsic::umul_with_overflow:
291       case Intrinsic::smul_with_overflow:
292         return true;
293       default:
294         return false;
295       }
296     }
classof(const Value * V)297     static bool classof(const Value *V) {
298       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
299     }
300   };
301 
302   /// Represents a saturating add/sub intrinsic.
303   class SaturatingInst : public BinaryOpIntrinsic {
304   public:
classof(const IntrinsicInst * I)305     static bool classof(const IntrinsicInst *I) {
306       switch (I->getIntrinsicID()) {
307       case Intrinsic::uadd_sat:
308       case Intrinsic::sadd_sat:
309       case Intrinsic::usub_sat:
310       case Intrinsic::ssub_sat:
311         return true;
312       default:
313         return false;
314       }
315     }
classof(const Value * V)316     static bool classof(const Value *V) {
317       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
318     }
319   };
320 
321   /// Common base class for all memory intrinsics. Simply provides
322   /// common methods.
323   /// Written as CRTP to avoid a common base class amongst the
324   /// three atomicity hierarchies.
325   template <typename Derived> class MemIntrinsicBase : public IntrinsicInst {
326   private:
327     enum { ARG_DEST = 0, ARG_LENGTH = 2 };
328 
329   public:
getRawDest()330     Value *getRawDest() const {
331       return const_cast<Value *>(getArgOperand(ARG_DEST));
332     }
getRawDestUse()333     const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
getRawDestUse()334     Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
335 
getLength()336     Value *getLength() const {
337       return const_cast<Value *>(getArgOperand(ARG_LENGTH));
338     }
getLengthUse()339     const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
getLengthUse()340     Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
341 
342     /// This is just like getRawDest, but it strips off any cast
343     /// instructions (including addrspacecast) that feed it, giving the
344     /// original input.  The returned value is guaranteed to be a pointer.
getDest()345     Value *getDest() const { return getRawDest()->stripPointerCasts(); }
346 
getDestAddressSpace()347     unsigned getDestAddressSpace() const {
348       return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
349     }
350 
351     /// FIXME: Remove this function once transition to Align is over.
352     /// Use getDestAlign() instead.
getDestAlignment()353     unsigned getDestAlignment() const { return getParamAlignment(ARG_DEST); }
getDestAlign()354     MaybeAlign getDestAlign() const { return getParamAlign(ARG_DEST); }
355 
356     /// Set the specified arguments of the instruction.
setDest(Value * Ptr)357     void setDest(Value *Ptr) {
358       assert(getRawDest()->getType() == Ptr->getType() &&
359              "setDest called with pointer of wrong type!");
360       setArgOperand(ARG_DEST, Ptr);
361     }
362 
363     /// FIXME: Remove this function once transition to Align is over.
364     /// Use the version that takes MaybeAlign instead of this one.
setDestAlignment(unsigned Alignment)365     void setDestAlignment(unsigned Alignment) {
366       setDestAlignment(MaybeAlign(Alignment));
367     }
setDestAlignment(MaybeAlign Alignment)368     void setDestAlignment(MaybeAlign Alignment) {
369       removeParamAttr(ARG_DEST, Attribute::Alignment);
370       if (Alignment)
371         addParamAttr(ARG_DEST,
372                      Attribute::getWithAlignment(getContext(), *Alignment));
373     }
setDestAlignment(Align Alignment)374     void setDestAlignment(Align Alignment) {
375       removeParamAttr(ARG_DEST, Attribute::Alignment);
376       addParamAttr(ARG_DEST,
377                    Attribute::getWithAlignment(getContext(), Alignment));
378     }
379 
setLength(Value * L)380     void setLength(Value *L) {
381       assert(getLength()->getType() == L->getType() &&
382              "setLength called with value of wrong type!");
383       setArgOperand(ARG_LENGTH, L);
384     }
385   };
386 
387   /// Common base class for all memory transfer intrinsics. Simply provides
388   /// common methods.
389   template <class BaseCL> class MemTransferBase : public BaseCL {
390   private:
391     enum { ARG_SOURCE = 1 };
392 
393   public:
394     /// Return the arguments to the instruction.
getRawSource()395     Value *getRawSource() const {
396       return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE));
397     }
getRawSourceUse()398     const Use &getRawSourceUse() const {
399       return BaseCL::getArgOperandUse(ARG_SOURCE);
400     }
getRawSourceUse()401     Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); }
402 
403     /// This is just like getRawSource, but it strips off any cast
404     /// instructions that feed it, giving the original input.  The returned
405     /// value is guaranteed to be a pointer.
getSource()406     Value *getSource() const { return getRawSource()->stripPointerCasts(); }
407 
getSourceAddressSpace()408     unsigned getSourceAddressSpace() const {
409       return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
410     }
411 
412     /// FIXME: Remove this function once transition to Align is over.
413     /// Use getSourceAlign() instead.
getSourceAlignment()414     unsigned getSourceAlignment() const {
415       return BaseCL::getParamAlignment(ARG_SOURCE);
416     }
417 
getSourceAlign()418     MaybeAlign getSourceAlign() const {
419       return BaseCL::getParamAlign(ARG_SOURCE);
420     }
421 
setSource(Value * Ptr)422     void setSource(Value *Ptr) {
423       assert(getRawSource()->getType() == Ptr->getType() &&
424              "setSource called with pointer of wrong type!");
425       BaseCL::setArgOperand(ARG_SOURCE, Ptr);
426     }
427 
428     /// FIXME: Remove this function once transition to Align is over.
429     /// Use the version that takes MaybeAlign instead of this one.
setSourceAlignment(unsigned Alignment)430     void setSourceAlignment(unsigned Alignment) {
431       setSourceAlignment(MaybeAlign(Alignment));
432     }
setSourceAlignment(MaybeAlign Alignment)433     void setSourceAlignment(MaybeAlign Alignment) {
434       BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment);
435       if (Alignment)
436         BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment(
437                                              BaseCL::getContext(), *Alignment));
438     }
setSourceAlignment(Align Alignment)439     void setSourceAlignment(Align Alignment) {
440       BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment);
441       BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment(
442                                            BaseCL::getContext(), Alignment));
443     }
444   };
445 
446   /// Common base class for all memset intrinsics. Simply provides
447   /// common methods.
448   template <class BaseCL> class MemSetBase : public BaseCL {
449   private:
450     enum { ARG_VALUE = 1 };
451 
452   public:
getValue()453     Value *getValue() const {
454       return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE));
455     }
getValueUse()456     const Use &getValueUse() const {
457       return BaseCL::getArgOperandUse(ARG_VALUE);
458     }
getValueUse()459     Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); }
460 
setValue(Value * Val)461     void setValue(Value *Val) {
462       assert(getValue()->getType() == Val->getType() &&
463              "setValue called with value of wrong type!");
464       BaseCL::setArgOperand(ARG_VALUE, Val);
465     }
466   };
467 
468   // The common base class for the atomic memset/memmove/memcpy intrinsics
469   // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
470   class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> {
471   private:
472     enum { ARG_ELEMENTSIZE = 3 };
473 
474   public:
getRawElementSizeInBytes()475     Value *getRawElementSizeInBytes() const {
476       return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
477     }
478 
getElementSizeInBytesCst()479     ConstantInt *getElementSizeInBytesCst() const {
480       return cast<ConstantInt>(getRawElementSizeInBytes());
481     }
482 
getElementSizeInBytes()483     uint32_t getElementSizeInBytes() const {
484       return getElementSizeInBytesCst()->getZExtValue();
485     }
486 
setElementSizeInBytes(Constant * V)487     void setElementSizeInBytes(Constant *V) {
488       assert(V->getType() == Type::getInt8Ty(getContext()) &&
489              "setElementSizeInBytes called with value of wrong type!");
490       setArgOperand(ARG_ELEMENTSIZE, V);
491     }
492 
classof(const IntrinsicInst * I)493     static bool classof(const IntrinsicInst *I) {
494       switch (I->getIntrinsicID()) {
495       case Intrinsic::memcpy_element_unordered_atomic:
496       case Intrinsic::memmove_element_unordered_atomic:
497       case Intrinsic::memset_element_unordered_atomic:
498         return true;
499       default:
500         return false;
501       }
502     }
classof(const Value * V)503     static bool classof(const Value *V) {
504       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
505     }
506   };
507 
508   /// This class represents atomic memset intrinsic
509   // i.e. llvm.element.unordered.atomic.memset
510   class AtomicMemSetInst : public MemSetBase<AtomicMemIntrinsic> {
511   public:
classof(const IntrinsicInst * I)512     static bool classof(const IntrinsicInst *I) {
513       return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
514     }
classof(const Value * V)515     static bool classof(const Value *V) {
516       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
517     }
518   };
519 
520   // This class wraps the atomic memcpy/memmove intrinsics
521   // i.e. llvm.element.unordered.atomic.memcpy/memmove
522   class AtomicMemTransferInst : public MemTransferBase<AtomicMemIntrinsic> {
523   public:
classof(const IntrinsicInst * I)524     static bool classof(const IntrinsicInst *I) {
525       switch (I->getIntrinsicID()) {
526       case Intrinsic::memcpy_element_unordered_atomic:
527       case Intrinsic::memmove_element_unordered_atomic:
528         return true;
529       default:
530         return false;
531       }
532     }
classof(const Value * V)533     static bool classof(const Value *V) {
534       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
535     }
536   };
537 
538   /// This class represents the atomic memcpy intrinsic
539   /// i.e. llvm.element.unordered.atomic.memcpy
540   class AtomicMemCpyInst : public AtomicMemTransferInst {
541   public:
classof(const IntrinsicInst * I)542     static bool classof(const IntrinsicInst *I) {
543       return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
544     }
classof(const Value * V)545     static bool classof(const Value *V) {
546       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
547     }
548   };
549 
550   /// This class represents the atomic memmove intrinsic
551   /// i.e. llvm.element.unordered.atomic.memmove
552   class AtomicMemMoveInst : public AtomicMemTransferInst {
553   public:
classof(const IntrinsicInst * I)554     static bool classof(const IntrinsicInst *I) {
555       return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;
556     }
classof(const Value * V)557     static bool classof(const Value *V) {
558       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
559     }
560   };
561 
562   /// This is the common base class for memset/memcpy/memmove.
563   class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> {
564   private:
565     enum { ARG_VOLATILE = 3 };
566 
567   public:
getVolatileCst()568     ConstantInt *getVolatileCst() const {
569       return cast<ConstantInt>(
570           const_cast<Value *>(getArgOperand(ARG_VOLATILE)));
571     }
572 
isVolatile()573     bool isVolatile() const {
574       return !getVolatileCst()->isZero();
575     }
576 
setVolatile(Constant * V)577     void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); }
578 
579     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)580     static bool classof(const IntrinsicInst *I) {
581       switch (I->getIntrinsicID()) {
582       case Intrinsic::memcpy:
583       case Intrinsic::memmove:
584       case Intrinsic::memset:
585         return true;
586       default: return false;
587       }
588     }
classof(const Value * V)589     static bool classof(const Value *V) {
590       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
591     }
592   };
593 
594   /// This class wraps the llvm.memset intrinsic.
595   class MemSetInst : public MemSetBase<MemIntrinsic> {
596   public:
597     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)598     static bool classof(const IntrinsicInst *I) {
599       return I->getIntrinsicID() == Intrinsic::memset;
600     }
classof(const Value * V)601     static bool classof(const Value *V) {
602       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
603     }
604   };
605 
606   /// This class wraps the llvm.memcpy/memmove intrinsics.
607   class MemTransferInst : public MemTransferBase<MemIntrinsic> {
608   public:
609     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)610     static bool classof(const IntrinsicInst *I) {
611       return I->getIntrinsicID() == Intrinsic::memcpy ||
612              I->getIntrinsicID() == Intrinsic::memmove;
613     }
classof(const Value * V)614     static bool classof(const Value *V) {
615       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
616     }
617   };
618 
619   /// This class wraps the llvm.memcpy intrinsic.
620   class MemCpyInst : public MemTransferInst {
621   public:
622     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)623     static bool classof(const IntrinsicInst *I) {
624       return I->getIntrinsicID() == Intrinsic::memcpy;
625     }
classof(const Value * V)626     static bool classof(const Value *V) {
627       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
628     }
629   };
630 
631   /// This class wraps the llvm.memmove intrinsic.
632   class MemMoveInst : public MemTransferInst {
633   public:
634     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)635     static bool classof(const IntrinsicInst *I) {
636       return I->getIntrinsicID() == Intrinsic::memmove;
637     }
classof(const Value * V)638     static bool classof(const Value *V) {
639       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
640     }
641   };
642 
643   // The common base class for any memset/memmove/memcpy intrinsics;
644   // whether they be atomic or non-atomic.
645   // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
646   //  and llvm.memset/memcpy/memmove
647   class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> {
648   public:
isVolatile()649     bool isVolatile() const {
650       // Only the non-atomic intrinsics can be volatile
651       if (auto *MI = dyn_cast<MemIntrinsic>(this))
652         return MI->isVolatile();
653       return false;
654     }
655 
classof(const IntrinsicInst * I)656     static bool classof(const IntrinsicInst *I) {
657       switch (I->getIntrinsicID()) {
658       case Intrinsic::memcpy:
659       case Intrinsic::memmove:
660       case Intrinsic::memset:
661       case Intrinsic::memcpy_element_unordered_atomic:
662       case Intrinsic::memmove_element_unordered_atomic:
663       case Intrinsic::memset_element_unordered_atomic:
664         return true;
665       default:
666         return false;
667       }
668     }
classof(const Value * V)669     static bool classof(const Value *V) {
670       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
671     }
672   };
673 
674   /// This class represents any memset intrinsic
675   // i.e. llvm.element.unordered.atomic.memset
676   // and  llvm.memset
677   class AnyMemSetInst : public MemSetBase<AnyMemIntrinsic> {
678   public:
classof(const IntrinsicInst * I)679     static bool classof(const IntrinsicInst *I) {
680       switch (I->getIntrinsicID()) {
681       case Intrinsic::memset:
682       case Intrinsic::memset_element_unordered_atomic:
683         return true;
684       default:
685         return false;
686       }
687     }
classof(const Value * V)688     static bool classof(const Value *V) {
689       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
690     }
691   };
692 
693   // This class wraps any memcpy/memmove intrinsics
694   // i.e. llvm.element.unordered.atomic.memcpy/memmove
695   // and  llvm.memcpy/memmove
696   class AnyMemTransferInst : public MemTransferBase<AnyMemIntrinsic> {
697   public:
classof(const IntrinsicInst * I)698     static bool classof(const IntrinsicInst *I) {
699       switch (I->getIntrinsicID()) {
700       case Intrinsic::memcpy:
701       case Intrinsic::memmove:
702       case Intrinsic::memcpy_element_unordered_atomic:
703       case Intrinsic::memmove_element_unordered_atomic:
704         return true;
705       default:
706         return false;
707       }
708     }
classof(const Value * V)709     static bool classof(const Value *V) {
710       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
711     }
712   };
713 
714   /// This class represents any memcpy intrinsic
715   /// i.e. llvm.element.unordered.atomic.memcpy
716   ///  and llvm.memcpy
717   class AnyMemCpyInst : public AnyMemTransferInst {
718   public:
classof(const IntrinsicInst * I)719     static bool classof(const IntrinsicInst *I) {
720       switch (I->getIntrinsicID()) {
721       case Intrinsic::memcpy:
722       case Intrinsic::memcpy_element_unordered_atomic:
723         return true;
724       default:
725         return false;
726       }
727     }
classof(const Value * V)728     static bool classof(const Value *V) {
729       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
730     }
731   };
732 
733   /// This class represents any memmove intrinsic
734   /// i.e. llvm.element.unordered.atomic.memmove
735   ///  and llvm.memmove
736   class AnyMemMoveInst : public AnyMemTransferInst {
737   public:
classof(const IntrinsicInst * I)738     static bool classof(const IntrinsicInst *I) {
739       switch (I->getIntrinsicID()) {
740       case Intrinsic::memmove:
741       case Intrinsic::memmove_element_unordered_atomic:
742         return true;
743       default:
744         return false;
745       }
746     }
classof(const Value * V)747     static bool classof(const Value *V) {
748       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
749     }
750   };
751 
752   /// This represents the llvm.va_start intrinsic.
753   class VAStartInst : public IntrinsicInst {
754   public:
classof(const IntrinsicInst * I)755     static bool classof(const IntrinsicInst *I) {
756       return I->getIntrinsicID() == Intrinsic::vastart;
757     }
classof(const Value * V)758     static bool classof(const Value *V) {
759       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
760     }
761 
getArgList()762     Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); }
763   };
764 
765   /// This represents the llvm.va_end intrinsic.
766   class VAEndInst : public IntrinsicInst {
767   public:
classof(const IntrinsicInst * I)768     static bool classof(const IntrinsicInst *I) {
769       return I->getIntrinsicID() == Intrinsic::vaend;
770     }
classof(const Value * V)771     static bool classof(const Value *V) {
772       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
773     }
774 
getArgList()775     Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); }
776   };
777 
778   /// This represents the llvm.va_copy intrinsic.
779   class VACopyInst : public IntrinsicInst {
780   public:
classof(const IntrinsicInst * I)781     static bool classof(const IntrinsicInst *I) {
782       return I->getIntrinsicID() == Intrinsic::vacopy;
783     }
classof(const Value * V)784     static bool classof(const Value *V) {
785       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
786     }
787 
getDest()788     Value *getDest() const { return const_cast<Value*>(getArgOperand(0)); }
getSrc()789     Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); }
790   };
791 
792   /// This represents the llvm.instrprof_increment intrinsic.
793   class InstrProfIncrementInst : public IntrinsicInst {
794   public:
classof(const IntrinsicInst * I)795     static bool classof(const IntrinsicInst *I) {
796       return I->getIntrinsicID() == Intrinsic::instrprof_increment;
797     }
classof(const Value * V)798     static bool classof(const Value *V) {
799       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
800     }
801 
getName()802     GlobalVariable *getName() const {
803       return cast<GlobalVariable>(
804           const_cast<Value *>(getArgOperand(0))->stripPointerCasts());
805     }
806 
getHash()807     ConstantInt *getHash() const {
808       return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
809     }
810 
getNumCounters()811     ConstantInt *getNumCounters() const {
812       return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
813     }
814 
getIndex()815     ConstantInt *getIndex() const {
816       return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
817     }
818 
819     Value *getStep() const;
820   };
821 
822   class InstrProfIncrementInstStep : public InstrProfIncrementInst {
823   public:
classof(const IntrinsicInst * I)824     static bool classof(const IntrinsicInst *I) {
825       return I->getIntrinsicID() == Intrinsic::instrprof_increment_step;
826     }
classof(const Value * V)827     static bool classof(const Value *V) {
828       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
829     }
830   };
831 
832   /// This represents the llvm.instrprof_value_profile intrinsic.
833   class InstrProfValueProfileInst : public IntrinsicInst {
834   public:
classof(const IntrinsicInst * I)835     static bool classof(const IntrinsicInst *I) {
836       return I->getIntrinsicID() == Intrinsic::instrprof_value_profile;
837     }
classof(const Value * V)838     static bool classof(const Value *V) {
839       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
840     }
841 
getName()842     GlobalVariable *getName() const {
843       return cast<GlobalVariable>(
844           const_cast<Value *>(getArgOperand(0))->stripPointerCasts());
845     }
846 
getHash()847     ConstantInt *getHash() const {
848       return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
849     }
850 
getTargetValue()851     Value *getTargetValue() const {
852       return cast<Value>(const_cast<Value *>(getArgOperand(2)));
853     }
854 
getValueKind()855     ConstantInt *getValueKind() const {
856       return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
857     }
858 
859     // Returns the value site index.
getIndex()860     ConstantInt *getIndex() const {
861       return cast<ConstantInt>(const_cast<Value *>(getArgOperand(4)));
862     }
863   };
864 
865 } // end namespace llvm
866 
867 #endif // LLVM_IR_INTRINSICINST_H
868