diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/Bitcode/BitcodeReader.h | 30 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 37 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.h | 4 | ||||
-rw-r--r-- | llvm/lib/LTO/LTO.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/LTO/LTOBackend.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/Object/IRObjectFile.cpp | 3 | ||||
-rw-r--r-- | llvm/test/ThinLTO/X86/Inputs/debuginfo-compositetype-import.ll | 13 | ||||
-rw-r--r-- | llvm/test/ThinLTO/X86/debuginfo-compositetype-import.ll | 62 |
10 files changed, 173 insertions, 51 deletions
diff --git a/llvm/include/llvm/Bitcode/BitcodeReader.h b/llvm/include/llvm/Bitcode/BitcodeReader.h index ab2f25186d7..9e042b17241 100644 --- a/llvm/include/llvm/Bitcode/BitcodeReader.h +++ b/llvm/include/llvm/Bitcode/BitcodeReader.h @@ -61,9 +61,10 @@ namespace llvm { friend Expected<std::vector<BitcodeModule>> getBitcodeModuleList(MemoryBufferRef Buffer); - Expected<std::unique_ptr<Module>> - getModuleImpl(LLVMContext &Context, bool MaterializeAll, - bool ShouldLazyLoadMetadata); + Expected<std::unique_ptr<Module>> getModuleImpl(LLVMContext &Context, + bool MaterializeAll, + bool ShouldLazyLoadMetadata, + bool IsImporting); public: StringRef getBuffer() const { @@ -74,8 +75,11 @@ namespace llvm { /// Read the bitcode module and prepare for lazy deserialization of function /// bodies. If ShouldLazyLoadMetadata is true, lazily load metadata as well. - Expected<std::unique_ptr<Module>> - getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata); + /// If IsImporting is true, this module is being parsed for ThinLTO + /// importing into another module. + Expected<std::unique_ptr<Module>> getLazyModule(LLVMContext &Context, + bool ShouldLazyLoadMetadata, + bool IsImporting); /// Read the entire bitcode module and return it. Expected<std::unique_ptr<Module>> parseModule(LLVMContext &Context); @@ -93,18 +97,20 @@ namespace llvm { /// Read the header of the specified bitcode buffer and prepare for lazy /// deserialization of function bodies. If ShouldLazyLoadMetadata is true, - /// lazily load metadata as well. + /// lazily load metadata as well. If IsImporting is true, this module is + /// being parsed for ThinLTO importing into another module. Expected<std::unique_ptr<Module>> getLazyBitcodeModule(MemoryBufferRef Buffer, LLVMContext &Context, - bool ShouldLazyLoadMetadata = false); + bool ShouldLazyLoadMetadata = false, + bool IsImporting = false); /// Like getLazyBitcodeModule, except that the module takes ownership of /// the memory buffer if successful. If successful, this moves Buffer. On - /// error, this *does not* move Buffer. - Expected<std::unique_ptr<Module>> - getOwningLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer, - LLVMContext &Context, - bool ShouldLazyLoadMetadata = false); + /// error, this *does not* move Buffer. If IsImporting is true, this module is + /// being parsed for ThinLTO importing into another module. + Expected<std::unique_ptr<Module>> getOwningLazyBitcodeModule( + std::unique_ptr<MemoryBuffer> &&Buffer, LLVMContext &Context, + bool ShouldLazyLoadMetadata = false, bool IsImporting = false); /// Read the header of the specified bitcode buffer and extract just the /// triple information. If successful, this returns a string. On error, this diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index ad4d9cec717..4812b2cfe8e 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -488,7 +488,8 @@ public: /// \brief Main interface to parsing a bitcode buffer. /// \returns true if an error occurred. - Error parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata = false); + Error parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata = false, + bool IsImporting = false); static uint64_t decodeSignRotatedValue(uint64_t V); @@ -3084,9 +3085,10 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit, } } -Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata) { +Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata, + bool IsImporting) { TheModule = M; - MDLoader = MetadataLoader(Stream, *M, ValueList, + MDLoader = MetadataLoader(Stream, *M, ValueList, IsImporting, [&](unsigned ID) { return getTypeByID(ID); }); return parseModule(0, ShouldLazyLoadMetadata); } @@ -5220,7 +5222,7 @@ llvm::getBitcodeModuleList(MemoryBufferRef Buffer) { /// everything. Expected<std::unique_ptr<Module>> BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, - bool ShouldLazyLoadMetadata) { + bool ShouldLazyLoadMetadata, bool IsImporting) { BitstreamCursor Stream(Buffer); std::string ProducerIdentification; @@ -5243,7 +5245,8 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, M->setMaterializer(R); // Delay parsing Metadata if ShouldLazyLoadMetadata is true. - if (Error Err = R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata)) + if (Error Err = + R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata, IsImporting)) return std::move(Err); if (MaterializeAll) { @@ -5259,9 +5262,9 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, } Expected<std::unique_ptr<Module>> -BitcodeModule::getLazyModule(LLVMContext &Context, - bool ShouldLazyLoadMetadata) { - return getModuleImpl(Context, false, ShouldLazyLoadMetadata); +BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata, + bool IsImporting) { + return getModuleImpl(Context, false, ShouldLazyLoadMetadata, IsImporting); } // Parse the specified bitcode buffer, returning the function info index. @@ -5323,20 +5326,20 @@ static Expected<BitcodeModule> getSingleModule(MemoryBufferRef Buffer) { } Expected<std::unique_ptr<Module>> -llvm::getLazyBitcodeModule(MemoryBufferRef Buffer, - LLVMContext &Context, bool ShouldLazyLoadMetadata) { +llvm::getLazyBitcodeModule(MemoryBufferRef Buffer, LLVMContext &Context, + bool ShouldLazyLoadMetadata, bool IsImporting) { Expected<BitcodeModule> BM = getSingleModule(Buffer); if (!BM) return BM.takeError(); - return BM->getLazyModule(Context, ShouldLazyLoadMetadata); + return BM->getLazyModule(Context, ShouldLazyLoadMetadata, IsImporting); } -Expected<std::unique_ptr<Module>> -llvm::getOwningLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer, - LLVMContext &Context, - bool ShouldLazyLoadMetadata) { - auto MOrErr = getLazyBitcodeModule(*Buffer, Context, ShouldLazyLoadMetadata); +Expected<std::unique_ptr<Module>> llvm::getOwningLazyBitcodeModule( + std::unique_ptr<MemoryBuffer> &&Buffer, LLVMContext &Context, + bool ShouldLazyLoadMetadata, bool IsImporting) { + auto MOrErr = getLazyBitcodeModule(*Buffer, Context, ShouldLazyLoadMetadata, + IsImporting); if (MOrErr) (*MOrErr)->setOwnedMemoryBuffer(std::move(Buffer)); return MOrErr; @@ -5344,7 +5347,7 @@ llvm::getOwningLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer, Expected<std::unique_ptr<Module>> BitcodeModule::parseModule(LLVMContext &Context) { - return getModuleImpl(Context, true, false); + return getModuleImpl(Context, true, false, false); // TODO: Restore the use-lists to the in-memory state when the bitcode was // written. We must defer until the Module has been fully materialized. } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 1e28411d01e..eb24ac6def1 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -86,6 +86,12 @@ using namespace llvm; +/// Flag whether we need to import full type definitions for ThinLTO. +/// Currently needed for Darwin and LLDB. +static cl::opt<bool> ImportFullTypeDefinitions( + "import-full-type-definitions", cl::init(false), cl::Hidden, + cl::desc("Import full type definitions for ThinLTO.")); + namespace { static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >> 1; } @@ -399,7 +405,7 @@ public: Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule), getTypeByID(getTypeByID) {} - Error parseMetadata(bool ModuleLevel); + Error parseMetadata(bool ModuleLevel, bool IsImporting); bool hasFwdRefs() const { return MetadataList.hasFwdRefs(); } Metadata *getMetadataFwdRef(unsigned Idx) { @@ -435,7 +441,8 @@ Error error(const Twine &Message) { /// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing /// module level metadata. -Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { +Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel, + bool IsImporting) { if (!ModuleLevel && MetadataList.hasFwdRefs()) return error("Invalid metadata: fwd refs into function blocks"); @@ -709,18 +716,38 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { Metadata *File = getMDOrNull(Record[3]); unsigned Line = Record[4]; Metadata *Scope = getDITypeRefOrNull(Record[5]); - Metadata *BaseType = getDITypeRefOrNull(Record[6]); + Metadata *BaseType = nullptr; uint64_t SizeInBits = Record[7]; if (Record[8] > (uint64_t)std::numeric_limits<uint32_t>::max()) return error("Alignment value is too large"); uint32_t AlignInBits = Record[8]; - uint64_t OffsetInBits = Record[9]; + uint64_t OffsetInBits = 0; DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]); - Metadata *Elements = getMDOrNull(Record[11]); + Metadata *Elements = nullptr; unsigned RuntimeLang = Record[12]; - Metadata *VTableHolder = getDITypeRefOrNull(Record[13]); - Metadata *TemplateParams = getMDOrNull(Record[14]); + Metadata *VTableHolder = nullptr; + Metadata *TemplateParams = nullptr; auto *Identifier = getMDString(Record[15]); + // If this module is being parsed so that it can be ThinLTO imported + // into another module, composite types only need to be imported + // as type declarations (unless full type definitions requested). + // Create type declarations up front to save memory. Also, buildODRType + // handles the case where this is type ODRed with a definition needed + // by the importing module, in which case the existing definition is + // used. + if (IsImporting && !ImportFullTypeDefinitions && + (Tag == dwarf::DW_TAG_enumeration_type || + Tag == dwarf::DW_TAG_class_type || + Tag == dwarf::DW_TAG_structure_type || + Tag == dwarf::DW_TAG_union_type)) { + Flags = Flags | DINode::FlagFwdDecl; + } else { + BaseType = getDITypeRefOrNull(Record[6]); + OffsetInBits = Record[9]; + Elements = getMDOrNull(Record[11]); + VTableHolder = getDITypeRefOrNull(Record[13]); + TemplateParams = getMDOrNull(Record[14]); + } DICompositeType *CT = nullptr; if (Identifier) CT = DICompositeType::buildODRType( @@ -1281,17 +1308,19 @@ MetadataLoader &MetadataLoader::operator=(MetadataLoader &&RHS) { return *this; } MetadataLoader::MetadataLoader(MetadataLoader &&RHS) - : Pimpl(std::move(RHS.Pimpl)) {} + : Pimpl(std::move(RHS.Pimpl)), IsImporting(RHS.IsImporting) {} MetadataLoader::~MetadataLoader() = default; MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module &TheModule, BitcodeReaderValueList &ValueList, + bool IsImporting, std::function<Type *(unsigned)> getTypeByID) : Pimpl(llvm::make_unique<MetadataLoaderImpl>(Stream, TheModule, ValueList, - getTypeByID)) {} + getTypeByID)), + IsImporting(IsImporting) {} Error MetadataLoader::parseMetadata(bool ModuleLevel) { - return Pimpl->parseMetadata(ModuleLevel); + return Pimpl->parseMetadata(ModuleLevel, IsImporting); } bool MetadataLoader::hasFwdRefs() const { return Pimpl->hasFwdRefs(); } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.h b/llvm/lib/Bitcode/Reader/MetadataLoader.h index 7d1027e9d52..351857e342c 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.h +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.h @@ -36,12 +36,14 @@ class Type; class MetadataLoader { class MetadataLoaderImpl; std::unique_ptr<MetadataLoaderImpl> Pimpl; + /// True if metadata is being parsed for a module being ThinLTO imported. + bool IsImporting = false; Error parseMetadata(bool ModuleLevel); public: ~MetadataLoader(); MetadataLoader(BitstreamCursor &Stream, Module &TheModule, - BitcodeReaderValueList &ValueList, + BitcodeReaderValueList &ValueList, bool IsImporting, std::function<Type *(unsigned)> getTypeByID); MetadataLoader &operator=(MetadataLoader &&); MetadataLoader(MetadataLoader &&); diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 09198591da9..7364f0e0cd3 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -252,7 +252,8 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) { // ModuleSymbolTable. for (auto BM : *BMsOrErr) { Expected<std::unique_ptr<Module>> MOrErr = - BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true); + BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true, + /*IsImporting*/ false); if (!MOrErr) return MOrErr.takeError(); @@ -415,7 +416,8 @@ Error LTO::addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI, RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule); } Expected<std::unique_ptr<Module>> MOrErr = - BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true); + BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true, + /*IsImporting*/ false); if (!MOrErr) return MOrErr.takeError(); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index dbb54f34565..6342cbe4fd9 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -356,7 +356,8 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream, auto I = ModuleMap.find(Identifier); assert(I != ModuleMap.end()); return I->second.getLazyModule(Mod.getContext(), - /*ShouldLazyLoadMetadata=*/true); + /*ShouldLazyLoadMetadata=*/true, + /*IsImporting*/ true); }; FunctionImporter Importer(CombinedIndex, ModuleLoader); diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 950930176c0..2791efc69cd 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -168,12 +168,13 @@ static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index) { static std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context, - bool Lazy) { + bool Lazy, bool IsImporting) { SMDiagnostic Err; Expected<std::unique_ptr<Module>> ModuleOrErr = - Lazy ? getLazyBitcodeModule(Buffer, Context, - /* ShouldLazyLoadMetadata */ true) - : parseBitcodeFile(Buffer, Context); + Lazy + ? getLazyBitcodeModule(Buffer, Context, + /* ShouldLazyLoadMetadata */ true, IsImporting) + : parseBitcodeFile(Buffer, Context); if (!ModuleOrErr) { handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) { SMDiagnostic Err = SMDiagnostic(Buffer.getBufferIdentifier(), @@ -191,7 +192,7 @@ crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index, const FunctionImporter::ImportMapTy &ImportList) { auto Loader = [&](StringRef Identifier) { return loadModuleFromBuffer(ModuleMap[Identifier], TheModule.getContext(), - /*Lazy=*/true); + /*Lazy=*/true, /*IsImporting*/ true); }; FunctionImporter Importer(Index, Loader); @@ -787,7 +788,8 @@ void ThinLTOCodeGenerator::run() { Context.setDiscardValueNames(LTODiscardValueNames); // Parse module now - auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false); + auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false, + /*IsImporting*/ false); // CodeGen ProducedBinaries[count] = codegen(*TheModule); @@ -933,7 +935,8 @@ void ThinLTOCodeGenerator::run() { } // Parse module now - auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false); + auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false, + /*IsImporting*/ false); // Save temps: original file. saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc"); diff --git a/llvm/lib/Object/IRObjectFile.cpp b/llvm/lib/Object/IRObjectFile.cpp index 2d055e14470..adbf0de6d1b 100644 --- a/llvm/lib/Object/IRObjectFile.cpp +++ b/llvm/lib/Object/IRObjectFile.cpp @@ -127,7 +127,8 @@ IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) { std::vector<std::unique_ptr<Module>> Mods; for (auto BM : *BMsOrErr) { Expected<std::unique_ptr<Module>> MOrErr = - BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true); + BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true, + /*IsImporting*/ false); if (!MOrErr) return MOrErr.takeError(); diff --git a/llvm/test/ThinLTO/X86/Inputs/debuginfo-compositetype-import.ll b/llvm/test/ThinLTO/X86/Inputs/debuginfo-compositetype-import.ll new file mode 100644 index 00000000000..7e80c4d7c44 --- /dev/null +++ b/llvm/test/ThinLTO/X86/Inputs/debuginfo-compositetype-import.ll @@ -0,0 +1,13 @@ +; ModuleID = 'debuginfo-compositetype-import2.c' +source_filename = "debuginfo-compositetype-import2.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define i32 @main() { +entry: + call void (...) @foo() + ret i32 0 +} + +declare void @foo(...) #1 diff --git a/llvm/test/ThinLTO/X86/debuginfo-compositetype-import.ll b/llvm/test/ThinLTO/X86/debuginfo-compositetype-import.ll new file mode 100644 index 00000000000..0b3a7a45224 --- /dev/null +++ b/llvm/test/ThinLTO/X86/debuginfo-compositetype-import.ll @@ -0,0 +1,62 @@ +; Test to ensure DICompositeType are imported as type declarations +; for ThinLTO + +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/debuginfo-compositetype-import.ll -o %t2.bc +; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc + +; By default, composite types are imported as type declarations +; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s +; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.out -save-temps \ +; RUN: -r %t2.bc,main,plx \ +; RUN: -r %t2.bc,foo,l \ +; RUN: -r %t1.bc,foo,pl +; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s + +; CHECK: distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "enum", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 50, size: 32, flags: DIFlagFwdDecl, identifier: "enum") +; CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, name: "class", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 728, size: 448, flags: DIFlagFwdDecl, identifier: "class") +; CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 309, size: 128, flags: DIFlagFwdDecl, identifier: "list") +; CHECK: distinct !DICompositeType(tag: DW_TAG_union_type, file: !{{[0-9]+}}, line: 115, size: 384, flags: DIFlagFwdDecl, identifier: "union") + +; Ensure that full type definitions of composite types are imported if requested +; RUN: llvm-lto -import-full-type-definitions -thinlto-action=import %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL +; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.out -save-temps \ +; RUN: -import-full-type-definitions \ +; RUN: -r %t2.bc,main,plx \ +; RUN: -r %t2.bc,foo,l \ +; RUN: -r %t1.bc,foo,pl +; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s --check-prefix=FULL + +; FULL: distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "enum", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 50, size: 32, elements: !{{[0-9]+}}, identifier: "enum") +; FULL: distinct !DICompositeType(tag: DW_TAG_class_type, name: "class", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 728, size: 448, elements: !{{[0-9]+}}, identifier: "class") +; FULL: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 309, baseType: !{{[0-9]+}}, size: 128, offset: 64, elements: !{{[0-9]+}}, vtableHolder: !{{[0-9]+}}, templateParams: !{{[0-9]+}}, identifier: "list") +; FULL: distinct !DICompositeType(tag: DW_TAG_union_type, file: !{{[0-9]+}}, line: 115, size: 384, elements: !{{[0-9]+}}, identifier: "union") + +; ModuleID = 'debuginfo-compositetype-import.c' +source_filename = "debuginfo-compositetype-import.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define void @foo() #0 !dbg !6 { +entry: + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} +!llvm.ident = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 (trunk 286863) (llvm/trunk 286875)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "debuginfo-compositetype-import.c", directory: "") +!2 = !{i32 2, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{!"clang version 4.0.0 (trunk 286863) (llvm/trunk 286875)"} +!5 = !{} +!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, variables: !5) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !10, !11, !12} +!9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "enum", scope: !1, file: !1, line: 50, size: 32, elements: !5, identifier: "enum") +!10 = !DICompositeType(tag: DW_TAG_class_type, name: "class", scope: !1, file: !1, line: 728, size: 448, elements: !5, identifier: "class") +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", scope: !1, file: !1, line: 309, baseType: !10, size: 128, offset: 64, elements: !5, vtableHolder: !10, templateParams: !5, identifier: "list") +!12 = distinct !DICompositeType(tag: DW_TAG_union_type, file: !1, line: 115, size: 384, elements: !5, identifier: "union") |