X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FValueHandle.h;h=dbcf0fd11d19d8c3c5784fefdcdd82ca443248ab;hb=cee033188f7b1a4f1b28b8edce0c1358f19f8158;hp=a668656a07e485d5900b733de27d88c6fb188cf6;hpb=b7a00daa1165576dd2bb9d17970c249d536f4a82;p=oota-llvm.git diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index a668656a07e..dbcf0fd11d1 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_VALUEHANDLE_H #define LLVM_SUPPORT_VALUEHANDLE_H +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Value.h" @@ -39,90 +40,102 @@ public: class ValueHandleBase { friend class Value; protected: - /// HandleBaseKind - This indicates what base class the handle actually is. + /// HandleBaseKind - This indicates what sub class the handle actually is. /// This is to avoid having a vtable for the light-weight handle pointers. The - /// fully generally Callback version does have a vtable. + /// fully general Callback version does have a vtable. enum HandleBaseKind { Assert, - Weak, - Callback + Callback, + Tracking, + Weak }; + private: - PointerIntPair PrevPair; ValueHandleBase *Next; - Value *VP; + + // A subclass may want to store some information along with the value + // pointer. Allow them to do this by making the value pointer a pointer-int + // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this + // access. + PointerIntPair VP; + + ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; public: - ValueHandleBase(HandleBaseKind Kind) : PrevPair(0, Kind), Next(0), VP(0) {} + explicit ValueHandleBase(HandleBaseKind Kind) + : PrevPair(0, Kind), Next(0), VP(0, 0) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(0, Kind), Next(0), VP(V) { - if (V) + : PrevPair(0, Kind), Next(0), VP(V, 0) { + if (isValid(VP.getPointer())) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) : PrevPair(0, Kind), Next(0), VP(RHS.VP) { - if (VP) + if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); } ~ValueHandleBase() { - if (VP) - RemoveFromUseList(); + if (isValid(VP.getPointer())) + RemoveFromUseList(); } - + Value *operator=(Value *RHS) { - if (VP == RHS) return RHS; - if (VP) RemoveFromUseList(); - VP = RHS; - if (VP) AddToUseList(); + if (VP.getPointer() == RHS) return RHS; + if (isValid(VP.getPointer())) RemoveFromUseList(); + VP.setPointer(RHS); + if (isValid(VP.getPointer())) AddToUseList(); return RHS; } Value *operator=(const ValueHandleBase &RHS) { - if (VP == RHS.VP) return RHS.VP; - if (VP) RemoveFromUseList(); - VP = RHS.VP; - if (VP) AddToExistingUseList(RHS.getPrevPtr()); - return VP; + if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); + if (isValid(VP.getPointer())) RemoveFromUseList(); + VP.setPointer(RHS.VP.getPointer()); + if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); + return VP.getPointer(); } - + Value *operator->() const { return getValPtr(); } Value &operator*() const { return *getValPtr(); } - - bool operator==(const Value *RHS) const { return VP == RHS; } - bool operator==(const ValueHandleBase &RHS) const { return VP == RHS.VP; } - bool operator!=(const Value *RHS) const { return VP != RHS; } - bool operator!=(const ValueHandleBase &RHS) const { return VP != RHS.VP; } - bool operator<(const Value *RHS) const { return VP < RHS; } - bool operator<(const ValueHandleBase &RHS) const { return VP < RHS.VP; } - bool operator>(const Value *RHS) const { return VP > RHS; } - bool operator>(const ValueHandleBase &RHS) const { return VP > RHS.VP; } - bool operator<=(const Value *RHS) const { return VP <= RHS; } - bool operator<=(const ValueHandleBase &RHS) const { return VP <= RHS.VP; } - bool operator>=(const Value *RHS) const { return VP >= RHS; } - bool operator>=(const ValueHandleBase &RHS) const { return VP >= RHS.VP; } - + protected: - Value *getValPtr() const { return VP; } -private: + Value *getValPtr() const { return VP.getPointer(); } + + void setValPtrInt(unsigned K) { VP.setInt(K); } + unsigned getValPtrInt() const { return VP.getInt(); } + + static bool isValid(Value *V) { + return V && + V != DenseMapInfo::getEmptyKey() && + V != DenseMapInfo::getTombstoneKey(); + } + +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); } - - /// AddToUseList - Add this ValueHandle to the use list for VP, where List is - /// known to point into the existing use list. + + /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where + /// List is the address of either the head of the list or a Next node within + /// the existing use list. void AddToExistingUseList(ValueHandleBase **List); - + + /// AddToExistingUseListAfter - Add this ValueHandle to the use list after + /// Node. + void AddToExistingUseListAfter(ValueHandleBase *Node); + /// AddToUseList - Add this ValueHandle to the use list for VP. void AddToUseList(); /// RemoveFromUseList - Remove this ValueHandle from its current use list. void RemoveFromUseList(); }; - + /// WeakVH - 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 @@ -135,11 +148,29 @@ public: WeakVH(const WeakVH &RHS) : ValueHandleBase(Weak, RHS) {} + 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; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const WeakVH &WVH) { + return static_cast(WVH); + } +}; +template<> struct simplify_type : public simplify_type {}; + /// AssertingVH - 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 @@ -152,9 +183,9 @@ public: /// 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. +/// class turns into a trivial wrapper around a pointer. template -class AssertingVH +class AssertingVH #ifndef NDEBUG : public ValueHandleBase #endif @@ -165,7 +196,7 @@ class AssertingVH return static_cast(ValueHandleBase::getValPtr()); } void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(P); + ValueHandleBase::operator=(GetAsValue(P)); } #else ValueTy *ThePtr; @@ -173,10 +204,15 @@ class AssertingVH void setValPtr(ValueTy *P) { ThePtr = P; } #endif + // 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(V); } + public: #ifndef NDEBUG AssertingVH() : ValueHandleBase(Assert) {} - AssertingVH(ValueTy *P) : ValueHandleBase(Assert, P) {} + AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else AssertingVH() : ThePtr(0) {} @@ -191,41 +227,189 @@ public: setValPtr(RHS); return getValPtr(); } - ValueTy *operator=(AssertingVH &RHS) { + ValueTy *operator=(const AssertingVH &RHS) { setValPtr(RHS.getValPtr()); return getValPtr(); } ValueTy *operator->() const { return getValPtr(); } ValueTy &operator*() const { return *getValPtr(); } +}; + +// Specialize simplify_type to allow AssertingVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const AssertingVH &AVH) { + return static_cast(AVH); + } +}; +template<> struct simplify_type > + : public simplify_type > {}; + +// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. +template +struct DenseMapInfo > { + typedef DenseMapInfo PointerInfo; + static inline AssertingVH getEmptyKey() { + return AssertingVH(PointerInfo::getEmptyKey()); + } + static inline T* getTombstoneKey() { + return AssertingVH(PointerInfo::getTombstoneKey()); + } + static unsigned getHashValue(const AssertingVH &Val) { + return PointerInfo::getHashValue(Val); + } + static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { + return LHS == RHS; + } +}; + +template +struct isPodLike > { +#ifdef NDEBUG + static const bool value = true; +#else + static const bool value = false; +#endif +}; + + +/// TrackingVH - This is a value handle that tracks a Value (or Value subclass), +/// even across RAUW operations. +/// +/// 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 do anything with a TrackingVH whose value has been +/// destroyed, except to destruct it. +/// +/// It is an error to attempt to replace a value with one of a type which is +/// incompatible with any of its outstanding TrackingVHs. +template +class TrackingVH : public ValueHandleBase { + void CheckValidity() const { + Value *VP = ValueHandleBase::getValPtr(); + + // Null is always ok. + if (!VP) return; + + // Check that this value is valid (i.e., it hasn't been deleted). We + // explicitly delay this check until access to avoid requiring clients to be + // unnecessarily careful w.r.t. destruction. + assert(ValueHandleBase::isValid(VP) && "Tracked Value was deleted!"); + + // 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(VP) && + "Tracked Value was replaced by one with an invalid type!"); + } + + ValueTy *getValPtr() const { + CheckValidity(); + return (ValueTy*)ValueHandleBase::getValPtr(); + } + void setValPtr(ValueTy *P) { + CheckValidity(); + ValueHandleBase::operator=(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(V); } + +public: + TrackingVH() : ValueHandleBase(Tracking) {} + TrackingVH(ValueTy *P) : ValueHandleBase(Tracking, GetAsValue(P)) {} + TrackingVH(const TrackingVH &RHS) : ValueHandleBase(Tracking, RHS) {} + + operator ValueTy*() const { + return getValPtr(); + } - // Duplicate these from the base class so that they work when assertions are - // off. - bool operator==(const Value *RHS) const { return getValPtr() == RHS; } - bool operator!=(const Value *RHS) const { return getValPtr() != RHS; } - bool operator<(const Value *RHS) const { return getValPtr() < RHS; } - bool operator>(const Value *RHS) const { return getValPtr() > RHS; } - bool operator<=(const Value *RHS) const { return getValPtr() <= RHS; } - bool operator>=(const Value *RHS) const { return getValPtr() >= RHS; } - bool operator==(const AssertingVH &RHS) const { - return getValPtr() == RHS.getValPtr(); + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); } - bool operator!=(const AssertingVH &RHS) const { - return getValPtr() != RHS.getValPtr(); + ValueTy *operator=(const TrackingVH &RHS) { + setValPtr(RHS.getValPtr()); + return getValPtr(); } - bool operator<(const AssertingVH &RHS) const { - return getValPtr() < RHS.getValPtr(); + + ValueTy *operator->() const { return getValPtr(); } + ValueTy &operator*() const { return *getValPtr(); } +}; + +// Specialize simplify_type to allow TrackingVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const TrackingVH &AVH) { + return static_cast(AVH); } - bool operator>(const AssertingVH &RHS) const { - return getValPtr() > RHS.getValPtr(); +}; +template<> struct simplify_type > + : public simplify_type > {}; + +/// CallbackVH - 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 and a virtual destructor. +class CallbackVH : public ValueHandleBase { +protected: + CallbackVH(const CallbackVH &RHS) + : ValueHandleBase(Callback, RHS) {} + + virtual ~CallbackVH() {} + + void setValPtr(Value *P) { + ValueHandleBase::operator=(P); } - bool operator<=(const AssertingVH &RHS) const { - return getValPtr() <= RHS.getValPtr(); + +public: + CallbackVH() : ValueHandleBase(Callback) {} + CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} + + operator Value*() const { + return getValPtr(); } - bool operator>=(const AssertingVH &RHS) const { - return getValPtr() >= RHS.getValPtr(); + + /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may + /// call any non-virtual Value method on getValPtr(), but no subclass methods. + /// If WeakVH 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(); + + /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, + /// _before_ any of the uses have actually been replaced. If WeakVH 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 *); +}; + +// Specialize simplify_type to allow CallbackVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const CallbackVH &CVH) { + return static_cast(CVH); } }; +template<> struct simplify_type + : public simplify_type {}; } // End llvm namespace