DebugInfo: Add forwarding getFilename() accessor to new hierarchy
[oota-llvm.git] / include / llvm / IR / DebugInfoMetadata.h
index a03e8764adea959ce40c18e45b88223a4166ae3e..374f72776369e451e137e513b1dc0f478e83866a 100644 (file)
 
 namespace llvm {
 
+/// \brief Pointer union between a subclass of DebugNode and MDString.
+///
+/// \a MDCompositeType can be referenced via an \a MDString unique identifier.
+/// This class allows some type safety in the face of that, requiring either a
+/// node of a particular type or an \a MDString.
+template <class T> class TypedDebugNodeRef {
+  const Metadata *MD = nullptr;
+
+public:
+  TypedDebugNodeRef() = default;
+  TypedDebugNodeRef(std::nullptr_t) {}
+
+  /// \brief Construct from a raw pointer.
+  explicit TypedDebugNodeRef(const Metadata *MD) : MD(MD) {
+    assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref");
+  }
+
+  template <class U>
+  TypedDebugNodeRef(
+      const TypedDebugNodeRef<U> &X,
+      typename std::enable_if<std::is_convertible<U *, T *>::value>::type * =
+          nullptr)
+      : MD(X) {}
+
+  operator Metadata *() const { return const_cast<Metadata *>(MD); }
+
+  bool operator==(const TypedDebugNodeRef<T> &X) const { return MD == X.MD; };
+  bool operator!=(const TypedDebugNodeRef<T> &X) const { return MD != X.MD; };
+
+  /// \brief Create a reference.
+  ///
+  /// Get a reference to \c N, using an \a MDString reference if available.
+  static TypedDebugNodeRef get(const T *N);
+
+  template <class MapTy> T *resolve(const MapTy &Map) const {
+    if (!MD)
+      return nullptr;
+
+    if (auto *Typed = dyn_cast<T>(MD))
+      return const_cast<T *>(Typed);
+
+    auto *S = cast<MDString>(MD);
+    auto I = Map.find(S);
+    assert(I != Map.end() && "Missing identifier in type map");
+    return cast<T>(I->second);
+  }
+};
+
+typedef TypedDebugNodeRef<DebugNode> DebugNodeRef;
+typedef TypedDebugNodeRef<MDScope> MDScopeRef;
+typedef TypedDebugNodeRef<MDType> MDTypeRef;
+
+class MDTypeRefArray {
+  const MDTuple *N = nullptr;
+
+public:
+  MDTypeRefArray(const MDTuple *N) : N(N) {}
+
+  explicit operator bool() const { return get(); }
+  explicit operator MDTuple *() const { return get(); }
+
+  MDTuple *get() const { return const_cast<MDTuple *>(N); }
+  MDTuple *operator->() const { return get(); }
+  MDTuple &operator*() const { return *get(); }
+
+  // FIXME: Fix callers and remove condition on N.
+  unsigned size() const { return N ? N->getNumOperands() : 0u; }
+  MDTypeRef operator[](unsigned I) const { return MDTypeRef(N->getOperand(I)); }
+
+  class iterator : std::iterator<std::input_iterator_tag, MDTypeRef,
+                                 std::ptrdiff_t, void, MDTypeRef> {
+    MDNode::op_iterator I = nullptr;
+
+  public:
+    iterator() = default;
+    explicit iterator(MDNode::op_iterator I) : I(I) {}
+    MDTypeRef operator*() const { return MDTypeRef(*I); }
+    iterator &operator++() {
+      ++I;
+      return *this;
+    }
+    iterator operator++(int) {
+      iterator Temp(*this);
+      ++I;
+      return Temp;
+    }
+    bool operator==(const iterator &X) const { return I == X.I; }
+    bool operator!=(const iterator &X) const { return I != X.I; }
+  };
+
+  // FIXME: Fix callers and remove condition on N.
+  iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); }
+  iterator end() const { return N ? iterator(N->op_end()) : iterator(); }
+};
+
 /// \brief Tagged DWARF-like metadata node.
 ///
 /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*,
@@ -88,6 +183,18 @@ public:
     FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic
   };
 
+  static unsigned getFlag(StringRef Flag);
+  static const char *getFlagString(unsigned Flag);
+
+  /// \brief Split up a flags bitfield.
+  ///
+  /// Split \c Flags into \c SplitFlags, a vector of its components.  Returns
+  /// any remaining (unrecognized) bits.
+  static unsigned splitFlags(unsigned Flags,
+                             SmallVectorImpl<unsigned> &SplitFlags);
+
+  DebugNodeRef getRef() const { return DebugNodeRef::get(this); }
+
   static bool classof(const Metadata *MD) {
     switch (MD->getMetadataID()) {
     default:
@@ -116,6 +223,18 @@ public:
   }
 };
 
+template <class T>
+struct simplify_type<const TypedDebugNodeRef<T>> {
+  typedef Metadata *SimpleType;
+  static SimpleType getSimplifiedValue(const TypedDebugNodeRef<T> &MD) {
+    return MD;
+  }
+};
+
+template <class T>
+struct simplify_type<TypedDebugNodeRef<T>>
+    : simplify_type<const TypedDebugNodeRef<T>> {};
+
 /// \brief Generic tagged DWARF-like metadata node.
 ///
 /// An un-specialized DWARF-like metadata node.  The first operand is a
@@ -202,27 +321,30 @@ class MDSubrange : public DebugNode {
   friend class MDNode;
 
   int64_t Count;
-  int64_t Lo;
+  int64_t LowerBound;
 
-  MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo)
+  MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count,
+             int64_t LowerBound)
       : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type,
                   None),
-        Count(Count), Lo(Lo) {}
+        Count(Count), LowerBound(LowerBound) {}
   ~MDSubrange() {}
 
-  static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
-                             StorageType Storage, bool ShouldCreate = true);
+  static MDSubrange *getImpl(LLVMContext &Context, int64_t Count,
+                             int64_t LowerBound, StorageType Storage,
+                             bool ShouldCreate = true);
 
   TempMDSubrange cloneImpl() const {
-    return getTemporary(getContext(), getCount(), getLo());
+    return getTemporary(getContext(), getCount(), getLowerBound());
   }
 
 public:
-  DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo))
+  DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t LowerBound = 0),
+                    (Count, LowerBound))
 
   TempMDSubrange clone() const { return cloneImpl(); }
 
-  int64_t getLo() const { return Lo; }
+  int64_t getLowerBound() const { return LowerBound; }
   int64_t getCount() const { return Count; }
 
   static bool classof(const Metadata *MD) {
@@ -294,6 +416,9 @@ protected:
 public:
   MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
 
+  inline StringRef getFilename() const;
+  inline StringRef getDirectory() const;
+
   /// \brief Return the raw underlying file.
   ///
   /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file
@@ -305,6 +430,8 @@ public:
                              : static_cast<Metadata *>(getOperand(0));
   }
 
+  MDScopeRef getRef() const { return MDScopeRef::get(this); }
+
   static bool classof(const Metadata *MD) {
     switch (MD->getMetadataID()) {
     default:
@@ -370,6 +497,18 @@ public:
   }
 };
 
+StringRef MDScope::getFilename() const {
+  if (auto *F = getFile())
+    return F->getFilename();
+  return "";
+}
+
+StringRef MDScope::getDirectory() const {
+  if (auto *F = getFile())
+    return F->getDirectory();
+  return "";
+}
+
 /// \brief Base class for types.
 ///
 /// TODO: Remove the hardcoded name and context, since many types don't use
@@ -402,7 +541,7 @@ public:
   uint64_t getOffsetInBits() const { return OffsetInBits; }
   unsigned getFlags() const { return Flags; }
 
-  Metadata *getScope() const { return getRawScope(); }
+  MDScopeRef getScope() const { return MDScopeRef(getRawScope()); }
   StringRef getName() const { return getStringOperand(2); }
 
 
@@ -414,6 +553,31 @@ public:
     Flags = NewFlags;
   }
 
+  bool isPrivate() const {
+    return (getFlags() & FlagAccessibility) == FlagPrivate;
+  }
+  bool isProtected() const {
+    return (getFlags() & FlagAccessibility) == FlagProtected;
+  }
+  bool isPublic() const {
+    return (getFlags() & FlagAccessibility) == FlagPublic;
+  }
+  bool isForwardDecl() const { return getFlags() & FlagFwdDecl; }
+  bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; }
+  bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; }
+  bool isVirtual() const { return getFlags() & FlagVirtual; }
+  bool isArtificial() const { return getFlags() & FlagArtificial; }
+  bool isObjectPointer() const { return getFlags() & FlagObjectPointer; }
+  bool isObjcClassComplete() const {
+    return getFlags() & FlagObjcClassComplete;
+  }
+  bool isVector() const { return getFlags() & FlagVector; }
+  bool isStaticMember() const { return getFlags() & FlagStaticMember; }
+  bool isLValueReference() const { return getFlags() & FlagLValueReference; }
+  bool isRValueReference() const { return getFlags() & FlagRValueReference; }
+
+  MDTypeRef getRef() const { return MDTypeRef::get(this); }
+
   static bool classof(const Metadata *MD) {
     switch (MD->getMetadataID()) {
     default:
@@ -497,7 +661,7 @@ protected:
   ~MDDerivedTypeBase() {}
 
 public:
-  Metadata *getBaseType() const { return getRawBaseType(); }
+  MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); }
   Metadata *getRawBaseType() const { return getOperand(3); }
 
   static bool classof(const Metadata *MD) {
@@ -526,7 +690,7 @@ class MDDerivedType : public MDDerivedTypeBase {
 
   static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
                                 StringRef Name, MDFile *File, unsigned Line,
-                                Metadata *Scope, Metadata *BaseType,
+                                MDScopeRef Scope, MDTypeRef BaseType,
                                 uint64_t SizeInBits, uint64_t AlignInBits,
                                 uint64_t OffsetInBits, unsigned Flags,
                                 Metadata *ExtraData, StorageType Storage,
@@ -560,11 +724,10 @@ public:
                     (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                      AlignInBits, OffsetInBits, Flags, ExtraData))
   DEFINE_MDNODE_GET(MDDerivedType,
-                    (unsigned Tag, StringRef Name, MDFile *File,
-                     unsigned Line, Metadata *Scope, Metadata *BaseType,
-                     uint64_t SizeInBits, uint64_t AlignInBits,
-                     uint64_t OffsetInBits, unsigned Flags,
-                     Metadata *ExtraData = nullptr),
+                    (unsigned Tag, StringRef Name, MDFile *File, unsigned Line,
+                     MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits,
+                     uint64_t AlignInBits, uint64_t OffsetInBits,
+                     unsigned Flags, Metadata *ExtraData = nullptr),
                     (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                      AlignInBits, OffsetInBits, Flags, ExtraData))
 
@@ -603,10 +766,10 @@ protected:
   ~MDCompositeTypeBase() {}
 
 public:
-  MDTuple *getElements() const {
+  DebugNodeArray getElements() const {
     return cast_or_null<MDTuple>(getRawElements());
   }
-  Metadata *getVTableHolder() const { return getRawVTableHolder(); }
+  MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); }
   MDTemplateParameterArray getTemplateParams() const {
     return cast_or_null<MDTuple>(getRawTemplateParams());
   }
@@ -624,20 +787,19 @@ public:
   /// this will be RAUW'ed and deleted.  Use a \a TrackingMDRef to keep track
   /// of its movement if necessary.
   /// @{
-  void replaceElements(MDTuple *Elements) {
+  void replaceElements(DebugNodeArray Elements) {
 #ifndef NDEBUG
-    if (auto *Old = cast_or_null<MDTuple>(getElements()))
-      for (const auto &Op : Old->operands())
-        assert(std::find(Elements->op_begin(), Elements->op_end(), Op) &&
-               "Lost a member during member list replacement");
+    for (DebugNode *Op : getElements())
+      assert(std::find(Elements->op_begin(), Elements->op_end(), Op) &&
+             "Lost a member during member list replacement");
 #endif
-    replaceOperandWith(4, Elements);
+    replaceOperandWith(4, Elements.get());
   }
-  void replaceVTableHolder(Metadata *VTableHolder) {
+  void replaceVTableHolder(MDTypeRef VTableHolder) {
     replaceOperandWith(5, VTableHolder);
   }
   void replaceTemplateParams(MDTemplateParameterArray TemplateParams) {
-    replaceOperandWith(6, TemplateParams);
+    replaceOperandWith(6, TemplateParams.get());
   }
   /// @}
 
@@ -666,16 +828,16 @@ class MDCompositeType : public MDCompositeTypeBase {
 
   static MDCompositeType *
   getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
-          unsigned Line, Metadata *Scope, Metadata *BaseType,
+          unsigned Line, MDScopeRef Scope, MDTypeRef BaseType,
           uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
-          uint64_t Flags, Metadata *Elements, unsigned RuntimeLang,
-          Metadata *VTableHolder, Metadata *TemplateParams,
+          uint64_t Flags, DebugNodeArray Elements, unsigned RuntimeLang,
+          MDTypeRef VTableHolder, MDTemplateParameterArray TemplateParams,
           StringRef Identifier, StorageType Storage, bool ShouldCreate = true) {
-    return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
-                   Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
-                   Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
-                   getCanonicalMDString(Context, Identifier), Storage,
-                   ShouldCreate);
+    return getImpl(
+        Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
+        BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
+        RuntimeLang, VTableHolder, TemplateParams.get(),
+        getCanonicalMDString(Context, Identifier), Storage, ShouldCreate);
   }
   static MDCompositeType *
   getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@@ -695,12 +857,12 @@ class MDCompositeType : public MDCompositeTypeBase {
 
 public:
   DEFINE_MDNODE_GET(MDCompositeType,
-                    (unsigned Tag, StringRef Name, Metadata *File,
-                     unsigned Line, Metadata *Scope, Metadata *BaseType,
-                     uint64_t SizeInBits, uint64_t AlignInBits,
-                     uint64_t OffsetInBits, unsigned Flags, Metadata *Elements,
-                     unsigned RuntimeLang, Metadata *VTableHolder,
-                     Metadata *TemplateParams = nullptr,
+                    (unsigned Tag, StringRef Name, MDFile *File, unsigned Line,
+                     MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits,
+                     uint64_t AlignInBits, uint64_t OffsetInBits,
+                     unsigned Flags, DebugNodeArray Elements,
+                     unsigned RuntimeLang, MDTypeRef VTableHolder,
+                     MDTemplateParameterArray TemplateParams = nullptr,
                      StringRef Identifier = ""),
                     (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                      AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
@@ -724,6 +886,14 @@ public:
   }
 };
 
+template <class T> TypedDebugNodeRef<T> TypedDebugNodeRef<T>::get(const T *N) {
+  if (N)
+    if (auto *Composite = dyn_cast<MDCompositeType>(N))
+      if (auto *S = Composite->getRawIdentifier())
+        return TypedDebugNodeRef<T>(S);
+  return TypedDebugNodeRef<T>(N);
+}
+
 /// \brief Type array for a subprogram.
 ///
 /// TODO: Detach from CompositeType, and fold the array of types in directly
@@ -739,6 +909,12 @@ class MDSubroutineType : public MDCompositeTypeBase {
                             Ops) {}
   ~MDSubroutineType() {}
 
+  static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
+                                   MDTypeRefArray TypeArray,
+                                   StorageType Storage,
+                                   bool ShouldCreate = true) {
+    return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate);
+  }
   static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
                                    Metadata *TypeArray, StorageType Storage,
                                    bool ShouldCreate = true);
@@ -748,12 +924,17 @@ class MDSubroutineType : public MDCompositeTypeBase {
   }
 
 public:
+  DEFINE_MDNODE_GET(MDSubroutineType,
+                    (unsigned Flags, MDTypeRefArray TypeArray),
+                    (Flags, TypeArray))
   DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray),
                     (Flags, TypeArray))
 
   TempMDSubroutineType clone() const { return cloneImpl(); }
 
-  MDTuple *getTypeArray() const { return getElements(); }
+  MDTypeRefArray getTypeArray() const {
+    return cast_or_null<MDTuple>(getRawTypeArray());
+  }
   Metadata *getRawTypeArray() const { return getRawElements(); }
 
   static bool classof(const Metadata *MD) {
@@ -783,16 +964,17 @@ class MDCompileUnit : public MDScope {
   getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File,
           StringRef Producer, bool IsOptimized, StringRef Flags,
           unsigned RuntimeVersion, StringRef SplitDebugFilename,
-          unsigned EmissionKind, MDTuple *EnumTypes, MDTuple *RetainedTypes,
-          MDTuple *Subprograms, MDTuple *GlobalVariables,
-          MDTuple *ImportedEntities, StorageType Storage,
+          unsigned EmissionKind, MDCompositeTypeArray EnumTypes,
+          MDTypeArray RetainedTypes, MDSubprogramArray Subprograms,
+          MDGlobalVariableArray GlobalVariables,
+          MDImportedEntityArray ImportedEntities, StorageType Storage,
           bool ShouldCreate = true) {
-    return getImpl(Context, SourceLanguage, File,
-                   getCanonicalMDString(Context, Producer), IsOptimized,
-                   getCanonicalMDString(Context, Flags), RuntimeVersion,
-                   getCanonicalMDString(Context, SplitDebugFilename),
-                   EmissionKind, EnumTypes, RetainedTypes, Subprograms,
-                   GlobalVariables, ImportedEntities, Storage, ShouldCreate);
+    return getImpl(
+        Context, SourceLanguage, File, getCanonicalMDString(Context, Producer),
+        IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion,
+        getCanonicalMDString(Context, SplitDebugFilename), EmissionKind,
+        EnumTypes.get(), RetainedTypes.get(), Subprograms.get(),
+        GlobalVariables.get(), ImportedEntities.get(), Storage, ShouldCreate);
   }
   static MDCompileUnit *
   getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
@@ -816,9 +998,10 @@ public:
                     (unsigned SourceLanguage, MDFile *File, StringRef Producer,
                      bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
                      StringRef SplitDebugFilename, unsigned EmissionKind,
-                     MDTuple *EnumTypes, MDTuple *RetainedTypes,
-                     MDTuple *Subprograms, MDTuple *GlobalVariables,
-                     MDTuple *ImportedEntities),
+                     MDCompositeTypeArray EnumTypes, MDTypeArray RetainedTypes,
+                     MDSubprogramArray Subprograms,
+                     MDGlobalVariableArray GlobalVariables,
+                     MDImportedEntityArray ImportedEntities),
                     (SourceLanguage, File, Producer, IsOptimized, Flags,
                      RuntimeVersion, SplitDebugFilename, EmissionKind,
                      EnumTypes, RetainedTypes, Subprograms, GlobalVariables,
@@ -877,8 +1060,12 @@ public:
   /// deleted on a uniquing collision.  In practice, uniquing collisions on \a
   /// MDCompileUnit should be fairly rare.
   /// @{
-  void replaceSubprograms(MDTuple *N) { replaceOperandWith(6, N); }
-  void replaceGlobalVariables(MDTuple *N) { replaceOperandWith(7, N); }
+  void replaceSubprograms(MDSubprogramArray N) {
+    replaceOperandWith(6, N.get());
+  }
+  void replaceGlobalVariables(MDGlobalVariableArray N) {
+    replaceOperandWith(7, N.get());
+  }
   /// @}
 
   static bool classof(const Metadata *MD) {
@@ -959,12 +1146,16 @@ public:
   unsigned getLine() const { return SubclassData32; }
   unsigned getColumn() const { return SubclassData16; }
   MDLocalScope *getScope() const {
-    return cast_or_null<MDLocalScope>(getRawScope());
+    return cast<MDLocalScope>(getRawScope());
   }
   MDLocation *getInlinedAt() const {
     return cast_or_null<MDLocation>(getRawInlinedAt());
   }
 
+  MDFile *getFile() const { return getScope()->getFile(); }
+  StringRef getFilename() const { return getScope()->getFilename(); }
+  StringRef getDirectory() const { return getScope()->getDirectory(); }
+
   /// \brief Get the scope where this is inlined.
   ///
   /// Walk through \a getInlinedAt() and return \a getScope() from the deepest
@@ -1016,19 +1207,19 @@ class MDSubprogram : public MDLocalScope {
   ~MDSubprogram() {}
 
   static MDSubprogram *
-  getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name,
+  getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name,
           StringRef LinkageName, MDFile *File, unsigned Line,
           MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition,
-          unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
+          unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality,
           unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-          ConstantAsMetadata *Function, MDTuple *TemplateParams,
-          MDSubprogram *Declaration, MDTuple *Variables, StorageType Storage,
-          bool ShouldCreate = true) {
+          ConstantAsMetadata *Function, MDTemplateParameterArray TemplateParams,
+          MDSubprogram *Declaration, MDLocalVariableArray Variables,
+          StorageType Storage, bool ShouldCreate = true) {
     return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
                    getCanonicalMDString(Context, LinkageName), File, Line, Type,
                    IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
                    Virtuality, VirtualIndex, Flags, IsOptimized, Function,
-                   TemplateParams, Declaration, Variables, Storage,
+                   TemplateParams.get(), Declaration, Variables.get(), Storage,
                    ShouldCreate);
   }
   static MDSubprogram *
@@ -1050,18 +1241,20 @@ class MDSubprogram : public MDLocalScope {
   }
 
 public:
-  DEFINE_MDNODE_GET(
-      MDSubprogram,
-      (Metadata * Scope, StringRef Name, StringRef LinkageName, MDFile *File,
-       unsigned Line, MDSubroutineType *Type, bool IsLocalToUnit,
-       bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType,
-       unsigned Virtuality, unsigned VirtualIndex, unsigned Flags,
-       bool IsOptimized, ConstantAsMetadata *Function = nullptr,
-       MDTuple *TemplateParams = nullptr, MDSubprogram *Declaration = nullptr,
-       MDTuple *Variables = nullptr),
-      (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
-       ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized,
-       Function, TemplateParams, Declaration, Variables))
+  DEFINE_MDNODE_GET(MDSubprogram,
+                    (MDScopeRef Scope, StringRef Name, StringRef LinkageName,
+                     MDFile *File, unsigned Line, MDSubroutineType *Type,
+                     bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+                     MDTypeRef ContainingType, unsigned Virtuality,
+                     unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+                     ConstantAsMetadata *Function = nullptr,
+                     MDTemplateParameterArray TemplateParams = nullptr,
+                     MDSubprogram *Declaration = nullptr,
+                     MDLocalVariableArray Variables = nullptr),
+                    (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+                     IsDefinition, ScopeLine, ContainingType, Virtuality,
+                     VirtualIndex, Flags, IsOptimized, Function, TemplateParams,
+                     Declaration, Variables))
   DEFINE_MDNODE_GET(
       MDSubprogram,
       (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
@@ -1086,7 +1279,36 @@ public:
   bool isDefinition() const { return IsDefinition; }
   bool isOptimized() const { return IsOptimized; }
 
-  Metadata *getScope() const { return getRawScope(); }
+  unsigned isArtificial() const { return getFlags() & FlagArtificial; }
+  bool isPrivate() const {
+    return (getFlags() & FlagAccessibility) == FlagPrivate;
+  }
+  bool isProtected() const {
+    return (getFlags() & FlagAccessibility) == FlagProtected;
+  }
+  bool isPublic() const {
+    return (getFlags() & FlagAccessibility) == FlagPublic;
+  }
+  bool isExplicit() const { return getFlags() & FlagExplicit; }
+  bool isPrototyped() const { return getFlags() & FlagPrototyped; }
+
+  /// \brief Check if this is reference-qualified.
+  ///
+  /// Return true if this subprogram is a C++11 reference-qualified non-static
+  /// member function (void foo() &).
+  unsigned isLValueReference() const {
+    return getFlags() & FlagLValueReference;
+  }
+
+  /// \brief Check if this is rvalue-reference-qualified.
+  ///
+  /// Return true if this subprogram is a C++11 rvalue-reference-qualified
+  /// non-static member function (void foo() &&).
+  unsigned isRValueReference() const {
+    return getFlags() & FlagRValueReference;
+  }
+
+  MDScopeRef getScope() const { return MDScopeRef(getRawScope()); }
 
   StringRef getName() const { return getStringOperand(2); }
   StringRef getDisplayName() const { return getStringOperand(3); }
@@ -1098,7 +1320,9 @@ public:
   MDSubroutineType *getType() const {
     return cast_or_null<MDSubroutineType>(getRawType());
   }
-  Metadata *getContainingType() const { return getRawContainingType(); }
+  MDTypeRef getContainingType() const {
+    return MDTypeRef(getRawContainingType());
+  }
 
   ConstantAsMetadata *getFunction() const {
     return cast_or_null<ConstantAsMetadata>(getRawFunction());
@@ -1312,9 +1536,10 @@ protected:
 
 public:
   StringRef getName() const { return getStringOperand(0); }
-  Metadata *getType() const { return getOperand(1); }
+  MDTypeRef getType() const { return MDTypeRef(getRawType()); }
 
   MDString *getRawName() const { return getOperandAs<MDString>(0); }
+  Metadata *getRawType() const { return getOperand(1); }
 
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == MDTemplateTypeParameterKind ||
@@ -1333,7 +1558,7 @@ class MDTemplateTypeParameter : public MDTemplateParameter {
   ~MDTemplateTypeParameter() {}
 
   static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name,
-                                          Metadata *Type, StorageType Storage,
+                                          MDTypeRef Type, StorageType Storage,
                                           bool ShouldCreate = true) {
     return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage,
                    ShouldCreate);
@@ -1347,7 +1572,7 @@ class MDTemplateTypeParameter : public MDTemplateParameter {
   }
 
 public:
-  DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type),
+  DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, MDTypeRef Type),
                     (Name, Type))
   DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type),
                     (Name, Type))
@@ -1370,7 +1595,7 @@ class MDTemplateValueParameter : public MDTemplateParameter {
   ~MDTemplateValueParameter() {}
 
   static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
-                                           StringRef Name, Metadata *Type,
+                                           StringRef Name, MDTypeRef Type,
                                            Metadata *Value, StorageType Storage,
                                            bool ShouldCreate = true) {
     return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type,
@@ -1388,7 +1613,7 @@ class MDTemplateValueParameter : public MDTemplateParameter {
 
 public:
   DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name,
-                                               Metadata *Type, Metadata *Value),
+                                               MDTypeRef Type, Metadata *Value),
                     (Tag, Name, Type, Value))
   DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name,
                                                Metadata *Type, Metadata *Value),
@@ -1420,7 +1645,18 @@ public:
   MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); }
   StringRef getName() const { return getStringOperand(1); }
   MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
-  Metadata *getType() const { return getRawType(); }
+  MDTypeRef getType() const { return MDTypeRef(getRawType()); }
+
+  StringRef getFilename() const {
+    if (auto *F = getFile())
+      return F->getFilename();
+    return "";
+  }
+  StringRef getDirectory() const {
+    if (auto *F = getFile())
+      return F->getDirectory();
+    return "";
+  }
 
   Metadata *getRawScope() const { return getOperand(0); }
   MDString *getRawName() const { return getOperandAs<MDString>(1); }
@@ -1453,7 +1689,7 @@ class MDGlobalVariable : public MDVariable {
 
   static MDGlobalVariable *
   getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name,
-          StringRef LinkageName, MDFile *File, unsigned Line, Metadata *Type,
+          StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type,
           bool IsLocalToUnit, bool IsDefinition, ConstantAsMetadata *Variable,
           MDDerivedType *StaticDataMemberDeclaration, StorageType Storage,
           bool ShouldCreate = true) {
@@ -1479,7 +1715,7 @@ class MDGlobalVariable : public MDVariable {
 public:
   DEFINE_MDNODE_GET(MDGlobalVariable,
                     (MDScope * Scope, StringRef Name, StringRef LinkageName,
-                     MDFile *File, unsigned Line, Metadata *Type,
+                     MDFile *File, unsigned Line, MDTypeRef Type,
                      bool IsLocalToUnit, bool IsDefinition,
                      ConstantAsMetadata *Variable,
                      MDDerivedType *StaticDataMemberDeclaration),
@@ -1536,7 +1772,7 @@ class MDLocalVariable : public MDVariable {
 
   static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag,
                                   MDScope *Scope, StringRef Name, MDFile *File,
-                                  unsigned Line, Metadata *Type, unsigned Arg,
+                                  unsigned Line, MDTypeRef Type, unsigned Arg,
                                   unsigned Flags, MDLocation *InlinedAt,
                                   StorageType Storage,
                                   bool ShouldCreate = true) {
@@ -1560,7 +1796,7 @@ class MDLocalVariable : public MDVariable {
 public:
   DEFINE_MDNODE_GET(MDLocalVariable,
                     (unsigned Tag, MDLocalScope *Scope, StringRef Name,
-                     MDFile *File, unsigned Line, Metadata *Type, unsigned Arg,
+                     MDFile *File, unsigned Line, MDTypeRef Type, unsigned Arg,
                      unsigned Flags, MDLocation *InlinedAt = nullptr),
                     (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt))
   DEFINE_MDNODE_GET(MDLocalVariable,
@@ -1587,6 +1823,9 @@ public:
 
   Metadata *getRawInlinedAt() const { return getOperand(4); }
 
+  bool isArtificial() const { return getFlags() & FlagArtificial; }
+  bool isObjectPointer() const { return getFlags() & FlagObjectPointer; }
+
   /// \brief Check that a location is valid for this variable.
   ///
   /// Check that \c DL has the same inlined-at location as this variable,
@@ -1649,6 +1888,15 @@ public:
     return Elements[I];
   }
 
+  /// \brief Return whether this is a piece of an aggregate variable.
+  bool isBitPiece() const;
+
+  /// \brief Return the offset of this piece in bits.
+  uint64_t getBitPieceOffset() const;
+
+  /// \brief Return the size of this piece in bits.
+  uint64_t getBitPieceSize() const;
+
   typedef ArrayRef<uint64_t>::iterator element_iterator;
   element_iterator elements_begin() const { return getElements().begin(); }
   element_iterator elements_end() const { return getElements().end(); }
@@ -1703,6 +1951,13 @@ public:
       return T;
     }
 
+    /// \brief Get the next iterator.
+    ///
+    /// \a std::next() doesn't work because this is technically an
+    /// input_iterator, but it's a perfectly valid operation.  This is an
+    /// accessor to provide the same functionality.
+    expr_op_iterator getNext() const { return ++expr_op_iterator(*this); }
+
     bool operator==(const expr_op_iterator &X) const {
       return getBase() == X.getBase();
     }
@@ -1796,6 +2051,17 @@ public:
   StringRef getSetterName() const { return getStringOperand(3); }
   MDType *getType() const { return cast_or_null<MDType>(getRawType()); }
 
+  StringRef getFilename() const {
+    if (auto *F = getFile())
+      return F->getFilename();
+    return "";
+  }
+  StringRef getDirectory() const {
+    if (auto *F = getFile())
+      return F->getDirectory();
+    return "";
+  }
+
   MDString *getRawName() const { return getOperandAs<MDString>(0); }
   Metadata *getRawFile() const { return getOperand(1); }
   MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }
@@ -1819,7 +2085,7 @@ class MDImportedEntity : public DebugNode {
   ~MDImportedEntity() {}
 
   static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
-                                   MDScope *Scope, Metadata *Entity,
+                                   MDScope *Scope, DebugNodeRef Entity,
                                    unsigned Line, StringRef Name,
                                    StorageType Storage,
                                    bool ShouldCreate = true) {
@@ -1839,7 +2105,7 @@ class MDImportedEntity : public DebugNode {
 
 public:
   DEFINE_MDNODE_GET(MDImportedEntity,
-                    (unsigned Tag, MDScope *Scope, Metadata *Entity,
+                    (unsigned Tag, MDScope *Scope, DebugNodeRef Entity,
                      unsigned Line, StringRef Name = ""),
                     (Tag, Scope, Entity, Line, Name))
   DEFINE_MDNODE_GET(MDImportedEntity,
@@ -1851,7 +2117,7 @@ public:
 
   unsigned getLine() const { return Line; }
   MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); }
-  Metadata *getEntity() const { return getRawEntity(); }
+  DebugNodeRef getEntity() const { return DebugNodeRef(getRawEntity()); }
   StringRef getName() const { return getStringOperand(2); }
 
   Metadata *getRawScope() const { return getOperand(0); }