Line data Source code
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 : /// 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 123531544 : TrackingMDRef() = default;
31 6754509 : explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
32 :
33 132417279 : TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
34 238843656 : TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
35 :
36 109587054 : TrackingMDRef &operator=(TrackingMDRef &&X) {
37 109587054 : if (&X == this)
38 : return *this;
39 :
40 : untrack();
41 109587054 : MD = X.MD;
42 : retrack(X);
43 : return *this;
44 : }
45 :
46 41620625 : TrackingMDRef &operator=(const TrackingMDRef &X) {
47 41620625 : if (&X == this)
48 : return *this;
49 :
50 : untrack();
51 41618668 : MD = X.MD;
52 : track();
53 : return *this;
54 : }
55 :
56 574892 : ~TrackingMDRef() { untrack(); }
57 :
58 0 : Metadata *get() const { return MD; }
59 713880 : operator Metadata *() const { return get(); }
60 : Metadata *operator->() const { return get(); }
61 : Metadata &operator*() const { return *get(); }
62 :
63 : void reset() {
64 : untrack();
65 1 : MD = nullptr;
66 : }
67 572451 : void reset(Metadata *MD) {
68 : untrack();
69 571999 : this->MD = MD;
70 : track();
71 572451 : }
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 0 : bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
81 0 : bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
82 :
83 : private:
84 : void track() {
85 416141276 : if (MD)
86 13284317 : MetadataTracking::track(MD);
87 : }
88 :
89 : void untrack() {
90 706681708 : if (MD)
91 64376838 : MetadataTracking::untrack(MD);
92 : }
93 :
94 : void retrack(TrackingMDRef &X) {
95 : assert(MD == X.MD && "Expected values to match");
96 241970510 : if (X.MD) {
97 90579996 : MetadataTracking::retrack(X.MD, MD);
98 90562928 : 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.
107 497818 : 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 109581549 : Ref = std::move(X.Ref);
119 : return *this;
120 : }
121 :
122 : TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
123 40630080 : Ref = X.Ref;
124 : return *this;
125 : }
126 :
127 602009728 : 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 2006292 : bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
133 7024970 : bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
134 :
135 : void reset() { Ref.reset(); }
136 308414 : 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 :
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 29404 : 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 14944 : 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
|