1 //===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // References to metadata that track RAUW. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_IR_TRACKINGMDREF_H 15 #define LLVM_IR_TRACKINGMDREF_H 16 17 #include "llvm/IR/Metadata.h" 18 19 namespace llvm { 20 21 /// \brief Tracking metadata reference. 22 /// 23 /// This class behaves like \a TrackingVH, but for metadata. 24 class TrackingMDRef { 25 Metadata *MD; 26 27 public: TrackingMDRef()28 TrackingMDRef() : MD(nullptr) {} TrackingMDRef(Metadata * MD)29 explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } 30 TrackingMDRef(TrackingMDRef && X)31 TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } TrackingMDRef(const TrackingMDRef & X)32 TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } 33 TrackingMDRef &operator=(TrackingMDRef &&X) { 34 if (&X == this) 35 return *this; 36 37 untrack(); 38 MD = X.MD; 39 retrack(X); 40 return *this; 41 } 42 TrackingMDRef &operator=(const TrackingMDRef &X) { 43 if (&X == this) 44 return *this; 45 46 untrack(); 47 MD = X.MD; 48 track(); 49 return *this; 50 } ~TrackingMDRef()51 ~TrackingMDRef() { untrack(); } 52 get()53 Metadata *get() const { return MD; } 54 operator Metadata *() const { return get(); } 55 Metadata *operator->() const { return get(); } 56 Metadata &operator*() const { return *get(); } 57 reset()58 void reset() { 59 untrack(); 60 MD = nullptr; 61 } reset(Metadata * MD)62 void reset(Metadata *MD) { 63 untrack(); 64 this->MD = MD; 65 track(); 66 } 67 68 /// \brief Check whether this has a trivial destructor. 69 /// 70 /// If \c MD isn't replaceable, the destructor will be a no-op. hasTrivialDestructor()71 bool hasTrivialDestructor() const { 72 return !MD || !MetadataTracking::isReplaceable(*MD); 73 } 74 75 bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } 76 bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } 77 78 private: track()79 void track() { 80 if (MD) 81 MetadataTracking::track(MD); 82 } untrack()83 void untrack() { 84 if (MD) 85 MetadataTracking::untrack(MD); 86 } retrack(TrackingMDRef & X)87 void retrack(TrackingMDRef &X) { 88 assert(MD == X.MD && "Expected values to match"); 89 if (X.MD) { 90 MetadataTracking::retrack(X.MD, MD); 91 X.MD = nullptr; 92 } 93 } 94 }; 95 96 /// \brief Typed tracking ref. 97 /// 98 /// Track refererences of a particular type. It's useful to use this for \a 99 /// MDNode and \a ValueAsMetadata. 100 template <class T> class TypedTrackingMDRef { 101 TrackingMDRef Ref; 102 103 public: TypedTrackingMDRef()104 TypedTrackingMDRef() {} TypedTrackingMDRef(T * MD)105 explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {} 106 TypedTrackingMDRef(TypedTrackingMDRef && X)107 TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} TypedTrackingMDRef(const TypedTrackingMDRef & X)108 TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} 109 TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { 110 Ref = std::move(X.Ref); 111 return *this; 112 } 113 TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { 114 Ref = X.Ref; 115 return *this; 116 } 117 get()118 T *get() const { return (T *)Ref.get(); } 119 operator T *() const { return get(); } 120 T *operator->() const { return get(); } 121 T &operator*() const { return *get(); } 122 123 bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } 124 bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } 125 reset()126 void reset() { Ref.reset(); } reset(T * MD)127 void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); } 128 129 /// \brief Check whether this has a trivial destructor. hasTrivialDestructor()130 bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } 131 }; 132 133 typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef; 134 typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef; 135 136 // Expose the underlying metadata to casting. 137 template <> struct simplify_type<TrackingMDRef> { 138 typedef Metadata *SimpleType; 139 static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } 140 }; 141 142 template <> struct simplify_type<const TrackingMDRef> { 143 typedef Metadata *SimpleType; 144 static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { 145 return MD.get(); 146 } 147 }; 148 149 template <class T> struct simplify_type<TypedTrackingMDRef<T>> { 150 typedef T *SimpleType; 151 static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) { 152 return MD.get(); 153 } 154 }; 155 156 template <class T> struct simplify_type<const TypedTrackingMDRef<T>> { 157 typedef T *SimpleType; 158 static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) { 159 return MD.get(); 160 } 161 }; 162 163 } // end namespace llvm 164 165 #endif 166