TrackingMDRef.h 4.5 KB

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