]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/IR/TrackingMDRef.h
Add LLVM openmp trunk r351319 (just before the release_80 branch point)
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / IR / TrackingMDRef.h
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   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
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 /// 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   /// 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