X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FValueHandle.h;h=c0cdc35e99bfae5a541f8f8a2180c36ce321a914;hb=867fe8570f299a058f155f98646d85cabc27155b;hp=91e529e959b568bf88c59b1c293723791b63da8d;hpb=7e32c4fa72f8663abce1121965c3065f5dfa6747;p=oota-llvm.git diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index 91e529e959b..c0cdc35e99b 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -45,14 +45,17 @@ protected: /// fully general Callback version does have a vtable. enum HandleBaseKind { Assert, - Weak, - Callback + Callback, + Tracking, + Weak }; private: - + PointerIntPair PrevPair; ValueHandleBase *Next; Value *VP; + + explicit ValueHandleBase(const ValueHandleBase&); // DO NOT IMPLEMENT. public: explicit ValueHandleBase(HandleBaseKind Kind) : PrevPair(0, Kind), Next(0), VP(0) {} @@ -68,9 +71,9 @@ public: } ~ValueHandleBase() { if (isValid(VP)) - RemoveFromUseList(); + RemoveFromUseList(); } - + Value *operator=(Value *RHS) { if (VP == RHS) return RHS; if (isValid(VP)) RemoveFromUseList(); @@ -86,38 +89,43 @@ public: if (isValid(VP)) AddToExistingUseList(RHS.getPrevPtr()); return VP; } - + Value *operator->() const { return getValPtr(); } Value &operator*() const { return *getValPtr(); } protected: Value *getValPtr() const { return VP; } -private: static bool isValid(Value *V) { return V && V != DenseMapInfo::getEmptyKey() && V != DenseMapInfo::getTombstoneKey(); } +private: // Callbacks made from Value. static void ValueIsDeleted(Value *V); static void ValueIsRAUWd(Value *Old, Value *New); - + // Internal implementation details. ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - - /// AddToExistingUseList - 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 @@ -130,6 +138,13 @@ 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(); } @@ -160,7 +175,7 @@ template<> struct simplify_type : public simplify_type {}; /// AssertingVH's as it moves. This is required because in non-assert mode this /// class turns into a trivial wrapper around a pointer. template -class AssertingVH +class AssertingVH #ifndef NDEBUG : public ValueHandleBase #endif @@ -223,6 +238,115 @@ template<> struct simplify_type > { 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(); + } + + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); + } + ValueTy *operator=(const TrackingVH &RHS) { + setValPtr(RHS.getValPtr()); + return 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); + } +}; +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 @@ -264,7 +388,7 @@ public: /// _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 *new_value) {} + virtual void allUsesReplacedWith(Value *) {} }; // Specialize simplify_type to allow CallbackVH to participate in