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