Home | History | Annotate | Download | only in IR
      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 
     30 namespace llvm {
     31 /// The statepoint intrinsic accepts a set of flags as its third argument.
     32 /// Valid values come out of this set.
     33 enum 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 
     41 class GCRelocateInst;
     42 class GCResultInst;
     43 class ImmutableStatepoint;
     44 
     45 bool isStatepoint(ImmutableCallSite CS);
     46 bool isStatepoint(const Value *V);
     47 bool isStatepoint(const Value &V);
     48 
     49 bool isGCRelocate(ImmutableCallSite CS);
     50 bool 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.
     58 template <typename FunTy, typename InstructionTy, typename ValueTy,
     59           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) {
     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 
     77 public:
     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.
    285 class 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 
    291 public:
    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.
    298 class Statepoint
    299     : public StatepointBase<Function, Instruction, Value, CallSite> {
    300   typedef StatepointBase<Function, Instruction, Value, CallSite> Base;
    301 
    302 public:
    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.
    309 class GCProjectionInst : public IntrinsicInst {
    310 public:
    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.
    352 class GCRelocateInst : public GCProjectionInst {
    353 public:
    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.
    386 class GCResultInst : public GCProjectionInst {
    387 public:
    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 
    396 template <typename FunTy, typename InstructionTy, typename ValueTy,
    397           typename CallSiteTy>
    398 std::vector<const GCRelocateInst *>
    399 StatepointBase<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.
    432 struct 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.
    442 StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeSet AS);
    443 
    444 /// Return \c true if the the \p Attr is an attribute that is a statepoint
    445 /// directive.
    446 bool isStatepointDirectiveAttr(Attribute Attr);
    447 }
    448 
    449 #endif
    450