| //===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// |
| // |
| // 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 declares the ValueHandle class and its sub-classes. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_IR_VALUEHANDLE_H |
| #define LLVM_IR_VALUEHANDLE_H |
| |
| #include "llvm/ADT/DenseMapInfo.h" |
| #include "llvm/ADT/PointerIntPair.h" |
| #include "llvm/IR/Value.h" |
| #include "llvm/Support/Casting.h" |
| #include <cassert> |
| |
| namespace llvm { |
| |
| /// This is the common base class of value handles. |
| /// |
| /// ValueHandle's are smart pointers to Value's that have special behavior when |
| /// the value is deleted or ReplaceAllUsesWith'd. See the specific handles |
| /// below for details. |
| class ValueHandleBase { |
| friend class Value; |
| |
| protected: |
| /// This indicates what sub class the handle actually is. |
| /// |
| /// This is to avoid having a vtable for the light-weight handle pointers. The |
| /// fully general Callback version does have a vtable. |
| enum HandleBaseKind { Assert, Callback, Weak, WeakTracking }; |
| |
| ValueHandleBase(const ValueHandleBase &RHS) |
| : ValueHandleBase(RHS.PrevPair.getInt(), RHS) {} |
| |
| ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) |
| : PrevPair(nullptr, Kind), Val(RHS.getValPtr()) { |
| if (isValid(getValPtr())) |
| AddToExistingUseList(RHS.getPrevPtr()); |
| } |
| |
| private: |
| PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair; |
| ValueHandleBase *Next = nullptr; |
| Value *Val = nullptr; |
| |
| void setValPtr(Value *V) { Val = V; } |
| |
| public: |
| explicit ValueHandleBase(HandleBaseKind Kind) |
| : PrevPair(nullptr, Kind) {} |
| ValueHandleBase(HandleBaseKind Kind, Value *V) |
| : PrevPair(nullptr, Kind), Val(V) { |
| if (isValid(getValPtr())) |
| AddToUseList(); |
| } |
| |
| ~ValueHandleBase() { |
| if (isValid(getValPtr())) |
| RemoveFromUseList(); |
| } |
| |
| Value *operator=(Value *RHS) { |
| if (getValPtr() == RHS) |
| return RHS; |
| if (isValid(getValPtr())) |
| RemoveFromUseList(); |
| setValPtr(RHS); |
| if (isValid(getValPtr())) |
| AddToUseList(); |
| return RHS; |
| } |
| |
| Value *operator=(const ValueHandleBase &RHS) { |
| if (getValPtr() == RHS.getValPtr()) |
| return RHS.getValPtr(); |
| if (isValid(getValPtr())) |
| RemoveFromUseList(); |
| setValPtr(RHS.getValPtr()); |
| if (isValid(getValPtr())) |
| AddToExistingUseList(RHS.getPrevPtr()); |
| return getValPtr(); |
| } |
| |
| Value *operator->() const { return getValPtr(); } |
| Value &operator*() const { |
| Value *V = getValPtr(); |
| assert(V && "Dereferencing deleted ValueHandle"); |
| return *V; |
| } |
| |
| protected: |
| Value *getValPtr() const { return Val; } |
| |
| static bool isValid(Value *V) { |
| return V && |
| V != DenseMapInfo<Value *>::getEmptyKey() && |
| V != DenseMapInfo<Value *>::getTombstoneKey(); |
| } |
| |
| /// Remove this ValueHandle from its current use list. |
| void RemoveFromUseList(); |
| |
| /// Clear the underlying pointer without clearing the use list. |
| /// |
| /// This should only be used if a derived class has manually removed the |
| /// handle from the use list. |
| void clearValPtr() { setValPtr(nullptr); } |
| |
| public: |
| // Callbacks made from Value. |
| static void ValueIsDeleted(Value *V); |
| static void ValueIsRAUWd(Value *Old, Value *New); |
| |
| private: |
| // Internal implementation details. |
| ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } |
| HandleBaseKind getKind() const { return PrevPair.getInt(); } |
| void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } |
| |
| /// Add this ValueHandle to the use list for V. |
| /// |
| /// List is the address of either the head of the list or a Next node within |
| /// the existing use list. |
| void AddToExistingUseList(ValueHandleBase **List); |
| |
| /// Add this ValueHandle to the use list after Node. |
| void AddToExistingUseListAfter(ValueHandleBase *Node); |
| |
| /// Add this ValueHandle to the use list for V. |
| void AddToUseList(); |
| }; |
| |
| /// A nullable Value handle that is nullable. |
| /// |
| /// This is a value handle that points to a value, and nulls itself |
| /// out if that value is deleted. |
| class WeakVH : public ValueHandleBase { |
| public: |
| WeakVH() : ValueHandleBase(Weak) {} |
| WeakVH(Value *P) : ValueHandleBase(Weak, P) {} |
| WeakVH(const WeakVH &RHS) |
| : ValueHandleBase(Weak, RHS) {} |
| |
| WeakVH &operator=(const WeakVH &RHS) = default; |
| |
| Value *operator=(Value *RHS) { |
| return ValueHandleBase::operator=(RHS); |
| } |
| Value *operator=(const ValueHandleBase &RHS) { |
| return ValueHandleBase::operator=(RHS); |
| } |
| |
| operator Value*() const { |
| return getValPtr(); |
| } |
| }; |
| |
| // Specialize simplify_type to allow WeakVH to participate in |
| // dyn_cast, isa, etc. |
| template <> struct simplify_type<WeakVH> { |
| using SimpleType = Value *; |
| |
| static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; } |
| }; |
| template <> struct simplify_type<const WeakVH> { |
| using SimpleType = Value *; |
| |
| static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } |
| }; |
| |
| // Specialize DenseMapInfo to allow WeakVH to participate in DenseMap. |
| template <> struct DenseMapInfo<WeakVH> { |
| static inline WeakVH getEmptyKey() { |
| return WeakVH(DenseMapInfo<Value *>::getEmptyKey()); |
| } |
| |
| static inline WeakVH getTombstoneKey() { |
| return WeakVH(DenseMapInfo<Value *>::getTombstoneKey()); |
| } |
| |
| static unsigned getHashValue(const WeakVH &Val) { |
| return DenseMapInfo<Value *>::getHashValue(Val); |
| } |
| |
| static bool isEqual(const WeakVH &LHS, const WeakVH &RHS) { |
| return DenseMapInfo<Value *>::isEqual(LHS, RHS); |
| } |
| }; |
| |
| /// Value handle that is nullable, but tries to track the Value. |
| /// |
| /// This is a value handle that tries hard to point to a Value, even across |
| /// RAUW operations, but will null itself out if the value is destroyed. this |
| /// is useful for advisory sorts of information, but should not be used as the |
| /// key of a map (since the map would have to rearrange itself when the pointer |
| /// changes). |
| class WeakTrackingVH : public ValueHandleBase { |
| public: |
| WeakTrackingVH() : ValueHandleBase(WeakTracking) {} |
| WeakTrackingVH(Value *P) : ValueHandleBase(WeakTracking, P) {} |
| WeakTrackingVH(const WeakTrackingVH &RHS) |
| : ValueHandleBase(WeakTracking, RHS) {} |
| |
| WeakTrackingVH &operator=(const WeakTrackingVH &RHS) = default; |
| |
| Value *operator=(Value *RHS) { |
| return ValueHandleBase::operator=(RHS); |
| } |
| Value *operator=(const ValueHandleBase &RHS) { |
| return ValueHandleBase::operator=(RHS); |
| } |
| |
| operator Value*() const { |
| return getValPtr(); |
| } |
| |
| bool pointsToAliveValue() const { |
| return ValueHandleBase::isValid(getValPtr()); |
| } |
| }; |
| |
| // Specialize simplify_type to allow WeakTrackingVH to participate in |
| // dyn_cast, isa, etc. |
| template <> struct simplify_type<WeakTrackingVH> { |
| using SimpleType = Value *; |
| |
| static SimpleType getSimplifiedValue(WeakTrackingVH &WVH) { return WVH; } |
| }; |
| template <> struct simplify_type<const WeakTrackingVH> { |
| using SimpleType = Value *; |
| |
| static SimpleType getSimplifiedValue(const WeakTrackingVH &WVH) { |
| return WVH; |
| } |
| }; |
| |
| /// Value handle that asserts if the Value is deleted. |
| /// |
| /// This is a Value Handle that points to a value and asserts out if the value |
| /// is destroyed while the handle is still live. This is very useful for |
| /// catching dangling pointer bugs and other things which can be non-obvious. |
| /// One particularly useful place to use this is as the Key of a map. Dangling |
| /// pointer bugs often lead to really subtle bugs that only occur if another |
| /// object happens to get allocated to the same address as the old one. Using |
| /// an AssertingVH ensures that an assert is triggered as soon as the bad |
| /// delete occurs. |
| /// |
| /// Note that an AssertingVH handle does *not* follow values across RAUW |
| /// operations. This means that RAUW's need to explicitly update the |
| /// AssertingVH's as it moves. This is required because in non-assert mode this |
| /// class turns into a trivial wrapper around a pointer. |
| template <typename ValueTy> |
| class AssertingVH |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| : public ValueHandleBase |
| #endif |
| { |
| friend struct DenseMapInfo<AssertingVH<ValueTy>>; |
| |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } |
| void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } |
| #else |
| Value *ThePtr; |
| Value *getRawValPtr() const { return ThePtr; } |
| void setRawValPtr(Value *P) { ThePtr = P; } |
| #endif |
| // Convert a ValueTy*, which may be const, to the raw Value*. |
| static Value *GetAsValue(Value *V) { return V; } |
| static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } |
| |
| ValueTy *getValPtr() const { return static_cast<ValueTy *>(getRawValPtr()); } |
| void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } |
| |
| public: |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| AssertingVH() : ValueHandleBase(Assert) {} |
| AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} |
| AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} |
| #else |
| AssertingVH() : ThePtr(nullptr) {} |
| AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} |
| AssertingVH(const AssertingVH &) = default; |
| #endif |
| |
| operator ValueTy*() const { |
| return getValPtr(); |
| } |
| |
| ValueTy *operator=(ValueTy *RHS) { |
| setValPtr(RHS); |
| return getValPtr(); |
| } |
| ValueTy *operator=(const AssertingVH<ValueTy> &RHS) { |
| setValPtr(RHS.getValPtr()); |
| return getValPtr(); |
| } |
| |
| ValueTy *operator->() const { return getValPtr(); } |
| ValueTy &operator*() const { return *getValPtr(); } |
| }; |
| |
| // Treat AssertingVH<T> like T* inside maps. This also allows using find_as() |
| // to look up a value without constructing a value handle. |
| template<typename T> |
| struct DenseMapInfo<AssertingVH<T>> : DenseMapInfo<T *> {}; |
| |
| /// Value handle that tracks a Value across RAUW. |
| /// |
| /// TrackingVH is designed for situations where a client needs to hold a handle |
| /// to a Value (or subclass) across some operations which may move that value, |
| /// but should never destroy it or replace it with some unacceptable type. |
| /// |
| /// It is an error to attempt to replace a value with one of a type which is |
| /// incompatible with any of its outstanding TrackingVHs. |
| /// |
| /// It is an error to read from a TrackingVH that does not point to a valid |
| /// value. A TrackingVH is said to not point to a valid value if either it |
| /// hasn't yet been assigned a value yet or because the value it was tracking |
| /// has since been deleted. |
| /// |
| /// Assigning a value to a TrackingVH is always allowed, even if said TrackingVH |
| /// no longer points to a valid value. |
| template <typename ValueTy> class TrackingVH { |
| WeakTrackingVH InnerHandle; |
| |
| public: |
| ValueTy *getValPtr() const { |
| assert(InnerHandle.pointsToAliveValue() && |
| "TrackingVH must be non-null and valid on dereference!"); |
| |
| // Check that the value is a member of the correct subclass. We would like |
| // to check this property on assignment for better debugging, but we don't |
| // want to require a virtual interface on this VH. Instead we allow RAUW to |
| // replace this value with a value of an invalid type, and check it here. |
| assert(isa<ValueTy>(InnerHandle) && |
| "Tracked Value was replaced by one with an invalid type!"); |
| return cast<ValueTy>(InnerHandle); |
| } |
| |
| void setValPtr(ValueTy *P) { |
| // Assigning to non-valid TrackingVH's are fine so we just unconditionally |
| // assign here. |
| InnerHandle = GetAsValue(P); |
| } |
| |
| // Convert a ValueTy*, which may be const, to the type the base |
| // class expects. |
| static Value *GetAsValue(Value *V) { return V; } |
| static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } |
| |
| public: |
| TrackingVH() = default; |
| TrackingVH(ValueTy *P) { setValPtr(P); } |
| |
| operator ValueTy*() const { |
| return getValPtr(); |
| } |
| |
| ValueTy *operator=(ValueTy *RHS) { |
| setValPtr(RHS); |
| return getValPtr(); |
| } |
| |
| ValueTy *operator->() const { return getValPtr(); } |
| ValueTy &operator*() const { return *getValPtr(); } |
| }; |
| |
| /// Value handle with callbacks on RAUW and destruction. |
| /// |
| /// This is a value handle that allows subclasses to define callbacks that run |
| /// when the underlying Value has RAUW called on it or is destroyed. This |
| /// class can be used as the key of a map, as long as the user takes it out of |
| /// the map before calling setValPtr() (since the map has to rearrange itself |
| /// when the pointer changes). Unlike ValueHandleBase, this class has a vtable. |
| class CallbackVH : public ValueHandleBase { |
| virtual void anchor(); |
| protected: |
| ~CallbackVH() = default; |
| CallbackVH(const CallbackVH &) = default; |
| CallbackVH &operator=(const CallbackVH &) = default; |
| |
| void setValPtr(Value *P) { |
| ValueHandleBase::operator=(P); |
| } |
| |
| public: |
| CallbackVH() : ValueHandleBase(Callback) {} |
| CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} |
| CallbackVH(const Value *P) : CallbackVH(const_cast<Value *>(P)) {} |
| |
| operator Value*() const { |
| return getValPtr(); |
| } |
| |
| /// Callback for Value destruction. |
| /// |
| /// Called when this->getValPtr() is destroyed, inside ~Value(), so you |
| /// may call any non-virtual Value method on getValPtr(), but no subclass |
| /// methods. If WeakTrackingVH were implemented as a CallbackVH, it would use |
| /// this |
| /// method to call setValPtr(NULL). AssertingVH would use this method to |
| /// cause an assertion failure. |
| /// |
| /// All implementations must remove the reference from this object to the |
| /// Value that's being destroyed. |
| virtual void deleted() { setValPtr(nullptr); } |
| |
| /// Callback for Value RAUW. |
| /// |
| /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, |
| /// _before_ any of the uses have actually been replaced. If WeakTrackingVH |
| /// were |
| /// implemented as a CallbackVH, it would use this method to call |
| /// setValPtr(new_value). AssertingVH would do nothing in this method. |
| virtual void allUsesReplacedWith(Value *) {} |
| }; |
| |
| /// Value handle that poisons itself if the Value is deleted. |
| /// |
| /// This is a Value Handle that points to a value and poisons itself if the |
| /// value is destroyed while the handle is still live. This is very useful for |
| /// catching dangling pointer bugs where an \c AssertingVH cannot be used |
| /// because the dangling handle needs to outlive the value without ever being |
| /// used. |
| /// |
| /// One particularly useful place to use this is as the Key of a map. Dangling |
| /// pointer bugs often lead to really subtle bugs that only occur if another |
| /// object happens to get allocated to the same address as the old one. Using |
| /// a PoisoningVH ensures that an assert is triggered if looking up a new value |
| /// in the map finds a handle from the old value. |
| /// |
| /// Note that a PoisoningVH handle does *not* follow values across RAUW |
| /// operations. This means that RAUW's need to explicitly update the |
| /// PoisoningVH's as it moves. This is required because in non-assert mode this |
| /// class turns into a trivial wrapper around a pointer. |
| template <typename ValueTy> |
| class PoisoningVH final |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| : public CallbackVH |
| #endif |
| { |
| friend struct DenseMapInfo<PoisoningVH<ValueTy>>; |
| |
| // Convert a ValueTy*, which may be const, to the raw Value*. |
| static Value *GetAsValue(Value *V) { return V; } |
| static Value *GetAsValue(const Value *V) { return const_cast<Value *>(V); } |
| |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| /// A flag tracking whether this value has been poisoned. |
| /// |
| /// On delete and RAUW, we leave the value pointer alone so that as a raw |
| /// pointer it produces the same value (and we fit into the same key of |
| /// a hash table, etc), but we poison the handle so that any top-level usage |
| /// will fail. |
| bool Poisoned = false; |
| |
| Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } |
| void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } |
| |
| /// Handle deletion by poisoning the handle. |
| void deleted() override { |
| assert(!Poisoned && "Tried to delete an already poisoned handle!"); |
| Poisoned = true; |
| RemoveFromUseList(); |
| } |
| |
| /// Handle RAUW by poisoning the handle. |
| void allUsesReplacedWith(Value *) override { |
| assert(!Poisoned && "Tried to RAUW an already poisoned handle!"); |
| Poisoned = true; |
| RemoveFromUseList(); |
| } |
| #else // LLVM_ENABLE_ABI_BREAKING_CHECKS |
| Value *ThePtr = nullptr; |
| |
| Value *getRawValPtr() const { return ThePtr; } |
| void setRawValPtr(Value *P) { ThePtr = P; } |
| #endif |
| |
| ValueTy *getValPtr() const { |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| assert(!Poisoned && "Accessed a poisoned value handle!"); |
| #endif |
| return static_cast<ValueTy *>(getRawValPtr()); |
| } |
| void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } |
| |
| public: |
| PoisoningVH() = default; |
| #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| PoisoningVH(ValueTy *P) : CallbackVH(GetAsValue(P)) {} |
| PoisoningVH(const PoisoningVH &RHS) |
| : CallbackVH(RHS), Poisoned(RHS.Poisoned) {} |
| |
| ~PoisoningVH() { |
| if (Poisoned) |
| clearValPtr(); |
| } |
| |
| PoisoningVH &operator=(const PoisoningVH &RHS) { |
| if (Poisoned) |
| clearValPtr(); |
| CallbackVH::operator=(RHS); |
| Poisoned = RHS.Poisoned; |
| return *this; |
| } |
| #else |
| PoisoningVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} |
| #endif |
| |
| operator ValueTy *() const { return getValPtr(); } |
| |
| ValueTy *operator->() const { return getValPtr(); } |
| ValueTy &operator*() const { return *getValPtr(); } |
| }; |
| |
| // Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap. |
| template <typename T> struct DenseMapInfo<PoisoningVH<T>> { |
| static inline PoisoningVH<T> getEmptyKey() { |
| PoisoningVH<T> Res; |
| Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey()); |
| return Res; |
| } |
| |
| static inline PoisoningVH<T> getTombstoneKey() { |
| PoisoningVH<T> Res; |
| Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey()); |
| return Res; |
| } |
| |
| static unsigned getHashValue(const PoisoningVH<T> &Val) { |
| return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr()); |
| } |
| |
| static bool isEqual(const PoisoningVH<T> &LHS, const PoisoningVH<T> &RHS) { |
| return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(), |
| RHS.getRawValPtr()); |
| } |
| |
| // Allow lookup by T* via find_as(), without constructing a temporary |
| // value handle. |
| |
| static unsigned getHashValue(const T *Val) { |
| return DenseMapInfo<Value *>::getHashValue(Val); |
| } |
| |
| static bool isEqual(const T *LHS, const PoisoningVH<T> &RHS) { |
| return DenseMapInfo<Value *>::isEqual(LHS, RHS.getRawValPtr()); |
| } |
| }; |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_IR_VALUEHANDLE_H |