diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index ba0c2320f63..fdb6dd8964c 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -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 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 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 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 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 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 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 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(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 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 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 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(getOperand(0)); } + + StringRef getFilename() const { + if (auto *S = cast_or_null(getFileNode()->getOperand(0))) + return S->getString(); + return StringRef(); + } + StringRef getDirectory() const { + if (auto *S = cast_or_null(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 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 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 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 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 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 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 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 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 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 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 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 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 Elements; + + MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) + : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None), + Elements(Elements.begin(), Elements.end()) {} + ~MDExpression() {} + + static MDExpression *getImpl(LLVMContext &Context, + ArrayRef Elements, StorageType Storage, + bool ShouldCreate = true); + + TempMDExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(MDExpression, (ArrayRef Elements), (Elements)) + + ArrayRef getElements() const { return Elements; } + + typedef ArrayRef::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 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 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 diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 7ff8fa990d8..ca72e2618f4 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -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 diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index da6d5cb5e7c..5ccfc113ac2 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -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. diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 6f8c26069a6..1c2424ce11b 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -809,6 +809,106 @@ static void WriteGenericDebugNode(const GenericDebugNode *N, Record.clear(); } +static void WriteMDSubrange(const MDSubrange *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDEnumerator(const MDEnumerator *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDBasicType(const MDBasicType *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDDerivedType(const MDDerivedType *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDCompositeType(const MDCompositeType *, + const ValueEnumerator &, BitstreamWriter &, + SmallVectorImpl &, unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDSubroutineType(const MDSubroutineType *, + const ValueEnumerator &, BitstreamWriter &, + SmallVectorImpl &, unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDFile(const MDFile *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDCompileUnit(const MDCompileUnit *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDSubprogram(const MDSubprogram *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDLexicalBlock(const MDLexicalBlock *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDLexicalBlockFile(const MDLexicalBlockFile *, + const ValueEnumerator &, BitstreamWriter &, + SmallVectorImpl &, unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDNamespace(const MDNamespace *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDTemplateTypeParameter(const MDTemplateTypeParameter *, + const ValueEnumerator &, + BitstreamWriter &, + SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDTemplateValueParameter(const MDTemplateValueParameter *, + const ValueEnumerator &, + BitstreamWriter &, + SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDGlobalVariable(const MDGlobalVariable *, + const ValueEnumerator &, BitstreamWriter &, + SmallVectorImpl &, unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDLocalVariable(const MDLocalVariable *, + const ValueEnumerator &, BitstreamWriter &, + SmallVectorImpl &, unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDExpression(const MDExpression *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDObjCProperty(const MDObjCProperty *, const ValueEnumerator &, + BitstreamWriter &, SmallVectorImpl &, + unsigned) { + llvm_unreachable("write not implemented"); +} +static void WriteMDImportedEntity(const MDImportedEntity *, + const ValueEnumerator &, BitstreamWriter &, + SmallVectorImpl &, unsigned) { + llvm_unreachable("write not implemented"); +} + static void WriteModuleMetadata(const Module *M, const ValueEnumerator &VE, BitstreamWriter &Stream) { diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 43ae3feb363..d1beb166a18 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -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, diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index c540cc45a61..68f6bf843d8 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -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(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(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 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); +} diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 3640495dd97..6a3d59289f4 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -273,6 +273,581 @@ template <> struct MDNodeKeyImpl : MDNodeOpsKey { } }; +template <> struct MDNodeKeyImpl { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + ArrayRef Elements; + + MDNodeKeyImpl(ArrayRef 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 { + 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 { + 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 struct MDNodeInfo { typedef MDNodeKeyImpl KeyTy; diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index ce55d954fb7..8a1da4f325d 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -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) {