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,
12// gc.result intrinsics; and some general utilities helpful when dealing with
13// gc.statepoint.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_IR_STATEPOINT_H
18#define LLVM_IR_STATEPOINT_H
19
20#include "llvm/ADT/iterator_range.h"
21#include "llvm/ADT/Optional.h"
22#include "llvm/IR/BasicBlock.h"
23#include "llvm/IR/CallSite.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/Instructions.h"
27#include "llvm/IR/IntrinsicInst.h"
28#include "llvm/IR/Intrinsics.h"
29
30namespace llvm {
31/// The statepoint intrinsic accepts a set of flags as its third argument.
32/// Valid values come out of this set.
33enum class StatepointFlags {
34  None = 0,
35  GCTransition = 1, ///< Indicates that this statepoint is a transition from
36                    ///< GC-aware code to code that is not GC-aware.
37
38  MaskAll = GCTransition ///< A bitmask that includes all valid flags.
39};
40
41class GCRelocateInst;
42class GCResultInst;
43class ImmutableStatepoint;
44
45bool isStatepoint(ImmutableCallSite CS);
46bool isStatepoint(const Value *V);
47bool isStatepoint(const Value &V);
48
49bool isGCRelocate(ImmutableCallSite CS);
50bool isGCResult(ImmutableCallSite CS);
51
52/// Analogous to CallSiteBase, this provides most of the actual
53/// functionality for Statepoint and ImmutableStatepoint.  It is
54/// templatized to allow easily specializing of const and non-const
55/// concrete subtypes.  This is structured analogous to CallSite
56/// rather than the IntrinsicInst.h helpers since we need to support
57/// invokable statepoints.
58template <typename FunTy, typename InstructionTy, typename ValueTy,
59          typename CallSiteTy>
60class StatepointBase {
61  CallSiteTy StatepointCS;
62  void *operator new(size_t, unsigned) = delete;
63  void *operator new(size_t s) = delete;
64
65protected:
66  explicit StatepointBase(InstructionTy *I) {
67    if (isStatepoint(I)) {
68      StatepointCS = CallSiteTy(I);
69      assert(StatepointCS && "isStatepoint implies CallSite");
70    }
71  }
72  explicit StatepointBase(CallSiteTy CS) {
73    if (isStatepoint(CS))
74      StatepointCS = CS;
75  }
76
77public:
78  typedef typename CallSiteTy::arg_iterator arg_iterator;
79
80  enum {
81    IDPos = 0,
82    NumPatchBytesPos = 1,
83    CalledFunctionPos = 2,
84    NumCallArgsPos = 3,
85    FlagsPos = 4,
86    CallArgsBeginPos = 5,
87  };
88
89  explicit operator bool() const {
90    // We do not assign non-statepoint CallSites to StatepointCS.
91    return (bool)StatepointCS;
92  }
93
94  /// Return the underlying CallSite.
95  CallSiteTy getCallSite() const {
96    assert(*this && "check validity first!");
97    return StatepointCS;
98  }
99
100  uint64_t getFlags() const {
101    return cast<ConstantInt>(getCallSite().getArgument(FlagsPos))
102        ->getZExtValue();
103  }
104
105  /// Return the ID associated with this statepoint.
106  uint64_t getID() const {
107    const Value *IDVal = getCallSite().getArgument(IDPos);
108    return cast<ConstantInt>(IDVal)->getZExtValue();
109  }
110
111  /// Return the number of patchable bytes associated with this statepoint.
112  uint32_t getNumPatchBytes() const {
113    const Value *NumPatchBytesVal = getCallSite().getArgument(NumPatchBytesPos);
114    uint64_t NumPatchBytes =
115      cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
116    assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
117    return NumPatchBytes;
118  }
119
120  /// Return the value actually being called or invoked.
121  ValueTy *getCalledValue() const {
122    return getCallSite().getArgument(CalledFunctionPos);
123  }
124
125  InstructionTy *getInstruction() const {
126    return getCallSite().getInstruction();
127  }
128
129  /// Return the function being called if this is a direct call, otherwise
130  /// return null (if it's an indirect call).
131  FunTy *getCalledFunction() const {
132    return dyn_cast<Function>(getCalledValue());
133  }
134
135  /// Return the caller function for this statepoint.
136  FunTy *getCaller() const { return getCallSite().getCaller(); }
137
138  /// Determine if the statepoint cannot unwind.
139  bool doesNotThrow() const {
140    Function *F = getCalledFunction();
141    return getCallSite().doesNotThrow() || (F ? F->doesNotThrow() : false);
142  }
143
144  /// Return the type of the value returned by the call underlying the
145  /// statepoint.
146  Type *getActualReturnType() const {
147    auto *FTy = cast<FunctionType>(
148        cast<PointerType>(getCalledValue()->getType())->getElementType());
149    return FTy->getReturnType();
150  }
151
152  /// Number of arguments to be passed to the actual callee.
153  int getNumCallArgs() const {
154    const Value *NumCallArgsVal = getCallSite().getArgument(NumCallArgsPos);
155    return cast<ConstantInt>(NumCallArgsVal)->getZExtValue();
156  }
157
158  size_t arg_size() const { return getNumCallArgs(); }
159  typename CallSiteTy::arg_iterator arg_begin() const {
160    assert(CallArgsBeginPos <= (int)getCallSite().arg_size());
161    return getCallSite().arg_begin() + CallArgsBeginPos;
162  }
163  typename CallSiteTy::arg_iterator arg_end() const {
164    auto I = arg_begin() + arg_size();
165    assert((getCallSite().arg_end() - I) >= 0);
166    return I;
167  }
168
169  ValueTy *getArgument(unsigned Index) {
170    assert(Index < arg_size() && "out of bounds!");
171    return *(arg_begin() + Index);
172  }
173
174  /// range adapter for call arguments
175  iterator_range<arg_iterator> call_args() const {
176    return make_range(arg_begin(), arg_end());
177  }
178
179  /// \brief Return true if the call or the callee has the given attribute.
180  bool paramHasAttr(unsigned i, Attribute::AttrKind A) const {
181    Function *F = getCalledFunction();
182    return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) ||
183          (F ? F->getAttributes().hasAttribute(i, A) : false);
184  }
185
186  /// Number of GC transition args.
187  int getNumTotalGCTransitionArgs() const {
188    const Value *NumGCTransitionArgs = *arg_end();
189    return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
190  }
191  typename CallSiteTy::arg_iterator gc_transition_args_begin() const {
192    auto I = arg_end() + 1;
193    assert((getCallSite().arg_end() - I) >= 0);
194    return I;
195  }
196  typename CallSiteTy::arg_iterator gc_transition_args_end() const {
197    auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs();
198    assert((getCallSite().arg_end() - I) >= 0);
199    return I;
200  }
201
202  /// range adapter for GC transition arguments
203  iterator_range<arg_iterator> gc_transition_args() const {
204    return make_range(gc_transition_args_begin(), gc_transition_args_end());
205  }
206
207  /// Number of additional arguments excluding those intended
208  /// for garbage collection.
209  int getNumTotalVMSArgs() const {
210    const Value *NumVMSArgs = *gc_transition_args_end();
211    return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
212  }
213
214  typename CallSiteTy::arg_iterator vm_state_begin() const {
215    auto I = gc_transition_args_end() + 1;
216    assert((getCallSite().arg_end() - I) >= 0);
217    return I;
218  }
219  typename CallSiteTy::arg_iterator vm_state_end() const {
220    auto I = vm_state_begin() + getNumTotalVMSArgs();
221    assert((getCallSite().arg_end() - I) >= 0);
222    return I;
223  }
224
225  /// range adapter for vm state arguments
226  iterator_range<arg_iterator> vm_state_args() const {
227    return make_range(vm_state_begin(), vm_state_end());
228  }
229
230  typename CallSiteTy::arg_iterator gc_args_begin() const {
231    return vm_state_end();
232  }
233  typename CallSiteTy::arg_iterator gc_args_end() const {
234    return getCallSite().arg_end();
235  }
236
237  unsigned gcArgsStartIdx() const {
238    return gc_args_begin() - getInstruction()->op_begin();
239  }
240
241  /// range adapter for gc arguments
242  iterator_range<arg_iterator> gc_args() const {
243    return make_range(gc_args_begin(), gc_args_end());
244  }
245
246  /// Get list of all gc reloactes linked to this statepoint
247  /// May contain several relocations for the same base/derived pair.
248  /// For example this could happen due to relocations on unwinding
249  /// path of invoke.
250  std::vector<const GCRelocateInst *> getRelocates() const;
251
252  /// Get the experimental_gc_result call tied to this statepoint.  Can be
253  /// nullptr if there isn't a gc_result tied to this statepoint.  Guaranteed to
254  /// be a CallInst if non-null.
255  const GCResultInst *getGCResult() const {
256    for (auto *U : getInstruction()->users())
257      if (auto *GRI = dyn_cast<GCResultInst>(U))
258        return GRI;
259    return nullptr;
260  }
261
262#ifndef NDEBUG
263  /// Asserts if this statepoint is malformed.  Common cases for failure
264  /// include incorrect length prefixes for variable length sections or
265  /// illegal values for parameters.
266  void verify() {
267    assert(getNumCallArgs() >= 0 &&
268           "number of arguments to actually callee can't be negative");
269
270    // The internal asserts in the iterator accessors do the rest.
271    (void)arg_begin();
272    (void)arg_end();
273    (void)gc_transition_args_begin();
274    (void)gc_transition_args_end();
275    (void)vm_state_begin();
276    (void)vm_state_end();
277    (void)gc_args_begin();
278    (void)gc_args_end();
279  }
280#endif
281};
282
283/// A specialization of it's base class for read only access
284/// to a gc.statepoint.
285class ImmutableStatepoint
286    : public StatepointBase<const Function, const Instruction, const Value,
287                            ImmutableCallSite> {
288  typedef StatepointBase<const Function, const Instruction, const Value,
289                         ImmutableCallSite> Base;
290
291public:
292  explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
293  explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
294};
295
296/// A specialization of it's base class for read-write access
297/// to a gc.statepoint.
298class Statepoint
299    : public StatepointBase<Function, Instruction, Value, CallSite> {
300  typedef StatepointBase<Function, Instruction, Value, CallSite> Base;
301
302public:
303  explicit Statepoint(Instruction *I) : Base(I) {}
304  explicit Statepoint(CallSite CS) : Base(CS) {}
305};
306
307/// Common base class for representing values projected from a statepoint.
308/// Currently, the only projections available are gc.result and gc.relocate.
309class GCProjectionInst : public IntrinsicInst {
310public:
311  static inline bool classof(const IntrinsicInst *I) {
312    return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate ||
313      I->getIntrinsicID() == Intrinsic::experimental_gc_result;
314  }
315  static inline bool classof(const Value *V) {
316    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
317  }
318
319  /// Return true if this relocate is tied to the invoke statepoint.
320  /// This includes relocates which are on the unwinding path.
321  bool isTiedToInvoke() const {
322    const Value *Token = getArgOperand(0);
323
324    return isa<LandingPadInst>(Token) || isa<InvokeInst>(Token);
325  }
326
327  /// The statepoint with which this gc.relocate is associated.
328  const Instruction *getStatepoint() const {
329    const Value *Token = getArgOperand(0);
330
331    // This takes care both of relocates for call statepoints and relocates
332    // on normal path of invoke statepoint.
333    if (!isa<LandingPadInst>(Token)) {
334      assert(isStatepoint(Token));
335      return cast<Instruction>(Token);
336    }
337
338    // This relocate is on exceptional path of an invoke statepoint
339    const BasicBlock *InvokeBB =
340        cast<Instruction>(Token)->getParent()->getUniquePredecessor();
341
342    assert(InvokeBB && "safepoints should have unique landingpads");
343    assert(InvokeBB->getTerminator() &&
344           "safepoint block should be well formed");
345    assert(isStatepoint(InvokeBB->getTerminator()));
346
347    return InvokeBB->getTerminator();
348  }
349};
350
351/// Represents calls to the gc.relocate intrinsic.
352class GCRelocateInst : public GCProjectionInst {
353public:
354  static inline bool classof(const IntrinsicInst *I) {
355    return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
356  }
357  static inline bool classof(const Value *V) {
358    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
359  }
360
361  /// The index into the associate statepoint's argument list
362  /// which contains the base pointer of the pointer whose
363  /// relocation this gc.relocate describes.
364  unsigned getBasePtrIndex() const {
365    return cast<ConstantInt>(getArgOperand(1))->getZExtValue();
366  }
367
368  /// The index into the associate statepoint's argument list which
369  /// contains the pointer whose relocation this gc.relocate describes.
370  unsigned getDerivedPtrIndex() const {
371    return cast<ConstantInt>(getArgOperand(2))->getZExtValue();
372  }
373
374  Value *getBasePtr() const {
375    ImmutableCallSite CS(getStatepoint());
376    return *(CS.arg_begin() + getBasePtrIndex());
377  }
378
379  Value *getDerivedPtr() const {
380    ImmutableCallSite CS(getStatepoint());
381    return *(CS.arg_begin() + getDerivedPtrIndex());
382  }
383};
384
385/// Represents calls to the gc.result intrinsic.
386class GCResultInst : public GCProjectionInst {
387public:
388  static inline bool classof(const IntrinsicInst *I) {
389    return I->getIntrinsicID() == Intrinsic::experimental_gc_result;
390  }
391  static inline bool classof(const Value *V) {
392    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
393  }
394};
395
396template <typename FunTy, typename InstructionTy, typename ValueTy,
397          typename CallSiteTy>
398std::vector<const GCRelocateInst *>
399StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates()
400    const {
401
402  std::vector<const GCRelocateInst *> Result;
403
404  CallSiteTy StatepointCS = getCallSite();
405
406  // Search for relocated pointers.  Note that working backwards from the
407  // gc_relocates ensures that we only get pairs which are actually relocated
408  // and used after the statepoint.
409  for (const User *U : getInstruction()->users())
410    if (auto *Relocate = dyn_cast<GCRelocateInst>(U))
411      Result.push_back(Relocate);
412
413  if (!StatepointCS.isInvoke())
414    return Result;
415
416  // We need to scan thorough exceptional relocations if it is invoke statepoint
417  LandingPadInst *LandingPad =
418      cast<InvokeInst>(getInstruction())->getLandingPadInst();
419
420  // Search for gc relocates that are attached to this landingpad.
421  for (const User *LandingPadUser : LandingPad->users()) {
422    if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser))
423      Result.push_back(Relocate);
424  }
425  return Result;
426}
427
428/// Call sites that get wrapped by a gc.statepoint (currently only in
429/// RewriteStatepointsForGC and potentially in other passes in the future) can
430/// have attributes that describe properties of gc.statepoint call they will be
431/// eventually be wrapped in.  This struct is used represent such directives.
432struct StatepointDirectives {
433  Optional<uint32_t> NumPatchBytes;
434  Optional<uint64_t> StatepointID;
435
436  static const uint64_t DefaultStatepointID = 0xABCDEF00;
437  static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F;
438};
439
440/// Parse out statepoint directives from the function attributes present in \p
441/// AS.
442StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeSet AS);
443
444/// Return \c true if the the \p Attr is an attribute that is a statepoint
445/// directive.
446bool isStatepointDirectiveAttr(Attribute Attr);
447}
448
449#endif
450