7c08b74fdb23c900380702c95a9171a85d153fc9
[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     IDPos = 0,
78     NumPatchBytesPos = 1,
79     ActualCalleePos = 2,
80     NumCallArgsPos = 3,
81     FlagsPos = 4,
82     CallArgsBeginPos = 5,
83   };
84
85   /// Return the underlying CallSite.
86   CallSiteTy getCallSite() { return StatepointCS; }
87
88   uint64_t getFlags() const {
89     return cast<ConstantInt>(StatepointCS.getArgument(FlagsPos))
90         ->getZExtValue();
91   }
92
93   /// Return the ID associated with this statepoint.
94   uint64_t getID() {
95     const Value *IDVal = StatepointCS.getArgument(IDPos);
96     return cast<ConstantInt>(IDVal)->getZExtValue();
97   }
98
99   /// Return the number of patchable bytes associated with this statepoint.
100   uint32_t getNumPatchBytes() {
101     const Value *NumPatchBytesVal = StatepointCS.getArgument(NumPatchBytesPos);
102     uint64_t NumPatchBytes =
103       cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
104     assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
105     return NumPatchBytes;
106   }
107
108   /// Return the value actually being called or invoked.
109   ValueTy *getActualCallee() {
110     return StatepointCS.getArgument(ActualCalleePos);
111   }
112
113   /// Return the type of the value returned by the call underlying the
114   /// statepoint.
115   Type *getActualReturnType() {
116     auto *FTy = cast<FunctionType>(
117         cast<PointerType>(getActualCallee()->getType())->getElementType());
118     return FTy->getReturnType();
119   }
120
121   /// Number of arguments to be passed to the actual callee.
122   int getNumCallArgs() {
123     const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos);
124     return cast<ConstantInt>(NumCallArgsVal)->getZExtValue();
125   }
126
127   typename CallSiteTy::arg_iterator call_args_begin() {
128     assert(CallArgsBeginPos <= (int)StatepointCS.arg_size());
129     return StatepointCS.arg_begin() + CallArgsBeginPos;
130   }
131   typename CallSiteTy::arg_iterator call_args_end() {
132     auto I = call_args_begin() + getNumCallArgs();
133     assert((StatepointCS.arg_end() - I) >= 0);
134     return I;
135   }
136
137   /// range adapter for call arguments
138   iterator_range<arg_iterator> call_args() {
139     return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
140   }
141
142   /// Number of GC transition args.
143   int getNumTotalGCTransitionArgs() {
144     const Value *NumGCTransitionArgs = *call_args_end();
145     return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
146   }
147   typename CallSiteTy::arg_iterator gc_transition_args_begin() {
148     auto I = call_args_end() + 1;
149     assert((StatepointCS.arg_end() - I) >= 0);
150     return I;
151   }
152   typename CallSiteTy::arg_iterator gc_transition_args_end() {
153     auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs();
154     assert((StatepointCS.arg_end() - I) >= 0);
155     return I;
156   }
157
158   /// range adapter for GC transition arguments
159   iterator_range<arg_iterator> gc_transition_args() {
160     return iterator_range<arg_iterator>(gc_transition_args_begin(),
161                                         gc_transition_args_end());
162   }
163
164   /// Number of additional arguments excluding those intended
165   /// for garbage collection.
166   int getNumTotalVMSArgs() {
167     const Value *NumVMSArgs = *gc_transition_args_end();
168     return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
169   }
170
171   typename CallSiteTy::arg_iterator vm_state_begin() {
172     auto I = gc_transition_args_end() + 1;
173     assert((StatepointCS.arg_end() - I) >= 0);
174     return I;
175   }
176   typename CallSiteTy::arg_iterator vm_state_end() {
177     auto I = vm_state_begin() + getNumTotalVMSArgs();
178     assert((StatepointCS.arg_end() - I) >= 0);
179     return I;
180   }
181
182   /// range adapter for vm state arguments
183   iterator_range<arg_iterator> vm_state_args() {
184     return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
185   }
186
187   typename CallSiteTy::arg_iterator gc_args_begin() { return vm_state_end(); }
188   typename CallSiteTy::arg_iterator gc_args_end() {
189     return StatepointCS.arg_end();
190   }
191
192   /// range adapter for gc arguments
193   iterator_range<arg_iterator> gc_args() {
194     return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
195   }
196
197   /// Get list of all gc reloactes linked to this statepoint
198   /// May contain several relocations for the same base/derived pair.
199   /// For example this could happen due to relocations on unwinding
200   /// path of invoke.
201   std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
202
203 #ifndef NDEBUG
204   /// Asserts if this statepoint is malformed.  Common cases for failure
205   /// include incorrect length prefixes for variable length sections or
206   /// illegal values for parameters.
207   void verify() {
208     assert(getNumCallArgs() >= 0 &&
209            "number of arguments to actually callee can't be negative");
210
211     // The internal asserts in the iterator accessors do the rest.
212     (void)call_args_begin();
213     (void)call_args_end();
214     (void)gc_transition_args_begin();
215     (void)gc_transition_args_end();
216     (void)vm_state_begin();
217     (void)vm_state_end();
218     (void)gc_args_begin();
219     (void)gc_args_end();
220   }
221 #endif
222 };
223
224 /// A specialization of it's base class for read only access
225 /// to a gc.statepoint.
226 class ImmutableStatepoint
227     : public StatepointBase<const Instruction, const Value, ImmutableCallSite> {
228   typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
229       Base;
230
231 public:
232   explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
233   explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
234 };
235
236 /// A specialization of it's base class for read-write access
237 /// to a gc.statepoint.
238 class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
239   typedef StatepointBase<Instruction, Value, CallSite> Base;
240
241 public:
242   explicit Statepoint(Instruction *I) : Base(I) {}
243   explicit Statepoint(CallSite CS) : Base(CS) {}
244 };
245
246 /// Wraps a call to a gc.relocate and provides access to it's operands.
247 /// TODO: This should likely be refactored to resememble the wrappers in
248 /// InstrinsicInst.h.
249 class GCRelocateOperands {
250   ImmutableCallSite RelocateCS;
251
252 public:
253   GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); }
254   GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
255     assert(isGCRelocate(inst));
256   }
257   GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); }
258
259   /// Return true if this relocate is tied to the invoke statepoint.
260   /// This includes relocates which are on the unwinding path.
261   bool isTiedToInvoke() const {
262     const Value *Token = RelocateCS.getArgument(0);
263
264     return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token);
265   }
266
267   /// Get enclosed relocate intrinsic
268   ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; }
269
270   /// The statepoint with which this gc.relocate is associated.
271   const Instruction *getStatepoint() {
272     const Value *Token = RelocateCS.getArgument(0);
273
274     // This takes care both of relocates for call statepoints and relocates
275     // on normal path of invoke statepoint.
276     if (!isa<ExtractValueInst>(Token)) {
277       return cast<Instruction>(Token);
278     }
279
280     // This relocate is on exceptional path of an invoke statepoint
281     const BasicBlock *InvokeBB =
282         cast<Instruction>(Token)->getParent()->getUniquePredecessor();
283
284     assert(InvokeBB && "safepoints should have unique landingpads");
285     assert(InvokeBB->getTerminator() &&
286            "safepoint block should be well formed");
287     assert(isStatepoint(InvokeBB->getTerminator()));
288
289     return InvokeBB->getTerminator();
290   }
291
292   /// The index into the associate statepoint's argument list
293   /// which contains the base pointer of the pointer whose
294   /// relocation this gc.relocate describes.
295   unsigned getBasePtrIndex() {
296     return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
297   }
298
299   /// The index into the associate statepoint's argument list which
300   /// contains the pointer whose relocation this gc.relocate describes.
301   unsigned getDerivedPtrIndex() {
302     return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
303   }
304
305   Value *getBasePtr() {
306     ImmutableCallSite CS(getStatepoint());
307     return *(CS.arg_begin() + getBasePtrIndex());
308   }
309
310   Value *getDerivedPtr() {
311     ImmutableCallSite CS(getStatepoint());
312     return *(CS.arg_begin() + getDerivedPtrIndex());
313   }
314 };
315
316 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
317 std::vector<GCRelocateOperands>
318 StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates(
319     ImmutableStatepoint &IS) {
320
321   std::vector<GCRelocateOperands> Result;
322
323   ImmutableCallSite StatepointCS = IS.getCallSite();
324
325   // Search for relocated pointers.  Note that working backwards from the
326   // gc_relocates ensures that we only get pairs which are actually relocated
327   // and used after the statepoint.
328   for (const User *U : StatepointCS.getInstruction()->users())
329     if (isGCRelocate(U))
330       Result.push_back(GCRelocateOperands(U));
331
332   if (!StatepointCS.isInvoke())
333     return Result;
334
335   // We need to scan thorough exceptional relocations if it is invoke statepoint
336   LandingPadInst *LandingPad =
337       cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
338
339   // Search for extract value from landingpad instruction to which
340   // gc relocates will be attached
341   for (const User *LandingPadUser : LandingPad->users()) {
342     if (!isa<ExtractValueInst>(LandingPadUser))
343       continue;
344
345     // gc relocates should be attached to this extract value
346     for (const User *U : LandingPadUser->users())
347       if (isGCRelocate(U))
348         Result.push_back(GCRelocateOperands(U));
349   }
350   return Result;
351 }
352 } // namespace llvm
353
354 #endif