LCOV - code coverage report
Current view: top level - include/llvm/IR - Statepoint.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 62 64 96.9 %
Date: 2018-10-20 13:21:21 Functions: 20 22 90.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13