Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -167,6 +167,7 @@ METADATA_EXPRESSION = 29, // [distinct, n x element] METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...] METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name] + METADATA_EXTERNAL_TYPE_REF=32,// [distinct, tag, file, uid] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -386,6 +386,13 @@ DITypeRefArray ParameterTypes, unsigned Flags = 0); + /// createExternalTypeRef - Create external type ref. + /// @param Tag Dwarf TAG. + /// @param File Module in which this type is defined. + /// @param UniqueIdentifire Mangled name or unique identifier for the type. + DIExternalTypeRef *createExternalTypeRef(unsigned Tag, DIFile *File, + StringRef UniqueIdentifier); + /// createArtificialType - Create a new DIType* with "artificial" flag set. DIType *createArtificialType(DIType *Ty); Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -206,6 +206,7 @@ case DIDerivedTypeKind: case DICompositeTypeKind: case DISubroutineTypeKind: + case DIExternalTypeRefKind: case DIFileKind: case DICompileUnitKind: case DISubprogramKind: @@ -437,6 +438,7 @@ case DIDerivedTypeKind: case DICompositeTypeKind: case DISubroutineTypeKind: + case DIExternalTypeRefKind: case DIFileKind: case DICompileUnitKind: case DISubprogramKind: @@ -583,6 +585,7 @@ case DIDerivedTypeKind: case DICompositeTypeKind: case DISubroutineTypeKind: + case DIExternalTypeRefKind: return true; } } @@ -664,7 +667,8 @@ static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIDerivedTypeKind || MD->getMetadataID() == DICompositeTypeKind || - MD->getMetadataID() == DISubroutineTypeKind; + MD->getMetadataID() == DISubroutineTypeKind || + MD->getMetadataID() == DIExternalTypeRefKind; } }; @@ -762,7 +766,8 @@ } }; -/// \brief Base class for DICompositeType and DISubroutineType. +/// \brief Base class for DICompositeType, DISubroutineType +/// and DIExternalTypeRef. /// /// TODO: Delete; they're not really related. class DICompositeTypeBase : public DIDerivedTypeBase { @@ -825,7 +830,8 @@ static bool classof(const Metadata *MD) { return MD->getMetadataID() == DICompositeTypeKind || - MD->getMetadataID() == DISubroutineTypeKind; + MD->getMetadataID() == DISubroutineTypeKind || + MD->getMetadataID() == DIExternalTypeRefKind; } }; @@ -962,6 +968,46 @@ } }; +/// \brief External (module) type references. +/// +/// TODO: Detach from CompositeType. +class DIExternalTypeRef : public DICompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DIExternalTypeRef(LLVMContext &C, StorageType Storage, unsigned Tag, + ArrayRef Ops) + : DICompositeTypeBase(C, DIExternalTypeRefKind, Storage, Tag, 0, 0, 0, 0, + 0, 0, Ops) {} + ~DIExternalTypeRef() {} + + static DIExternalTypeRef * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *File, StringRef Identifier, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, File, getCanonicalMDString(Context, Identifier), + Storage, ShouldCreate); + } + static DIExternalTypeRef * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *File, MDString *Identifier, + StorageType Storage, bool ShouldCreate = true); + + TempDIExternalTypeRef cloneImpl() const { + return getTemporary(getContext(), getTag(), getFile(), getIdentifier()); + } + +public: + DEFINE_MDNODE_GET(DIExternalTypeRef, (unsigned Tag, Metadata *File, + StringRef Identifier), (Tag, File, Identifier)) + DEFINE_MDNODE_GET(DIExternalTypeRef, (unsigned Tag, Metadata *File, + MDString *Identifier), (Tag, File, Identifier)) + + TempDIExternalTypeRef clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIExternalTypeRefKind; + } +}; + /// \brief Compile unit. class DICompileUnit : public DIScope { friend class LLVMContextImpl; Index: include/llvm/IR/Metadata.h =================================================================== --- include/llvm/IR/Metadata.h +++ include/llvm/IR/Metadata.h @@ -67,6 +67,7 @@ DIDerivedTypeKind, DICompositeTypeKind, DISubroutineTypeKind, + DIExternalTypeRefKind, DIFileKind, DICompileUnitKind, DISubprogramKind, Index: include/llvm/IR/Metadata.def =================================================================== --- include/llvm/IR/Metadata.def +++ include/llvm/IR/Metadata.def @@ -74,6 +74,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DICompositeTypeBase) HANDLE_SPECIALIZED_MDNODE_LEAF(DICompositeType) HANDLE_SPECIALIZED_MDNODE_LEAF(DISubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIExternalTypeRef) HANDLE_SPECIALIZED_MDNODE_LEAF(DIFile) HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -3529,6 +3529,21 @@ return false; } +/// ParseDIExternalTypeRef: +/// ::= !DIExternalTypeRef(tag: DW_TAG_class_type, module: !1, identifier: "UUID") +bool LLParser::ParseDIExternalTypeRef(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + REQUIRED(file, MDField, ); \ + REQUIRED(identifier, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIExternalTypeRef, + (Context, tag.Val, file.Val, identifier.Val)); + return false; +} + /// ParseDIFileType: /// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir") bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) { Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -1824,6 +1824,17 @@ NextMDValueNo++); break; } + case bitc::METADATA_EXTERNAL_TYPE_REF: { + if (Record.size() != 4) + return Error("Invalid record"); + + MDValueList.AssignValue( + GET_OR_DISTINCT(DIExternalTypeRef, Record[0], + (Context, Record[1], getMDOrNull(Record[2]), + getMDString(Record[3]))), + NextMDValueNo++); + break; + } case bitc::METADATA_FILE: { if (Record.size() != 3) return Error("Invalid record"); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -919,6 +919,20 @@ Record.clear(); } +static void WriteDIExternalTypeRef(const DIExternalTypeRef *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &Record, + unsigned Abbrev) { + Record.push_back(N->isDistinct()); + Record.push_back(N->getTag()); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); + Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier())); + + Stream.EmitRecord(bitc::METADATA_EXTERNAL_TYPE_REF, Record, Abbrev); + Record.clear(); +} + static void WriteDIFile(const DIFile *N, const ValueEnumerator &VE, BitstreamWriter &Stream, SmallVectorImpl &Record, unsigned Abbrev) { Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1591,6 +1591,18 @@ Out << ")"; } +static void writeDIExternalTypeRef(raw_ostream &Out, + const DIExternalTypeRef *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DIExternalTypeRef("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printMetadata("file", N->getFile()); + Printer.printString("identifier", N->getIdentifier()); + Out << ")"; +} + static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *, SlotTracker *, const Module *) { Out << "!DIFile("; Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -425,6 +425,11 @@ return DISubroutineType::get(VMContext, Flags, ParameterTypes); } +DIExternalTypeRef *DIBuilder::createExternalTypeRef(unsigned Tag, DIFile *File, + StringRef Identifier) { + return DIExternalTypeRef::get(VMContext, Tag, File, Identifier); +} + DICompositeType *DIBuilder::createEnumerationType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements, Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -295,6 +295,18 @@ DEFINE_GETIMPL_STORE(DISubroutineType, (Flags), Ops); } +DIExternalTypeRef *DIExternalTypeRef::getImpl(LLVMContext &Context, + unsigned Tag, + Metadata *File, + MDString *Identifier, + StorageType Storage, + bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DIExternalTypeRef, (Tag, File, getString(Identifier))); + Metadata *Ops[] = {File, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, Identifier}; + DEFINE_GETIMPL_STORE(DIExternalTypeRef, (Tag), Ops); +} + DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, MDString *Directory, StorageType Storage, bool ShouldCreate) { Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -443,6 +443,24 @@ unsigned getHashValue() const { return hash_combine(Flags, TypeArray); } }; +template <> struct MDNodeKeyImpl { + unsigned Tag; + Metadata *File; + StringRef Identifier; + + MDNodeKeyImpl(unsigned Tag, Metadata *File, StringRef Identifier) + : Tag(Tag), File(File), Identifier(Identifier) {} + MDNodeKeyImpl(const DIExternalTypeRef *N) + : Tag(N->getTag()), File(N->getRawFile()), + Identifier(N->getIdentifier()) {} + + bool isKeyOf(const DIExternalTypeRef *RHS) const { + return Tag == RHS->getTag() && File == RHS->getRawFile() && + Identifier == RHS->getIdentifier(); + } + unsigned getHashValue() const { return hash_combine(Tag, File, Identifier); } +}; + template <> struct MDNodeKeyImpl { StringRef Filename; StringRef Directory; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -880,6 +880,10 @@ &N); } +void Verifier::visitDIExternalTypeRef(const DIExternalTypeRef &N) { + Assert(!N.getIdentifier().empty(), "invalid identifier", &N); +} + void Verifier::visitDIFile(const DIFile &N) { Assert(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N); } Index: test/Assembler/DIExternalTypeRef.ll =================================================================== --- /dev/null +++ test/Assembler/DIExternalTypeRef.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s +; RUN: verify-uselistorder %s + +; CHECK: !named = !{!0, !1} +!named = !{!0, !1} + +!0 = !DIFile(filename: "foo", directory: "/dir") + +; CHECK: !1 = !DIExternalTypeRef(tag: DW_TAG_structure_type, file: !0, identifier: "c:objc(cs)Foo") +!1 = !DIExternalTypeRef(tag: DW_TAG_structure_type, file: !0, identifier: "c:objc(cs)Foo") +