TrackingMDRef.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // References to metadata that track RAUW.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_IR_TRACKINGMDREF_H
  18. #define LLVM_IR_TRACKINGMDREF_H
  19. #include "llvm/IR/Metadata.h"
  20. #include <algorithm>
  21. #include <cassert>
  22. namespace llvm {
  23. /// Tracking metadata reference.
  24. ///
  25. /// This class behaves like \a TrackingVH, but for metadata.
  26. class TrackingMDRef {
  27. Metadata *MD = nullptr;
  28. public:
  29. TrackingMDRef() = default;
  30. explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
  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. untrack();
  37. MD = X.MD;
  38. retrack(X);
  39. return *this;
  40. }
  41. TrackingMDRef &operator=(const TrackingMDRef &X) {
  42. if (&X == this)
  43. return *this;
  44. untrack();
  45. MD = X.MD;
  46. track();
  47. return *this;
  48. }
  49. ~TrackingMDRef() { untrack(); }
  50. Metadata *get() const { return MD; }
  51. operator Metadata *() const { return get(); }
  52. Metadata *operator->() const { return get(); }
  53. Metadata &operator*() const { return *get(); }
  54. void reset() {
  55. untrack();
  56. MD = nullptr;
  57. }
  58. void reset(Metadata *MD) {
  59. untrack();
  60. this->MD = MD;
  61. track();
  62. }
  63. /// Check whether this has a trivial destructor.
  64. ///
  65. /// If \c MD isn't replaceable, the destructor will be a no-op.
  66. bool hasTrivialDestructor() const {
  67. return !MD || !MetadataTracking::isReplaceable(*MD);
  68. }
  69. bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
  70. bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
  71. private:
  72. void track() {
  73. if (MD)
  74. MetadataTracking::track(MD);
  75. }
  76. void untrack() {
  77. if (MD)
  78. MetadataTracking::untrack(MD);
  79. }
  80. void retrack(TrackingMDRef &X) {
  81. assert(MD == X.MD && "Expected values to match");
  82. if (X.MD) {
  83. MetadataTracking::retrack(X.MD, MD);
  84. X.MD = nullptr;
  85. }
  86. }
  87. };
  88. /// Typed tracking ref.
  89. ///
  90. /// Track refererences of a particular type. It's useful to use this for \a
  91. /// MDNode and \a ValueAsMetadata.
  92. template <class T> class TypedTrackingMDRef {
  93. TrackingMDRef Ref;
  94. public:
  95. TypedTrackingMDRef() = default;
  96. explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
  97. TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
  98. TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
  99. TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
  100. Ref = std::move(X.Ref);
  101. return *this;
  102. }
  103. TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
  104. Ref = X.Ref;
  105. return *this;
  106. }
  107. T *get() const { return (T *)Ref.get(); }
  108. operator T *() const { return get(); }
  109. T *operator->() const { return get(); }
  110. T &operator*() const { return *get(); }
  111. bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
  112. bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
  113. void reset() { Ref.reset(); }
  114. void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
  115. /// Check whether this has a trivial destructor.
  116. bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
  117. };
  118. using TrackingMDNodeRef = TypedTrackingMDRef<MDNode>;
  119. using TrackingValueAsMetadataRef = TypedTrackingMDRef<ValueAsMetadata>;
  120. // Expose the underlying metadata to casting.
  121. template <> struct simplify_type<TrackingMDRef> {
  122. using SimpleType = Metadata *;
  123. static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
  124. };
  125. template <> struct simplify_type<const TrackingMDRef> {
  126. using SimpleType = Metadata *;
  127. static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
  128. return MD.get();
  129. }
  130. };
  131. template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
  132. using SimpleType = T *;
  133. static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
  134. return MD.get();
  135. }
  136. };
  137. template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
  138. using SimpleType = T *;
  139. static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
  140. return MD.get();
  141. }
  142. };
  143. } // end namespace llvm
  144. #endif // LLVM_IR_TRACKINGMDREF_H
  145. #ifdef __GNUC__
  146. #pragma GCC diagnostic pop
  147. #endif