17ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===//
27ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
37ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//                     The LLVM Compiler Infrastructure
47ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
57ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// This file is distributed under the University of Illinois Open Source
67ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// License. See LICENSE.TXT for details.
77ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
87ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//===----------------------------------------------------------------------===//
97ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
107ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// References to metadata that track RAUW.
117ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
127ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//===----------------------------------------------------------------------===//
137ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
147ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#ifndef LLVM_IR_TRACKINGMDREF_H
157ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#define LLVM_IR_TRACKINGMDREF_H
167ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
177ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#include "llvm/IR/Metadata.h"
187ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
197ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensnamespace llvm {
207ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
217ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// \brief Tracking metadata reference.
227ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens///
237ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// This class behaves like \a TrackingVH, but for metadata.
247ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensclass TrackingMDRef {
257ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  Metadata *MD;
267ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
277ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenspublic:
287ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TrackingMDRef() : MD(nullptr) {}
297ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
307ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
317ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
327ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
337ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TrackingMDRef &operator=(TrackingMDRef &&X) {
347ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    if (&X == this)
357ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens      return *this;
367ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
377ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    untrack();
387ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    MD = X.MD;
397ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    retrack(X);
407ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return *this;
417ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
427ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TrackingMDRef &operator=(const TrackingMDRef &X) {
437ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    if (&X == this)
447ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens      return *this;
457ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
467ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    untrack();
477ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    MD = X.MD;
487ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    track();
497ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return *this;
507ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
517ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  ~TrackingMDRef() { untrack(); }
527ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
537ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  Metadata *get() const { return MD; }
547ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  operator Metadata *() const { return get(); }
557ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  Metadata *operator->() const { return get(); }
567ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  Metadata &operator*() const { return *get(); }
577ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
587ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void reset() {
597ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    untrack();
607ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    MD = nullptr;
617ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
627ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void reset(Metadata *MD) {
637ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    untrack();
647ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    this->MD = MD;
657ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    track();
667ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
677ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
687ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  /// \brief Check whether this has a trivial destructor.
697ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  ///
707ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  /// If \c MD isn't replaceable, the destructor will be a no-op.
717ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  bool hasTrivialDestructor() const {
727ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return !MD || !MetadataTracking::isReplaceable(*MD);
737ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
747ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
757ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
767ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
777ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
787ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensprivate:
797ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void track() {
807ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    if (MD)
817ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens      MetadataTracking::track(MD);
827ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
837ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void untrack() {
847ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    if (MD)
857ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens      MetadataTracking::untrack(MD);
867ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
877ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void retrack(TrackingMDRef &X) {
887ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    assert(MD == X.MD && "Expected values to match");
897ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    if (X.MD) {
907ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens      MetadataTracking::retrack(X.MD, MD);
917ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens      X.MD = nullptr;
927ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    }
937ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
947ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
957ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
967ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// \brief Typed tracking ref.
977ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens///
987ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// Track refererences of a particular type.  It's useful to use this for \a
997ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// MDNode and \a ValueAsMetadata.
1007ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <class T> class TypedTrackingMDRef {
1017ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TrackingMDRef Ref;
1027ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1037ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenspublic:
1047ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TypedTrackingMDRef() {}
1057ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
1067ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1077ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
1087ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
1097ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
1107ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    Ref = std::move(X.Ref);
1117ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return *this;
1127ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
1137ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
1147ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    Ref = X.Ref;
1157ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return *this;
1167ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
1177ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1187ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  T *get() const { return (T *)Ref.get(); }
1197ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  operator T *() const { return get(); }
1207ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  T *operator->() const { return get(); }
1217ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  T &operator*() const { return *get(); }
1227ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1237ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
1247ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
1257ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1267ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void reset() { Ref.reset(); }
1277ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
1287ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1297ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  /// \brief Check whether this has a trivial destructor.
1307ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
1317ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1327ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1337ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstypedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
1347ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstypedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
1357ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1367ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// Expose the underlying metadata to casting.
1377ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <> struct simplify_type<TrackingMDRef> {
1387ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  typedef Metadata *SimpleType;
1397ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
1407ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1417ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1427ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <> struct simplify_type<const TrackingMDRef> {
1437ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  typedef Metadata *SimpleType;
1447ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
1457ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return MD.get();
1467ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
1477ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1487ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1497ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <class T> struct simplify_type<TypedTrackingMDRef<T>> {
1507ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  typedef T *SimpleType;
1517ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
1527ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return MD.get();
1537ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
1547ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1557ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1567ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
1577ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  typedef T *SimpleType;
1587ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
1597ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    return MD.get();
1607ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  }
1617ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1627ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1637ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens} // end namespace llvm
1647ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1657ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#endif
166