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
21namespace llvm {
22
23/// Tracking metadata reference.
24///
25/// This class behaves like \a TrackingVH, but for metadata.
26class TrackingMDRef {
27 Metadata *MD = nullptr;
28
29public:
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 /// 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
83private:
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/// Typed tracking ref.
104///
105/// Track refererences of a particular type. It's useful to use this for \a
106/// MDNode and \a ValueAsMetadata.
107template <class T> class TypedTrackingMDRef {
108 TrackingMDRef Ref;
109
110public:
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 /// Check whether this has a trivial destructor.
139 bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
140};
141
142using TrackingMDNodeRef = TypedTrackingMDRef<MDNode>;
143using TrackingValueAsMetadataRef = TypedTrackingMDRef<ValueAsMetadata>;
144
145// Expose the underlying metadata to casting.
146template <> struct simplify_type<TrackingMDRef> {
147 using SimpleType = Metadata *;
148
149 static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
150};
151
152template <> struct simplify_type<const TrackingMDRef> {
153 using SimpleType = Metadata *;
154
155 static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
156 return MD.get();
157 }
158};
159
160template <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
168template <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