IR: Add specialized debug info metadata nodes
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 10 Feb 2015 00:52:32 +0000 (00:52 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 10 Feb 2015 00:52:32 +0000 (00:52 +0000)
Add specialized debug info metadata nodes that match the `DIDescriptor`
wrappers (used by `DIBuilder`) closely.  Assembly and bitcode support to
follow soon (it'll mostly just be obvious), but this sketches in today's
schema.  This is the first big commit (well, the only *big* one aside
from the testcase changes that'll come when I move this into place) for
PR22464.

I've marked a bunch of obvious changes as `TODO`s in the source; I plan
to make those changes promptly after this hierarchy is moved underneath
`DIDescriptor`, but for now I'm aiming mostly to match the status quo.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228640 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/DebugInfoMetadata.h
include/llvm/IR/Metadata.def
include/llvm/IR/Metadata.h
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/IR/AsmWriter.cpp
lib/IR/DebugInfoMetadata.cpp
lib/IR/LLVMContextImpl.h
unittests/IR/MetadataTest.cpp

index ba0c2320f636b6038f79fe902a5d28b638756711..fdb6dd8964c72400c0cf51a02b3ef8fd49d8c9ca 100644 (file)
@@ -15,6 +15,7 @@
 #define LLVM_IR_DEBUGINFOMETADATA_H
 
 #include "llvm/IR/Metadata.h"
+#include "llvm/Support/Dwarf.h"
 
 // Helper macros for defining get() overrides.
 #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__
@@ -125,7 +126,31 @@ public:
   unsigned getTag() const { return SubclassData16; }
 
   static bool classof(const Metadata *MD) {
-    return MD->getMetadataID() == GenericDebugNodeKind;
+    switch (MD->getMetadataID()) {
+    default:
+      return false;
+    case GenericDebugNodeKind:
+    case MDSubrangeKind:
+    case MDEnumeratorKind:
+    case MDBasicTypeKind:
+    case MDDerivedTypeKind:
+    case MDCompositeTypeKind:
+    case MDSubroutineTypeKind:
+    case MDFileKind:
+    case MDCompileUnitKind:
+    case MDSubprogramKind:
+    case MDLexicalBlockKind:
+    case MDLexicalBlockFileKind:
+    case MDNamespaceKind:
+    case MDTemplateTypeParameterKind:
+    case MDTemplateValueParameterKind:
+    case MDGlobalVariableKind:
+    case MDLocalVariableKind:
+    case MDExpressionKind:
+    case MDObjCPropertyKind:
+    case MDImportedEntityKind:
+      return true;
+    }
   }
 };
 
@@ -206,6 +231,1308 @@ public:
   }
 };
 
+/// \brief Array subrange.
+///
+/// TODO: Merge into node for DW_TAG_array_type, which should have a custom
+/// type.
+class MDSubrange : public DebugNode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  int64_t Count;
+  int64_t Lo;
+
+  MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo)
+      : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type,
+                  None),
+        Count(Count), Lo(Lo) {}
+  ~MDSubrange() {}
+
+  static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
+                             StorageType Storage, bool ShouldCreate = true);
+
+  TempMDSubrange cloneImpl() const {
+    return getTemporary(getContext(), getCount(), getLo());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo))
+
+  TempMDSubrange clone() const { return cloneImpl(); }
+
+  int64_t getLo() const { return Lo; }
+  int64_t getCount() const { return Count; }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDSubrangeKind;
+  }
+};
+
+/// \brief Enumeration value.
+///
+/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no
+/// longer creates a type cycle.
+class MDEnumerator : public DebugNode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  int64_t Value;
+
+  MDEnumerator(LLVMContext &C, StorageType Storage, int64_t Value,
+               ArrayRef<Metadata *> Ops)
+      : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
+        Value(Value) {}
+  ~MDEnumerator() {}
+
+  static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value,
+                               StringRef Name, StorageType Storage,
+                               bool ShouldCreate = true) {
+    return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage,
+                   ShouldCreate);
+  }
+  static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value,
+                               MDString *Name, StorageType Storage,
+                               bool ShouldCreate = true);
+
+  TempMDEnumerator cloneImpl() const {
+    return getTemporary(getContext(), getValue(), getName());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, StringRef Name),
+                    (Value, Name))
+  DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, MDString *Name),
+                    (Value, Name))
+
+  TempMDEnumerator clone() const { return cloneImpl(); }
+
+  int64_t getValue() const { return Value; }
+  StringRef getName() const { return getStringOperand(0); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDEnumeratorKind;
+  }
+};
+
+/// \brief Base class for scope-like contexts.
+///
+/// Base class for lexical scopes and types (which are also declaration
+/// contexts).
+///
+/// TODO: Separate the concepts of declaration contexts and lexical scopes.
+class MDScope : public DebugNode {
+protected:
+  MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+          ArrayRef<Metadata *> Ops)
+      : DebugNode(C, ID, Storage, Tag, Ops) {}
+  ~MDScope() {}
+
+public:
+  Metadata *getFile() const { return getOperand(0); }
+
+  static bool classof(const Metadata *MD) {
+    switch (MD->getMetadataID()) {
+    default:
+      return false;
+    case MDBasicTypeKind:
+    case MDDerivedTypeKind:
+    case MDCompositeTypeKind:
+    case MDSubroutineTypeKind:
+    case MDFileKind:
+    case MDCompileUnitKind:
+    case MDSubprogramKind:
+    case MDLexicalBlockKind:
+    case MDLexicalBlockFileKind:
+    case MDNamespaceKind:
+      return true;
+    }
+  }
+};
+
+/// \brief Base class for types.
+///
+/// TODO: Remove the hardcoded name and context, since many types don't use
+/// them.
+/// TODO: Split up flags.
+class MDType : public MDScope {
+  unsigned Line;
+  unsigned SizeInBits;
+  unsigned AlignInBits;
+  unsigned OffsetInBits;
+  unsigned Flags;
+
+protected:
+  MDType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+         unsigned Line, unsigned SizeInBits, unsigned AlignInBits,
+         unsigned OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
+      : MDScope(C, ID, Storage, Tag, Ops), Line(Line), SizeInBits(SizeInBits),
+        AlignInBits(AlignInBits), OffsetInBits(OffsetInBits), Flags(Flags) {}
+  ~MDType() {}
+
+public:
+  unsigned getLine() const { return Line; }
+  unsigned getSizeInBits() const { return SizeInBits; }
+  unsigned getAlignInBits() const { return AlignInBits; }
+  unsigned getOffsetInBits() const { return OffsetInBits; }
+  unsigned getFlags() const { return Flags; }
+
+  Metadata *getScope() const { return getOperand(1); }
+  StringRef getName() const { return getStringOperand(2); }
+
+  static bool classof(const Metadata *MD) {
+    switch (MD->getMetadataID()) {
+    default:
+      return false;
+    case MDBasicTypeKind:
+    case MDDerivedTypeKind:
+    case MDCompositeTypeKind:
+    case MDSubroutineTypeKind:
+      return true;
+    }
+  }
+};
+
+/// \brief Basic type.
+///
+/// TODO: Split out DW_TAG_unspecified_type.
+/// TODO: Drop unused accessors.
+class MDBasicType : public MDType {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Encoding;
+
+  MDBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
+              unsigned SizeInBits, unsigned AlignInBits, unsigned Encoding,
+              ArrayRef<Metadata *> Ops)
+      : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
+               0, Ops),
+        Encoding(Encoding) {}
+  ~MDBasicType() {}
+
+  static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag,
+                              StringRef Name, unsigned SizeInBits,
+                              unsigned AlignInBits, unsigned Encoding,
+                              StorageType Storage, bool ShouldCreate = true) {
+    return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
+                   SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate);
+  }
+  static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag,
+                              MDString *Name, unsigned SizeInBits,
+                              unsigned AlignInBits, unsigned Encoding,
+                              StorageType Storage, bool ShouldCreate = true);
+
+  TempMDBasicType cloneImpl() const {
+    return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
+                        getAlignInBits(), getEncoding());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDBasicType,
+                    (unsigned Tag, StringRef Name, unsigned SizeInBits,
+                     unsigned AlignInBits, unsigned Encoding),
+                    (Tag, Name, SizeInBits, AlignInBits, Encoding))
+  DEFINE_MDNODE_GET(MDBasicType,
+                    (unsigned Tag, MDString *Name, unsigned SizeInBits,
+                     unsigned AlignInBits, unsigned Encoding),
+                    (Tag, Name, SizeInBits, AlignInBits, Encoding))
+
+  TempMDBasicType clone() const { return cloneImpl(); }
+
+  unsigned getEncoding() const { return Encoding; }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDBasicTypeKind;
+  }
+};
+
+/// \brief Base class for MDDerivedType and MDCompositeType.
+///
+/// TODO: Delete; they're not really related.
+class MDDerivedTypeBase : public MDType {
+protected:
+  MDDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage,
+                    unsigned Tag, unsigned Line, unsigned SizeInBits,
+                    unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
+                    ArrayRef<Metadata *> Ops)
+      : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
+               Flags, Ops) {}
+  ~MDDerivedTypeBase() {}
+
+public:
+  Metadata *getBaseType() const { return getOperand(3); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDDerivedTypeKind ||
+           MD->getMetadataID() == MDCompositeTypeKind ||
+           MD->getMetadataID() == MDSubroutineTypeKind;
+  }
+};
+
+/// \brief Derived types.
+///
+/// This includes qualified types, pointers, references, friends, typedefs, and
+/// class members.
+///
+/// TODO: Split out members (inheritance, fields, methods, etc.).
+class MDDerivedType : public MDDerivedTypeBase {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
+                unsigned Line, unsigned SizeInBits, unsigned AlignInBits,
+                unsigned OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
+      : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits,
+                          AlignInBits, OffsetInBits, Flags, Ops) {}
+  ~MDDerivedType() {}
+
+  static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
+                                StringRef Name, Metadata *File, unsigned Line,
+                                Metadata *Scope, Metadata *BaseType,
+                                unsigned SizeInBits, unsigned AlignInBits,
+                                unsigned OffsetInBits, unsigned Flags,
+                                Metadata *ExtraData, StorageType Storage,
+                                bool ShouldCreate = true) {
+    return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
+                   Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
+                   Flags, ExtraData, Storage, ShouldCreate);
+  }
+  static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
+                                MDString *Name, Metadata *File, unsigned Line,
+                                Metadata *Scope, Metadata *BaseType,
+                                unsigned SizeInBits, unsigned AlignInBits,
+                                unsigned OffsetInBits, unsigned Flags,
+                                Metadata *ExtraData, StorageType Storage,
+                                bool ShouldCreate = true);
+
+  TempMDDerivedType cloneImpl() const {
+    return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
+                        getScope(), getBaseType(), getSizeInBits(),
+                        getAlignInBits(), getOffsetInBits(), getFlags(),
+                        getExtraData());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDDerivedType,
+                    (unsigned Tag, MDString *Name, Metadata *File,
+                     unsigned Line, Metadata *Scope, Metadata *BaseType,
+                     unsigned SizeInBits, unsigned AlignInBits,
+                     unsigned OffsetInBits, unsigned Flags,
+                     Metadata *ExtraData = nullptr),
+                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                     AlignInBits, OffsetInBits, Flags, ExtraData))
+  DEFINE_MDNODE_GET(MDDerivedType,
+                    (unsigned Tag, StringRef Name, Metadata *File,
+                     unsigned Line, Metadata *Scope, Metadata *BaseType,
+                     unsigned SizeInBits, unsigned AlignInBits,
+                     unsigned OffsetInBits, unsigned Flags,
+                     Metadata *ExtraData = nullptr),
+                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                     AlignInBits, OffsetInBits, Flags, ExtraData))
+
+  TempMDDerivedType clone() const { return cloneImpl(); }
+
+  /// \brief Get extra data associated with this derived type.
+  ///
+  /// Class type for pointer-to-members, objective-c property node for ivars,
+  /// or global constant wrapper for static members.
+  ///
+  /// TODO: Separate out types that need this extra operand: pointer-to-member
+  /// types and member fields (static members and ivars).
+  Metadata *getExtraData() const { return getOperand(4); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDDerivedTypeKind;
+  }
+};
+
+/// \brief Base class for MDCompositeType and MDSubroutineType.
+///
+/// TODO: Delete; they're not really related.
+class MDCompositeTypeBase : public MDDerivedTypeBase {
+  unsigned RuntimeLang;
+
+protected:
+  MDCompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage,
+                      unsigned Tag, unsigned Line, unsigned RuntimeLang,
+                      unsigned SizeInBits, unsigned AlignInBits,
+                      unsigned OffsetInBits, unsigned Flags,
+                      ArrayRef<Metadata *> Ops)
+      : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits,
+                          OffsetInBits, Flags, Ops),
+        RuntimeLang(RuntimeLang) {}
+  ~MDCompositeTypeBase() {}
+
+public:
+  Metadata *getElements() const { return getOperand(4); }
+  Metadata *getVTableHolder() const { return getOperand(5); }
+  Metadata *getTemplateParams() const { return getOperand(6); }
+  StringRef getIdentifier() const { return getStringOperand(7); }
+  unsigned getRuntimeLang() const { return RuntimeLang; }
+
+  MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDCompositeTypeKind ||
+           MD->getMetadataID() == MDSubroutineTypeKind;
+  }
+};
+
+/// \brief Composite types.
+///
+/// TODO: Detach from DerivedTypeBase (split out MDEnumType?).
+/// TODO: Create a custom, unrelated node for DW_TAG_array_type.
+class MDCompositeType : public MDCompositeTypeBase {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDCompositeType(LLVMContext &C, StorageType Storage, unsigned Tag,
+                  unsigned Line, unsigned RuntimeLang, unsigned SizeInBits,
+                  unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
+                  ArrayRef<Metadata *> Ops)
+      : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line,
+                            RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
+                            Flags, Ops) {}
+  ~MDCompositeType() {}
+
+  static MDCompositeType *
+  getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
+          unsigned Line, Metadata *Scope, Metadata *BaseType,
+          unsigned SizeInBits, unsigned AlignInBits, unsigned OffsetInBits,
+          unsigned Flags, Metadata *Elements, unsigned RuntimeLang,
+          Metadata *VTableHolder, Metadata *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);
+  }
+  static MDCompositeType *
+  getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
+          unsigned Line, Metadata *Scope, Metadata *BaseType,
+          unsigned SizeInBits, unsigned AlignInBits, unsigned OffsetInBits,
+          unsigned Flags, Metadata *Elements, unsigned RuntimeLang,
+          Metadata *VTableHolder, Metadata *TemplateParams,
+          MDString *Identifier, StorageType Storage, bool ShouldCreate = true);
+
+  TempMDCompositeType cloneImpl() const {
+    return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
+                        getScope(), getBaseType(), getSizeInBits(),
+                        getAlignInBits(), getOffsetInBits(), getFlags(),
+                        getElements(), getRuntimeLang(), getVTableHolder(),
+                        getTemplateParams(), getIdentifier());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDCompositeType,
+                    (unsigned Tag, StringRef Name, Metadata *File,
+                     unsigned Line, Metadata *Scope, Metadata *BaseType,
+                     unsigned SizeInBits, unsigned AlignInBits,
+                     unsigned OffsetInBits, unsigned Flags, Metadata *Elements,
+                     unsigned RuntimeLang, Metadata *VTableHolder,
+                     Metadata *TemplateParams = nullptr,
+                     StringRef Identifier = ""),
+                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                     AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+                     VTableHolder, TemplateParams, Identifier))
+  DEFINE_MDNODE_GET(MDCompositeType,
+                    (unsigned Tag, MDString *Name, Metadata *File,
+                     unsigned Line, Metadata *Scope, Metadata *BaseType,
+                     unsigned SizeInBits, unsigned AlignInBits,
+                     unsigned OffsetInBits, unsigned Flags, Metadata *Elements,
+                     unsigned RuntimeLang, Metadata *VTableHolder,
+                     Metadata *TemplateParams = nullptr,
+                     MDString *Identifier = nullptr),
+                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                     AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+                     VTableHolder, TemplateParams, Identifier))
+
+  TempMDCompositeType clone() const { return cloneImpl(); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDCompositeTypeKind;
+  }
+};
+
+/// \brief Type array for a subprogram.
+///
+/// TODO: Detach from CompositeType, and fold the array of types in directly
+/// as operands.
+class MDSubroutineType : public MDCompositeTypeBase {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDSubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags,
+                   ArrayRef<Metadata *> Ops)
+      : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage,
+                            dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags,
+                            Ops) {}
+  ~MDSubroutineType() {}
+
+  static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
+                                   Metadata *TypeArray, StorageType Storage,
+                                   bool ShouldCreate = true);
+
+  TempMDSubroutineType cloneImpl() const {
+    return getTemporary(getContext(), getFlags(), getTypeArray());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray),
+                    (Flags, TypeArray))
+
+  TempMDSubroutineType clone() const { return cloneImpl(); }
+
+  Metadata *getTypeArray() const { return getElements(); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDSubroutineTypeKind;
+  }
+};
+
+/// \brief File.
+///
+/// TODO: Merge with directory/file node (including users).
+/// TODO: Canonicalize paths on creation.
+class MDFile : public MDScope {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops)
+      : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {}
+  ~MDFile() {}
+
+  static MDFile *getImpl(LLVMContext &Context, StringRef Filename,
+                         StringRef Directory, StorageType Storage,
+                         bool ShouldCreate = true) {
+    return getImpl(Context, getCanonicalMDString(Context, Filename),
+                   getCanonicalMDString(Context, Directory), Storage,
+                   ShouldCreate);
+  }
+  static MDFile *getImpl(LLVMContext &Context, MDString *Filename,
+                         MDString *Directory, StorageType Storage,
+                         bool ShouldCreate = true);
+
+  TempMDFile cloneImpl() const {
+    return getTemporary(getContext(), getFilename(), getDirectory());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory),
+                    (Filename, Directory))
+  DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory),
+                    (Filename, Directory))
+
+  TempMDFile clone() const { return cloneImpl(); }
+
+  MDTuple *getFileNode() const { return cast<MDTuple>(getOperand(0)); }
+
+  StringRef getFilename() const {
+    if (auto *S = cast_or_null<MDString>(getFileNode()->getOperand(0)))
+      return S->getString();
+    return StringRef();
+  }
+  StringRef getDirectory() const {
+    if (auto *S = cast_or_null<MDString>(getFileNode()->getOperand(1)))
+      return S->getString();
+    return StringRef();
+  }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDFileKind;
+  }
+};
+
+/// \brief Compile unit.
+class MDCompileUnit : public MDScope {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned SourceLanguage;
+  bool IsOptimized;
+  unsigned RuntimeVersion;
+  unsigned EmissionKind;
+
+  MDCompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage,
+                bool IsOptimized, unsigned RuntimeVersion,
+                unsigned EmissionKind, ArrayRef<Metadata *> Ops)
+      : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
+        SourceLanguage(SourceLanguage), IsOptimized(IsOptimized),
+        RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {}
+  ~MDCompileUnit() {}
+
+  static MDCompileUnit *
+  getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
+          StringRef Producer, bool IsOptimized, StringRef Flags,
+          unsigned RuntimeVersion, StringRef SplitDebugFilename,
+          unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
+          Metadata *Subprograms, Metadata *GlobalVariables,
+          Metadata *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);
+  }
+  static MDCompileUnit *
+  getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
+          MDString *Producer, bool IsOptimized, MDString *Flags,
+          unsigned RuntimeVersion, MDString *SplitDebugFilename,
+          unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
+          Metadata *Subprograms, Metadata *GlobalVariables,
+          Metadata *ImportedEntities, StorageType Storage,
+          bool ShouldCreate = true);
+
+  TempMDCompileUnit cloneImpl() const {
+    return getTemporary(
+        getContext(), getSourceLanguage(), getFile(), getProducer(),
+        isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(),
+        getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(),
+        getGlobalVariables(), getImportedEntities());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDCompileUnit,
+                    (unsigned SourceLanguage, Metadata *File,
+                     StringRef Producer, bool IsOptimized, StringRef Flags,
+                     unsigned RuntimeVersion, StringRef SplitDebugFilename,
+                     unsigned EmissionKind, Metadata *EnumTypes,
+                     Metadata *RetainedTypes, Metadata *Subprograms,
+                     Metadata *GlobalVariables, Metadata *ImportedEntities),
+                    (SourceLanguage, File, Producer, IsOptimized, Flags,
+                     RuntimeVersion, SplitDebugFilename, EmissionKind,
+                     EnumTypes, RetainedTypes, Subprograms, GlobalVariables,
+                     ImportedEntities))
+  DEFINE_MDNODE_GET(MDCompileUnit,
+                    (unsigned SourceLanguage, Metadata *File,
+                     MDString *Producer, bool IsOptimized, MDString *Flags,
+                     unsigned RuntimeVersion, MDString *SplitDebugFilename,
+                     unsigned EmissionKind, Metadata *EnumTypes,
+                     Metadata *RetainedTypes, Metadata *Subprograms,
+                     Metadata *GlobalVariables, Metadata *ImportedEntities),
+                    (SourceLanguage, File, Producer, IsOptimized, Flags,
+                     RuntimeVersion, SplitDebugFilename, EmissionKind,
+                     EnumTypes, RetainedTypes, Subprograms, GlobalVariables,
+                     ImportedEntities))
+
+  TempMDCompileUnit clone() const { return cloneImpl(); }
+
+  unsigned getSourceLanguage() const { return SourceLanguage; }
+  bool isOptimized() const { return IsOptimized; }
+  unsigned getRuntimeVersion() const { return RuntimeVersion; }
+  unsigned getEmissionKind() const { return EmissionKind; }
+  StringRef getProducer() const { return getStringOperand(1); }
+  StringRef getFlags() const { return getStringOperand(2); }
+  StringRef getSplitDebugFilename() const { return getStringOperand(3); }
+  Metadata *getEnumTypes() const { return getOperand(4); }
+  Metadata *getRetainedTypes() const { return getOperand(5); }
+  Metadata *getSubprograms() const { return getOperand(6); }
+  Metadata *getGlobalVariables() const { return getOperand(7); }
+  Metadata *getImportedEntities() const { return getOperand(8); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDCompileUnitKind;
+  }
+};
+
+/// \brief Subprogram description.
+///
+/// TODO: Remove DisplayName.  It's always equal to Name.
+/// TODO: Split up flags.
+class MDSubprogram : public MDScope {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Line;
+  unsigned ScopeLine;
+  unsigned Virtuality;
+  unsigned VirtualIndex;
+  unsigned Flags;
+  bool IsLocalToUnit;
+  bool IsDefinition;
+  bool IsOptimized;
+
+  MDSubprogram(LLVMContext &C, StorageType Storage, unsigned Line,
+               unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex,
+               unsigned Flags, bool IsLocalToUnit, bool IsDefinition,
+               bool IsOptimized, ArrayRef<Metadata *> Ops)
+      : MDScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops),
+        Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality),
+        VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit),
+        IsDefinition(IsDefinition), IsOptimized(IsOptimized) {}
+  ~MDSubprogram() {}
+
+  static MDSubprogram *
+  getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name,
+          StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+          bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+          Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
+          unsigned Flags, bool IsOptimized, Metadata *Function,
+          Metadata *TemplateParams, Metadata *Declaration, Metadata *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,
+                   ShouldCreate);
+  }
+  static MDSubprogram *
+  getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
+          MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+          bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+          Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
+          unsigned Flags, bool IsOptimized, Metadata *Function,
+          Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+          StorageType Storage, bool ShouldCreate = true);
+
+  TempMDSubprogram cloneImpl() const {
+    return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
+                        getFile(), getLine(), getType(), isLocalToUnit(),
+                        isDefinition(), getScopeLine(), getContainingType(),
+                        getVirtuality(), getVirtualIndex(), getFlags(),
+                        isOptimized(), getFunction(), getTemplateParams(),
+                        getDeclaration(), getVariables());
+  }
+
+public:
+  DEFINE_MDNODE_GET(
+      MDSubprogram,
+      (Metadata * Scope, StringRef Name, StringRef LinkageName, Metadata *File,
+       unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
+       unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
+       unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+       Metadata *Function = nullptr, Metadata *TemplateParams = nullptr,
+       Metadata *Declaration = nullptr, Metadata *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,
+       unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
+       unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
+       unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+       Metadata *Function = nullptr, Metadata *TemplateParams = nullptr,
+       Metadata *Declaration = nullptr, Metadata *Variables = nullptr),
+      (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
+       ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized,
+       Function, TemplateParams, Declaration, Variables))
+
+  TempMDSubprogram clone() const { return cloneImpl(); }
+
+public:
+  unsigned getLine() const { return Line; }
+  unsigned getVirtuality() const { return Virtuality; }
+  unsigned getVirtualIndex() const { return VirtualIndex; }
+  unsigned getScopeLine() const { return ScopeLine; }
+  unsigned getFlags() const { return Flags; }
+  bool isLocalToUnit() const { return IsLocalToUnit; }
+  bool isDefinition() const { return IsDefinition; }
+  bool isOptimized() const { return IsOptimized; }
+
+  Metadata *getScope() const { return getOperand(1); }
+
+  StringRef getName() const { return getStringOperand(2); }
+  StringRef getDisplayName() const { return getStringOperand(3); }
+  StringRef getLinkageName() const { return getStringOperand(4); }
+
+  Metadata *getType() const { return getOperand(5); }
+  Metadata *getContainingType() const { return getOperand(6); }
+
+  Metadata *getFunction() const { return getOperand(7); }
+  Metadata *getTemplateParams() const { return getOperand(8); }
+  Metadata *getDeclaration() const { return getOperand(9); }
+  Metadata *getVariables() const { return getOperand(10); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDSubprogramKind;
+  }
+};
+
+class MDLexicalBlockBase : public MDScope {
+protected:
+  MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage,
+                     ArrayRef<Metadata *> Ops)
+      : MDScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {}
+  ~MDLexicalBlockBase() {}
+
+public:
+  Metadata *getScope() const { return getOperand(1); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDLexicalBlockKind ||
+           MD->getMetadataID() == MDLexicalBlockFileKind;
+  }
+};
+
+class MDLexicalBlock : public MDLexicalBlockBase {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Line;
+  unsigned Column;
+
+  MDLexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line,
+                 unsigned Column, ArrayRef<Metadata *> Ops)
+      : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line),
+        Column(Column) {}
+  ~MDLexicalBlock() {}
+
+  static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope,
+                                 Metadata *File, unsigned Line, unsigned Column,
+                                 StorageType Storage, bool ShouldCreate = true);
+
+  TempMDLexicalBlock cloneImpl() const {
+    return getTemporary(getContext(), getScope(), getFile(), getLine(),
+                        getColumn());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File,
+                                     unsigned Line, unsigned Column),
+                    (Scope, File, Line, Column))
+
+  TempMDLexicalBlock clone() const { return cloneImpl(); }
+
+  unsigned getLine() const { return Line; }
+  unsigned getColumn() const { return Column; }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDLexicalBlockKind;
+  }
+};
+
+class MDLexicalBlockFile : public MDLexicalBlockBase {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Discriminator;
+
+  MDLexicalBlockFile(LLVMContext &C, StorageType Storage,
+                     unsigned Discriminator, ArrayRef<Metadata *> Ops)
+      : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops),
+        Discriminator(Discriminator) {}
+  ~MDLexicalBlockFile() {}
+
+  static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope,
+                                     Metadata *File, unsigned Discriminator,
+                                     StorageType Storage,
+                                     bool ShouldCreate = true);
+
+  TempMDLexicalBlockFile cloneImpl() const {
+    return getTemporary(getContext(), getScope(), getFile(),
+                        getDiscriminator());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDLexicalBlockFile,
+                    (Metadata * Scope, Metadata *File, unsigned Discriminator),
+                    (Scope, File, Discriminator))
+
+  TempMDLexicalBlockFile clone() const { return cloneImpl(); }
+
+  unsigned getDiscriminator() const { return Discriminator; }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDLexicalBlockFileKind;
+  }
+};
+
+class MDNamespace : public MDScope {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Line;
+
+  MDNamespace(LLVMContext &Context, StorageType Storage, unsigned Line,
+              ArrayRef<Metadata *> Ops)
+      : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace,
+                Ops),
+        Line(Line) {}
+  ~MDNamespace() {}
+
+  static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope,
+                              Metadata *File, StringRef Name, unsigned Line,
+                              StorageType Storage, bool ShouldCreate = true) {
+    return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name),
+                   Line, Storage, ShouldCreate);
+  }
+  static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope,
+                              Metadata *File, MDString *Name, unsigned Line,
+                              StorageType Storage, bool ShouldCreate = true);
+
+  TempMDNamespace cloneImpl() const {
+    return getTemporary(getContext(), getScope(), getFile(), getName(),
+                        getLine());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File,
+                                  StringRef Name, unsigned Line),
+                    (Scope, File, Name, Line))
+  DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File,
+                                  MDString *Name, unsigned Line),
+                    (Scope, File, Name, Line))
+
+  TempMDNamespace clone() const { return cloneImpl(); }
+
+  unsigned getLine() const { return Line; }
+  Metadata *getScope() const { return getOperand(1); }
+  StringRef getName() const { return getStringOperand(2); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDNamespaceKind;
+  }
+};
+
+/// \brief Base class for template parameters.
+///
+/// TODO: Remove the scope.  It's always the compile unit, and never
+/// referenced.
+/// TODO: Remove File, Line and Column.  They're always 0 and never
+/// referenced.
+class MDTemplateParameter : public DebugNode {
+  unsigned Line;
+  unsigned Column;
+
+protected:
+  MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,
+                      unsigned Tag, unsigned Line, unsigned Column,
+                      ArrayRef<Metadata *> Ops)
+      : DebugNode(Context, ID, Storage, Tag, Ops), Line(Line), Column(Column) {}
+  ~MDTemplateParameter() {}
+
+public:
+  unsigned getLine() const { return Line; }
+  unsigned getColumn() const { return Column; }
+
+  Metadata *getFile() const { return getOperand(0); }
+  Metadata *getScope() const { return getOperand(1); }
+  StringRef getName() const { return getStringOperand(2); }
+  Metadata *getType() const { return getOperand(3); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDTemplateTypeParameterKind ||
+           MD->getMetadataID() == MDTemplateValueParameterKind;
+  }
+};
+
+class MDTemplateTypeParameter : public MDTemplateParameter {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDTemplateTypeParameter(LLVMContext &Context, StorageType Storage,
+                          unsigned Line, unsigned Column,
+                          ArrayRef<Metadata *> Ops)
+      : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage,
+                            dwarf::DW_TAG_template_type_parameter, Line, Column,
+                            Ops) {}
+  ~MDTemplateTypeParameter() {}
+
+  static MDTemplateTypeParameter *getImpl(LLVMContext &Context, Metadata *Scope,
+                                          StringRef Name, Metadata *Type,
+                                          Metadata *File, unsigned Line,
+                                          unsigned Column, StorageType Storage,
+                                          bool ShouldCreate = true) {
+    return getImpl(Context, Scope, getCanonicalMDString(Context, Name), Type,
+                   File, Line, Column, Storage, ShouldCreate);
+  }
+  static MDTemplateTypeParameter *getImpl(LLVMContext &Context, Metadata *Scope,
+                                          MDString *Name, Metadata *Type,
+                                          Metadata *File, unsigned Line,
+                                          unsigned Column, StorageType Storage,
+                                          bool ShouldCreate = true);
+
+  TempMDTemplateTypeParameter cloneImpl() const {
+    return getTemporary(getContext(), getScope(), getName(), getType(),
+                        getFile(), getLine(), getColumn());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDTemplateTypeParameter,
+                    (Metadata * Scope, StringRef Name, Metadata *Type,
+                     Metadata *File = nullptr, unsigned Line = 0,
+                     unsigned Column = 0),
+                    (Scope, Name, Type, File, Line, Column))
+  DEFINE_MDNODE_GET(MDTemplateTypeParameter,
+                    (Metadata * Scope, MDString *Name, Metadata *Type,
+                     Metadata *File = nullptr, unsigned Line = 0,
+                     unsigned Column = 0),
+                    (Scope, Name, Type, File, Line, Column))
+
+  TempMDTemplateTypeParameter clone() const { return cloneImpl(); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDTemplateTypeParameterKind;
+  }
+};
+
+class MDTemplateValueParameter : public MDTemplateParameter {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDTemplateValueParameter(LLVMContext &Context, StorageType Storage,
+                           unsigned Tag, unsigned Line, unsigned Column,
+                           ArrayRef<Metadata *> Ops)
+      : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag,
+                            Line, Column, Ops) {}
+  ~MDTemplateValueParameter() {}
+
+  static MDTemplateValueParameter *
+  getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, StringRef Name,
+          Metadata *Type, Metadata *Value, Metadata *File, unsigned Line,
+          unsigned Column, StorageType Storage, bool ShouldCreate = true) {
+    return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name),
+                   Type, Value, File, Line, Column, Storage, ShouldCreate);
+  }
+  static MDTemplateValueParameter *
+  getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name,
+          Metadata *Type, Metadata *Value, Metadata *File, unsigned Line,
+          unsigned Column, StorageType Storage, bool ShouldCreate = true);
+
+  TempMDTemplateValueParameter cloneImpl() const {
+    return getTemporary(getContext(), getTag(), getScope(), getName(),
+                        getType(), getValue(), getFile(), getLine(),
+                        getColumn());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDTemplateValueParameter,
+                    (unsigned Tag, Metadata *Scope, StringRef Name,
+                     Metadata *Type, Metadata *Value, Metadata *File = nullptr,
+                     unsigned Line = 0, unsigned Column = 0),
+                    (Tag, Scope, Name, Type, Value, File, Line, Column))
+  DEFINE_MDNODE_GET(MDTemplateValueParameter,
+                    (unsigned Tag, Metadata *Scope, MDString *Name,
+                     Metadata *Type, Metadata *Value, Metadata *File = nullptr,
+                     unsigned Line = 0, unsigned Column = 0),
+                    (Tag, Scope, Name, Type, Value, File, Line, Column))
+
+  Metadata *getValue() const { return getOperand(4); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDTemplateValueParameterKind;
+  }
+};
+
+/// \brief Base class for variables.
+///
+/// TODO: Hardcode to DW_TAG_variable.
+class MDVariable : public DebugNode {
+  unsigned Line;
+
+protected:
+  MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+             unsigned Line, ArrayRef<Metadata *> Ops)
+      : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {}
+  ~MDVariable() {}
+
+public:
+  unsigned getLine() const { return Line; }
+  Metadata *getScope() const { return getOperand(0); }
+  StringRef getName() const { return getStringOperand(1); }
+  Metadata *getFile() const { return getOperand(2); }
+  Metadata *getType() const { return getOperand(3); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDLocalVariableKind ||
+           MD->getMetadataID() == MDGlobalVariableKind;
+  }
+};
+
+/// \brief Global variables.
+///
+/// TODO: Remove DisplayName.  It's always equal to Name.
+class MDGlobalVariable : public MDVariable {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  bool IsLocalToUnit;
+  bool IsDefinition;
+
+  MDGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line,
+                   bool IsLocalToUnit, bool IsDefinition,
+                   ArrayRef<Metadata *> Ops)
+      : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable,
+                   Line, Ops),
+        IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {}
+  ~MDGlobalVariable() {}
+
+  static MDGlobalVariable *
+  getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name,
+          StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+          bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+          Metadata *StaticDataMemberDeclaration, StorageType Storage,
+          bool ShouldCreate = true) {
+    return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
+                   getCanonicalMDString(Context, LinkageName), File, Line, Type,
+                   IsLocalToUnit, IsDefinition, Variable,
+                   StaticDataMemberDeclaration, Storage, ShouldCreate);
+  }
+  static MDGlobalVariable *
+  getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
+          MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+          bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+          Metadata *StaticDataMemberDeclaration, StorageType Storage,
+          bool ShouldCreate = true);
+
+  TempMDGlobalVariable cloneImpl() const {
+    return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
+                        getFile(), getLine(), getType(), isLocalToUnit(),
+                        isDefinition(), getVariable(),
+                        getStaticDataMemberDeclaration());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDGlobalVariable,
+                    (Metadata * Scope, StringRef Name, StringRef LinkageName,
+                     Metadata *File, unsigned Line, Metadata *Type,
+                     bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+                     Metadata *StaticDataMemberDeclaration),
+                    (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+                     IsDefinition, Variable, StaticDataMemberDeclaration))
+  DEFINE_MDNODE_GET(MDGlobalVariable,
+                    (Metadata * Scope, MDString *Name, MDString *LinkageName,
+                     Metadata *File, unsigned Line, Metadata *Type,
+                     bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+                     Metadata *StaticDataMemberDeclaration),
+                    (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+                     IsDefinition, Variable, StaticDataMemberDeclaration))
+
+  bool isLocalToUnit() const { return IsLocalToUnit; }
+  bool isDefinition() const { return IsDefinition; }
+  StringRef getDisplayName() const { return getStringOperand(4); }
+  StringRef getLinkageName() const { return getStringOperand(5); }
+  Metadata *getVariable() const { return getOperand(6); }
+  Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDGlobalVariableKind;
+  }
+};
+
+/// \brief Local variable.
+///
+/// TODO: Split between arguments and otherwise.
+/// TODO: Use \c DW_TAG_variable instead of fake tags.
+/// TODO: Split up flags.
+class MDLocalVariable : public MDVariable {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Arg;
+  unsigned Flags;
+
+  MDLocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag,
+                  unsigned Line, unsigned Arg, unsigned Flags,
+                  ArrayRef<Metadata *> Ops)
+      : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg),
+        Flags(Flags) {}
+  ~MDLocalVariable() {}
+
+  static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag,
+                                  Metadata *Scope, StringRef Name,
+                                  Metadata *File, unsigned Line, Metadata *Type,
+                                  unsigned Arg, unsigned Flags,
+                                  Metadata *InlinedAt, StorageType Storage,
+                                  bool ShouldCreate = true) {
+    return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name),
+                   File, Line, Type, Arg, Flags, InlinedAt, Storage,
+                   ShouldCreate);
+  }
+  static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag,
+                                  Metadata *Scope, MDString *Name,
+                                  Metadata *File, unsigned Line, Metadata *Type,
+                                  unsigned Arg, unsigned Flags,
+                                  Metadata *InlinedAt, StorageType Storage,
+                                  bool ShouldCreate = true);
+
+  TempMDLocalVariable cloneImpl() const {
+    return getTemporary(getContext(), getTag(), getScope(), getName(),
+                        getFile(), getLine(), getType(), getArg(), getFlags(),
+                        getInlinedAt());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDLocalVariable,
+                    (unsigned Tag, Metadata *Scope, StringRef Name,
+                     Metadata *File, unsigned Line, Metadata *Type,
+                     unsigned Arg, unsigned Flags,
+                     Metadata *InlinedAt = nullptr),
+                    (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt))
+  DEFINE_MDNODE_GET(MDLocalVariable,
+                    (unsigned Tag, Metadata *Scope, MDString *Name,
+                     Metadata *File, unsigned Line, Metadata *Type,
+                     unsigned Arg, unsigned Flags,
+                     Metadata *InlinedAt = nullptr),
+                    (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt))
+
+  unsigned getArg() const { return Arg; }
+  unsigned getFlags() const { return Flags; }
+  Metadata *getInlinedAt() const { return getOperand(4); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDLocalVariableKind;
+  }
+};
+
+/// \brief DWARF expression.
+///
+/// TODO: Co-allocate the expression elements.
+/// TODO: Drop fake DW_TAG_expression and separate from DebugNode.
+/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
+/// storage types.
+class MDExpression : public DebugNode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  std::vector<uint64_t> Elements;
+
+  MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements)
+      : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None),
+        Elements(Elements.begin(), Elements.end()) {}
+  ~MDExpression() {}
+
+  static MDExpression *getImpl(LLVMContext &Context,
+                               ArrayRef<uint64_t> Elements, StorageType Storage,
+                               bool ShouldCreate = true);
+
+  TempMDExpression cloneImpl() const {
+    return getTemporary(getContext(), getElements());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDExpression, (ArrayRef<uint64_t> Elements), (Elements))
+
+  ArrayRef<uint64_t> getElements() const { return Elements; }
+
+  typedef ArrayRef<uint64_t>::iterator element_iterator;
+  element_iterator elements_begin() const { return getElements().begin(); }
+  element_iterator elements_end() const { return getElements().end(); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDExpressionKind;
+  }
+};
+
+class MDObjCProperty : public DebugNode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Line;
+  unsigned Attributes;
+
+  MDObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line,
+                 unsigned Attributes, ArrayRef<Metadata *> Ops)
+      : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property,
+                  Ops),
+        Line(Line), Attributes(Attributes) {}
+  ~MDObjCProperty() {}
+
+  static MDObjCProperty *
+  getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line,
+          StringRef GetterName, StringRef SetterName, unsigned Attributes,
+          Metadata *Type, StorageType Storage, bool ShouldCreate = true) {
+    return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
+                   getCanonicalMDString(Context, GetterName),
+                   getCanonicalMDString(Context, SetterName), Attributes, Type,
+                   Storage, ShouldCreate);
+  }
+  static MDObjCProperty *getImpl(LLVMContext &Context, MDString *Name,
+                                 Metadata *File, unsigned Line,
+                                 MDString *GetterName, MDString *SetterName,
+                                 unsigned Attributes, Metadata *Type,
+                                 StorageType Storage, bool ShouldCreate = true);
+
+  TempMDObjCProperty cloneImpl() const {
+    return getTemporary(getContext(), getName(), getFile(), getLine(),
+                        getGetterName(), getSetterName(), getAttributes(),
+                        getType());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDObjCProperty,
+                    (StringRef Name, Metadata *File, unsigned Line,
+                     StringRef GetterName, StringRef SetterName,
+                     unsigned Attributes, Metadata *Type),
+                    (Name, File, Line, GetterName, SetterName, Attributes,
+                     Type))
+  DEFINE_MDNODE_GET(MDObjCProperty,
+                    (MDString * Name, Metadata *File, unsigned Line,
+                     MDString *GetterName, MDString *SetterName,
+                     unsigned Attributes, Metadata *Type),
+                    (Name, File, Line, GetterName, SetterName, Attributes,
+                     Type))
+
+  unsigned getLine() const { return Line; }
+  unsigned getAttributes() const { return Attributes; }
+  StringRef getName() const { return getStringOperand(0); }
+  Metadata *getFile() const { return getOperand(1); }
+  StringRef getGetterName() const { return getStringOperand(2); }
+  StringRef getSetterName() const { return getStringOperand(3); }
+  Metadata *getType() const { return getOperand(4); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDObjCPropertyKind;
+  }
+};
+
+class MDImportedEntity : public DebugNode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Line;
+
+  MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag,
+                   unsigned Line, ArrayRef<Metadata *> Ops)
+      : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {}
+  ~MDImportedEntity() {}
+
+  static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
+                                   Metadata *Scope, Metadata *Entity,
+                                   unsigned Line, StringRef Name,
+                                   StorageType Storage,
+                                   bool ShouldCreate = true) {
+    return getImpl(Context, Tag, Scope, Entity, Line,
+                   getCanonicalMDString(Context, Name), Storage, ShouldCreate);
+  }
+  static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
+                                   Metadata *Scope, Metadata *Entity,
+                                   unsigned Line, MDString *Name,
+                                   StorageType Storage,
+                                   bool ShouldCreate = true);
+
+  TempMDImportedEntity cloneImpl() const {
+    return getTemporary(getContext(), getTag(), getScope(), getEntity(),
+                        getLine(), getName());
+  }
+
+public:
+  DEFINE_MDNODE_GET(MDImportedEntity,
+                    (unsigned Tag, Metadata *Scope, Metadata *Entity,
+                     unsigned Line, StringRef Name = ""),
+                    (Tag, Scope, Entity, Line, Name))
+  DEFINE_MDNODE_GET(MDImportedEntity,
+                    (unsigned Tag, Metadata *Scope, Metadata *Entity,
+                     unsigned Line, MDString *Name),
+                    (Tag, Scope, Entity, Line, Name))
+
+  TempMDImportedEntity clone() const { return cloneImpl(); }
+
+  unsigned getLine() const { return Line; }
+  Metadata *getScope() const { return getOperand(0); }
+  Metadata *getEntity() const { return getOperand(1); }
+  StringRef getName() const { return getStringOperand(2); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDImportedEntityKind;
+  }
+};
+
 } // end namespace llvm
 
 #undef DEFINE_MDNODE_GET_UNPACK_IMPL
index 7ff8fa990d8a267e8f1ad984cb3125d2429ca827..ca72e2618f4e26ebe77ecbb7ff595331fbb4fb6e 100644 (file)
@@ -51,6 +51,32 @@ HANDLE_MDNODE_LEAF(MDTuple)
 HANDLE_MDNODE_LEAF(MDLocation)
 HANDLE_MDNODE_BRANCH(DebugNode)
 HANDLE_MDNODE_LEAF(GenericDebugNode)
+HANDLE_MDNODE_LEAF(MDSubrange)
+HANDLE_MDNODE_LEAF(MDEnumerator)
+HANDLE_MDNODE_BRANCH(MDScope)
+HANDLE_MDNODE_BRANCH(MDType)
+HANDLE_MDNODE_LEAF(MDBasicType)
+HANDLE_MDNODE_BRANCH(MDDerivedTypeBase)
+HANDLE_MDNODE_LEAF(MDDerivedType)
+HANDLE_MDNODE_BRANCH(MDCompositeTypeBase)
+HANDLE_MDNODE_LEAF(MDCompositeType)
+HANDLE_MDNODE_LEAF(MDSubroutineType)
+HANDLE_MDNODE_LEAF(MDFile)
+HANDLE_MDNODE_LEAF(MDCompileUnit)
+HANDLE_MDNODE_LEAF(MDSubprogram)
+HANDLE_MDNODE_BRANCH(MDLexicalBlockBase)
+HANDLE_MDNODE_LEAF(MDLexicalBlock)
+HANDLE_MDNODE_LEAF(MDLexicalBlockFile)
+HANDLE_MDNODE_LEAF(MDNamespace)
+HANDLE_MDNODE_BRANCH(MDTemplateParameter)
+HANDLE_MDNODE_LEAF(MDTemplateTypeParameter)
+HANDLE_MDNODE_LEAF(MDTemplateValueParameter)
+HANDLE_MDNODE_BRANCH(MDVariable)
+HANDLE_MDNODE_LEAF(MDGlobalVariable)
+HANDLE_MDNODE_LEAF(MDLocalVariable)
+HANDLE_MDNODE_LEAF(MDExpression)
+HANDLE_MDNODE_LEAF(MDObjCProperty)
+HANDLE_MDNODE_LEAF(MDImportedEntity)
 
 #undef HANDLE_METADATA
 #undef HANDLE_METADATA_LEAF
index da6d5cb5e7ccf0130b8f3ce172bc362ce041fc99..5ccfc113ac290d3cecc08af7ee66d333c9d561f1 100644 (file)
@@ -62,6 +62,25 @@ public:
     MDTupleKind,
     MDLocationKind,
     GenericDebugNodeKind,
+    MDSubrangeKind,
+    MDEnumeratorKind,
+    MDBasicTypeKind,
+    MDDerivedTypeKind,
+    MDCompositeTypeKind,
+    MDSubroutineTypeKind,
+    MDFileKind,
+    MDCompileUnitKind,
+    MDSubprogramKind,
+    MDLexicalBlockKind,
+    MDLexicalBlockFileKind,
+    MDNamespaceKind,
+    MDTemplateTypeParameterKind,
+    MDTemplateValueParameterKind,
+    MDGlobalVariableKind,
+    MDLocalVariableKind,
+    MDExpressionKind,
+    MDObjCPropertyKind,
+    MDImportedEntityKind,
     ConstantAsMetadataKind,
     LocalAsMetadataKind,
     MDStringKind
@@ -865,9 +884,14 @@ public:
 
   /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const Metadata *MD) {
-    return MD->getMetadataID() == MDTupleKind ||
-           MD->getMetadataID() == MDLocationKind ||
-           MD->getMetadataID() == GenericDebugNodeKind;
+    switch (MD->getMetadataID()) {
+    default:
+      return false;
+#define HANDLE_MDNODE_LEAF(CLASS)                                              \
+  case CLASS##Kind:                                                            \
+    return true;
+#include "llvm/IR/Metadata.def"
+    }
   }
 
   /// \brief Check whether MDNode is a vtable access.
index 6f8c26069a67b1c2a6c215733b5231d571f2ecf0..1c2424ce11bc718211d5da80968253d8d5904546 100644 (file)
@@ -809,6 +809,106 @@ static void WriteGenericDebugNode(const GenericDebugNode *N,
   Record.clear();
 }
 
+static void WriteMDSubrange(const MDSubrange *, const ValueEnumerator &,
+                            BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                            unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDEnumerator(const MDEnumerator *, const ValueEnumerator &,
+                              BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                              unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDBasicType(const MDBasicType *, const ValueEnumerator &,
+                             BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                             unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDDerivedType(const MDDerivedType *, const ValueEnumerator &,
+                               BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                               unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDCompositeType(const MDCompositeType *,
+                                 const ValueEnumerator &, BitstreamWriter &,
+                                 SmallVectorImpl<uint64_t> &, unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDSubroutineType(const MDSubroutineType *,
+                                  const ValueEnumerator &, BitstreamWriter &,
+                                  SmallVectorImpl<uint64_t> &, unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDFile(const MDFile *, const ValueEnumerator &,
+                        BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                        unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDCompileUnit(const MDCompileUnit *, const ValueEnumerator &,
+                               BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                               unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDSubprogram(const MDSubprogram *, const ValueEnumerator &,
+                              BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                              unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDLexicalBlock(const MDLexicalBlock *, const ValueEnumerator &,
+                                BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                                unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDLexicalBlockFile(const MDLexicalBlockFile *,
+                                    const ValueEnumerator &, BitstreamWriter &,
+                                    SmallVectorImpl<uint64_t> &, unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDNamespace(const MDNamespace *, const ValueEnumerator &,
+                             BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                             unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDTemplateTypeParameter(const MDTemplateTypeParameter *,
+                                         const ValueEnumerator &,
+                                         BitstreamWriter &,
+                                         SmallVectorImpl<uint64_t> &,
+                                         unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDTemplateValueParameter(const MDTemplateValueParameter *,
+                                          const ValueEnumerator &,
+                                          BitstreamWriter &,
+                                          SmallVectorImpl<uint64_t> &,
+                                          unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDGlobalVariable(const MDGlobalVariable *,
+                                  const ValueEnumerator &, BitstreamWriter &,
+                                  SmallVectorImpl<uint64_t> &, unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDLocalVariable(const MDLocalVariable *,
+                                 const ValueEnumerator &, BitstreamWriter &,
+                                 SmallVectorImpl<uint64_t> &, unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDExpression(const MDExpression *, const ValueEnumerator &,
+                              BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                              unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDObjCProperty(const MDObjCProperty *, const ValueEnumerator &,
+                                BitstreamWriter &, SmallVectorImpl<uint64_t> &,
+                                unsigned) {
+  llvm_unreachable("write not implemented");
+}
+static void WriteMDImportedEntity(const MDImportedEntity *,
+                                  const ValueEnumerator &, BitstreamWriter &,
+                                  SmallVectorImpl<uint64_t> &, unsigned) {
+  llvm_unreachable("write not implemented");
+}
+
 static void WriteModuleMetadata(const Module *M,
                                 const ValueEnumerator &VE,
                                 BitstreamWriter &Stream) {
index 43ae3feb36390f97dc24ac47716684bc789f8db3..d1beb166a184559b79345a81ac3eed32363398f8 100644 (file)
@@ -1347,6 +1347,93 @@ static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
   Out << ")";
 }
 
+static void writeMDSubrange(raw_ostream &, const MDSubrange *, TypePrinting *,
+                            SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDEnumerator(raw_ostream &, const MDEnumerator *,
+                              TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDBasicType(raw_ostream &, const MDBasicType *, TypePrinting *,
+                             SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDDerivedType(raw_ostream &, const MDDerivedType *,
+                               TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDCompositeType(raw_ostream &, const MDCompositeType *,
+                                 TypePrinting *, SlotTracker *,
+                                 const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDSubroutineType(raw_ostream &, const MDSubroutineType *,
+                                  TypePrinting *, SlotTracker *,
+                                  const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDFile(raw_ostream &, const MDFile *, TypePrinting *,
+                        SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDCompileUnit(raw_ostream &, const MDCompileUnit *,
+                               TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDSubprogram(raw_ostream &, const MDSubprogram *,
+                              TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDLexicalBlock(raw_ostream &, const MDLexicalBlock *,
+                                TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDLexicalBlockFile(raw_ostream &, const MDLexicalBlockFile *,
+                                    TypePrinting *, SlotTracker *,
+                                    const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDNamespace(raw_ostream &, const MDNamespace *, TypePrinting *,
+                             SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDTemplateTypeParameter(raw_ostream &,
+                                         const MDTemplateTypeParameter *,
+                                         TypePrinting *, SlotTracker *,
+                                         const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDTemplateValueParameter(raw_ostream &,
+                                          const MDTemplateValueParameter *,
+                                          TypePrinting *, SlotTracker *,
+                                          const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDGlobalVariable(raw_ostream &, const MDGlobalVariable *,
+                                  TypePrinting *, SlotTracker *,
+                                  const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDLocalVariable(raw_ostream &, const MDLocalVariable *,
+                                 TypePrinting *, SlotTracker *,
+                                 const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDExpression(raw_ostream &, const MDExpression *,
+                              TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDObjCProperty(raw_ostream &, const MDObjCProperty *,
+                                TypePrinting *, SlotTracker *, const Module *) {
+  llvm_unreachable("write not implemented");
+}
+static void writeMDImportedEntity(raw_ostream &, const MDImportedEntity *,
+                                  TypePrinting *, SlotTracker *,
+                                  const Module *) {
+  llvm_unreachable("write not implemented");
+}
+
 static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
                                     TypePrinting *TypePrinter,
                                     SlotTracker *Machine,
index c540cc45a61a18cb4fd50c26f6e1a2c8835940f8..68f6bf843d813fcd931880e6f1f3b07a32c41dfb 100644 (file)
@@ -103,3 +103,274 @@ GenericDebugNode *GenericDebugNode::getImpl(LLVMContext &Context, unsigned Tag,
 void GenericDebugNode::recalculateHash() {
   setHash(GenericDebugNodeInfo::KeyTy::calculateHash(this));
 }
+
+#define UNWRAP_ARGS_IMPL(...) __VA_ARGS__
+#define UNWRAP_ARGS(ARGS) UNWRAP_ARGS_IMPL ARGS
+#define DEFINE_GETIMPL_LOOKUP(CLASS, ARGS)                                     \
+  do {                                                                         \
+    if (Storage == Uniqued) {                                                  \
+      if (auto *N = getUniqued(Context.pImpl->CLASS##s,                        \
+                               CLASS##Info::KeyTy(UNWRAP_ARGS(ARGS))))         \
+        return N;                                                              \
+      if (!ShouldCreate)                                                       \
+        return nullptr;                                                        \
+    } else {                                                                   \
+      assert(ShouldCreate &&                                                   \
+             "Expected non-uniqued nodes to always be created");               \
+    }                                                                          \
+  } while (false)
+#define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS)                                 \
+  return storeImpl(new (ArrayRef<Metadata *>(OPS).size())                      \
+                       CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS),        \
+                   Storage, Context.pImpl->CLASS##s)
+#define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS)                               \
+  return storeImpl(new (0u) CLASS(Context, Storage, UNWRAP_ARGS(ARGS)),        \
+                   Storage, Context.pImpl->CLASS##s)
+
+MDSubrange *MDSubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
+                                StorageType Storage, bool ShouldCreate) {
+  DEFINE_GETIMPL_LOOKUP(MDSubrange, (Count, Lo));
+  DEFINE_GETIMPL_STORE_NO_OPS(MDSubrange, (Count, Lo));
+}
+
+MDEnumerator *MDEnumerator::getImpl(LLVMContext &Context, int64_t Value,
+                                    MDString *Name, StorageType Storage,
+                                    bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDEnumerator, (Value, getString(Name)));
+  Metadata *Ops[] = {Name};
+  DEFINE_GETIMPL_STORE(MDEnumerator, (Value), Ops);
+}
+
+MDBasicType *MDBasicType::getImpl(LLVMContext &Context, unsigned Tag,
+                                  MDString *Name, unsigned SizeInBits,
+                                  unsigned AlignInBits, unsigned Encoding,
+                                  StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(
+      MDBasicType, (Tag, getString(Name), SizeInBits, AlignInBits, Encoding));
+  Metadata *Ops[] = {nullptr, nullptr, Name};
+  DEFINE_GETIMPL_STORE(MDBasicType, (Tag, SizeInBits, AlignInBits, Encoding),
+                       Ops);
+}
+
+MDDerivedType *MDDerivedType::getImpl(
+    LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
+    unsigned Line, Metadata *Scope, Metadata *BaseType, unsigned SizeInBits,
+    unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
+    Metadata *ExtraData, StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDDerivedType, (Tag, getString(Name), File, Line, Scope,
+                                        BaseType, SizeInBits, AlignInBits,
+                                        OffsetInBits, Flags, ExtraData));
+  Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData};
+  DEFINE_GETIMPL_STORE(
+      MDDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags),
+      Ops);
+}
+
+MDCompositeType *MDCompositeType::getImpl(
+    LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
+    unsigned Line, Metadata *Scope, Metadata *BaseType, unsigned SizeInBits,
+    unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
+    Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
+    Metadata *TemplateParams, MDString *Identifier, StorageType Storage,
+    bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDCompositeType,
+                        (Tag, getString(Name), File, Line, Scope, BaseType,
+                         SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
+                         RuntimeLang, VTableHolder, TemplateParams,
+                         getString(Identifier)));
+  Metadata *Ops[] = {File,     Scope,        Name,           BaseType,
+                     Elements, VTableHolder, TemplateParams, Identifier};
+  DEFINE_GETIMPL_STORE(MDCompositeType, (Tag, Line, RuntimeLang, SizeInBits,
+                                         AlignInBits, OffsetInBits, Flags),
+                       Ops);
+}
+
+MDSubroutineType *MDSubroutineType::getImpl(LLVMContext &Context,
+                                            unsigned Flags, Metadata *TypeArray,
+                                            StorageType Storage,
+                                            bool ShouldCreate) {
+  DEFINE_GETIMPL_LOOKUP(MDSubroutineType, (Flags, TypeArray));
+  Metadata *Ops[] = {nullptr,   nullptr, nullptr, nullptr,
+                     TypeArray, nullptr, nullptr};
+  DEFINE_GETIMPL_STORE(MDSubroutineType, (Flags), Ops);
+}
+
+MDFile *MDFile::getImpl(LLVMContext &Context, MDString *Filename,
+                        MDString *Directory, StorageType Storage,
+                        bool ShouldCreate) {
+  assert(isCanonical(Filename) && "Expected canonical MDString");
+  assert(isCanonical(Directory) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDFile, (getString(Filename), getString(Directory)));
+  Metadata *NodeOps[] = {Filename, Directory};
+  Metadata *Ops[] = {MDTuple::get(Context, NodeOps)};
+  return storeImpl(new (ArrayRef<Metadata *>(Ops).size())
+                       MDFile(Context, Storage, Ops),
+                   Storage, Context.pImpl->MDFiles);
+}
+
+MDCompileUnit *MDCompileUnit::getImpl(
+    LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
+    MDString *Producer, bool IsOptimized, MDString *Flags,
+    unsigned RuntimeVersion, MDString *SplitDebugFilename,
+    unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
+    Metadata *Subprograms, Metadata *GlobalVariables,
+    Metadata *ImportedEntities, StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Producer) && "Expected canonical MDString");
+  assert(isCanonical(Flags) && "Expected canonical MDString");
+  assert(isCanonical(SplitDebugFilename) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(
+      MDCompileUnit,
+      (SourceLanguage, File, getString(Producer), IsOptimized, getString(Flags),
+       RuntimeVersion, getString(SplitDebugFilename), EmissionKind, EnumTypes,
+       RetainedTypes, Subprograms, GlobalVariables, ImportedEntities));
+  Metadata *Ops[] = {File, Producer, Flags, SplitDebugFilename, EnumTypes,
+                     RetainedTypes, Subprograms, GlobalVariables,
+                     ImportedEntities};
+  DEFINE_GETIMPL_STORE(
+      MDCompileUnit,
+      (SourceLanguage, IsOptimized, RuntimeVersion, EmissionKind), Ops);
+}
+
+MDSubprogram *MDSubprogram::getImpl(
+    LLVMContext &Context, Metadata *Scope, MDString *Name,
+    MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+    bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+    Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
+    unsigned Flags, bool IsOptimized, Metadata *Function,
+    Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+    StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  assert(isCanonical(LinkageName) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDSubprogram,
+                        (Scope, getString(Name), getString(LinkageName), File,
+                         Line, Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                         ContainingType, Virtuality, VirtualIndex, Flags,
+                         IsOptimized, Function, TemplateParams, Declaration,
+                         Variables));
+  Metadata *Ops[] = {File,           Scope,       Name,           Name,
+                     LinkageName,    Type,        ContainingType, Function,
+                     TemplateParams, Declaration, Variables};
+  DEFINE_GETIMPL_STORE(MDSubprogram,
+                       (Line, ScopeLine, Virtuality, VirtualIndex, Flags,
+                        IsLocalToUnit, IsDefinition, IsOptimized),
+                       Ops);
+}
+
+MDLexicalBlock *MDLexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope,
+                                        Metadata *File, unsigned Line,
+                                        unsigned Column, StorageType Storage,
+                                        bool ShouldCreate) {
+  DEFINE_GETIMPL_LOOKUP(MDLexicalBlock, (Scope, File, Line, Column));
+  Metadata *Ops[] = {File, Scope};
+  DEFINE_GETIMPL_STORE(MDLexicalBlock, (Line, Column), Ops);
+}
+
+MDLexicalBlockFile *MDLexicalBlockFile::getImpl(LLVMContext &Context,
+                                                Metadata *Scope, Metadata *File,
+                                                unsigned Discriminator,
+                                                StorageType Storage,
+                                                bool ShouldCreate) {
+  DEFINE_GETIMPL_LOOKUP(MDLexicalBlockFile, (Scope, File, Discriminator));
+  Metadata *Ops[] = {File, Scope};
+  DEFINE_GETIMPL_STORE(MDLexicalBlockFile, (Discriminator), Ops);
+}
+
+MDNamespace *MDNamespace::getImpl(LLVMContext &Context, Metadata *Scope,
+                                  Metadata *File, MDString *Name, unsigned Line,
+                                  StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDNamespace, (Scope, File, getString(Name), Line));
+  Metadata *Ops[] = {File, Scope, Name};
+  DEFINE_GETIMPL_STORE(MDNamespace, (Line), Ops);
+}
+
+MDTemplateTypeParameter *
+MDTemplateTypeParameter::getImpl(LLVMContext &Context, Metadata *Scope,
+                                 MDString *Name, Metadata *Type, Metadata *File,
+                                 unsigned Line, unsigned Column,
+                                 StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDTemplateTypeParameter,
+                        (Scope, getString(Name), Type, File, Line, Column));
+  Metadata *Ops[] = {File, Scope, Name, Type};
+  DEFINE_GETIMPL_STORE(MDTemplateTypeParameter, (Line, Column), Ops);
+}
+
+MDTemplateValueParameter *MDTemplateValueParameter::getImpl(
+    LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name,
+    Metadata *Type, Metadata *Value, Metadata *File, unsigned Line,
+    unsigned Column, StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(
+      MDTemplateValueParameter,
+      (Tag, Scope, getString(Name), Type, Value, File, Line, Column));
+  Metadata *Ops[] = {File, Scope, Name, Type, Value};
+  DEFINE_GETIMPL_STORE(MDTemplateValueParameter, (Tag, Line, Column), Ops);
+}
+
+MDGlobalVariable *
+MDGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
+                          MDString *LinkageName, Metadata *File, unsigned Line,
+                          Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
+                          Metadata *Variable,
+                          Metadata *StaticDataMemberDeclaration,
+                          StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  assert(isCanonical(LinkageName) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDGlobalVariable,
+                        (Scope, getString(Name), getString(LinkageName), File,
+                         Line, Type, IsLocalToUnit, IsDefinition, Variable,
+                         StaticDataMemberDeclaration));
+  Metadata *Ops[] = {Scope, Name,        File,     Type,
+                     Name,  LinkageName, Variable, StaticDataMemberDeclaration};
+  DEFINE_GETIMPL_STORE(MDGlobalVariable, (Line, IsLocalToUnit, IsDefinition),
+                       Ops);
+}
+
+MDLocalVariable *MDLocalVariable::getImpl(
+    LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name,
+    Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags,
+    Metadata *InlinedAt, StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDLocalVariable, (Tag, Scope, getString(Name), File,
+                                          Line, Type, Arg, Flags, InlinedAt));
+  Metadata *Ops[] = {Scope, Name, File, Type, InlinedAt};
+  DEFINE_GETIMPL_STORE(MDLocalVariable, (Tag, Line, Arg, Flags), Ops);
+}
+
+MDExpression *MDExpression::getImpl(LLVMContext &Context,
+                                    ArrayRef<uint64_t> Elements,
+                                    StorageType Storage, bool ShouldCreate) {
+  DEFINE_GETIMPL_LOOKUP(MDExpression, (Elements));
+  DEFINE_GETIMPL_STORE_NO_OPS(MDExpression, (Elements));
+}
+
+MDObjCProperty *MDObjCProperty::getImpl(
+    LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,
+    MDString *GetterName, MDString *SetterName, unsigned Attributes,
+    Metadata *Type, StorageType Storage, bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  assert(isCanonical(GetterName) && "Expected canonical MDString");
+  assert(isCanonical(SetterName) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDObjCProperty,
+                        (getString(Name), File, Line, getString(GetterName),
+                         getString(SetterName), Attributes, Type));
+  Metadata *Ops[] = {Name, File, GetterName, SetterName, Type};
+  DEFINE_GETIMPL_STORE(MDObjCProperty, (Line, Attributes), Ops);
+}
+
+MDImportedEntity *MDImportedEntity::getImpl(LLVMContext &Context, unsigned Tag,
+                                            Metadata *Scope, Metadata *Entity,
+                                            unsigned Line, MDString *Name,
+                                            StorageType Storage,
+                                            bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(MDImportedEntity,
+                        (Tag, Scope, Entity, Line, getString(Name)));
+  Metadata *Ops[] = {Scope, Entity, Name};
+  DEFINE_GETIMPL_STORE(MDImportedEntity, (Tag, Line), Ops);
+}
index 3640495dd97aac1f2d631a7a63adc9ed92ce8533..6a3d59289f40ed00e5bd7db1187c7b298b2beb84 100644 (file)
@@ -273,6 +273,581 @@ template <> struct MDNodeKeyImpl<GenericDebugNode> : MDNodeOpsKey {
   }
 };
 
+template <> struct MDNodeKeyImpl<MDSubrange> {
+  int64_t Count;
+  int64_t Lo;
+
+  MDNodeKeyImpl(int64_t Count, int64_t Lo) : Count(Count), Lo(Lo) {}
+  MDNodeKeyImpl(const MDSubrange *N) : Count(N->getCount()), Lo(N->getLo()) {}
+
+  bool isKeyOf(const MDSubrange *RHS) const {
+    return Count == RHS->getCount() && Lo == RHS->getLo();
+  }
+  unsigned getHashValue() const { return hash_combine(Count, Lo); }
+};
+
+template <> struct MDNodeKeyImpl<MDEnumerator> {
+  int64_t Value;
+  StringRef Name;
+
+  MDNodeKeyImpl(int64_t Value, StringRef Name) : Value(Value), Name(Name) {}
+  MDNodeKeyImpl(const MDEnumerator *N)
+      : Value(N->getValue()), Name(N->getName()) {}
+
+  bool isKeyOf(const MDEnumerator *RHS) const {
+    return Value == RHS->getValue() && Name == RHS->getName();
+  }
+  unsigned getHashValue() const { return hash_combine(Value, Name); }
+};
+
+template <> struct MDNodeKeyImpl<MDBasicType> {
+  unsigned Tag;
+  StringRef Name;
+  unsigned SizeInBits;
+  unsigned AlignInBits;
+  unsigned Encoding;
+
+  MDNodeKeyImpl(unsigned Tag, StringRef Name, unsigned SizeInBits,
+                unsigned AlignInBits, unsigned Encoding)
+      : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
+        Encoding(Encoding) {}
+  MDNodeKeyImpl(const MDBasicType *N)
+      : Tag(N->getTag()), Name(N->getName()), SizeInBits(N->getSizeInBits()),
+        AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()) {}
+
+  bool isKeyOf(const MDBasicType *RHS) const {
+    return Tag == RHS->getTag() && Name == RHS->getName() &&
+           SizeInBits == RHS->getSizeInBits() &&
+           AlignInBits == RHS->getAlignInBits() &&
+           Encoding == RHS->getEncoding();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDDerivedType> {
+  unsigned Tag;
+  StringRef Name;
+  Metadata *File;
+  unsigned Line;
+  Metadata *Scope;
+  Metadata *BaseType;
+  unsigned SizeInBits;
+  unsigned AlignInBits;
+  unsigned OffsetInBits;
+  unsigned Flags;
+  Metadata *ExtraData;
+
+  MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *File, unsigned Line,
+                Metadata *Scope, Metadata *BaseType, unsigned SizeInBits,
+                unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
+                Metadata *ExtraData)
+      : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
+        BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
+        OffsetInBits(OffsetInBits), Flags(Flags), ExtraData(ExtraData) {}
+  MDNodeKeyImpl(const MDDerivedType *N)
+      : Tag(N->getTag()), Name(N->getName()), File(N->getFile()),
+        Line(N->getLine()), Scope(N->getScope()), BaseType(N->getBaseType()),
+        SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),
+        OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()),
+        ExtraData(N->getExtraData()) {}
+
+  bool isKeyOf(const MDDerivedType *RHS) const {
+    return Tag == RHS->getTag() && Name == RHS->getName() &&
+           File == RHS->getFile() && Line == RHS->getLine() &&
+           Scope == RHS->getScope() && BaseType == RHS->getBaseType() &&
+           SizeInBits == RHS->getSizeInBits() &&
+           AlignInBits == RHS->getAlignInBits() &&
+           OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&
+           ExtraData == RHS->getExtraData();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                        AlignInBits, OffsetInBits, Flags, ExtraData);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDCompositeType> {
+  unsigned Tag;
+  StringRef Name;
+  Metadata *File;
+  unsigned Line;
+  Metadata *Scope;
+  Metadata *BaseType;
+  unsigned SizeInBits;
+  unsigned AlignInBits;
+  unsigned OffsetInBits;
+  unsigned Flags;
+  Metadata *Elements;
+  unsigned RuntimeLang;
+  Metadata *VTableHolder;
+  Metadata *TemplateParams;
+  StringRef Identifier;
+
+  MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *File, unsigned Line,
+                Metadata *Scope, Metadata *BaseType, unsigned SizeInBits,
+                unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
+                Metadata *Elements, unsigned RuntimeLang,
+                Metadata *VTableHolder, Metadata *TemplateParams,
+                StringRef Identifier)
+      : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
+        BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
+        OffsetInBits(OffsetInBits), Flags(Flags), Elements(Elements),
+        RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
+        TemplateParams(TemplateParams), Identifier(Identifier) {}
+  MDNodeKeyImpl(const MDCompositeType *N)
+      : Tag(N->getTag()), Name(N->getName()), File(N->getFile()),
+        Line(N->getLine()), Scope(N->getScope()), BaseType(N->getBaseType()),
+        SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),
+        OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()),
+        Elements(N->getElements()), RuntimeLang(N->getRuntimeLang()),
+        VTableHolder(N->getVTableHolder()),
+        TemplateParams(N->getTemplateParams()), Identifier(N->getIdentifier()) {
+  }
+
+  bool isKeyOf(const MDCompositeType *RHS) const {
+    return Tag == RHS->getTag() && Name == RHS->getName() &&
+           File == RHS->getFile() && Line == RHS->getLine() &&
+           Scope == RHS->getScope() && BaseType == RHS->getBaseType() &&
+           SizeInBits == RHS->getSizeInBits() &&
+           AlignInBits == RHS->getAlignInBits() &&
+           OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&
+           Elements == RHS->getElements() &&
+           RuntimeLang == RHS->getRuntimeLang() &&
+           VTableHolder == RHS->getVTableHolder() &&
+           TemplateParams == RHS->getTemplateParams() &&
+           Identifier == RHS->getIdentifier();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                        AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+                        VTableHolder, TemplateParams, Identifier);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDSubroutineType> {
+  unsigned Flags;
+  Metadata *TypeArray;
+
+  MDNodeKeyImpl(int64_t Flags, Metadata *TypeArray)
+      : Flags(Flags), TypeArray(TypeArray) {}
+  MDNodeKeyImpl(const MDSubroutineType *N)
+      : Flags(N->getFlags()), TypeArray(N->getTypeArray()) {}
+
+  bool isKeyOf(const MDSubroutineType *RHS) const {
+    return Flags == RHS->getFlags() && TypeArray == RHS->getTypeArray();
+  }
+  unsigned getHashValue() const { return hash_combine(Flags, TypeArray); }
+};
+
+template <> struct MDNodeKeyImpl<MDFile> {
+  StringRef Filename;
+  StringRef Directory;
+
+  MDNodeKeyImpl(StringRef Filename, StringRef Directory)
+      : Filename(Filename), Directory(Directory) {}
+  MDNodeKeyImpl(const MDFile *N)
+      : Filename(N->getFilename()), Directory(N->getDirectory()) {}
+
+  bool isKeyOf(const MDFile *RHS) const {
+    return Filename == RHS->getFilename() && Directory == RHS->getDirectory();
+  }
+  unsigned getHashValue() const { return hash_combine(Filename, Directory); }
+};
+
+template <> struct MDNodeKeyImpl<MDCompileUnit> {
+  unsigned SourceLanguage;
+  Metadata *File;
+  StringRef Producer;
+  bool IsOptimized;
+  StringRef Flags;
+  unsigned RuntimeVersion;
+  StringRef SplitDebugFilename;
+  unsigned EmissionKind;
+  Metadata *EnumTypes;
+  Metadata *RetainedTypes;
+  Metadata *Subprograms;
+  Metadata *GlobalVariables;
+  Metadata *ImportedEntities;
+
+  MDNodeKeyImpl(unsigned SourceLanguage, Metadata *File, StringRef Producer,
+                bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
+                StringRef SplitDebugFilename, unsigned EmissionKind,
+                Metadata *EnumTypes, Metadata *RetainedTypes,
+                Metadata *Subprograms, Metadata *GlobalVariables,
+                Metadata *ImportedEntities)
+      : SourceLanguage(SourceLanguage), File(File), Producer(Producer),
+        IsOptimized(IsOptimized), Flags(Flags), RuntimeVersion(RuntimeVersion),
+        SplitDebugFilename(SplitDebugFilename), EmissionKind(EmissionKind),
+        EnumTypes(EnumTypes), RetainedTypes(RetainedTypes),
+        Subprograms(Subprograms), GlobalVariables(GlobalVariables),
+        ImportedEntities(ImportedEntities) {}
+  MDNodeKeyImpl(const MDCompileUnit *N)
+      : SourceLanguage(N->getSourceLanguage()), File(N->getFile()),
+        Producer(N->getProducer()), IsOptimized(N->isOptimized()),
+        Flags(N->getFlags()), RuntimeVersion(N->getRuntimeVersion()),
+        SplitDebugFilename(N->getSplitDebugFilename()),
+        EmissionKind(N->getEmissionKind()), EnumTypes(N->getEnumTypes()),
+        RetainedTypes(N->getRetainedTypes()), Subprograms(N->getSubprograms()),
+        GlobalVariables(N->getGlobalVariables()),
+        ImportedEntities(N->getImportedEntities()) {}
+
+  bool isKeyOf(const MDCompileUnit *RHS) const {
+    return SourceLanguage == RHS->getSourceLanguage() &&
+           File == RHS->getFile() && Producer == RHS->getProducer() &&
+           IsOptimized == RHS->isOptimized() && Flags == RHS->getFlags() &&
+           RuntimeVersion == RHS->getRuntimeVersion() &&
+           SplitDebugFilename == RHS->getSplitDebugFilename() &&
+           EmissionKind == RHS->getEmissionKind() &&
+           EnumTypes == RHS->getEnumTypes() &&
+           RetainedTypes == RHS->getRetainedTypes() &&
+           Subprograms == RHS->getSubprograms() &&
+           GlobalVariables == RHS->getGlobalVariables() &&
+           ImportedEntities == RHS->getImportedEntities();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(SourceLanguage, File, Producer, IsOptimized, Flags,
+                        RuntimeVersion, SplitDebugFilename, EmissionKind,
+                        EnumTypes, RetainedTypes, Subprograms, GlobalVariables,
+                        ImportedEntities);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDSubprogram> {
+  Metadata *Scope;
+  StringRef Name;
+  StringRef LinkageName;
+  Metadata *File;
+  unsigned Line;
+  Metadata *Type;
+  bool IsLocalToUnit;
+  bool IsDefinition;
+  unsigned ScopeLine;
+  Metadata *ContainingType;
+  unsigned Virtuality;
+  unsigned VirtualIndex;
+  unsigned Flags;
+  bool IsOptimized;
+  Metadata *Function;
+  Metadata *TemplateParams;
+  Metadata *Declaration;
+  Metadata *Variables;
+
+  MDNodeKeyImpl(Metadata *Scope, StringRef Name, StringRef LinkageName,
+                Metadata *File, unsigned Line, Metadata *Type,
+                bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+                Metadata *ContainingType, unsigned Virtuality,
+                unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+                Metadata *Function, Metadata *TemplateParams,
+                Metadata *Declaration, Metadata *Variables)
+      : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
+        Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
+        IsDefinition(IsDefinition), ScopeLine(ScopeLine),
+        ContainingType(ContainingType), Virtuality(Virtuality),
+        VirtualIndex(VirtualIndex), Flags(Flags), IsOptimized(IsOptimized),
+        Function(Function), TemplateParams(TemplateParams),
+        Declaration(Declaration), Variables(Variables) {}
+  MDNodeKeyImpl(const MDSubprogram *N)
+      : Scope(N->getScope()), Name(N->getName()),
+        LinkageName(N->getLinkageName()), File(N->getFile()),
+        Line(N->getLine()), Type(N->getType()),
+        IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
+        ScopeLine(N->getScopeLine()), ContainingType(N->getContainingType()),
+        Virtuality(N->getVirtuality()), VirtualIndex(N->getVirtualIndex()),
+        Flags(N->getFlags()), IsOptimized(N->isOptimized()),
+        Function(N->getFunction()), TemplateParams(N->getTemplateParams()),
+        Declaration(N->getDeclaration()), Variables(N->getVariables()) {}
+
+  bool isKeyOf(const MDSubprogram *RHS) const {
+    return Scope == RHS->getScope() && Name == RHS->getName() &&
+           LinkageName == RHS->getLinkageName() && File == RHS->getFile() &&
+           Line == RHS->getLine() && Type == RHS->getType() &&
+           IsLocalToUnit == RHS->isLocalToUnit() &&
+           IsDefinition == RHS->isDefinition() &&
+           ScopeLine == RHS->getScopeLine() &&
+           ContainingType == RHS->getContainingType() &&
+           Virtuality == RHS->getVirtuality() &&
+           VirtualIndex == RHS->getVirtualIndex() && Flags == RHS->getFlags() &&
+           IsOptimized == RHS->isOptimized() &&
+           Function == RHS->getFunction() &&
+           TemplateParams == RHS->getTemplateParams() &&
+           Declaration == RHS->getDeclaration() &&
+           Variables == RHS->getVariables();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Scope, Name, LinkageName, File, Line, Type,
+                        IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
+                        Virtuality, VirtualIndex, Flags, IsOptimized, Function,
+                        TemplateParams, Declaration, Variables);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDLexicalBlock> {
+  Metadata *Scope;
+  Metadata *File;
+  unsigned Line;
+  unsigned Column;
+
+  MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column)
+      : Scope(Scope), File(File), Line(Line), Column(Column) {}
+  MDNodeKeyImpl(const MDLexicalBlock *N)
+      : Scope(N->getScope()), File(N->getFile()), Line(N->getLine()),
+        Column(N->getColumn()) {}
+
+  bool isKeyOf(const MDLexicalBlock *RHS) const {
+    return Scope == RHS->getScope() && File == RHS->getFile() &&
+           Line == RHS->getLine() && Column == RHS->getColumn();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Scope, File, Line, Column);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDLexicalBlockFile> {
+  Metadata *Scope;
+  Metadata *File;
+  unsigned Discriminator;
+
+  MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)
+      : Scope(Scope), File(File), Discriminator(Discriminator) {}
+  MDNodeKeyImpl(const MDLexicalBlockFile *N)
+      : Scope(N->getScope()), File(N->getFile()),
+        Discriminator(N->getDiscriminator()) {}
+
+  bool isKeyOf(const MDLexicalBlockFile *RHS) const {
+    return Scope == RHS->getScope() && File == RHS->getFile() &&
+           Discriminator == RHS->getDiscriminator();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Scope, File, Discriminator);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDNamespace> {
+  Metadata *Scope;
+  Metadata *File;
+  StringRef Name;
+  unsigned Line;
+
+  MDNodeKeyImpl(Metadata *Scope, Metadata *File, StringRef Name, unsigned Line)
+      : Scope(Scope), File(File), Name(Name), Line(Line) {}
+  MDNodeKeyImpl(const MDNamespace *N)
+      : Scope(N->getScope()), File(N->getFile()), Name(N->getName()),
+        Line(N->getLine()) {}
+
+  bool isKeyOf(const MDNamespace *RHS) const {
+    return Scope == RHS->getScope() && File == RHS->getFile() &&
+           Name == RHS->getName() && Line == RHS->getLine();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Scope, File, Name, Line);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDTemplateTypeParameter> {
+  Metadata *Scope;
+  StringRef Name;
+  Metadata *Type;
+  Metadata *File;
+  unsigned Line;
+  unsigned Column;
+
+  MDNodeKeyImpl(Metadata *Scope, StringRef Name, Metadata *Type, Metadata *File,
+                unsigned Line, unsigned Column)
+      : Scope(Scope), Name(Name), Type(Type), File(File), Line(Line),
+        Column(Column) {}
+  MDNodeKeyImpl(const MDTemplateTypeParameter *N)
+      : Scope(N->getScope()), Name(N->getName()), Type(N->getType()),
+        File(N->getFile()), Line(N->getLine()), Column(N->getColumn()) {}
+
+  bool isKeyOf(const MDTemplateTypeParameter *RHS) const {
+    return Scope == RHS->getScope() && Name == RHS->getName() &&
+           Type == RHS->getType() && File == RHS->getFile() &&
+           Line == RHS->getLine() && Column == RHS->getColumn();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Scope, Name, Type, File, Line, Column);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDTemplateValueParameter> {
+  unsigned Tag;
+  Metadata *Scope;
+  StringRef Name;
+  Metadata *Type;
+  Metadata *Value;
+  Metadata *File;
+  unsigned Line;
+  unsigned Column;
+
+  MDNodeKeyImpl(unsigned Tag, Metadata *Scope, StringRef Name, Metadata *Type,
+                Metadata *Value, Metadata *File, unsigned Line, unsigned Column)
+      : Tag(Tag), Scope(Scope), Name(Name), Type(Type), Value(Value),
+        File(File), Line(Line), Column(Column) {}
+  MDNodeKeyImpl(const MDTemplateValueParameter *N)
+      : Tag(N->getTag()), Scope(N->getScope()), Name(N->getName()),
+        Type(N->getType()), Value(N->getValue()), File(N->getFile()),
+        Line(N->getLine()), Column(N->getColumn()) {}
+
+  bool isKeyOf(const MDTemplateValueParameter *RHS) const {
+    return Tag == RHS->getTag() && Scope == RHS->getScope() &&
+           Name == RHS->getName() && Type == RHS->getType() &&
+           Value == RHS->getValue() && File == RHS->getFile() &&
+           Line == RHS->getLine() && Column == RHS->getColumn();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Tag, Scope, Name, Type, Value, File, Line, Column);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDGlobalVariable> {
+  Metadata *Scope;
+  StringRef Name;
+  StringRef LinkageName;
+  Metadata *File;
+  unsigned Line;
+  Metadata *Type;
+  bool IsLocalToUnit;
+  bool IsDefinition;
+  Metadata *Variable;
+  Metadata *StaticDataMemberDeclaration;
+
+  MDNodeKeyImpl(Metadata *Scope, StringRef Name, StringRef LinkageName,
+                Metadata *File, unsigned Line, Metadata *Type,
+                bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+                Metadata *StaticDataMemberDeclaration)
+      : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
+        Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
+        IsDefinition(IsDefinition), Variable(Variable),
+        StaticDataMemberDeclaration(StaticDataMemberDeclaration) {}
+  MDNodeKeyImpl(const MDGlobalVariable *N)
+      : Scope(N->getScope()), Name(N->getName()),
+        LinkageName(N->getLinkageName()), File(N->getFile()),
+        Line(N->getLine()), Type(N->getType()),
+        IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
+        Variable(N->getVariable()),
+        StaticDataMemberDeclaration(N->getStaticDataMemberDeclaration()) {}
+
+  bool isKeyOf(const MDGlobalVariable *RHS) const {
+    return Scope == RHS->getScope() && Name == RHS->getName() &&
+           LinkageName == RHS->getLinkageName() && File == RHS->getFile() &&
+           Line == RHS->getLine() && Type == RHS->getType() &&
+           IsLocalToUnit == RHS->isLocalToUnit() &&
+           IsDefinition == RHS->isDefinition() &&
+           Variable == RHS->getVariable() &&
+           StaticDataMemberDeclaration == RHS->getStaticDataMemberDeclaration();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Scope, Name, LinkageName, File, Line, Type,
+                        IsLocalToUnit, IsDefinition, Variable,
+                        StaticDataMemberDeclaration);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDLocalVariable> {
+  unsigned Tag;
+  Metadata *Scope;
+  StringRef Name;
+  Metadata *File;
+  unsigned Line;
+  Metadata *Type;
+  unsigned Arg;
+  unsigned Flags;
+  Metadata *InlinedAt;
+
+  MDNodeKeyImpl(unsigned Tag, Metadata *Scope, StringRef Name, Metadata *File,
+                unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags,
+                Metadata *InlinedAt)
+      : Tag(Tag), Scope(Scope), Name(Name), File(File), Line(Line), Type(Type),
+        Arg(Arg), Flags(Flags), InlinedAt(InlinedAt) {}
+  MDNodeKeyImpl(const MDLocalVariable *N)
+      : Tag(N->getTag()), Scope(N->getScope()), Name(N->getName()),
+        File(N->getFile()), Line(N->getLine()), Type(N->getType()),
+        Arg(N->getArg()), Flags(N->getFlags()), InlinedAt(N->getInlinedAt()) {}
+
+  bool isKeyOf(const MDLocalVariable *RHS) const {
+    return Tag == RHS->getTag() && Scope == RHS->getScope() &&
+           Name == RHS->getName() && File == RHS->getFile() &&
+           Line == RHS->getLine() && Type == RHS->getType() &&
+           Arg == RHS->getArg() && Flags == RHS->getFlags() &&
+           InlinedAt == RHS->getInlinedAt();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Tag, Scope, Name, File, Line, Type, Arg, Flags,
+                        InlinedAt);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDExpression> {
+  ArrayRef<uint64_t> Elements;
+
+  MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {}
+  MDNodeKeyImpl(const MDExpression *N) : Elements(N->getElements()) {}
+
+  bool isKeyOf(const MDExpression *RHS) const {
+    return Elements == RHS->getElements();
+  }
+  unsigned getHashValue() const {
+    return hash_combine_range(Elements.begin(), Elements.end());
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDObjCProperty> {
+  StringRef Name;
+  Metadata *File;
+  unsigned Line;
+  StringRef GetterName;
+  StringRef SetterName;
+  unsigned Attributes;
+  Metadata *Type;
+
+  MDNodeKeyImpl(StringRef Name, Metadata *File, unsigned Line,
+                StringRef GetterName, StringRef SetterName, unsigned Attributes,
+                Metadata *Type)
+      : Name(Name), File(File), Line(Line), GetterName(GetterName),
+        SetterName(SetterName), Attributes(Attributes), Type(Type) {}
+  MDNodeKeyImpl(const MDObjCProperty *N)
+      : Name(N->getName()), File(N->getFile()), Line(N->getLine()),
+        GetterName(N->getGetterName()), SetterName(N->getSetterName()),
+        Attributes(N->getAttributes()), Type(N->getType()) {}
+
+  bool isKeyOf(const MDObjCProperty *RHS) const {
+    return Name == RHS->getName() && File == RHS->getFile() &&
+           Line == RHS->getLine() && GetterName == RHS->getGetterName() &&
+           SetterName == RHS->getSetterName() &&
+           Attributes == RHS->getAttributes() && Type == RHS->getType();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Name, File, Line, GetterName, SetterName, Attributes,
+                        Type);
+  }
+};
+
+template <> struct MDNodeKeyImpl<MDImportedEntity> {
+  unsigned Tag;
+  Metadata *Scope;
+  Metadata *Entity;
+  unsigned Line;
+  StringRef Name;
+
+  MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, unsigned Line,
+                StringRef Name)
+      : Tag(Tag), Scope(Scope), Entity(Entity), Line(Line), Name(Name) {}
+  MDNodeKeyImpl(const MDImportedEntity *N)
+      : Tag(N->getTag()), Scope(N->getScope()), Entity(N->getEntity()),
+        Line(N->getLine()), Name(N->getName()) {}
+
+  bool isKeyOf(const MDImportedEntity *RHS) const {
+    return Tag == RHS->getTag() && Scope == RHS->getScope() &&
+           Entity == RHS->getEntity() && Line == RHS->getLine() &&
+           Name == RHS->getName();
+  }
+  unsigned getHashValue() const {
+    return hash_combine(Tag, Scope, Entity, Line, Name);
+  }
+};
+
 /// \brief DenseMapInfo for MDNode subclasses.
 template <class NodeTy> struct MDNodeInfo {
   typedef MDNodeKeyImpl<NodeTy> KeyTy;
index ce55d954fb7f9d4ad0a76c673fc1123d025660b6..8a1da4f325de39a4c424ac57c90beecb072feaed 100644 (file)
@@ -614,6 +614,853 @@ TEST_F(GenericDebugNodeTest, getEmptyHeader) {
   EXPECT_EQ(nullptr, N->getOperand(0));
 }
 
+typedef MetadataTest MDSubrangeTest;
+
+TEST_F(MDSubrangeTest, get) {
+  auto *N = MDSubrange::get(Context, 5, 7);
+  EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());
+  EXPECT_EQ(5, N->getCount());
+  EXPECT_EQ(7, N->getLo());
+  EXPECT_EQ(N, MDSubrange::get(Context, 5, 7));
+  EXPECT_EQ(MDSubrange::get(Context, 5, 0), MDSubrange::get(Context, 5));
+}
+
+typedef MetadataTest MDEnumeratorTest;
+
+TEST_F(MDEnumeratorTest, get) {
+  auto *N = MDEnumerator::get(Context, 7, "name");
+  EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());
+  EXPECT_EQ(7, N->getValue());
+  EXPECT_EQ("name", N->getName());
+  EXPECT_EQ(N, MDEnumerator::get(Context, 7, "name"));
+
+  EXPECT_NE(N, MDEnumerator::get(Context, 8, "name"));
+  EXPECT_NE(N, MDEnumerator::get(Context, 7, "nam"));
+}
+
+typedef MetadataTest MDBasicTypeTest;
+
+TEST_F(MDBasicTypeTest, get) {
+  auto *N =
+      MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, 26, 7);
+  EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag());
+  EXPECT_EQ("special", N->getName());
+  EXPECT_EQ(33u, N->getSizeInBits());
+  EXPECT_EQ(26u, N->getAlignInBits());
+  EXPECT_EQ(7u, N->getEncoding());
+  EXPECT_EQ(0u, N->getLine());
+  EXPECT_EQ(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
+                                26, 7));
+
+  EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_unspecified_type,
+                                "special", 33, 26, 7));
+  EXPECT_NE(N,
+            MDBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26, 7));
+  EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 32,
+                                26, 7));
+  EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
+                                25, 7));
+  EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
+                                26, 6));
+}
+
+typedef MetadataTest MDDerivedTypeTest;
+
+TEST_F(MDDerivedTypeTest, get) {
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  Metadata *BaseType = MDTuple::getDistinct(Context, None);
+  Metadata *ExtraData = MDTuple::getDistinct(Context, None);
+
+  auto *N = MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",
+                               File, 1, Scope, BaseType, 2, 3, 4, 5, ExtraData);
+  EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag());
+  EXPECT_EQ("something", N->getName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(1u, N->getLine());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(BaseType, N->getBaseType());
+  EXPECT_EQ(2u, N->getSizeInBits());
+  EXPECT_EQ(3u, N->getAlignInBits());
+  EXPECT_EQ(4u, N->getOffsetInBits());
+  EXPECT_EQ(5u, N->getFlags());
+  EXPECT_EQ(ExtraData, N->getExtraData());
+  EXPECT_EQ(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", File, 1, Scope, BaseType, 2, 3,
+                                  4, 5, ExtraData));
+
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_reference_type,
+                                  "something", File, 1, Scope, BaseType, 2, 3,
+                                  4, 5, ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else",
+                                  File, 1, Scope, BaseType, 2, 3, 4, 5,
+                                  ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", Scope, 1, Scope, BaseType, 2, 3,
+                                  4, 5, ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", File, 2, Scope, BaseType, 2, 3,
+                                  4, 5, ExtraData));
+  EXPECT_NE(N,
+            MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",
+                               File, 1, File, BaseType, 2, 3, 4, 5, ExtraData));
+  EXPECT_NE(N,
+            MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",
+                               File, 1, Scope, File, 2, 3, 4, 5, ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", File, 1, Scope, BaseType, 3, 3,
+                                  4, 5, ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", File, 1, Scope, BaseType, 2, 2,
+                                  4, 5, ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", File, 1, Scope, BaseType, 2, 3,
+                                  5, 5, ExtraData));
+  EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+                                  "something", File, 1, Scope, BaseType, 2, 3,
+                                  4, 4, ExtraData));
+  EXPECT_NE(N,
+            MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",
+                               File, 1, Scope, BaseType, 2, 3, 4, 5, File));
+}
+
+typedef MetadataTest MDCompositeTypeTest;
+
+TEST_F(MDCompositeTypeTest, get) {
+  unsigned Tag = dwarf::DW_TAG_structure_type;
+  StringRef Name = "some name";
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 1;
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  Metadata *BaseType = MDTuple::getDistinct(Context, None);
+  unsigned SizeInBits = 2;
+  unsigned AlignInBits = 3;
+  unsigned OffsetInBits = 4;
+  unsigned Flags = 5;
+  Metadata *Elements = MDTuple::getDistinct(Context, None);
+  unsigned RuntimeLang = 6;
+  Metadata *VTableHolder = MDTuple::getDistinct(Context, None);
+  Metadata *TemplateParams = MDTuple::getDistinct(Context, None);
+  StringRef Identifier = "some id";
+
+  auto *N = MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                 BaseType, SizeInBits, AlignInBits,
+                                 OffsetInBits, Flags, Elements, RuntimeLang,
+                                 VTableHolder, TemplateParams, Identifier);
+  EXPECT_EQ(Tag, N->getTag());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(BaseType, N->getBaseType());
+  EXPECT_EQ(SizeInBits, N->getSizeInBits());
+  EXPECT_EQ(AlignInBits, N->getAlignInBits());
+  EXPECT_EQ(OffsetInBits, N->getOffsetInBits());
+  EXPECT_EQ(Flags, N->getFlags());
+  EXPECT_EQ(Elements, N->getElements());
+  EXPECT_EQ(RuntimeLang, N->getRuntimeLang());
+  EXPECT_EQ(VTableHolder, N->getVTableHolder());
+  EXPECT_EQ(TemplateParams, N->getTemplateParams());
+  EXPECT_EQ(Identifier, N->getIdentifier());
+
+  EXPECT_EQ(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag + 1, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, "abc", File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, Scope, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line + 1, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, File,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, File,
+                                    SizeInBits, AlignInBits, OffsetInBits,
+                                    Flags, Elements, RuntimeLang, VTableHolder,
+                                    TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits + 1, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits + 1,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(
+                   Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                   AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang,
+                   VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(
+                   Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                   AlignInBits, OffsetInBits, Flags + 1, Elements, RuntimeLang,
+                   VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, File, RuntimeLang,
+                                    VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(
+                   Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                   AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1,
+                   VTableHolder, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    File, TemplateParams, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, File, Identifier));
+  EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope,
+                                    BaseType, SizeInBits, AlignInBits,
+                                    OffsetInBits, Flags, Elements, RuntimeLang,
+                                    VTableHolder, TemplateParams, "other"));
+
+  // Be sure that missing identifiers get null pointers.
+  EXPECT_FALSE(MDCompositeType::get(
+                   Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                   AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+                   VTableHolder, TemplateParams, "")->getRawIdentifier());
+  EXPECT_FALSE(MDCompositeType::get(
+                   Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                   AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+                   VTableHolder, TemplateParams)->getRawIdentifier());
+}
+
+typedef MetadataTest MDSubroutineTypeTest;
+
+TEST_F(MDSubroutineTypeTest, get) {
+  unsigned Flags = 1;
+  Metadata *TypeArray = MDTuple::getDistinct(Context, None);
+
+  auto *N = MDSubroutineType::get(Context, Flags, TypeArray);
+  EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag());
+  EXPECT_EQ(Flags, N->getFlags());
+  EXPECT_EQ(TypeArray, N->getTypeArray());
+  EXPECT_EQ(N, MDSubroutineType::get(Context, Flags, TypeArray));
+
+  EXPECT_NE(N, MDSubroutineType::get(Context, Flags + 1, TypeArray));
+  EXPECT_NE(N, MDSubroutineType::get(Context, Flags,
+                                     MDTuple::getDistinct(Context, None)));
+}
+
+typedef MetadataTest MDFileTest;
+
+TEST_F(MDFileTest, get) {
+  StringRef Filename = "file";
+  StringRef Directory = "dir";
+  auto *N = MDFile::get(Context, Filename, Directory);
+
+  EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag());
+  EXPECT_EQ(Filename, N->getFilename());
+  EXPECT_EQ(Directory, N->getDirectory());
+  EXPECT_EQ(N, MDFile::get(Context, Filename, Directory));
+
+  EXPECT_NE(N, MDFile::get(Context, "other", Directory));
+  EXPECT_NE(N, MDFile::get(Context, Filename, "other"));
+}
+
+typedef MetadataTest MDCompileUnitTest;
+
+TEST_F(MDCompileUnitTest, get) {
+  unsigned SourceLanguage = 1;
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  StringRef Producer = "some producer";
+  bool IsOptimized = false;
+  StringRef Flags = "flag after flag";
+  unsigned RuntimeVersion = 2;
+  StringRef SplitDebugFilename = "another/file";
+  unsigned EmissionKind = 3;
+  Metadata *EnumTypes = MDTuple::getDistinct(Context, None);
+  Metadata *RetainedTypes = MDTuple::getDistinct(Context, None);
+  Metadata *Subprograms = MDTuple::getDistinct(Context, None);
+  Metadata *GlobalVariables = MDTuple::getDistinct(Context, None);
+  Metadata *ImportedEntities = MDTuple::getDistinct(Context, None);
+  auto *N = MDCompileUnit::get(
+      Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+      RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+      RetainedTypes, Subprograms, GlobalVariables, ImportedEntities);
+
+  EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag());
+  EXPECT_EQ(SourceLanguage, N->getSourceLanguage());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Producer, N->getProducer());
+  EXPECT_EQ(IsOptimized, N->isOptimized());
+  EXPECT_EQ(Flags, N->getFlags());
+  EXPECT_EQ(RuntimeVersion, N->getRuntimeVersion());
+  EXPECT_EQ(SplitDebugFilename, N->getSplitDebugFilename());
+  EXPECT_EQ(EmissionKind, N->getEmissionKind());
+  EXPECT_EQ(EnumTypes, N->getEnumTypes());
+  EXPECT_EQ(RetainedTypes, N->getRetainedTypes());
+  EXPECT_EQ(Subprograms, N->getSubprograms());
+  EXPECT_EQ(GlobalVariables, N->getGlobalVariables());
+  EXPECT_EQ(ImportedEntities, N->getImportedEntities());
+  EXPECT_EQ(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                                  IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage + 1, File, Producer,
+                                  IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, EnumTypes, Producer,
+                                  IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, "other",
+                                  IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                                  !IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                                  IsOptimized, "other", RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                                  IsOptimized, Flags, RuntimeVersion + 1,
+                                  SplitDebugFilename, EmissionKind, EnumTypes,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N,
+            MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                               IsOptimized, Flags, RuntimeVersion, "other",
+                               EmissionKind, EnumTypes, RetainedTypes,
+                               Subprograms, GlobalVariables, ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                                  IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind + 1,
+                                  EnumTypes, RetainedTypes, Subprograms,
+                                  GlobalVariables, ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer,
+                                  IsOptimized, Flags, RuntimeVersion,
+                                  SplitDebugFilename, EmissionKind, File,
+                                  RetainedTypes, Subprograms, GlobalVariables,
+                                  ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(
+                   Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+                   RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+                   File, Subprograms, GlobalVariables, ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(
+                   Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+                   RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+                   RetainedTypes, File, GlobalVariables, ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(
+                   Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+                   RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+                   RetainedTypes, Subprograms, File, ImportedEntities));
+  EXPECT_NE(N, MDCompileUnit::get(
+                   Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+                   RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+                   RetainedTypes, Subprograms, GlobalVariables, File));
+}
+
+typedef MetadataTest MDSubprogramTest;
+
+TEST_F(MDSubprogramTest, get) {
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  StringRef Name = "name";
+  StringRef LinkageName = "linkage";
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 2;
+  Metadata *Type = MDTuple::getDistinct(Context, None);
+  bool IsLocalToUnit = false;
+  bool IsDefinition = true;
+  unsigned ScopeLine = 3;
+  Metadata *ContainingType = MDTuple::getDistinct(Context, None);
+  unsigned Virtuality = 4;
+  unsigned VirtualIndex = 5;
+  unsigned Flags = 6;
+  bool IsOptimized = false;
+  Metadata *Function = MDTuple::getDistinct(Context, None);
+  Metadata *TemplateParams = MDTuple::getDistinct(Context, None);
+  Metadata *Declaration = MDTuple::getDistinct(Context, None);
+  Metadata *Variables = MDTuple::getDistinct(Context, None);
+
+  auto *N = MDSubprogram::get(
+      Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+      IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags,
+      IsOptimized, Function, TemplateParams, Declaration, Variables);
+
+  EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(LinkageName, N->getLinkageName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());
+  EXPECT_EQ(IsDefinition, N->isDefinition());
+  EXPECT_EQ(ScopeLine, N->getScopeLine());
+  EXPECT_EQ(ContainingType, N->getContainingType());
+  EXPECT_EQ(Virtuality, N->getVirtuality());
+  EXPECT_EQ(VirtualIndex, N->getVirtualIndex());
+  EXPECT_EQ(Flags, N->getFlags());
+  EXPECT_EQ(IsOptimized, N->isOptimized());
+  EXPECT_EQ(Function, N->getFunction());
+  EXPECT_EQ(TemplateParams, N->getTemplateParams());
+  EXPECT_EQ(Declaration, N->getDeclaration());
+  EXPECT_EQ(Variables, N->getVariables());
+  EXPECT_EQ(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+
+  EXPECT_NE(N, MDSubprogram::get(Context, File, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, "other", LinkageName, File,
+                                 Line, Type, IsLocalToUnit, IsDefinition,
+                                 ScopeLine, ContainingType, Virtuality,
+                                 VirtualIndex, Flags, IsOptimized, Function,
+                                 TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, "other", File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, Scope, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File,
+                                 Line + 1, Type, IsLocalToUnit, IsDefinition,
+                                 ScopeLine, ContainingType, Virtuality,
+                                 VirtualIndex, Flags, IsOptimized, Function,
+                                 TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Scope, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, !IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, !IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition,
+                                 ScopeLine + 1, ContainingType, Virtuality,
+                                 VirtualIndex, Flags, IsOptimized, Function,
+                                 TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 Type, Virtuality, VirtualIndex, Flags,
+                                 IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality + 1, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex + 1,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 ~Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, !IsOptimized, Function, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Type, TemplateParams,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, Type,
+                                 Declaration, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Type, Variables));
+  EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                                 Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                                 ContainingType, Virtuality, VirtualIndex,
+                                 Flags, IsOptimized, Function, TemplateParams,
+                                 Declaration, Type));
+}
+
+typedef MetadataTest MDLexicalBlockTest;
+
+TEST_F(MDLexicalBlockTest, get) {
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  unsigned Column = 8;
+
+  auto *N = MDLexicalBlock::get(Context, Scope, File, Line, Column);
+
+  EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Column, N->getColumn());
+  EXPECT_EQ(N, MDLexicalBlock::get(Context, Scope, File, Line, Column));
+
+  EXPECT_NE(N, MDLexicalBlock::get(Context, File, File, Line, Column));
+  EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, Scope, Line, Column));
+  EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, File, Line + 1, Column));
+  EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, File, Line, Column + 1));
+}
+
+typedef MetadataTest MDLexicalBlockFileTest;
+
+TEST_F(MDLexicalBlockFileTest, get) {
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Discriminator = 5;
+
+  auto *N = MDLexicalBlockFile::get(Context, Scope, File, Discriminator);
+
+  EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Discriminator, N->getDiscriminator());
+  EXPECT_EQ(N, MDLexicalBlockFile::get(Context, Scope, File, Discriminator));
+
+  EXPECT_NE(N, MDLexicalBlockFile::get(Context, File, File, Discriminator));
+  EXPECT_NE(N, MDLexicalBlockFile::get(Context, Scope, Scope, Discriminator));
+  EXPECT_NE(N,
+            MDLexicalBlockFile::get(Context, Scope, File, Discriminator + 1));
+}
+
+typedef MetadataTest MDNamespaceTest;
+
+TEST_F(MDNamespaceTest, get) {
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  StringRef Name = "namespace";
+  unsigned Line = 5;
+
+  auto *N = MDNamespace::get(Context, Scope, File, Name, Line);
+
+  EXPECT_EQ(dwarf::DW_TAG_namespace, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(N, MDNamespace::get(Context, Scope, File, Name, Line));
+
+  EXPECT_NE(N, MDNamespace::get(Context, File, File, Name, Line));
+  EXPECT_NE(N, MDNamespace::get(Context, Scope, Scope, Name, Line));
+  EXPECT_NE(N, MDNamespace::get(Context, Scope, File, "other", Line));
+  EXPECT_NE(N, MDNamespace::get(Context, Scope, File, Name, Line + 1));
+}
+
+typedef MetadataTest MDTemplateTypeParameterTest;
+
+TEST_F(MDTemplateTypeParameterTest, get) {
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  StringRef Name = "template";
+  Metadata *Type = MDTuple::getDistinct(Context, None);
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  unsigned Column = 7;
+
+  auto *N = MDTemplateTypeParameter::get(Context, Scope, Name, Type, File, Line,
+                                         Column);
+
+  EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Column, N->getColumn());
+  EXPECT_EQ(N, MDTemplateTypeParameter::get(Context, Scope, Name, Type, File,
+                                            Line, Column));
+
+  EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Type, Name, Type, File,
+                                            Line, Column));
+  EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Scope, "other", Type, File,
+                                            Line, Column));
+  EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Scope, Name, Scope, File,
+                                            Line, Column));
+  EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Scope, Name, Type, Scope,
+                                            Line, Column));
+  EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Scope, Name, Type, File,
+                                            Line + 1, Column));
+  EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Scope, Name, Type, File,
+                                            Line, Column + 1));
+}
+
+typedef MetadataTest MDTemplateValueParameterTest;
+
+TEST_F(MDTemplateValueParameterTest, get) {
+  unsigned Tag = dwarf::DW_TAG_template_value_parameter;
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  StringRef Name = "template";
+  Metadata *Type = MDTuple::getDistinct(Context, None);
+  Metadata *Value = MDTuple::getDistinct(Context, None);
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  unsigned Column = 7;
+
+  auto *N = MDTemplateValueParameter::get(Context, Tag, Scope, Name, Type,
+                                          Value, File, Line, Column);
+  EXPECT_EQ(Tag, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(Value, N->getValue());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Column, N->getColumn());
+  EXPECT_EQ(N, MDTemplateValueParameter::get(Context, Tag, Scope, Name, Type,
+                                             Value, File, Line, Column));
+
+  EXPECT_NE(N, MDTemplateValueParameter::get(
+                   Context, dwarf::DW_TAG_GNU_template_template_param, Scope,
+                   Name, Type, Value, File, Line, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Type, Name, Type,
+                                             Value, File, Line, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Scope, "other", Type,
+                                             Value, File, Line, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Scope, Name, Scope,
+                                             Value, File, Line, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Scope, Name, Type,
+                                             Scope, File, Line, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Scope, Name, Type,
+                                             Value, Scope, Line, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Scope, Name, Type,
+                                             Value, File, Line + 1, Column));
+  EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Scope, Name, Type,
+                                             Value, File, Line, Column + 1));
+}
+
+typedef MetadataTest MDGlobalVariableTest;
+
+TEST_F(MDGlobalVariableTest, get) {
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  StringRef Name = "name";
+  StringRef LinkageName = "linkage";
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  Metadata *Type = MDTuple::getDistinct(Context, None);
+  bool IsLocalToUnit = false;
+  bool IsDefinition = true;
+  Metadata *Variable = MDTuple::getDistinct(Context, None);
+  Metadata *StaticDataMemberDeclaration = MDTuple::getDistinct(Context, None);
+
+  auto *N = MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line,
+                                  Type, IsLocalToUnit, IsDefinition, Variable,
+                                  StaticDataMemberDeclaration);
+  EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(LinkageName, N->getLinkageName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());
+  EXPECT_EQ(IsDefinition, N->isDefinition());
+  EXPECT_EQ(Variable, N->getVariable());
+  EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration());
+  EXPECT_EQ(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                     Line, Type, IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+
+  EXPECT_NE(N, MDGlobalVariable::get(Context, File, Name, LinkageName, File,
+                                     Line, Type, IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, "other", LinkageName, File,
+                                     Line, Type, IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, "other", File, Line,
+                                     Type, IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, Scope,
+                                     Line, Type, IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N,
+            MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                  Line + 1, Type, IsLocalToUnit, IsDefinition,
+                                  Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                     Line, Scope, IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                     Line, Type, !IsLocalToUnit, IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                     Line, Type, IsLocalToUnit, !IsDefinition,
+                                     Variable, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                     Line, Type, IsLocalToUnit, IsDefinition,
+                                     Type, StaticDataMemberDeclaration));
+  EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+                                     Line, Type, IsLocalToUnit, IsDefinition,
+                                     Variable, Type));
+}
+
+typedef MetadataTest MDLocalVariableTest;
+
+TEST_F(MDLocalVariableTest, get) {
+  unsigned Tag = dwarf::DW_TAG_arg_variable;
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  StringRef Name = "name";
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  Metadata *Type = MDTuple::getDistinct(Context, None);
+  unsigned Arg = 6;
+  unsigned Flags = 7;
+  Metadata *InlinedAt = MDTuple::getDistinct(Context, None);
+
+  auto *N = MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type,
+                                 Arg, Flags, InlinedAt);
+  EXPECT_EQ(Tag, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(Arg, N->getArg());
+  EXPECT_EQ(Flags, N->getFlags());
+  EXPECT_EQ(InlinedAt, N->getInlinedAt());
+  EXPECT_EQ(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type,
+                                    Arg, Flags, InlinedAt));
+
+  EXPECT_NE(N, MDLocalVariable::get(Context, dwarf::DW_TAG_auto_variable, Scope,
+                                    Name, File, Line, Type, Arg, Flags,
+                                    InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, File, Name, File, Line,
+                                    Type, Arg, Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, "other", File, Line,
+                                    Type, Arg, Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, Scope, Line,
+                                    Type, Arg, Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line + 1,
+                                    Type, Arg, Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line,
+                                    Scope, Arg, Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type,
+                                    Arg + 1, Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type,
+                                    Arg, ~Flags, InlinedAt));
+  EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type,
+                                    Arg, Flags, Scope));
+}
+
+typedef MetadataTest MDExpressionTest;
+
+TEST_F(MDExpressionTest, get) {
+  uint64_t Elements[] = {2, 6, 9, 78, 0};
+  auto *N = MDExpression::get(Context, Elements);
+  EXPECT_EQ(makeArrayRef(Elements), N->getElements());
+  EXPECT_EQ(N, MDExpression::get(Context, Elements));
+}
+
+typedef MetadataTest MDObjCPropertyTest;
+
+TEST_F(MDObjCPropertyTest, get) {
+  StringRef Name = "name";
+  Metadata *File = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  StringRef GetterName = "getter";
+  StringRef SetterName = "setter";
+  unsigned Attributes = 7;
+  Metadata *Type = MDTuple::getDistinct(Context, None);
+
+  auto *N = MDObjCProperty::get(Context, Name, File, Line, GetterName,
+                                SetterName, Attributes, Type);
+
+  EXPECT_EQ(dwarf::DW_TAG_APPLE_property, N->getTag());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(GetterName, N->getGetterName());
+  EXPECT_EQ(SetterName, N->getSetterName());
+  EXPECT_EQ(Attributes, N->getAttributes());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(N, MDObjCProperty::get(Context, Name, File, Line, GetterName,
+                                   SetterName, Attributes, Type));
+
+  EXPECT_NE(N, MDObjCProperty::get(Context, "other", File, Line, GetterName,
+                                   SetterName, Attributes, Type));
+  EXPECT_NE(N, MDObjCProperty::get(Context, Name, Type, Line, GetterName,
+                                   SetterName, Attributes, Type));
+  EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line + 1, GetterName,
+                                   SetterName, Attributes, Type));
+  EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, "other",
+                                   SetterName, Attributes, Type));
+  EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, GetterName,
+                                   "other", Attributes, Type));
+  EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, GetterName,
+                                   SetterName, Attributes + 1, Type));
+  EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, GetterName,
+                                   SetterName, Attributes, File));
+}
+
+typedef MetadataTest MDImportedEntityTest;
+
+TEST_F(MDImportedEntityTest, get) {
+  unsigned Tag = dwarf::DW_TAG_imported_module;
+  Metadata *Scope = MDTuple::getDistinct(Context, None);
+  Metadata *Entity = MDTuple::getDistinct(Context, None);
+  unsigned Line = 5;
+  StringRef Name = "name";
+
+  auto *N = MDImportedEntity::get(Context, Tag, Scope, Entity, Line, Name);
+
+  EXPECT_EQ(Tag, N->getTag());
+  EXPECT_EQ(Scope, N->getScope());
+  EXPECT_EQ(Entity, N->getEntity());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(N, MDImportedEntity::get(Context, Tag, Scope, Entity, Line, Name));
+
+  EXPECT_NE(N,
+            MDImportedEntity::get(Context, dwarf::DW_TAG_imported_declaration,
+                                  Scope, Entity, Line, Name));
+  EXPECT_NE(N, MDImportedEntity::get(Context, Tag, Entity, Entity, Line, Name));
+  EXPECT_NE(N, MDImportedEntity::get(Context, Tag, Scope, Scope, Line, Name));
+  EXPECT_NE(N,
+            MDImportedEntity::get(Context, Tag, Scope, Entity, Line + 1, Name));
+  EXPECT_NE(N,
+            MDImportedEntity::get(Context, Tag, Scope, Entity, Line, "other"));
+}
+
 typedef MetadataTest MetadataAsValueTest;
 
 TEST_F(MetadataAsValueTest, MDNode) {