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