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