diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index 89f130bc335..f9eeddba778 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -65,26 +65,46 @@ bool isGCRelocate(const Value *V); bool isGCResult(const CallBase *Call); bool isGCResult(const Value *V); +/// Represents a gc.statepoint intrinsic call. This extends directly from +/// CallBase as the IntrinsicInst only supports calls and gc.statepoint is +/// invokable. +class GCStatepointInst : public CallBase { +public: + GCStatepointInst() = delete; + GCStatepointInst(const GCStatepointInst &) = delete; + GCStatepointInst &operator=(const GCStatepointInst &) = delete; + + static bool classof(const CallBase *I) { + if (const Function *CF = I->getCalledFunction()) + return CF->getIntrinsicID() == Intrinsic::experimental_gc_statepoint; + return false; + } + + static bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + /// 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. template + typename CallTy> class StatepointBase { - CallBaseTy *StatepointCall; + CallTy *StatepointCall; protected: explicit StatepointBase(InstructionTy *I) { - StatepointCall = isStatepoint(I) ? cast(I) : nullptr; + StatepointCall = isStatepoint(I) ? cast(I) : nullptr; } - explicit StatepointBase(CallBaseTy *Call) { + explicit StatepointBase(CallTy *Call) { StatepointCall = isStatepoint(Call) ? Call : nullptr; } public: - using arg_iterator = typename CallBaseTy::const_op_iterator; + using arg_iterator = typename CallTy::const_op_iterator; enum { IDPos = 0, @@ -104,7 +124,7 @@ public: } /// Return the underlying call instruction. - CallBaseTy *getCall() const { + CallTy *getCall() const { assert(*this && "check validity first!"); return StatepointCall; } @@ -291,9 +311,9 @@ public: /// to a gc.statepoint. class ImmutableStatepoint : public StatepointBase { + const GCStatepointInst> { using Base = StatepointBase; + const GCStatepointInst>; public: explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} @@ -303,8 +323,8 @@ public: /// A specialization of it's base class for read-write access /// to a gc.statepoint. class Statepoint - : public StatepointBase { - using Base = StatepointBase; + : public StatepointBase { + using Base = StatepointBase; public: explicit Statepoint(Instruction *I) : Base(I) {} @@ -402,9 +422,9 @@ public: }; template + typename CallTy> std::vector -StatepointBase::getRelocates() +StatepointBase::getRelocates() const { std::vector Result; diff --git a/lib/IR/Statepoint.cpp b/lib/IR/Statepoint.cpp index fce89b42e9b..53b0d1e0aa3 100644 --- a/lib/IR/Statepoint.cpp +++ b/lib/IR/Statepoint.cpp @@ -18,15 +18,11 @@ using namespace llvm; bool llvm::isStatepoint(const CallBase *Call) { - if (auto *F = Call->getCalledFunction()) - return F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint; - return false; + return isa(Call); } bool llvm::isStatepoint(const Value *V) { - if (auto *Call = dyn_cast(V)) - return isStatepoint(Call); - return false; + return isa(V); } bool llvm::isStatepoint(const Value &V) {