Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:10

0001 //===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // References to metadata that track RAUW.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_IR_TRACKINGMDREF_H
0014 #define LLVM_IR_TRACKINGMDREF_H
0015 
0016 #include "llvm/IR/Metadata.h"
0017 #include <algorithm>
0018 #include <cassert>
0019 
0020 namespace llvm {
0021 
0022 /// Tracking metadata reference.
0023 ///
0024 /// This class behaves like \a TrackingVH, but for metadata.
0025 class TrackingMDRef {
0026   Metadata *MD = nullptr;
0027 
0028 public:
0029   TrackingMDRef() = default;
0030   explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
0031 
0032   TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
0033   TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
0034 
0035   TrackingMDRef &operator=(TrackingMDRef &&X) {
0036     if (&X == this)
0037       return *this;
0038 
0039     untrack();
0040     MD = X.MD;
0041     retrack(X);
0042     return *this;
0043   }
0044 
0045   TrackingMDRef &operator=(const TrackingMDRef &X) {
0046     if (&X == this)
0047       return *this;
0048 
0049     untrack();
0050     MD = X.MD;
0051     track();
0052     return *this;
0053   }
0054 
0055   ~TrackingMDRef() { untrack(); }
0056 
0057   Metadata *get() const { return MD; }
0058   operator Metadata *() const { return get(); }
0059   Metadata *operator->() const { return get(); }
0060   Metadata &operator*() const { return *get(); }
0061 
0062   void reset() {
0063     untrack();
0064     MD = nullptr;
0065   }
0066   void reset(Metadata *MD) {
0067     untrack();
0068     this->MD = MD;
0069     track();
0070   }
0071 
0072   /// Check whether this has a trivial destructor.
0073   ///
0074   /// If \c MD isn't replaceable, the destructor will be a no-op.
0075   bool hasTrivialDestructor() const {
0076     return !MD || !MetadataTracking::isReplaceable(*MD);
0077   }
0078 
0079   bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
0080   bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
0081 
0082 private:
0083   void track() {
0084     if (MD)
0085       MetadataTracking::track(MD);
0086   }
0087 
0088   void untrack() {
0089     if (MD)
0090       MetadataTracking::untrack(MD);
0091   }
0092 
0093   void retrack(TrackingMDRef &X) {
0094     assert(MD == X.MD && "Expected values to match");
0095     if (X.MD) {
0096       MetadataTracking::retrack(X.MD, MD);
0097       X.MD = nullptr;
0098     }
0099   }
0100 };
0101 
0102 /// Typed tracking ref.
0103 ///
0104 /// Track refererences of a particular type.  It's useful to use this for \a
0105 /// MDNode and \a ValueAsMetadata.
0106 template <class T> class TypedTrackingMDRef {
0107   TrackingMDRef Ref;
0108 
0109 public:
0110   TypedTrackingMDRef() = default;
0111   explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
0112 
0113   TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
0114   TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
0115 
0116   TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
0117     Ref = std::move(X.Ref);
0118     return *this;
0119   }
0120 
0121   TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
0122     Ref = X.Ref;
0123     return *this;
0124   }
0125 
0126   T *get() const { return (T *)Ref.get(); }
0127   operator T *() const { return get(); }
0128   T *operator->() const { return get(); }
0129   T &operator*() const { return *get(); }
0130 
0131   bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
0132   bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
0133 
0134   void reset() { Ref.reset(); }
0135   void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
0136 
0137   /// Check whether this has a trivial destructor.
0138   bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
0139 };
0140 
0141 using TrackingMDNodeRef = TypedTrackingMDRef<MDNode>;
0142 using TrackingValueAsMetadataRef = TypedTrackingMDRef<ValueAsMetadata>;
0143 
0144 // Expose the underlying metadata to casting.
0145 template <> struct simplify_type<TrackingMDRef> {
0146   using SimpleType = Metadata *;
0147 
0148   static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
0149 };
0150 
0151 template <> struct simplify_type<const TrackingMDRef> {
0152   using SimpleType = Metadata *;
0153 
0154   static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
0155     return MD.get();
0156   }
0157 };
0158 
0159 template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
0160   using SimpleType = T *;
0161 
0162   static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
0163     return MD.get();
0164   }
0165 };
0166 
0167 template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
0168   using SimpleType = T *;
0169 
0170   static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
0171     return MD.get();
0172   }
0173 };
0174 
0175 } // end namespace llvm
0176 
0177 #endif // LLVM_IR_TRACKINGMDREF_H