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/Instructions.h"
     23 #include "llvm/IR/Intrinsics.h"
     24 #include "llvm/Support/Compiler.h"
     25 
     26 namespace llvm {
     27 
     28 class GCRelocateOperands;
     29 class ImmutableStatepoint;
     30 
     31 bool isStatepoint(const ImmutableCallSite &CS);
     32 bool isStatepoint(const Value *inst);
     33 bool isStatepoint(const Value &inst);
     34 
     35 bool isGCRelocate(const Value *inst);
     36 bool isGCRelocate(const ImmutableCallSite &CS);
     37 
     38 bool isGCResult(const Value *inst);
     39 bool isGCResult(const ImmutableCallSite &CS);
     40 
     41 /// Analogous to CallSiteBase, this provides most of the actual
     42 /// functionality for Statepoint and ImmutableStatepoint.  It is
     43 /// templatized to allow easily specializing of const and non-const
     44 /// concrete subtypes.  This is structured analogous to CallSite
     45 /// rather than the IntrinsicInst.h helpers since we want to support
     46 /// invokable statepoints in the near future.
     47 /// TODO: This does not currently allow the if(Statepoint S = ...)
     48 ///   idiom used with CallSites.  Consider refactoring to support.
     49 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
     50 class StatepointBase {
     51   CallSiteTy StatepointCS;
     52   void *operator new(size_t, unsigned) = delete;
     53   void *operator new(size_t s) = delete;
     54 
     55  protected:
     56   explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
     57     assert(isStatepoint(I));
     58   }
     59   explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) {
     60     assert(isStatepoint(CS));
     61   }
     62 
     63  public:
     64   typedef typename CallSiteTy::arg_iterator arg_iterator;
     65 
     66   /// Return the underlying CallSite.
     67   CallSiteTy getCallSite() {
     68     return StatepointCS;
     69   }
     70 
     71   /// Return the value actually being called or invoked.
     72   ValueTy *actualCallee() {
     73     return StatepointCS.getArgument(0);
     74   }
     75   /// Number of arguments to be passed to the actual callee.
     76   int numCallArgs() {
     77     return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
     78   }
     79   /// Number of additional arguments excluding those intended
     80   /// for garbage collection.
     81   int numTotalVMSArgs() {
     82     return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue();
     83   }
     84 
     85   typename CallSiteTy::arg_iterator call_args_begin() {
     86     // 3 = callTarget, #callArgs, flag
     87     int Offset = 3;
     88     assert(Offset <= (int)StatepointCS.arg_size());
     89     return StatepointCS.arg_begin() + Offset;
     90   }
     91   typename CallSiteTy::arg_iterator call_args_end() {
     92     int Offset = 3 + numCallArgs();
     93     assert(Offset <= (int)StatepointCS.arg_size());
     94     return StatepointCS.arg_begin() + Offset;
     95   }
     96 
     97   /// range adapter for call arguments
     98   iterator_range<arg_iterator> call_args() {
     99     return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
    100   }
    101 
    102   typename CallSiteTy::arg_iterator vm_state_begin() {
    103     return call_args_end();
    104   }
    105   typename CallSiteTy::arg_iterator vm_state_end() {
    106     int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs();
    107     assert(Offset <= (int)StatepointCS.arg_size());
    108     return StatepointCS.arg_begin() + Offset;
    109   }
    110 
    111   /// range adapter for vm state arguments
    112   iterator_range<arg_iterator> vm_state_args() {
    113     return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
    114   }
    115 
    116   typename CallSiteTy::arg_iterator first_vm_state_stack_begin() {
    117     // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci,
    118     //     1st_#stack, 1st_#local, 1st_#monitor
    119     return vm_state_begin() + 6;
    120   }
    121 
    122   typename CallSiteTy::arg_iterator gc_args_begin() {
    123     return vm_state_end();
    124   }
    125   typename CallSiteTy::arg_iterator gc_args_end() {
    126     return StatepointCS.arg_end();
    127   }
    128 
    129   /// range adapter for gc arguments
    130   iterator_range<arg_iterator> gc_args() {
    131     return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
    132   }
    133 
    134   /// Get list of all gc reloactes linked to this statepoint
    135   /// May contain several relocations for the same base/derived pair.
    136   /// For example this could happen due to relocations on unwinding
    137   /// path of invoke.
    138   std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
    139 
    140 #ifndef NDEBUG
    141   /// Asserts if this statepoint is malformed.  Common cases for failure
    142   /// include incorrect length prefixes for variable length sections or
    143   /// illegal values for parameters.
    144   void verify() {
    145     assert(numCallArgs() >= 0 &&
    146            "number of arguments to actually callee can't be negative");
    147 
    148     // The internal asserts in the iterator accessors do the rest.
    149     (void)call_args_begin();
    150     (void)call_args_end();
    151     (void)vm_state_begin();
    152     (void)vm_state_end();
    153     (void)gc_args_begin();
    154     (void)gc_args_end();
    155   }
    156 #endif
    157 };
    158 
    159 /// A specialization of it's base class for read only access
    160 /// to a gc.statepoint.
    161 class ImmutableStatepoint
    162     : public StatepointBase<const Instruction, const Value,
    163                             ImmutableCallSite> {
    164   typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
    165       Base;
    166 
    167 public:
    168   explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
    169   explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
    170 };
    171 
    172 /// A specialization of it's base class for read-write access
    173 /// to a gc.statepoint.
    174 class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
    175   typedef StatepointBase<Instruction, Value, CallSite> Base;
    176 
    177 public:
    178   explicit Statepoint(Instruction *I) : Base(I) {}
    179   explicit Statepoint(CallSite CS) : Base(CS) {}
    180 };
    181 
    182 /// Wraps a call to a gc.relocate and provides access to it's operands.
    183 /// TODO: This should likely be refactored to resememble the wrappers in
    184 /// InstrinsicInst.h.
    185 class GCRelocateOperands {
    186   ImmutableCallSite RelocateCS;
    187 
    188  public:
    189   GCRelocateOperands(const User* U) : RelocateCS(U) {
    190     assert(isGCRelocate(U));
    191   }
    192   GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
    193     assert(isGCRelocate(inst));
    194   }
    195   GCRelocateOperands(CallSite CS) : RelocateCS(CS) {
    196     assert(isGCRelocate(CS));
    197   }
    198 
    199   /// Return true if this relocate is tied to the invoke statepoint.
    200   /// This includes relocates which are on the unwinding path.
    201   bool isTiedToInvoke() const {
    202     const Value *Token = RelocateCS.getArgument(0);
    203 
    204     return isa<ExtractValueInst>(Token) ||
    205       isa<InvokeInst>(Token);
    206   }
    207 
    208   /// Get enclosed relocate intrinsic
    209   ImmutableCallSite getUnderlyingCallSite() {
    210     return RelocateCS;
    211   }
    212 
    213   /// The statepoint with which this gc.relocate is associated.
    214   const Instruction *statepoint() {
    215     const Value *token = RelocateCS.getArgument(0);
    216 
    217     // This takes care both of relocates for call statepoints and relocates
    218     // on normal path of invoke statepoint.
    219     if (!isa<ExtractValueInst>(token)) {
    220       return cast<Instruction>(token);
    221     }
    222 
    223     // This relocate is on exceptional path of an invoke statepoint
    224     const BasicBlock *invokeBB =
    225       cast<Instruction>(token)->getParent()->getUniquePredecessor();
    226 
    227     assert(invokeBB && "safepoints should have unique landingpads");
    228     assert(invokeBB->getTerminator() && "safepoint block should be well formed");
    229     assert(isStatepoint(invokeBB->getTerminator()));
    230 
    231     return invokeBB->getTerminator();
    232   }
    233   /// The index into the associate statepoint's argument list
    234   /// which contains the base pointer of the pointer whose
    235   /// relocation this gc.relocate describes.
    236   unsigned basePtrIndex() {
    237     return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
    238   }
    239   /// The index into the associate statepoint's argument list which
    240   /// contains the pointer whose relocation this gc.relocate describes.
    241   unsigned derivedPtrIndex() {
    242     return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
    243   }
    244   Value *basePtr() {
    245     ImmutableCallSite CS(statepoint());
    246     return *(CS.arg_begin() + basePtrIndex());
    247   }
    248   Value *derivedPtr() {
    249     ImmutableCallSite CS(statepoint());
    250     return *(CS.arg_begin() + derivedPtrIndex());
    251   }
    252 };
    253 
    254 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
    255 std::vector<GCRelocateOperands>
    256   StatepointBase<InstructionTy, ValueTy, CallSiteTy>::
    257     getRelocates(ImmutableStatepoint &IS) {
    258 
    259   std::vector<GCRelocateOperands> res;
    260 
    261   ImmutableCallSite StatepointCS = IS.getCallSite();
    262 
    263   // Search for relocated pointers.  Note that working backwards from the
    264   // gc_relocates ensures that we only get pairs which are actually relocated
    265   // and used after the statepoint.
    266   for (const User *U : StatepointCS.getInstruction()->users()) {
    267     if (isGCRelocate(U)) {
    268       res.push_back(GCRelocateOperands(U));
    269     }
    270   }
    271 
    272   if (!StatepointCS.isInvoke()) {
    273     return res;
    274   }
    275 
    276   // We need to scan thorough exceptional relocations if it is invoke statepoint
    277   LandingPadInst *LandingPad =
    278     cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
    279 
    280   // Search for extract value from landingpad instruction to which
    281   // gc relocates will be attached
    282   for (const User *LandingPadUser : LandingPad->users()) {
    283     if (!isa<ExtractValueInst>(LandingPadUser)) {
    284       continue;
    285     }
    286 
    287     // gc relocates should be attached to this extract value
    288     for (const User *U : LandingPadUser->users()) {
    289       if (isGCRelocate(U)) {
    290         res.push_back(GCRelocateOperands(U));
    291       }
    292     }
    293   }
    294   return res;
    295 }
    296 
    297 }
    298 #endif
    299