diff options
Diffstat (limited to 'include/llvm/Support')
-rw-r--r-- | include/llvm/Support/ValueHandle.h | 89 |
1 files changed, 86 insertions, 3 deletions
diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index 91b05b1..d22b30a 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -45,8 +45,9 @@ protected: /// fully general Callback version does have a vtable. enum HandleBaseKind { Assert, - Weak, - Callback + Callback, + Tracking, + Weak }; private: @@ -92,13 +93,13 @@ public: protected: Value *getValPtr() const { return VP; } -private: static bool isValid(Value *V) { return V && V != DenseMapInfo<Value *>::getEmptyKey() && V != DenseMapInfo<Value *>::getTombstoneKey(); } +private: // Callbacks made from Value. static void ValueIsDeleted(Value *V); static void ValueIsRAUWd(Value *Old, Value *New); @@ -223,6 +224,88 @@ template<> struct simplify_type<const AssertingVH<Value> > { template<> struct simplify_type<AssertingVH<Value> > : public simplify_type<const AssertingVH<Value> > {}; +/// 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<typename ValueTy> +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<ValueTy>(VP) && + "Tracked Value was replaced by one with an invalid type!"); + } + + ValueTy *getValPtr() const { + CheckValidity(); + return static_cast<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<Value*>(V); } + +public: + TrackingVH() : ValueHandleBase(Tracking) {} + TrackingVH(ValueTy *P) : ValueHandleBase(Tracking, 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<ValueTy> &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<typename From> struct simplify_type; +template<> struct simplify_type<const TrackingVH<Value> > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const TrackingVH<Value> &AVH) { + return static_cast<Value *>(AVH); + } +}; +template<> struct simplify_type<TrackingVH<Value> > + : public simplify_type<const TrackingVH<Value> > {}; + /// 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 |