From: Chandler Carruth Date: Tue, 4 Mar 2014 11:17:44 +0000 (+0000) Subject: [Modules] Move ValueHandle into the IR library where Value itself lives. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=eb3d76da81e2148ed7c577594c873ba147f4f435;p=oota-llvm.git [Modules] Move ValueHandle into the IR library where Value itself lives. Move the test for this class into the IR unittests as well. This uncovers that ValueMap too is in the IR library. Ironically, the unittest for ValueMap is useless in the Support library (honestly, so was the ValueHandle test) and so it already lives in the IR unittests. Mmmm, tasty layering. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202821 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/ADT/ValueMap.h index b4fed7a0ebd..18913d8b8d7 100644 --- a/include/llvm/ADT/ValueMap.h +++ b/include/llvm/ADT/ValueMap.h @@ -27,8 +27,8 @@ #define LLVM_ADT_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/type_traits.h" #include diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index da007072e55..a8005058e7e 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -20,7 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include namespace llvm { diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index c813e4b3189..2866ed6e92a 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -57,9 +57,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Function.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/IncludeFile.h" -#include "llvm/Support/ValueHandle.h" #include namespace llvm { diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index 58d347ed19b..52df2fff8e9 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -17,7 +17,7 @@ #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" namespace llvm { diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index ec2fea838fa..7784db402c1 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -19,10 +19,10 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/InstVisitor.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/TargetFolder.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class CallInst; diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index b4b401a1e6b..329aa253648 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -20,8 +20,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class Function; diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index e1d4861a555..e2d8765b4a8 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -26,11 +26,11 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/ValueHandle.h" #include namespace llvm { diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 167861db621..3e57ba877ee 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -17,8 +17,8 @@ #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/TargetFolder.h" -#include "llvm/Support/ValueHandle.h" #include namespace llvm { diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index af1f8470a42..bfa787dbe59 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -22,8 +22,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/DebugLoc.h" -#include "llvm/Support/ValueHandle.h" #include namespace llvm { diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 460c08c8ca7..b51020654af 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -36,13 +36,13 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index df900e29ef1..d795859adaa 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -18,8 +18,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class BasicBlock; diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index b906b274f31..605236ba87a 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -19,10 +19,10 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mutex.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index e43bc9fc5d3..29264668e1b 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -23,9 +23,9 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/ConstantFolder.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class MDNode; diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 858c6e3f4f8..f1945020d50 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -61,7 +61,7 @@ typedef StringMapEntry ValueName; /// Every value has a "use list" that keeps track of which other Values are /// using this Value. A Value can also have an arbitrary number of ValueHandle /// objects that watch it and listen to RAUW and Destroy events. See -/// llvm/Support/ValueHandle.h for details. +/// llvm/IR/ValueHandle.h for details. /// /// @brief LLVM Value Representation class Value { diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h new file mode 100644 index 00000000000..9b5e11aae43 --- /dev/null +++ b/include/llvm/IR/ValueHandle.h @@ -0,0 +1,380 @@ +//===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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" + +namespace llvm { +class ValueHandleBase; +template struct simplify_type; + +// ValueHandleBase** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(ValueHandleBase** P) { return P; } + static inline ValueHandleBase **getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +/// ValueHandleBase - 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: + /// 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 general Callback version does have a vtable. + enum HandleBaseKind { + Assert, + Callback, + Tracking, + Weak + }; + +private: + PointerIntPair PrevPair; + ValueHandleBase *Next; + + // 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: + explicit ValueHandleBase(HandleBaseKind Kind) + : PrevPair(0, Kind), Next(0), VP(0, 0) {} + ValueHandleBase(HandleBaseKind Kind, Value *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 (isValid(VP.getPointer())) + AddToExistingUseList(RHS.getPrevPtr()); + } + ~ValueHandleBase() { + if (isValid(VP.getPointer())) + RemoveFromUseList(); + } + + Value *operator=(Value *RHS) { + 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.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(); } + +protected: + 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); } + + /// 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 +/// the key of a map (since the map would have to rearrange itself when the +/// pointer changes). +class WeakVH : public ValueHandleBase { +public: + WeakVH() : ValueHandleBase(Weak) {} + WeakVH(Value *P) : ValueHandleBase(Weak, P) {} + 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 { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(WeakVH &WVH) { + return WVH; + } +}; + +/// 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 +/// 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 +class AssertingVH +#ifndef NDEBUG + : public ValueHandleBase +#endif + { + +#ifndef NDEBUG + ValueTy *getValPtr() const { + return static_cast(ValueHandleBase::getValPtr()); + } + void setValPtr(ValueTy *P) { + ValueHandleBase::operator=(GetAsValue(P)); + } +#else + ValueTy *ThePtr; + ValueTy *getValPtr() const { return ThePtr; } + 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, GetAsValue(P)) {} + AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} +#else + AssertingVH() : ThePtr(0) {} + AssertingVH(ValueTy *P) : ThePtr(P) {} +#endif + + operator ValueTy*() const { + return getValPtr(); + } + + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); + } + ValueTy *operator=(const AssertingVH &RHS) { + setValPtr(RHS.getValPtr()); + return getValPtr(); + } + + ValueTy *operator->() const { return getValPtr(); } + ValueTy &operator*() const { return *getValPtr(); } +}; + +// 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(); } +}; + +/// 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 { + virtual void anchor(); +protected: + CallbackVH(const CallbackVH &RHS) + : ValueHandleBase(Callback, RHS) {} + + virtual ~CallbackVH() {} + + void setValPtr(Value *P) { + ValueHandleBase::operator=(P); + } + +public: + CallbackVH() : ValueHandleBase(Callback) {} + CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} + + operator Value*() const { + return 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() { setValPtr(NULL); } + + /// 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 *) {} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h deleted file mode 100644 index bc02ba31b9b..00000000000 --- a/include/llvm/Support/ValueHandle.h +++ /dev/null @@ -1,380 +0,0 @@ -//===- llvm/Support/ValueHandle.h - Value Smart Pointer classes -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the ValueHandle class and its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_VALUEHANDLE_H -#define LLVM_SUPPORT_VALUEHANDLE_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/IR/Value.h" - -namespace llvm { -class ValueHandleBase; -template struct simplify_type; - -// ValueHandleBase** is only 4-byte aligned. -template<> -class PointerLikeTypeTraits { -public: - static inline void *getAsVoidPointer(ValueHandleBase** P) { return P; } - static inline ValueHandleBase **getFromVoidPointer(void *P) { - return static_cast(P); - } - enum { NumLowBitsAvailable = 2 }; -}; - -/// ValueHandleBase - 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: - /// 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 general Callback version does have a vtable. - enum HandleBaseKind { - Assert, - Callback, - Tracking, - Weak - }; - -private: - PointerIntPair PrevPair; - ValueHandleBase *Next; - - // 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: - explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(0, Kind), Next(0), VP(0, 0) {} - ValueHandleBase(HandleBaseKind Kind, Value *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 (isValid(VP.getPointer())) - AddToExistingUseList(RHS.getPrevPtr()); - } - ~ValueHandleBase() { - if (isValid(VP.getPointer())) - RemoveFromUseList(); - } - - Value *operator=(Value *RHS) { - 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.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(); } - -protected: - 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); } - - /// 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 -/// the key of a map (since the map would have to rearrange itself when the -/// pointer changes). -class WeakVH : public ValueHandleBase { -public: - WeakVH() : ValueHandleBase(Weak) {} - WeakVH(Value *P) : ValueHandleBase(Weak, P) {} - 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 { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(WeakVH &WVH) { - return WVH; - } -}; - -/// 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 -/// 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 -class AssertingVH -#ifndef NDEBUG - : public ValueHandleBase -#endif - { - -#ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } -#else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - 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, GetAsValue(P)) {} - AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} -#else - AssertingVH() : ThePtr(0) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} -#endif - - operator ValueTy*() const { - return getValPtr(); - } - - ValueTy *operator=(ValueTy *RHS) { - setValPtr(RHS); - return getValPtr(); - } - ValueTy *operator=(const AssertingVH &RHS) { - setValPtr(RHS.getValPtr()); - return getValPtr(); - } - - ValueTy *operator->() const { return getValPtr(); } - ValueTy &operator*() const { return *getValPtr(); } -}; - -// 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(); } -}; - -/// 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 { - virtual void anchor(); -protected: - CallbackVH(const CallbackVH &RHS) - : ValueHandleBase(Callback, RHS) {} - - virtual ~CallbackVH() {} - - void setValPtr(Value *P) { - ValueHandleBase::operator=(P); - } - -public: - CallbackVH() : ValueHandleBase(Callback) {} - CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} - - operator Value*() const { - return 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() { setValPtr(NULL); } - - /// 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 *) {} -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 7b6db47a81f..6c4e50125ef 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -21,7 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/ValueMap.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Transforms/Utils/ValueMapper.h" namespace llvm { diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h index a9adbd73c15..0f3da165081 100644 --- a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h +++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -17,9 +17,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h index 3c3de467c45..dedeca3b30a 100644 --- a/include/llvm/Transforms/Utils/SimplifyIndVar.h +++ b/include/llvm/Transforms/Utils/SimplifyIndVar.h @@ -16,8 +16,8 @@ #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H #define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index b1af8f81421..6cefc785baf 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -30,8 +30,8 @@ #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/Operator.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/ConstantRange.h" -#include "llvm/Support/ValueHandle.h" using namespace llvm; using namespace llvm::PatternMatch; diff --git a/lib/Analysis/LazyValueInfo.cpp b/lib/Analysis/LazyValueInfo.cpp index c78763f2069..b68b3869e70 100644 --- a/lib/Analysis/LazyValueInfo.cpp +++ b/lib/Analysis/LazyValueInfo.cpp @@ -23,10 +23,10 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CFG.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index d25374ff053..790ffd2c710 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -22,7 +22,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include namespace llvm { diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h index f6c9d6678a4..56795e23676 100644 --- a/lib/Bitcode/Reader/BitcodeReader.h +++ b/lib/Bitcode/Reader/BitcodeReader.h @@ -21,7 +21,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/OperandTraits.h" #include "llvm/IR/Type.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/system_error.h" #include diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5d466204233..91aa7639ad3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" @@ -42,7 +43,6 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" #include "llvm/Support/Timer.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index 8ad68bdfbb4..7e2dce6a717 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -32,10 +32,10 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetLowering.h" diff --git a/lib/ExecutionEngine/EventListenerCommon.h b/lib/ExecutionEngine/EventListenerCommon.h index 314db8bd84c..5d756ed062f 100644 --- a/lib/ExecutionEngine/EventListenerCommon.h +++ b/lib/ExecutionEngine/EventListenerCommon.h @@ -17,8 +17,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/DebugInfo.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Path.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 335efaf8a1b..062c13f2789 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -24,13 +24,13 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Host.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index 7dc295fcbf7..bfcbbc850c3 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -28,7 +28,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "EventListenerCommon.h" #include "IntelJITEventsWrapper.h" diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index 4f6416ff10b..6af2b4ae365 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -15,8 +15,8 @@ #define JIT_H #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/PassManager.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index acbbfa14552..ba5d4e42add 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -35,13 +35,13 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Disassembler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Memory.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetJITInfo.h" diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index df059c4d7fc..add4b87a8b1 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -24,9 +24,9 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::dwarf; diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 8b94ab1c779..7a3cdb9e9d3 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -30,7 +30,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include namespace llvm { diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index ad943de88cc..512dec196f2 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -22,9 +22,9 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/LeakDetector.h" -#include "llvm/Support/ValueHandle.h" using namespace llvm; //===----------------------------------------------------------------------===// diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index cc850cb2cb9..eb12bc5a8e3 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -23,12 +23,12 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/IR/ValueSymbolTable.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/ValueHandle.h" #include using namespace llvm; diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp index feba3f1b794..9c5db50b92d 100644 --- a/lib/Target/PowerPC/PPCCTRLoops.cpp +++ b/lib/Target/PowerPC/PPCCTRLoops.cpp @@ -39,10 +39,10 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" diff --git a/lib/Target/XCore/XCoreLowerThreadLocal.cpp b/lib/Target/XCore/XCoreLowerThreadLocal.cpp index 3a93d2ac2e7..da8309821c2 100644 --- a/lib/Target/XCore/XCoreLowerThreadLocal.cpp +++ b/lib/Target/XCore/XCoreLowerThreadLocal.cpp @@ -20,10 +20,10 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/NoFolder.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #define DEBUG_TYPE "xcore-lower-thread-local" diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 0a2338422d7..71c5e05b3d1 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -32,11 +32,11 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/Utils/GlobalStatus.h" diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index c4a39fa4128..ec8f72cdccd 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -59,10 +59,10 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm; diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index d6c8a54f092..b960d47b62c 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -47,10 +47,10 @@ #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CFG.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/Utils/Local.h" #include diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index ed784f661b3..d24148986b4 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -27,10 +27,10 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 5ab32d91f52..f4cf5704e74 100644 --- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -68,9 +68,9 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index b6535a735f0..99b55058b71 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -33,10 +33,10 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/Local.h" #include diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp index 855ae43cbe6..ad92a596143 100644 --- a/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -67,10 +67,10 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index 918bd16c98c..67c8649f27c 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -24,8 +24,8 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Type.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Local.h" #include diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index b6d9fb72c72..f437be62700 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -36,10 +36,10 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/lib/Transforms/Vectorize/BBVectorize.cpp b/lib/Transforms/Vectorize/BBVectorize.cpp index 4855d4e027f..df65e01d4a3 100644 --- a/lib/Transforms/Vectorize/BBVectorize.cpp +++ b/lib/Transforms/Vectorize/BBVectorize.cpp @@ -41,10 +41,10 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Type.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/Local.h" #include diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 70a0bafbe88..1ff347df6e7 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -78,12 +78,12 @@ #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/Scalar.h" diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index 305079f2dd8..fd8d842c80e 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -19,6 +19,7 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + ValueHandleTest.cpp ValueMapTest.cpp ValueTest.cpp VerifierTest.cpp diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 352e83ee662..00a2783fbf6 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -13,7 +13,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/IR/ValueHandleTest.cpp b/unittests/IR/ValueHandleTest.cpp new file mode 100644 index 00000000000..bbca7017769 --- /dev/null +++ b/unittests/IR/ValueHandleTest.cpp @@ -0,0 +1,408 @@ +//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ValueHandle.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; + +namespace { + +class ValueHandle : public testing::Test { +protected: + Constant *ConstantV; + std::auto_ptr BitcastV; + + ValueHandle() : + ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), + BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { + } +}; + +class ConcreteCallbackVH : public CallbackVH { +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(getGlobalContext()), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); +} + +TEST_F(ValueHandle, WeakVH_Comparisons) { + WeakVH BitcastWVH(BitcastV.get()); + WeakVH ConstantWVH(ConstantV); + + EXPECT_TRUE(BitcastWVH == BitcastWVH); + EXPECT_TRUE(BitcastV.get() == BitcastWVH); + EXPECT_TRUE(BitcastWVH == BitcastV.get()); + EXPECT_FALSE(BitcastWVH == ConstantWVH); + + EXPECT_TRUE(BitcastWVH != ConstantWVH); + EXPECT_TRUE(BitcastV.get() != ConstantWVH); + EXPECT_TRUE(BitcastWVH != ConstantV); + EXPECT_FALSE(BitcastWVH != BitcastWVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); +} + +TEST_F(ValueHandle, WeakVH_FollowsRAUW) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, WVH); + EXPECT_EQ(ConstantV, WVH_Copy); + EXPECT_EQ(ConstantV, WVH_Recreated); +} + +TEST_F(ValueHandle, WeakVH_NullOnDeletion) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV.reset(); + Value *null_value = NULL; + EXPECT_EQ(null_value, WVH); + EXPECT_EQ(null_value, WVH_Copy); + EXPECT_EQ(null_value, WVH_Recreated); +} + + +TEST_F(ValueHandle, AssertingVH_BasicOperation) { + AssertingVH AVH(BitcastV.get()); + CastInst *implicit_to_exact_type = AVH; + (void)implicit_to_exact_type; // Avoid warning. + + AssertingVH GenericAVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), GenericAVH); + GenericAVH = ConstantV; + EXPECT_EQ(ConstantV, GenericAVH); + + // Make sure I can call a method on the underlying CastInst. It + // doesn't matter which method. + EXPECT_FALSE(AVH->mayWriteToMemory()); + EXPECT_FALSE((*AVH).mayWriteToMemory()); +} + +TEST_F(ValueHandle, AssertingVH_Const) { + const CastInst *ConstBitcast = BitcastV.get(); + AssertingVH AVH(ConstBitcast); + const CastInst *implicit_to_exact_type = AVH; + (void)implicit_to_exact_type; // Avoid warning. +} + +TEST_F(ValueHandle, AssertingVH_Comparisons) { + AssertingVH BitcastAVH(BitcastV.get()); + AssertingVH ConstantAVH(ConstantV); + + EXPECT_TRUE(BitcastAVH == BitcastAVH); + EXPECT_TRUE(BitcastV.get() == BitcastAVH); + EXPECT_TRUE(BitcastAVH == BitcastV.get()); + EXPECT_FALSE(BitcastAVH == ConstantAVH); + + EXPECT_TRUE(BitcastAVH != ConstantAVH); + EXPECT_TRUE(BitcastV.get() != ConstantAVH); + EXPECT_TRUE(BitcastAVH != ConstantV); + EXPECT_FALSE(BitcastAVH != BitcastAVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); +} + +TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { + AssertingVH AVH(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(BitcastV.get(), AVH); +} + +#ifdef NDEBUG + +TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { + EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH)); +} + +#else // !NDEBUG + +#ifdef GTEST_HAS_DEATH_TEST + +TEST_F(ValueHandle, AssertingVH_Asserts) { + AssertingVH AVH(BitcastV.get()); + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + AssertingVH Copy(AVH); + AVH = NULL; + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + Copy = NULL; + BitcastV.reset(); +} + +#endif // GTEST_HAS_DEATH_TEST + +#endif // NDEBUG + +TEST_F(ValueHandle, CallbackVH_BasicOperation) { + ConcreteCallbackVH CVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), CVH); + CVH = ConstantV; + EXPECT_EQ(ConstantV, CVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); +} + +TEST_F(ValueHandle, CallbackVH_Comparisons) { + ConcreteCallbackVH BitcastCVH(BitcastV.get()); + ConcreteCallbackVH ConstantCVH(ConstantV); + + EXPECT_TRUE(BitcastCVH == BitcastCVH); + EXPECT_TRUE(BitcastV.get() == BitcastCVH); + EXPECT_TRUE(BitcastCVH == BitcastV.get()); + EXPECT_FALSE(BitcastCVH == ConstantCVH); + + EXPECT_TRUE(BitcastCVH != ConstantCVH); + EXPECT_TRUE(BitcastV.get() != ConstantCVH); + EXPECT_TRUE(BitcastCVH != ConstantV); + EXPECT_FALSE(BitcastCVH != BitcastCVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + int AURWCalls; + + RecordingVH() : DeletedCalls(0), AURWCalls(0) {} + RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *) { AURWCalls++; } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); + BitcastV.reset(); + EXPECT_EQ(1, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + + RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecordingVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *new_value) { + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(NULL, RVH.AURWArgument); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(ConstantV, RVH.AURWArgument); +} + +TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { + class RecoveringVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + LLVMContext *Context; + + RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} + RecoveringVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} + + private: + virtual void deleted() { + getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); + setValPtr(NULL); + } + virtual void allUsesReplacedWith(Value *new_value) { + ASSERT_TRUE(NULL != getValPtr()); + EXPECT_EQ(1U, getValPtr()->getNumUses()); + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + // Normally, if a value has uses, deleting it will crash. However, we can use + // a CallbackVH to remove the uses before the check for no uses. + RecoveringVH RVH; + RVH = BitcastV.get(); + std::auto_ptr BitcastUser( + BinaryOperator::CreateAdd(RVH, + Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); + EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); + BitcastV.reset(); // Would crash without the ValueHandler. + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), + BitcastUser->getOperand(0)); +} + +TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { + // When a CallbackVH modifies other ValueHandles in its callbacks, + // that shouldn't interfere with non-modified ValueHandles receiving + // their appropriate callbacks. + // + // We create the active CallbackVH in the middle of a palindromic + // arrangement of other VHs so that the bad behavior would be + // triggered in whichever order callbacks run. + + class DestroyingVH : public CallbackVH { + public: + OwningPtr ToClear[2]; + DestroyingVH(Value *V) { + ToClear[0].reset(new WeakVH(V)); + setValPtr(V); + ToClear[1].reset(new WeakVH(V)); + } + virtual void deleted() { + ToClear[0].reset(); + ToClear[1].reset(); + CallbackVH::deleted(); + } + virtual void allUsesReplacedWith(Value *) { + ToClear[0].reset(); + ToClear[1].reset(); + } + }; + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited1)); + EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited2)); + } + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV.reset(); + EXPECT_EQ(NULL, static_cast(ShouldBeVisited1)); + EXPECT_EQ(NULL, static_cast(ShouldBeVisited2)); + } +} + +TEST_F(ValueHandle, AssertingVHCheckedLast) { + // If a CallbackVH exists to clear out a group of AssertingVHs on + // Value deletion, the CallbackVH should get a chance to do so + // before the AssertingVHs assert. + + class ClearingVH : public CallbackVH { + public: + AssertingVH *ToClear[2]; + ClearingVH(Value *V, + AssertingVH &A0, AssertingVH &A1) + : CallbackVH(V) { + ToClear[0] = &A0; + ToClear[1] = &A1; + } + + virtual void deleted() { + *ToClear[0] = 0; + *ToClear[1] = 0; + CallbackVH::deleted(); + } + }; + + AssertingVH A1, A2; + A1 = BitcastV.get(); + ClearingVH C(BitcastV.get(), A1, A2); + A2 = BitcastV.get(); + // C.deleted() should run first, clearing the two AssertingVHs, + // which should prevent them from asserting. + BitcastV.reset(); +} + +} diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index bfbef982e2e..46c5c334ff4 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -35,7 +35,6 @@ add_llvm_unittest(SupportTests ThreadLocalTest.cpp TimeValueTest.cpp UnicodeTest.cpp - ValueHandleTest.cpp YAMLIOTest.cpp YAMLParserTest.cpp formatted_raw_ostream_test.cpp diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/Support/ValueHandleTest.cpp deleted file mode 100644 index 05aafa2d05d..00000000000 --- a/unittests/Support/ValueHandleTest.cpp +++ /dev/null @@ -1,408 +0,0 @@ -//===- llvm/unittest/Support/ValueHandleTest.cpp - ValueHandle tests --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/ValueHandle.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -namespace { - -class ValueHandle : public testing::Test { -protected: - Constant *ConstantV; - std::auto_ptr BitcastV; - - ValueHandle() : - ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), - BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { - } -}; - -class ConcreteCallbackVH : public CallbackVH { -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(getGlobalContext()), WVH->getType()); - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); -} - -TEST_F(ValueHandle, WeakVH_Comparisons) { - WeakVH BitcastWVH(BitcastV.get()); - WeakVH ConstantWVH(ConstantV); - - EXPECT_TRUE(BitcastWVH == BitcastWVH); - EXPECT_TRUE(BitcastV.get() == BitcastWVH); - EXPECT_TRUE(BitcastWVH == BitcastV.get()); - EXPECT_FALSE(BitcastWVH == ConstantWVH); - - EXPECT_TRUE(BitcastWVH != ConstantWVH); - EXPECT_TRUE(BitcastV.get() != ConstantWVH); - EXPECT_TRUE(BitcastWVH != ConstantV); - EXPECT_FALSE(BitcastWVH != BitcastWVH); - - // Cast to Value* so comparisons work. - Value *BV = BitcastV.get(); - Value *CV = ConstantV; - EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); - EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); - EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); - EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); - - EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); - EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); - EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); - EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); - - EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); - EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); - EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); - EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); -} - -TEST_F(ValueHandle, WeakVH_FollowsRAUW) { - WeakVH WVH(BitcastV.get()); - WeakVH WVH_Copy(WVH); - WeakVH WVH_Recreated(BitcastV.get()); - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(ConstantV, WVH); - EXPECT_EQ(ConstantV, WVH_Copy); - EXPECT_EQ(ConstantV, WVH_Recreated); -} - -TEST_F(ValueHandle, WeakVH_NullOnDeletion) { - WeakVH WVH(BitcastV.get()); - WeakVH WVH_Copy(WVH); - WeakVH WVH_Recreated(BitcastV.get()); - BitcastV.reset(); - Value *null_value = NULL; - EXPECT_EQ(null_value, WVH); - EXPECT_EQ(null_value, WVH_Copy); - EXPECT_EQ(null_value, WVH_Recreated); -} - - -TEST_F(ValueHandle, AssertingVH_BasicOperation) { - AssertingVH AVH(BitcastV.get()); - CastInst *implicit_to_exact_type = AVH; - (void)implicit_to_exact_type; // Avoid warning. - - AssertingVH GenericAVH(BitcastV.get()); - EXPECT_EQ(BitcastV.get(), GenericAVH); - GenericAVH = ConstantV; - EXPECT_EQ(ConstantV, GenericAVH); - - // Make sure I can call a method on the underlying CastInst. It - // doesn't matter which method. - EXPECT_FALSE(AVH->mayWriteToMemory()); - EXPECT_FALSE((*AVH).mayWriteToMemory()); -} - -TEST_F(ValueHandle, AssertingVH_Const) { - const CastInst *ConstBitcast = BitcastV.get(); - AssertingVH AVH(ConstBitcast); - const CastInst *implicit_to_exact_type = AVH; - (void)implicit_to_exact_type; // Avoid warning. -} - -TEST_F(ValueHandle, AssertingVH_Comparisons) { - AssertingVH BitcastAVH(BitcastV.get()); - AssertingVH ConstantAVH(ConstantV); - - EXPECT_TRUE(BitcastAVH == BitcastAVH); - EXPECT_TRUE(BitcastV.get() == BitcastAVH); - EXPECT_TRUE(BitcastAVH == BitcastV.get()); - EXPECT_FALSE(BitcastAVH == ConstantAVH); - - EXPECT_TRUE(BitcastAVH != ConstantAVH); - EXPECT_TRUE(BitcastV.get() != ConstantAVH); - EXPECT_TRUE(BitcastAVH != ConstantV); - EXPECT_FALSE(BitcastAVH != BitcastAVH); - - // Cast to Value* so comparisons work. - Value *BV = BitcastV.get(); - Value *CV = ConstantV; - EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); - EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); - EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); - EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); - - EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); - EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); - EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); - EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); - - EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); - EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); - EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); - EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); -} - -TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { - AssertingVH AVH(BitcastV.get()); - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(BitcastV.get(), AVH); -} - -#ifdef NDEBUG - -TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { - EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH)); -} - -#else // !NDEBUG - -#ifdef GTEST_HAS_DEATH_TEST - -TEST_F(ValueHandle, AssertingVH_Asserts) { - AssertingVH AVH(BitcastV.get()); - EXPECT_DEATH({BitcastV.reset();}, - "An asserting value handle still pointed to this value!"); - AssertingVH Copy(AVH); - AVH = NULL; - EXPECT_DEATH({BitcastV.reset();}, - "An asserting value handle still pointed to this value!"); - Copy = NULL; - BitcastV.reset(); -} - -#endif // GTEST_HAS_DEATH_TEST - -#endif // NDEBUG - -TEST_F(ValueHandle, CallbackVH_BasicOperation) { - ConcreteCallbackVH CVH(BitcastV.get()); - EXPECT_EQ(BitcastV.get(), CVH); - CVH = ConstantV; - EXPECT_EQ(ConstantV, CVH); - - // Make sure I can call a method on the underlying Value. It - // doesn't matter which method. - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); -} - -TEST_F(ValueHandle, CallbackVH_Comparisons) { - ConcreteCallbackVH BitcastCVH(BitcastV.get()); - ConcreteCallbackVH ConstantCVH(ConstantV); - - EXPECT_TRUE(BitcastCVH == BitcastCVH); - EXPECT_TRUE(BitcastV.get() == BitcastCVH); - EXPECT_TRUE(BitcastCVH == BitcastV.get()); - EXPECT_FALSE(BitcastCVH == ConstantCVH); - - EXPECT_TRUE(BitcastCVH != ConstantCVH); - EXPECT_TRUE(BitcastV.get() != ConstantCVH); - EXPECT_TRUE(BitcastCVH != ConstantV); - EXPECT_FALSE(BitcastCVH != BitcastCVH); - - // Cast to Value* so comparisons work. - Value *BV = BitcastV.get(); - Value *CV = ConstantV; - EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); - EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); - EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); - EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); - - EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); - EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); - EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); - EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); - - EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); - EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); - EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); - EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); -} - -TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { - class RecordingVH : public CallbackVH { - public: - int DeletedCalls; - int AURWCalls; - - RecordingVH() : DeletedCalls(0), AURWCalls(0) {} - RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} - - private: - virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } - virtual void allUsesReplacedWith(Value *) { AURWCalls++; } - }; - - RecordingVH RVH; - RVH = BitcastV.get(); - EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(0, RVH.AURWCalls); - BitcastV.reset(); - EXPECT_EQ(1, RVH.DeletedCalls); - EXPECT_EQ(0, RVH.AURWCalls); -} - -TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { - class RecordingVH : public CallbackVH { - public: - int DeletedCalls; - Value *AURWArgument; - - RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} - RecordingVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} - - private: - virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } - virtual void allUsesReplacedWith(Value *new_value) { - EXPECT_EQ(NULL, AURWArgument); - AURWArgument = new_value; - } - }; - - RecordingVH RVH; - RVH = BitcastV.get(); - EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(NULL, RVH.AURWArgument); - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(ConstantV, RVH.AURWArgument); -} - -TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { - class RecoveringVH : public CallbackVH { - public: - int DeletedCalls; - Value *AURWArgument; - LLVMContext *Context; - - RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), - Context(&getGlobalContext()) {} - RecoveringVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), - Context(&getGlobalContext()) {} - - private: - virtual void deleted() { - getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); - setValPtr(NULL); - } - virtual void allUsesReplacedWith(Value *new_value) { - ASSERT_TRUE(NULL != getValPtr()); - EXPECT_EQ(1U, getValPtr()->getNumUses()); - EXPECT_EQ(NULL, AURWArgument); - AURWArgument = new_value; - } - }; - - // Normally, if a value has uses, deleting it will crash. However, we can use - // a CallbackVH to remove the uses before the check for no uses. - RecoveringVH RVH; - RVH = BitcastV.get(); - std::auto_ptr BitcastUser( - BinaryOperator::CreateAdd(RVH, - Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); - EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); - BitcastV.reset(); // Would crash without the ValueHandler. - EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); - EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), - BitcastUser->getOperand(0)); -} - -TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { - // When a CallbackVH modifies other ValueHandles in its callbacks, - // that shouldn't interfere with non-modified ValueHandles receiving - // their appropriate callbacks. - // - // We create the active CallbackVH in the middle of a palindromic - // arrangement of other VHs so that the bad behavior would be - // triggered in whichever order callbacks run. - - class DestroyingVH : public CallbackVH { - public: - OwningPtr ToClear[2]; - DestroyingVH(Value *V) { - ToClear[0].reset(new WeakVH(V)); - setValPtr(V); - ToClear[1].reset(new WeakVH(V)); - } - virtual void deleted() { - ToClear[0].reset(); - ToClear[1].reset(); - CallbackVH::deleted(); - } - virtual void allUsesReplacedWith(Value *) { - ToClear[0].reset(); - ToClear[1].reset(); - } - }; - - { - WeakVH ShouldBeVisited1(BitcastV.get()); - DestroyingVH C(BitcastV.get()); - WeakVH ShouldBeVisited2(BitcastV.get()); - - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited1)); - EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited2)); - } - - { - WeakVH ShouldBeVisited1(BitcastV.get()); - DestroyingVH C(BitcastV.get()); - WeakVH ShouldBeVisited2(BitcastV.get()); - - BitcastV.reset(); - EXPECT_EQ(NULL, static_cast(ShouldBeVisited1)); - EXPECT_EQ(NULL, static_cast(ShouldBeVisited2)); - } -} - -TEST_F(ValueHandle, AssertingVHCheckedLast) { - // If a CallbackVH exists to clear out a group of AssertingVHs on - // Value deletion, the CallbackVH should get a chance to do so - // before the AssertingVHs assert. - - class ClearingVH : public CallbackVH { - public: - AssertingVH *ToClear[2]; - ClearingVH(Value *V, - AssertingVH &A0, AssertingVH &A1) - : CallbackVH(V) { - ToClear[0] = &A0; - ToClear[1] = &A1; - } - - virtual void deleted() { - *ToClear[0] = 0; - *ToClear[1] = 0; - CallbackVH::deleted(); - } - }; - - AssertingVH A1, A2; - A1 = BitcastV.get(); - ClearingVH C(BitcastV.get(), A1, A2); - A2 = BitcastV.get(); - // C.deleted() should run first, clearing the two AssertingVHs, - // which should prevent them from asserting. - BitcastV.reset(); -} - -}