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