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, 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/Function.h"
     24 #include "llvm/IR/Instructions.h"
     25 #include "llvm/IR/Intrinsics.h"
     26 #include "llvm/Support/Compiler.h"
     27 
     28 namespace llvm {
     29 /// The statepoint intrinsic accepts a set of flags as its third argument.
     30 /// Valid values come out of this set.
     31 enum class StatepointFlags {
     32   None = 0,
     33   GCTransition = 1, ///< Indicates that this statepoint is a transition from
     34                     ///< GC-aware code to code that is not GC-aware.
     35 
     36   MaskAll = GCTransition ///< A bitmask that includes all valid flags.
     37 };
     38 
     39 class GCRelocateOperands;
     40 class ImmutableStatepoint;
     41 
     42 bool isStatepoint(const ImmutableCallSite &CS);
     43 bool isStatepoint(const Value *V);
     44 bool isStatepoint(const Value &V);
     45 
     46 bool isGCRelocate(const Value *V);
     47 bool isGCRelocate(const ImmutableCallSite &CS);
     48 
     49 bool isGCResult(const Value *V);
     50 bool isGCResult(const 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 want to support
     57 /// invokable statepoints in the near future.
     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<GCRelocateOperands> 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   InstructionTy *getGCResult() const {
    256     for (auto *U : getInstruction()->users())
    257       if (isGCResult(U))
    258         return cast<CallInst>(U);
    259 
    260     return nullptr;
    261   }
    262 
    263 #ifndef NDEBUG
    264   /// Asserts if this statepoint is malformed.  Common cases for failure
    265   /// include incorrect length prefixes for variable length sections or
    266   /// illegal values for parameters.
    267   void verify() {
    268     assert(getNumCallArgs() >= 0 &&
    269            "number of arguments to actually callee can't be negative");
    270 
    271     // The internal asserts in the iterator accessors do the rest.
    272     (void)arg_begin();
    273     (void)arg_end();
    274     (void)gc_transition_args_begin();
    275     (void)gc_transition_args_end();
    276     (void)vm_state_begin();
    277     (void)vm_state_end();
    278     (void)gc_args_begin();
    279     (void)gc_args_end();
    280   }
    281 #endif
    282 };
    283 
    284 /// A specialization of it's base class for read only access
    285 /// to a gc.statepoint.
    286 class ImmutableStatepoint
    287     : public StatepointBase<const Function, const Instruction, const Value,
    288                             ImmutableCallSite> {
    289   typedef StatepointBase<const Function, const Instruction, const Value,
    290                          ImmutableCallSite> Base;
    291 
    292 public:
    293   explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
    294   explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
    295 };
    296 
    297 /// A specialization of it's base class for read-write access
    298 /// to a gc.statepoint.
    299 class Statepoint
    300     : public StatepointBase<Function, Instruction, Value, CallSite> {
    301   typedef StatepointBase<Function, Instruction, Value, CallSite> Base;
    302 
    303 public:
    304   explicit Statepoint(Instruction *I) : Base(I) {}
    305   explicit Statepoint(CallSite CS) : Base(CS) {}
    306 };
    307 
    308 /// Wraps a call to a gc.relocate and provides access to it's operands.
    309 /// TODO: This should likely be refactored to resememble the wrappers in
    310 /// InstrinsicInst.h.
    311 class GCRelocateOperands {
    312   ImmutableCallSite RelocateCS;
    313 
    314 public:
    315   GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); }
    316   GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
    317     assert(isGCRelocate(inst));
    318   }
    319   GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); }
    320 
    321   /// Return true if this relocate is tied to the invoke statepoint.
    322   /// This includes relocates which are on the unwinding path.
    323   bool isTiedToInvoke() const {
    324     const Value *Token = RelocateCS.getArgument(0);
    325 
    326     return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token);
    327   }
    328 
    329   /// Get enclosed relocate intrinsic
    330   ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; }
    331 
    332   /// The statepoint with which this gc.relocate is associated.
    333   const Instruction *getStatepoint() {
    334     const Value *Token = RelocateCS.getArgument(0);
    335 
    336     // This takes care both of relocates for call statepoints and relocates
    337     // on normal path of invoke statepoint.
    338     if (!isa<ExtractValueInst>(Token)) {
    339       return cast<Instruction>(Token);
    340     }
    341 
    342     // This relocate is on exceptional path of an invoke statepoint
    343     const BasicBlock *InvokeBB =
    344         cast<Instruction>(Token)->getParent()->getUniquePredecessor();
    345 
    346     assert(InvokeBB && "safepoints should have unique landingpads");
    347     assert(InvokeBB->getTerminator() &&
    348            "safepoint block should be well formed");
    349     assert(isStatepoint(InvokeBB->getTerminator()));
    350 
    351     return InvokeBB->getTerminator();
    352   }
    353 
    354   /// The index into the associate statepoint's argument list
    355   /// which contains the base pointer of the pointer whose
    356   /// relocation this gc.relocate describes.
    357   unsigned getBasePtrIndex() {
    358     return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
    359   }
    360 
    361   /// The index into the associate statepoint's argument list which
    362   /// contains the pointer whose relocation this gc.relocate describes.
    363   unsigned getDerivedPtrIndex() {
    364     return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
    365   }
    366 
    367   Value *getBasePtr() {
    368     ImmutableCallSite CS(getStatepoint());
    369     return *(CS.arg_begin() + getBasePtrIndex());
    370   }
    371 
    372   Value *getDerivedPtr() {
    373     ImmutableCallSite CS(getStatepoint());
    374     return *(CS.arg_begin() + getDerivedPtrIndex());
    375   }
    376 };
    377 
    378 template <typename FunTy, typename InstructionTy, typename ValueTy,
    379           typename CallSiteTy>
    380 std::vector<GCRelocateOperands>
    381 StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates()
    382     const {
    383 
    384   std::vector<GCRelocateOperands> Result;
    385 
    386   CallSiteTy StatepointCS = getCallSite();
    387 
    388   // Search for relocated pointers.  Note that working backwards from the
    389   // gc_relocates ensures that we only get pairs which are actually relocated
    390   // and used after the statepoint.
    391   for (const User *U : getInstruction()->users())
    392     if (isGCRelocate(U))
    393       Result.push_back(GCRelocateOperands(U));
    394 
    395   if (!StatepointCS.isInvoke())
    396     return Result;
    397 
    398   // We need to scan thorough exceptional relocations if it is invoke statepoint
    399   LandingPadInst *LandingPad =
    400       cast<InvokeInst>(getInstruction())->getLandingPadInst();
    401 
    402   // Search for extract value from landingpad instruction to which
    403   // gc relocates will be attached
    404   for (const User *LandingPadUser : LandingPad->users()) {
    405     if (!isa<ExtractValueInst>(LandingPadUser))
    406       continue;
    407 
    408     // gc relocates should be attached to this extract value
    409     for (const User *U : LandingPadUser->users())
    410       if (isGCRelocate(U))
    411         Result.push_back(GCRelocateOperands(U));
    412   }
    413   return Result;
    414 }
    415 }
    416 
    417 #endif
    418