Add more missing #includes, found by modules build.
[oota-llvm.git] / include / llvm / IR / Statepoint.h
1 //===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains utility functions and a wrapper class analogous to
11 // CallSite for accessing the fields of gc.statepoint, gc.relocate, and
12 // gc.result intrinsics
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef __LLVM_IR_STATEPOINT_H
17 #define __LLVM_IR_STATEPOINT_H
18
19 #include "llvm/ADT/iterator_range.h"
20 #include "llvm/IR/BasicBlock.h"
21 #include "llvm/IR/CallSite.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/Instructions.h"
24 #include "llvm/IR/Intrinsics.h"
25 #include "llvm/Support/Compiler.h"
26
27 namespace llvm {
28 /// The statepoint intrinsic accepts a set of flags as its third argument.
29 /// Valid values come out of this set.
30 enum class StatepointFlags {
31   None = 0,
32   GCTransition = 1, ///< Indicates that this statepoint is a transition from
33                     ///< GC-aware code to code that is not GC-aware.
34
35   MaskAll = GCTransition ///< A bitmask that includes all valid flags.
36 };
37
38 class GCRelocateOperands;
39 class ImmutableStatepoint;
40
41 bool isStatepoint(const ImmutableCallSite &CS);
42 bool isStatepoint(const Value *inst);
43 bool isStatepoint(const Value &inst);
44
45 bool isGCRelocate(const Value *inst);
46 bool isGCRelocate(const ImmutableCallSite &CS);
47
48 bool isGCResult(const Value *inst);
49 bool isGCResult(const ImmutableCallSite &CS);
50
51 /// Analogous to CallSiteBase, this provides most of the actual
52 /// functionality for Statepoint and ImmutableStatepoint.  It is
53 /// templatized to allow easily specializing of const and non-const
54 /// concrete subtypes.  This is structured analogous to CallSite
55 /// rather than the IntrinsicInst.h helpers since we want to support
56 /// invokable statepoints in the near future.
57 /// TODO: This does not currently allow the if(Statepoint S = ...)
58 ///   idiom used with CallSites.  Consider refactoring to support.
59 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
60 class StatepointBase {
61   CallSiteTy StatepointCS;
62   void *operator new(size_t, unsigned) = delete;
63   void *operator new(size_t s) = delete;
64
65 protected:
66   explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
67     assert(isStatepoint(I));
68   }
69   explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) {
70     assert(isStatepoint(CS));
71   }
72
73 public:
74   typedef typename CallSiteTy::arg_iterator arg_iterator;
75
76   enum {
77     ActualCalleePos = 0,
78     NumCallArgsPos = 1,
79     CallArgsBeginPos = 3,
80   };
81
82   /// Return the underlying CallSite.
83   CallSiteTy getCallSite() { return StatepointCS; }
84
85   uint64_t getFlags() const {
86     return cast<ConstantInt>(StatepointCS.getArgument(2))->getZExtValue();
87   }
88
89   /// Return the value actually being called or invoked.
90   ValueTy *getActualCallee() {
91     return StatepointCS.getArgument(ActualCalleePos);
92   }
93
94   /// Return the type of the value returned by the call underlying the
95   /// statepoint.
96   Type *getActualReturnType() {
97     auto *FTy = cast<FunctionType>(
98         cast<PointerType>(getActualCallee()->getType())->getElementType());
99     return FTy->getReturnType();
100   }
101
102   /// Number of arguments to be passed to the actual callee.
103   int getNumCallArgs() {
104     const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos);
105     return cast<ConstantInt>(NumCallArgsVal)->getZExtValue();
106   }
107
108   typename CallSiteTy::arg_iterator call_args_begin() {
109     assert(CallArgsBeginPos <= (int)StatepointCS.arg_size());
110     return StatepointCS.arg_begin() + CallArgsBeginPos;
111   }
112   typename CallSiteTy::arg_iterator call_args_end() {
113     int Offset = CallArgsBeginPos + getNumCallArgs();
114     assert(Offset <= (int)StatepointCS.arg_size());
115     return StatepointCS.arg_begin() + Offset;
116   }
117
118   /// range adapter for call arguments
119   iterator_range<arg_iterator> call_args() {
120     return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
121   }
122
123   /// Number of GC transition args.
124   int getNumTotalGCTransitionArgs() {
125     const Value *NumGCTransitionArgs = *gc_transition_args_begin();
126     return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
127   }
128   typename CallSiteTy::arg_iterator gc_transition_args_begin() {
129     int Offset = call_args_end() - StatepointCS.arg_begin();
130     assert(Offset <= (int)StatepointCS.arg_size());
131     return StatepointCS.arg_begin() + Offset;
132   }
133   typename CallSiteTy::arg_iterator gc_transition_args_end() {
134     int Offset = (gc_transition_args_begin() + 1 +
135                   getNumTotalGCTransitionArgs()) - StatepointCS.arg_begin();
136     assert(Offset <= (int)StatepointCS.arg_size());
137     return StatepointCS.arg_begin() + Offset;
138   }
139
140   /// range adapter for GC transition arguments
141   iterator_range<arg_iterator> gc_transition_args() {
142     return iterator_range<arg_iterator>(gc_transition_args_begin(),
143                                         gc_transition_args_end());
144   }
145
146   /// Number of additional arguments excluding those intended
147   /// for garbage collection.
148   int getNumTotalVMSArgs() {
149     Value *NumVMSArgs = *vm_state_begin();
150     return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
151   }
152
153   typename CallSiteTy::arg_iterator vm_state_begin() {
154     return gc_transition_args_end();
155   }
156   typename CallSiteTy::arg_iterator vm_state_end() {
157     int Offset = (gc_transition_args_end() + 1 + getNumTotalVMSArgs()) -
158                  StatepointCS.arg_begin();
159     assert(Offset <= (int)StatepointCS.arg_size());
160     return StatepointCS.arg_begin() + Offset;
161   }
162
163   /// range adapter for vm state arguments
164   iterator_range<arg_iterator> vm_state_args() {
165     return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
166   }
167
168   typename CallSiteTy::arg_iterator gc_args_begin() { return vm_state_end(); }
169   typename CallSiteTy::arg_iterator gc_args_end() {
170     return StatepointCS.arg_end();
171   }
172
173   /// range adapter for gc arguments
174   iterator_range<arg_iterator> gc_args() {
175     return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
176   }
177
178   /// Get list of all gc reloactes linked to this statepoint
179   /// May contain several relocations for the same base/derived pair.
180   /// For example this could happen due to relocations on unwinding
181   /// path of invoke.
182   std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
183
184 #ifndef NDEBUG
185   /// Asserts if this statepoint is malformed.  Common cases for failure
186   /// include incorrect length prefixes for variable length sections or
187   /// illegal values for parameters.
188   void verify() {
189     assert(getNumCallArgs() >= 0 &&
190            "number of arguments to actually callee can't be negative");
191
192     // The internal asserts in the iterator accessors do the rest.
193     (void)call_args_begin();
194     (void)call_args_end();
195     (void)gc_transition_args_begin();
196     (void)gc_transition_args_end();
197     (void)vm_state_begin();
198     (void)vm_state_end();
199     (void)gc_args_begin();
200     (void)gc_args_end();
201   }
202 #endif
203 };
204
205 /// A specialization of it's base class for read only access
206 /// to a gc.statepoint.
207 class ImmutableStatepoint
208     : public StatepointBase<const Instruction, const Value, ImmutableCallSite> {
209   typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
210       Base;
211
212 public:
213   explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
214   explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
215 };
216
217 /// A specialization of it's base class for read-write access
218 /// to a gc.statepoint.
219 class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
220   typedef StatepointBase<Instruction, Value, CallSite> Base;
221
222 public:
223   explicit Statepoint(Instruction *I) : Base(I) {}
224   explicit Statepoint(CallSite CS) : Base(CS) {}
225 };
226
227 /// Wraps a call to a gc.relocate and provides access to it's operands.
228 /// TODO: This should likely be refactored to resememble the wrappers in
229 /// InstrinsicInst.h.
230 class GCRelocateOperands {
231   ImmutableCallSite RelocateCS;
232
233 public:
234   GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); }
235   GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
236     assert(isGCRelocate(inst));
237   }
238   GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); }
239
240   /// Return true if this relocate is tied to the invoke statepoint.
241   /// This includes relocates which are on the unwinding path.
242   bool isTiedToInvoke() const {
243     const Value *Token = RelocateCS.getArgument(0);
244
245     return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token);
246   }
247
248   /// Get enclosed relocate intrinsic
249   ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; }
250
251   /// The statepoint with which this gc.relocate is associated.
252   const Instruction *getStatepoint() {
253     const Value *Token = RelocateCS.getArgument(0);
254
255     // This takes care both of relocates for call statepoints and relocates
256     // on normal path of invoke statepoint.
257     if (!isa<ExtractValueInst>(Token)) {
258       return cast<Instruction>(Token);
259     }
260
261     // This relocate is on exceptional path of an invoke statepoint
262     const BasicBlock *InvokeBB =
263         cast<Instruction>(Token)->getParent()->getUniquePredecessor();
264
265     assert(InvokeBB && "safepoints should have unique landingpads");
266     assert(InvokeBB->getTerminator() &&
267            "safepoint block should be well formed");
268     assert(isStatepoint(InvokeBB->getTerminator()));
269
270     return InvokeBB->getTerminator();
271   }
272
273   /// The index into the associate statepoint's argument list
274   /// which contains the base pointer of the pointer whose
275   /// relocation this gc.relocate describes.
276   unsigned getBasePtrIndex() {
277     return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
278   }
279
280   /// The index into the associate statepoint's argument list which
281   /// contains the pointer whose relocation this gc.relocate describes.
282   unsigned getDerivedPtrIndex() {
283     return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
284   }
285
286   Value *getBasePtr() {
287     ImmutableCallSite CS(getStatepoint());
288     return *(CS.arg_begin() + getBasePtrIndex());
289   }
290
291   Value *getDerivedPtr() {
292     ImmutableCallSite CS(getStatepoint());
293     return *(CS.arg_begin() + getDerivedPtrIndex());
294   }
295 };
296
297 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
298 std::vector<GCRelocateOperands>
299 StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates(
300     ImmutableStatepoint &IS) {
301
302   std::vector<GCRelocateOperands> Result;
303
304   ImmutableCallSite StatepointCS = IS.getCallSite();
305
306   // Search for relocated pointers.  Note that working backwards from the
307   // gc_relocates ensures that we only get pairs which are actually relocated
308   // and used after the statepoint.
309   for (const User *U : StatepointCS.getInstruction()->users())
310     if (isGCRelocate(U))
311       Result.push_back(GCRelocateOperands(U));
312
313   if (!StatepointCS.isInvoke())
314     return Result;
315
316   // We need to scan thorough exceptional relocations if it is invoke statepoint
317   LandingPadInst *LandingPad =
318       cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
319
320   // Search for extract value from landingpad instruction to which
321   // gc relocates will be attached
322   for (const User *LandingPadUser : LandingPad->users()) {
323     if (!isa<ExtractValueInst>(LandingPadUser))
324       continue;
325
326     // gc relocates should be attached to this extract value
327     for (const User *U : LandingPadUser->users())
328       if (isGCRelocate(U))
329         Result.push_back(GCRelocateOperands(U));
330   }
331   return Result;
332 }
333 }
334
335 #endif