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