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 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_IR_TRACKINGMDREF_H
15 #define LLVM_IR_TRACKINGMDREF_H
17 #include "llvm/IR/MetadataTracking.h"
18 #include "llvm/Support/Casting.h"
20 namespace llvm {
22 class Metadata;
23 class MDNode;
24 class ValueAsMetadata;
26 /// \brief Tracking metadata reference.
27 ///
28 /// This class behaves like \a TrackingVH, but for metadata.
29 class TrackingMDRef {
30 Metadata *MD;
32 public:
33 TrackingMDRef() : MD(nullptr) {}
34 explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
36 TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
37 TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
38 TrackingMDRef &operator=(TrackingMDRef &&X) {
39 if (&X == this)
40 return *this;
42 untrack();
43 MD = X.MD;
44 retrack(X);
45 return *this;
46 }
47 TrackingMDRef &operator=(const TrackingMDRef &X) {
48 if (&X == this)
49 return *this;
51 untrack();
52 MD = X.MD;
53 track();
54 return *this;
55 }
56 ~TrackingMDRef() { untrack(); }
58 Metadata *get() const { return MD; }
59 operator Metadata *() const { return get(); }
60 Metadata *operator->() const { return get(); }
61 Metadata &operator*() const { return *get(); }
63 void reset() {
64 untrack();
65 MD = nullptr;
66 }
67 void reset(Metadata *MD) {
68 untrack();
69 this->MD = MD;
70 track();
71 }
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 }
80 bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
81 bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
83 private:
84 void track() {
85 if (MD)
86 MetadataTracking::track(MD);
87 }
88 void untrack() {
89 if (MD)
90 MetadataTracking::untrack(MD);
91 }
92 void retrack(TrackingMDRef &X) {
93 assert(MD == X.MD && "Expected values to match");
94 if (X.MD) {
95 MetadataTracking::retrack(X.MD, MD);
96 X.MD = nullptr;
97 }
98 }
99 };
101 /// \brief Typed tracking ref.
102 ///
103 /// Track refererences of a particular type. It's useful to use this for \a
104 /// MDNode and \a ValueAsMetadata.
105 template <class T> class TypedTrackingMDRef {
106 TrackingMDRef Ref;
108 public:
109 TypedTrackingMDRef() {}
110 explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
112 TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
113 TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
114 TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
115 Ref = std::move(X.Ref);
116 return *this;
117 }
118 TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
119 Ref = X.Ref;
120 return *this;
121 }
123 T *get() const { return (T *)Ref.get(); }
124 operator T *() const { return get(); }
125 T *operator->() const { return get(); }
126 T &operator*() const { return *get(); }
128 bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
129 bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
131 void reset() { Ref.reset(); }
132 void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
134 /// \brief Check whether this has a trivial destructor.
135 bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
136 };
138 typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
139 typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
141 // Expose the underlying metadata to casting.
142 template <> struct simplify_type<TrackingMDRef> {
143 typedef Metadata *SimpleType;
144 static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
145 };
147 template <> struct simplify_type<const TrackingMDRef> {
148 typedef Metadata *SimpleType;
149 static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
150 return MD.get();
151 }
152 };
154 template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
155 typedef T *SimpleType;
156 static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
157 return MD.get();
158 }
159 };
161 template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
162 typedef T *SimpleType;
163 static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
164 return MD.get();
165 }
166 };
168 } // end namespace llvm
170 #endif