]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/IR/TrackingMDRef.h
MFV r311899:
[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
19 namespace llvm {
20
21 /// \brief Tracking metadata reference.
22 ///
23 /// This class behaves like \a TrackingVH, but for metadata.
24 class TrackingMDRef {
25   Metadata *MD;
26
27 public:
28   TrackingMDRef() : MD(nullptr) {}
29   explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
30
31   TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
32   TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
33   TrackingMDRef &operator=(TrackingMDRef &&X) {
34     if (&X == this)
35       return *this;
36
37     untrack();
38     MD = X.MD;
39     retrack(X);
40     return *this;
41   }
42   TrackingMDRef &operator=(const TrackingMDRef &X) {
43     if (&X == this)
44       return *this;
45
46     untrack();
47     MD = X.MD;
48     track();
49     return *this;
50   }
51   ~TrackingMDRef() { untrack(); }
52
53   Metadata *get() const { return MD; }
54   operator Metadata *() const { return get(); }
55   Metadata *operator->() const { return get(); }
56   Metadata &operator*() const { return *get(); }
57
58   void reset() {
59     untrack();
60     MD = nullptr;
61   }
62   void reset(Metadata *MD) {
63     untrack();
64     this->MD = MD;
65     track();
66   }
67
68   /// \brief Check whether this has a trivial destructor.
69   ///
70   /// If \c MD isn't replaceable, the destructor will be a no-op.
71   bool hasTrivialDestructor() const {
72     return !MD || !MetadataTracking::isReplaceable(*MD);
73   }
74
75   bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
76   bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
77
78 private:
79   void track() {
80     if (MD)
81       MetadataTracking::track(MD);
82   }
83   void untrack() {
84     if (MD)
85       MetadataTracking::untrack(MD);
86   }
87   void retrack(TrackingMDRef &X) {
88     assert(MD == X.MD && "Expected values to match");
89     if (X.MD) {
90       MetadataTracking::retrack(X.MD, MD);
91       X.MD = nullptr;
92     }
93   }
94 };
95
96 /// \brief Typed tracking ref.
97 ///
98 /// Track refererences of a particular type.  It's useful to use this for \a
99 /// MDNode and \a ValueAsMetadata.
100 template <class T> class TypedTrackingMDRef {
101   TrackingMDRef Ref;
102
103 public:
104   TypedTrackingMDRef() {}
105   explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
106
107   TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
108   TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
109   TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
110     Ref = std::move(X.Ref);
111     return *this;
112   }
113   TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
114     Ref = X.Ref;
115     return *this;
116   }
117
118   T *get() const { return (T *)Ref.get(); }
119   operator T *() const { return get(); }
120   T *operator->() const { return get(); }
121   T &operator*() const { return *get(); }
122
123   bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
124   bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
125
126   void reset() { Ref.reset(); }
127   void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
128
129   /// \brief Check whether this has a trivial destructor.
130   bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
131 };
132
133 typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
134 typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
135
136 // Expose the underlying metadata to casting.
137 template <> struct simplify_type<TrackingMDRef> {
138   typedef Metadata *SimpleType;
139   static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
140 };
141
142 template <> struct simplify_type<const TrackingMDRef> {
143   typedef Metadata *SimpleType;
144   static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
145     return MD.get();
146   }
147 };
148
149 template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
150   typedef T *SimpleType;
151   static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
152     return MD.get();
153   }
154 };
155
156 template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
157   typedef T *SimpleType;
158   static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
159     return MD.get();
160   }
161 };
162
163 } // end namespace llvm
164
165 #endif