From 147a8edb1b5b0a1b09591d4b09fa43ece7b37749 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Wed, 26 Apr 2017 16:20:59 +0000 Subject: [PATCH] Add a new WeakVH value handle; NFC Summary: WeakVH nulls itself out if the value it was tracking gets deleted, but it does not track RAUW. Reviewers: dblaikie, davide Subscribers: mcrosier, llvm-commits Differential Revision: https://reviews.llvm.org/D32267 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301425 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/ValueHandle.h | 40 ++++++++++++++++++++++++++++++-- lib/IR/Value.cpp | 7 ++++-- unittests/IR/ValueHandleTest.cpp | 18 ++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 7109c7b19f4..cba06671314 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -34,7 +34,7 @@ protected: /// /// 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, Tracking, WeakTracking }; + enum HandleBaseKind { Assert, Callback, Tracking, Weak, WeakTracking }; ValueHandleBase(const ValueHandleBase &RHS) : ValueHandleBase(RHS.PrevPair.getInt(), RHS) {} @@ -46,7 +46,7 @@ protected: } private: - PointerIntPair PrevPair; + PointerIntPair PrevPair; ValueHandleBase *Next; Value* V; @@ -126,6 +126,42 @@ private: void AddToUseList(); }; +/// \brief 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 { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; } +}; +template <> struct simplify_type { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } +}; + /// \brief 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 diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 23a0f7a2601..18e44dcd352 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -825,8 +825,10 @@ void ValueHandleBase::ValueIsDeleted(Value *V) { // pointer. Entry->operator=(DenseMapInfo::getTombstoneKey()); break; + case Weak: case WeakTracking: - // WeakTracking just goes to null, which will unlink it from the list. + // WeakTracking and Weak just go to null, which unlinks them + // from the list. Entry->operator=(nullptr); break; case Callback: @@ -874,7 +876,8 @@ void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { switch (Entry->getKind()) { case Assert: - // Asserting handle does not follow RAUW implicitly. + case Weak: + // Asserting and Weak handles do not follow RAUW implicitly. break; case Tracking: // Tracking goes to new value like a WeakTrackingVH. Note that this may diff --git a/unittests/IR/ValueHandleTest.cpp b/unittests/IR/ValueHandleTest.cpp index f4cacd3f7dd..191fdbb8f0f 100644 --- a/unittests/IR/ValueHandleTest.cpp +++ b/unittests/IR/ValueHandleTest.cpp @@ -34,6 +34,24 @@ public: ConcreteCallbackVH(Value *V) : CallbackVH(V) {} }; +TEST_F(ValueHandle, WeakVH_BasicOperation) { + WeakVH WVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), WVH); + WVH = ConstantV; + EXPECT_EQ(ConstantV, WVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(Context), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(Context), (*WVH).getType()); + + WVH = BitcastV.get(); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(WVH, BitcastV.get()); + BitcastV.reset(); + EXPECT_EQ(WVH, nullptr); +} + TEST_F(ValueHandle, WeakTrackingVH_BasicOperation) { WeakTrackingVH WVH(BitcastV.get()); EXPECT_EQ(BitcastV.get(), WVH); -- 2.50.1