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