diff options
Diffstat (limited to 'include/llvm/IR/Statepoint.h')
-rw-r--r-- | include/llvm/IR/Statepoint.h | 149 |
1 files changed, 65 insertions, 84 deletions
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index 8908e1b0d090..89f130bc3351 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -1,14 +1,13 @@ //===- llvm/IR/Statepoint.h - gc.statepoint utilities -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains utility functions and a wrapper class analogous to -// CallSite for accessing the fields of gc.statepoint, gc.relocate, +// CallBase for accessing the fields of gc.statepoint, gc.relocate, // gc.result intrinsics; and some general utilities helpful when dealing with // gc.statepoint. // @@ -21,7 +20,6 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -57,42 +55,36 @@ enum class StatepointFlags { class GCRelocateInst; class GCResultInst; -bool isStatepoint(ImmutableCallSite CS); +bool isStatepoint(const CallBase *Call); bool isStatepoint(const Value *V); bool isStatepoint(const Value &V); -bool isGCRelocate(ImmutableCallSite CS); +bool isGCRelocate(const CallBase *Call); bool isGCRelocate(const Value *V); -bool isGCResult(ImmutableCallSite CS); +bool isGCResult(const CallBase *Call); bool isGCResult(const Value *V); -/// Analogous to CallSiteBase, this provides most of the actual +/// A wrapper around a GC intrinsic call, this provides most of the actual /// functionality for Statepoint and ImmutableStatepoint. It is /// templatized to allow easily specializing of const and non-const -/// concrete subtypes. This is structured analogous to CallSite -/// rather than the IntrinsicInst.h helpers since we need to support -/// invokable statepoints. +/// concrete subtypes. template <typename FunTy, typename InstructionTy, typename ValueTy, - typename CallSiteTy> + typename CallBaseTy> class StatepointBase { - CallSiteTy StatepointCS; + CallBaseTy *StatepointCall; protected: explicit StatepointBase(InstructionTy *I) { - if (isStatepoint(I)) { - StatepointCS = CallSiteTy(I); - assert(StatepointCS && "isStatepoint implies CallSite"); - } + StatepointCall = isStatepoint(I) ? cast<CallBaseTy>(I) : nullptr; } - explicit StatepointBase(CallSiteTy CS) { - if (isStatepoint(CS)) - StatepointCS = CS; + explicit StatepointBase(CallBaseTy *Call) { + StatepointCall = isStatepoint(Call) ? Call : nullptr; } public: - using arg_iterator = typename CallSiteTy::arg_iterator; + using arg_iterator = typename CallBaseTy::const_op_iterator; enum { IDPos = 0, @@ -107,30 +99,30 @@ public: void *operator new(size_t s) = delete; explicit operator bool() const { - // We do not assign non-statepoint CallSites to StatepointCS. - return (bool)StatepointCS; + // We do not assign non-statepoint call instructions to StatepointCall. + return (bool)StatepointCall; } - /// Return the underlying CallSite. - CallSiteTy getCallSite() const { + /// Return the underlying call instruction. + CallBaseTy *getCall() const { assert(*this && "check validity first!"); - return StatepointCS; + return StatepointCall; } uint64_t getFlags() const { - return cast<ConstantInt>(getCallSite().getArgument(FlagsPos)) + return cast<ConstantInt>(getCall()->getArgOperand(FlagsPos)) ->getZExtValue(); } /// Return the ID associated with this statepoint. uint64_t getID() const { - const Value *IDVal = getCallSite().getArgument(IDPos); + const Value *IDVal = getCall()->getArgOperand(IDPos); return cast<ConstantInt>(IDVal)->getZExtValue(); } /// Return the number of patchable bytes associated with this statepoint. uint32_t getNumPatchBytes() const { - const Value *NumPatchBytesVal = getCallSite().getArgument(NumPatchBytesPos); + const Value *NumPatchBytesVal = getCall()->getArgOperand(NumPatchBytesPos); uint64_t NumPatchBytes = cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); @@ -139,12 +131,11 @@ public: /// Return the value actually being called or invoked. ValueTy *getCalledValue() const { - return getCallSite().getArgument(CalledFunctionPos); + return getCall()->getArgOperand(CalledFunctionPos); } - InstructionTy *getInstruction() const { - return getCallSite().getInstruction(); - } + // FIXME: Migrate users of this to `getCall` and remove it. + InstructionTy *getInstruction() const { return getCall(); } /// Return the function being called if this is a direct call, otherwise /// return null (if it's an indirect call). @@ -153,12 +144,12 @@ public: } /// Return the caller function for this statepoint. - FunTy *getCaller() const { return getCallSite().getCaller(); } + FunTy *getCaller() const { return getCall()->getCaller(); } /// Determine if the statepoint cannot unwind. bool doesNotThrow() const { Function *F = getCalledFunction(); - return getCallSite().doesNotThrow() || (F ? F->doesNotThrow() : false); + return getCall()->doesNotThrow() || (F ? F->doesNotThrow() : false); } /// Return the type of the value returned by the call underlying the @@ -171,18 +162,18 @@ public: /// Number of arguments to be passed to the actual callee. int getNumCallArgs() const { - const Value *NumCallArgsVal = getCallSite().getArgument(NumCallArgsPos); + const Value *NumCallArgsVal = getCall()->getArgOperand(NumCallArgsPos); return cast<ConstantInt>(NumCallArgsVal)->getZExtValue(); } size_t arg_size() const { return getNumCallArgs(); } - typename CallSiteTy::arg_iterator arg_begin() const { - assert(CallArgsBeginPos <= (int)getCallSite().arg_size()); - return getCallSite().arg_begin() + CallArgsBeginPos; + arg_iterator arg_begin() const { + assert(CallArgsBeginPos <= (int)getCall()->arg_size()); + return getCall()->arg_begin() + CallArgsBeginPos; } - typename CallSiteTy::arg_iterator arg_end() const { + arg_iterator arg_end() const { auto I = arg_begin() + arg_size(); - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } @@ -199,8 +190,8 @@ public: /// Return true if the call or the callee has the given attribute. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { Function *F = getCalledFunction(); - return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) || - (F ? F->getAttributes().hasAttribute(i, A) : false); + return getCall()->paramHasAttr(i + CallArgsBeginPos, A) || + (F ? F->getAttributes().hasAttribute(i, A) : false); } /// Number of GC transition args. @@ -208,14 +199,14 @@ public: const Value *NumGCTransitionArgs = *arg_end(); return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator gc_transition_args_begin() const { + arg_iterator gc_transition_args_begin() const { auto I = arg_end() + 1; - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } - typename CallSiteTy::arg_iterator gc_transition_args_end() const { + arg_iterator gc_transition_args_end() const { auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs(); - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } @@ -231,14 +222,14 @@ public: return cast<ConstantInt>(NumVMSArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator deopt_begin() const { + arg_iterator deopt_begin() const { auto I = gc_transition_args_end() + 1; - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } - typename CallSiteTy::arg_iterator deopt_end() const { + arg_iterator deopt_end() const { auto I = deopt_begin() + getNumTotalVMSArgs(); - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } @@ -247,15 +238,11 @@ public: return make_range(deopt_begin(), deopt_end()); } - typename CallSiteTy::arg_iterator gc_args_begin() const { - return deopt_end(); - } - typename CallSiteTy::arg_iterator gc_args_end() const { - return getCallSite().arg_end(); - } + arg_iterator gc_args_begin() const { return deopt_end(); } + arg_iterator gc_args_end() const { return getCall()->arg_end(); } unsigned gcArgsStartIdx() const { - return gc_args_begin() - getInstruction()->op_begin(); + return gc_args_begin() - getCall()->op_begin(); } /// range adapter for gc arguments @@ -304,25 +291,24 @@ public: /// to a gc.statepoint. class ImmutableStatepoint : public StatepointBase<const Function, const Instruction, const Value, - ImmutableCallSite> { - using Base = - StatepointBase<const Function, const Instruction, const Value, - ImmutableCallSite>; + const CallBase> { + using Base = StatepointBase<const Function, const Instruction, const Value, + const CallBase>; public: explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} - explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} + explicit ImmutableStatepoint(const CallBase *Call) : Base(Call) {} }; /// A specialization of it's base class for read-write access /// to a gc.statepoint. class Statepoint - : public StatepointBase<Function, Instruction, Value, CallSite> { - using Base = StatepointBase<Function, Instruction, Value, CallSite>; + : public StatepointBase<Function, Instruction, Value, CallBase> { + using Base = StatepointBase<Function, Instruction, Value, CallBase>; public: explicit Statepoint(Instruction *I) : Base(I) {} - explicit Statepoint(CallSite CS) : Base(CS) {} + explicit Statepoint(CallBase *Call) : Base(Call) {} }; /// Common base class for representing values projected from a statepoint. @@ -347,14 +333,14 @@ public: } /// The statepoint with which this gc.relocate is associated. - const Instruction *getStatepoint() const { + const CallBase *getStatepoint() const { const Value *Token = getArgOperand(0); // This takes care both of relocates for call statepoints and relocates // on normal path of invoke statepoint. if (!isa<LandingPadInst>(Token)) { assert(isStatepoint(Token)); - return cast<Instruction>(Token); + return cast<CallBase>(Token); } // This relocate is on exceptional path of an invoke statepoint @@ -366,7 +352,7 @@ public: "safepoint block should be well formed"); assert(isStatepoint(InvokeBB->getTerminator())); - return InvokeBB->getTerminator(); + return cast<CallBase>(InvokeBB->getTerminator()); } }; @@ -395,13 +381,11 @@ public: } Value *getBasePtr() const { - ImmutableCallSite CS(getStatepoint()); - return *(CS.arg_begin() + getBasePtrIndex()); + return *(getStatepoint()->arg_begin() + getBasePtrIndex()); } Value *getDerivedPtr() const { - ImmutableCallSite CS(getStatepoint()); - return *(CS.arg_begin() + getDerivedPtrIndex()); + return *(getStatepoint()->arg_begin() + getDerivedPtrIndex()); } }; @@ -418,28 +402,25 @@ public: }; template <typename FunTy, typename InstructionTy, typename ValueTy, - typename CallSiteTy> + typename CallBaseTy> std::vector<const GCRelocateInst *> -StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates() +StatepointBase<FunTy, InstructionTy, ValueTy, CallBaseTy>::getRelocates() const { - std::vector<const GCRelocateInst *> Result; - CallSiteTy StatepointCS = getCallSite(); - // Search for relocated pointers. Note that working backwards from the // gc_relocates ensures that we only get pairs which are actually relocated // and used after the statepoint. - for (const User *U : getInstruction()->users()) + for (const User *U : StatepointCall->users()) if (auto *Relocate = dyn_cast<GCRelocateInst>(U)) Result.push_back(Relocate); - if (!StatepointCS.isInvoke()) + auto *StatepointInvoke = dyn_cast<InvokeInst>(StatepointCall); + if (!StatepointInvoke) return Result; // We need to scan thorough exceptional relocations if it is invoke statepoint - LandingPadInst *LandingPad = - cast<InvokeInst>(getInstruction())->getLandingPadInst(); + LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst(); // Search for gc relocates that are attached to this landingpad. for (const User *LandingPadUser : LandingPad->users()) { |