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