1249259Sdim//===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file defines classes that make it really easy to deal with intrinsic
11249259Sdim// functions with the isa/dyncast family of functions.  In particular, this
12249259Sdim// allows you to do things like:
13249259Sdim//
14249259Sdim//     if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst))
15249259Sdim//        ... MCI->getDest() ... MCI->getSource() ...
16249259Sdim//
17249259Sdim// All intrinsic function calls are instances of the call instruction, so these
18249259Sdim// are all subclasses of the CallInst class.  Note that none of these classes
19249259Sdim// has state or virtual methods, which is an important part of this gross/neat
20249259Sdim// hack working.
21249259Sdim//
22249259Sdim//===----------------------------------------------------------------------===//
23249259Sdim
24249259Sdim#ifndef LLVM_IR_INTRINSICINST_H
25249259Sdim#define LLVM_IR_INTRINSICINST_H
26249259Sdim
27249259Sdim#include "llvm/IR/Constants.h"
28249259Sdim#include "llvm/IR/Function.h"
29249259Sdim#include "llvm/IR/Instructions.h"
30249259Sdim#include "llvm/IR/Intrinsics.h"
31249259Sdim
32249259Sdimnamespace llvm {
33249259Sdim  /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic
34249259Sdim  /// functions.  This allows the standard isa/dyncast/cast functionality to
35249259Sdim  /// work with calls to intrinsic functions.
36249259Sdim  class IntrinsicInst : public CallInst {
37249259Sdim    IntrinsicInst() LLVM_DELETED_FUNCTION;
38249259Sdim    IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION;
39249259Sdim    void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION;
40249259Sdim  public:
41249259Sdim    /// getIntrinsicID - Return the intrinsic ID of this intrinsic.
42249259Sdim    ///
43249259Sdim    Intrinsic::ID getIntrinsicID() const {
44249259Sdim      return (Intrinsic::ID)getCalledFunction()->getIntrinsicID();
45249259Sdim    }
46249259Sdim
47249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
48249259Sdim    static inline bool classof(const CallInst *I) {
49249259Sdim      if (const Function *CF = I->getCalledFunction())
50249259Sdim        return CF->isIntrinsic();
51249259Sdim      return false;
52249259Sdim    }
53249259Sdim    static inline bool classof(const Value *V) {
54249259Sdim      return isa<CallInst>(V) && classof(cast<CallInst>(V));
55249259Sdim    }
56249259Sdim  };
57249259Sdim
58249259Sdim  /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics
59249259Sdim  ///
60249259Sdim  class DbgInfoIntrinsic : public IntrinsicInst {
61249259Sdim  public:
62249259Sdim
63249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
64249259Sdim    static inline bool classof(const IntrinsicInst *I) {
65249259Sdim      switch (I->getIntrinsicID()) {
66249259Sdim      case Intrinsic::dbg_declare:
67249259Sdim      case Intrinsic::dbg_value:
68249259Sdim        return true;
69249259Sdim      default: return false;
70249259Sdim      }
71249259Sdim    }
72249259Sdim    static inline bool classof(const Value *V) {
73249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
74249259Sdim    }
75249259Sdim
76249259Sdim    static Value *StripCast(Value *C);
77249259Sdim  };
78249259Sdim
79249259Sdim  /// DbgDeclareInst - This represents the llvm.dbg.declare instruction.
80249259Sdim  ///
81249259Sdim  class DbgDeclareInst : public DbgInfoIntrinsic {
82249259Sdim  public:
83249259Sdim    Value *getAddress() const;
84249259Sdim    MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); }
85249259Sdim
86249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
87249259Sdim    static inline bool classof(const IntrinsicInst *I) {
88249259Sdim      return I->getIntrinsicID() == Intrinsic::dbg_declare;
89249259Sdim    }
90249259Sdim    static inline bool classof(const Value *V) {
91249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
92249259Sdim    }
93249259Sdim  };
94249259Sdim
95249259Sdim  /// DbgValueInst - This represents the llvm.dbg.value instruction.
96249259Sdim  ///
97249259Sdim  class DbgValueInst : public DbgInfoIntrinsic {
98249259Sdim  public:
99249259Sdim    const Value *getValue() const;
100249259Sdim    Value *getValue();
101249259Sdim    uint64_t getOffset() const {
102249259Sdim      return cast<ConstantInt>(
103249259Sdim                          const_cast<Value*>(getArgOperand(1)))->getZExtValue();
104249259Sdim    }
105249259Sdim    MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); }
106249259Sdim
107249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
108249259Sdim    static inline bool classof(const IntrinsicInst *I) {
109249259Sdim      return I->getIntrinsicID() == Intrinsic::dbg_value;
110249259Sdim    }
111249259Sdim    static inline bool classof(const Value *V) {
112249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
113249259Sdim    }
114249259Sdim  };
115249259Sdim
116249259Sdim  /// MemIntrinsic - This is the common base class for memset/memcpy/memmove.
117249259Sdim  ///
118249259Sdim  class MemIntrinsic : public IntrinsicInst {
119249259Sdim  public:
120249259Sdim    Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); }
121249259Sdim
122249259Sdim    Value *getLength() const { return const_cast<Value*>(getArgOperand(2)); }
123249259Sdim    ConstantInt *getAlignmentCst() const {
124249259Sdim      return cast<ConstantInt>(const_cast<Value*>(getArgOperand(3)));
125249259Sdim    }
126249259Sdim
127249259Sdim    unsigned getAlignment() const {
128249259Sdim      return getAlignmentCst()->getZExtValue();
129249259Sdim    }
130249259Sdim
131249259Sdim    ConstantInt *getVolatileCst() const {
132249259Sdim      return cast<ConstantInt>(const_cast<Value*>(getArgOperand(4)));
133249259Sdim    }
134249259Sdim    bool isVolatile() const {
135249259Sdim      return !getVolatileCst()->isZero();
136249259Sdim    }
137249259Sdim
138249259Sdim    unsigned getDestAddressSpace() const {
139249259Sdim      return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
140249259Sdim    }
141249259Sdim
142249259Sdim    /// getDest - This is just like getRawDest, but it strips off any cast
143249259Sdim    /// instructions that feed it, giving the original input.  The returned
144249259Sdim    /// value is guaranteed to be a pointer.
145249259Sdim    Value *getDest() const { return getRawDest()->stripPointerCasts(); }
146249259Sdim
147249259Sdim    /// set* - Set the specified arguments of the instruction.
148249259Sdim    ///
149249259Sdim    void setDest(Value *Ptr) {
150249259Sdim      assert(getRawDest()->getType() == Ptr->getType() &&
151249259Sdim             "setDest called with pointer of wrong type!");
152249259Sdim      setArgOperand(0, Ptr);
153249259Sdim    }
154249259Sdim
155249259Sdim    void setLength(Value *L) {
156249259Sdim      assert(getLength()->getType() == L->getType() &&
157249259Sdim             "setLength called with value of wrong type!");
158249259Sdim      setArgOperand(2, L);
159249259Sdim    }
160249259Sdim
161249259Sdim    void setAlignment(Constant* A) {
162249259Sdim      setArgOperand(3, A);
163249259Sdim    }
164249259Sdim
165249259Sdim    void setVolatile(Constant* V) {
166249259Sdim      setArgOperand(4, V);
167249259Sdim    }
168249259Sdim
169249259Sdim    Type *getAlignmentType() const {
170249259Sdim      return getArgOperand(3)->getType();
171249259Sdim    }
172249259Sdim
173249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
174249259Sdim    static inline bool classof(const IntrinsicInst *I) {
175249259Sdim      switch (I->getIntrinsicID()) {
176249259Sdim      case Intrinsic::memcpy:
177249259Sdim      case Intrinsic::memmove:
178249259Sdim      case Intrinsic::memset:
179249259Sdim        return true;
180249259Sdim      default: return false;
181249259Sdim      }
182249259Sdim    }
183249259Sdim    static inline bool classof(const Value *V) {
184249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
185249259Sdim    }
186249259Sdim  };
187249259Sdim
188249259Sdim  /// MemSetInst - This class wraps the llvm.memset intrinsic.
189249259Sdim  ///
190249259Sdim  class MemSetInst : public MemIntrinsic {
191249259Sdim  public:
192249259Sdim    /// get* - Return the arguments to the instruction.
193249259Sdim    ///
194249259Sdim    Value *getValue() const { return const_cast<Value*>(getArgOperand(1)); }
195249259Sdim
196249259Sdim    void setValue(Value *Val) {
197249259Sdim      assert(getValue()->getType() == Val->getType() &&
198249259Sdim             "setValue called with value of wrong type!");
199249259Sdim      setArgOperand(1, Val);
200249259Sdim    }
201249259Sdim
202249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
203249259Sdim    static inline bool classof(const IntrinsicInst *I) {
204249259Sdim      return I->getIntrinsicID() == Intrinsic::memset;
205249259Sdim    }
206249259Sdim    static inline bool classof(const Value *V) {
207249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
208249259Sdim    }
209249259Sdim  };
210249259Sdim
211249259Sdim  /// MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics.
212249259Sdim  ///
213249259Sdim  class MemTransferInst : public MemIntrinsic {
214249259Sdim  public:
215249259Sdim    /// get* - Return the arguments to the instruction.
216249259Sdim    ///
217249259Sdim    Value *getRawSource() const { return const_cast<Value*>(getArgOperand(1)); }
218249259Sdim
219249259Sdim    /// getSource - This is just like getRawSource, but it strips off any cast
220249259Sdim    /// instructions that feed it, giving the original input.  The returned
221249259Sdim    /// value is guaranteed to be a pointer.
222249259Sdim    Value *getSource() const { return getRawSource()->stripPointerCasts(); }
223249259Sdim
224249259Sdim    unsigned getSourceAddressSpace() const {
225249259Sdim      return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
226249259Sdim    }
227249259Sdim
228249259Sdim    void setSource(Value *Ptr) {
229249259Sdim      assert(getRawSource()->getType() == Ptr->getType() &&
230249259Sdim             "setSource called with pointer of wrong type!");
231249259Sdim      setArgOperand(1, Ptr);
232249259Sdim    }
233249259Sdim
234249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
235249259Sdim    static inline bool classof(const IntrinsicInst *I) {
236249259Sdim      return I->getIntrinsicID() == Intrinsic::memcpy ||
237249259Sdim             I->getIntrinsicID() == Intrinsic::memmove;
238249259Sdim    }
239249259Sdim    static inline bool classof(const Value *V) {
240249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
241249259Sdim    }
242249259Sdim  };
243249259Sdim
244249259Sdim
245249259Sdim  /// MemCpyInst - This class wraps the llvm.memcpy intrinsic.
246249259Sdim  ///
247249259Sdim  class MemCpyInst : public MemTransferInst {
248249259Sdim  public:
249249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
250249259Sdim    static inline bool classof(const IntrinsicInst *I) {
251249259Sdim      return I->getIntrinsicID() == Intrinsic::memcpy;
252249259Sdim    }
253249259Sdim    static inline bool classof(const Value *V) {
254249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
255249259Sdim    }
256249259Sdim  };
257249259Sdim
258249259Sdim  /// MemMoveInst - This class wraps the llvm.memmove intrinsic.
259249259Sdim  ///
260249259Sdim  class MemMoveInst : public MemTransferInst {
261249259Sdim  public:
262249259Sdim    // Methods for support type inquiry through isa, cast, and dyn_cast:
263249259Sdim    static inline bool classof(const IntrinsicInst *I) {
264249259Sdim      return I->getIntrinsicID() == Intrinsic::memmove;
265249259Sdim    }
266249259Sdim    static inline bool classof(const Value *V) {
267249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
268249259Sdim    }
269249259Sdim  };
270249259Sdim
271249259Sdim  /// VAStartInst - This represents the llvm.va_start intrinsic.
272249259Sdim  ///
273249259Sdim  class VAStartInst : public IntrinsicInst {
274249259Sdim  public:
275249259Sdim    static inline bool classof(const IntrinsicInst *I) {
276249259Sdim      return I->getIntrinsicID() == Intrinsic::vastart;
277249259Sdim    }
278249259Sdim    static inline bool classof(const Value *V) {
279249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
280249259Sdim    }
281249259Sdim
282249259Sdim    Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); }
283249259Sdim  };
284249259Sdim
285249259Sdim  /// VAEndInst - This represents the llvm.va_end intrinsic.
286249259Sdim  ///
287249259Sdim  class VAEndInst : public IntrinsicInst {
288249259Sdim  public:
289249259Sdim    static inline bool classof(const IntrinsicInst *I) {
290249259Sdim      return I->getIntrinsicID() == Intrinsic::vaend;
291249259Sdim    }
292249259Sdim    static inline bool classof(const Value *V) {
293249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
294249259Sdim    }
295249259Sdim
296249259Sdim    Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); }
297249259Sdim  };
298249259Sdim
299249259Sdim  /// VACopyInst - This represents the llvm.va_copy intrinsic.
300249259Sdim  ///
301249259Sdim  class VACopyInst : public IntrinsicInst {
302249259Sdim  public:
303249259Sdim    static inline bool classof(const IntrinsicInst *I) {
304249259Sdim      return I->getIntrinsicID() == Intrinsic::vacopy;
305249259Sdim    }
306249259Sdim    static inline bool classof(const Value *V) {
307249259Sdim      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
308249259Sdim    }
309249259Sdim
310249259Sdim    Value *getDest() const { return const_cast<Value*>(getArgOperand(0)); }
311249259Sdim    Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); }
312249259Sdim  };
313249259Sdim
314249259Sdim}
315249259Sdim
316249259Sdim#endif
317