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