Index: include/llvm/CodeGen/DwarfStringPoolEntry.h =================================================================== --- include/llvm/CodeGen/DwarfStringPoolEntry.h +++ include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -18,9 +18,13 @@ /// Data for a string pool entry. struct DwarfStringPoolEntry { + static constexpr unsigned NotIndexed = -1; + MCSymbol *Symbol; unsigned Offset; unsigned Index; + + bool isIndexed() const { return Index != NotIndexed; } }; /// String pool entry reference. Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2403,7 +2403,8 @@ assert(getAccelTableKind() == AccelTableKind::Dwarf); DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - AccelDebugNames.addName(Holder.getStringPool().getEntry(*Asm, Name), Die); + AccelDebugNames.addName( + Holder.getStringPool().getEntry(*Asm, Name, /*Indexed*/ false), Die); } // Accelerator table mutators - add each name along with its companion @@ -2413,7 +2414,9 @@ void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { switch (getAccelTableKind()) { case AccelTableKind::Apple: - AccelNames.addName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); + AccelNames.addName( + InfoHolder.getStringPool().getEntry(*Asm, Name, /*Indexed*/ false), + &Die); break; case AccelTableKind::Dwarf: addAccelDebugName(Name, Die); @@ -2428,14 +2431,16 @@ void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { if (getAccelTableKind() != AccelTableKind::Apple) return; - AccelObjC.addName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); + AccelObjC.addName( + InfoHolder.getStringPool().getEntry(*Asm, Name, /*Indexed*/ false), &Die); } void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { switch (getAccelTableKind()) { case AccelTableKind::Apple: - AccelNamespace.addName(InfoHolder.getStringPool().getEntry(*Asm, Name), - &Die); + AccelNamespace.addName( + InfoHolder.getStringPool().getEntry(*Asm, Name, /*Indexed*/ false), + &Die); break; case AccelTableKind::Dwarf: addAccelDebugName(Name, Die); @@ -2450,7 +2455,9 @@ void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { switch (getAccelTableKind()) { case AccelTableKind::Apple: - AccelTypes.addName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); + AccelTypes.addName( + InfoHolder.getStringPool().getEntry(*Asm, Name, /*Indexed*/ false), + &Die); break; case AccelTableKind::Dwarf: addAccelDebugName(Name, Die); Index: lib/CodeGen/AsmPrinter/DwarfFile.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -38,7 +38,7 @@ // table. The header consists of an entry with the contribution's // size (not including the size of the length field), the DWARF version and // 2 bytes of padding. - Asm->emitInt32(StrPool.size() * EntrySize + 4); + Asm->emitInt32(StrPool.getNumIndexedStrings() * EntrySize + 4); Asm->emitInt16(Asm->getDwarfVersion()); Asm->emitInt16(0); // Define the symbol that marks the start of the contribution. It is Index: lib/CodeGen/AsmPrinter/DwarfStringPool.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfStringPool.h +++ lib/CodeGen/AsmPrinter/DwarfStringPool.h @@ -29,6 +29,7 @@ StringMap Pool; StringRef Prefix; unsigned NumBytes = 0; + unsigned NumIndexedStrings = 0; bool ShouldCreateSymbols; public: @@ -44,8 +45,13 @@ unsigned size() const { return Pool.size(); } - /// Get a reference to an entry in the string pool. - EntryRef getEntry(AsmPrinter &Asm, StringRef Str); + unsigned getNumIndexedStrings() const { return NumIndexedStrings; } + + /// Get a reference to an entry in the string pool. Set Indexed to true if you + /// intend to refer to this string using the indexed forms (DW_FORM_strx, + /// ...). In this case, the string will be assigned an index ID, and it's + /// offset will be emitted in the respective offsets section. + EntryRef getEntry(AsmPrinter &Asm, StringRef Str, bool Indexed); }; } // end namespace llvm Index: lib/CodeGen/AsmPrinter/DwarfStringPool.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfStringPool.cpp +++ lib/CodeGen/AsmPrinter/DwarfStringPool.cpp @@ -24,18 +24,20 @@ : Pool(A), Prefix(Prefix), ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {} -DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm, - StringRef Str) { +DwarfStringPool::EntryRef +DwarfStringPool::getEntry(AsmPrinter &Asm, StringRef Str, bool Indexed) { auto I = Pool.insert(std::make_pair(Str, EntryTy())); + auto &Entry = I.first->second; if (I.second) { - auto &Entry = I.first->second; - Entry.Index = Pool.size() - 1; + Entry.Index = EntryTy::NotIndexed; Entry.Offset = NumBytes; Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr; NumBytes += Str.size() + 1; assert(NumBytes > Entry.Offset && "Unexpected overflow"); } + if (Indexed && !Entry.isIndexed()) + Entry.Index = NumIndexedStrings++; return EntryRef(*I.first); } @@ -47,12 +49,18 @@ // Start the dwarf str section. Asm.OutStreamer->SwitchSection(StrSection); - // Get all of the string pool entries and put them in an array by their ID so - // we can sort them. - SmallVector *, 64> Entries(Pool.size()); + // Get all of the string pool entries and sort them by their offset. + SmallVector *, 64> Entries; + Entries.reserve(Pool.size()); for (const auto &E : Pool) - Entries[E.getValue().Index] = &E; + Entries.push_back(&E); + + std::sort( + Entries.begin(), Entries.end(), + [](const StringMapEntry *A, const StringMapEntry *B) { + return A->getValue().Offset < B->getValue().Offset; + }); for (const auto &Entry : Entries) { assert(ShouldCreateSymbols == static_cast(Entry->getValue().Symbol) && @@ -71,6 +79,14 @@ // If we've got an offset section go ahead and emit that now as well. if (OffsetSection) { + // Now only take the indexed entries and put them in an array by their ID so + // we can emit them in order. + Entries.resize(NumIndexedStrings); + for (const auto &Entry : Pool) { + if (Entry.getValue().isIndexed()) + Entries[Entry.getValue().Index] = &Entry; + } + Asm.OutStreamer->SwitchSection(OffsetSection); unsigned size = 4; // FIXME: DWARF64 is 8. for (const auto &Entry : Entries) Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -240,9 +240,13 @@ DIEInlineString(String, DIEValueAllocator)); return; } - auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String); dwarf::Form IxForm = isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp; + + auto StringPoolEntry = + DU->getStringPool().getEntry(*Asm, String, + useSegmentedStringOffsetsTable() || + IxForm == dwarf::DW_FORM_GNU_str_index); // For DWARF v5 and beyond, use the smallest strx? form possible. if (useSegmentedStringOffsetsTable()) { IxForm = dwarf::DW_FORM_strx1; Index: test/DebugInfo/X86/string-offsets-table.ll =================================================================== --- test/DebugInfo/X86/string-offsets-table.ll +++ test/DebugInfo/X86/string-offsets-table.ll @@ -1,7 +1,7 @@ ; REQUIRES: object-emission ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj < %s | llvm-dwarfdump -v - \ ; RUN: | FileCheck --check-prefix=MONOLITHIC %s -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=%t.dwo -filetype=obj < %s \ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=foo.dwo -filetype=obj < %s \ ; RUN: | llvm-dwarfdump -v - | FileCheck --check-prefix=SPLIT %s ; This basic test checks the emission of a DWARF v5 string offsets table in @@ -59,6 +59,8 @@ ; SPLIT: DW_TAG_compile_unit ; SPLIT-NOT: {{DW_TAG|contents:}} ; SPLIT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) +; SPLIT: DW_AT_GNU_dwo_name [DW_FORM_strx1] ( indexed (00000000) string = "foo.dwo") +; SPLIT: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string = "/home/test") ; Check for the split CU in .debug_info.dwo. ; SPLIT: .debug_info.dwo contents: @@ -79,10 +81,10 @@ ; ; Extract the string offsets referenced in the main file by the skeleton unit. ; SPLIT: .debug_str contents: -; SPLIT-NEXT: 0x00000000:{{.*}} -; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]{{.*}} -; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]{{.*}} -; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]{{.*}} +; SPLIT-NEXT: 0x00000000: "foo.dwo" +; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]: "/home/test" +; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]: "E" +; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]: "glob" ; ; Extract the string offsets referenced in the .dwo file by the split unit. ; SPLIT: .debug_str.dwo contents: @@ -91,13 +93,15 @@ ; SPLIT-NEXT: 0x[[STRING3DWO:[0-9a-f]*]]{{.*}} ; ; Check the string offsets sections in both the main and the .dwo files and -; verify that the extracted string offsets are referenced correctly. +; verify that the extracted string offsets are referenced correctly. The +; sections should contain only the offsets that of strings that are actually +; referenced by the debug info. ; SPLIT: .debug_str_offsets contents: -; SPLIT-NEXT: 0x00000000: Contribution size = 20, Format = DWARF32, Version = 5 -; SPLIT-NEXT: 0x00000008: 00000000{{.*}} -; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]] -; SPLIT-NEXT: 0x00000010: [[STRING3SPLIT]] -; SPLIT-NEXT: 0x00000014: [[STRING4SPLIT]] +; SPLIT-NEXT: 0x00000000: Contribution size = 12, Format = DWARF32, Version = 5 +; SPLIT-NEXT: 0x00000008: 00000000 "foo.dwo" +; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]] "/home/test" +; SPLIT-EMPTY: + ; SPLIT: .debug_str_offsets.dwo contents: ; SPLIT-NEXT: 0x00000000: Contribution size = 36, Format = DWARF32, Version = 5 ; SPLIT-NEXT: 0x00000008: 00000000{{.*}} Index: unittests/DebugInfo/DWARF/DwarfGenerator.cpp =================================================================== --- unittests/DebugInfo/DWARF/DwarfGenerator.cpp +++ unittests/DebugInfo/DWARF/DwarfGenerator.cpp @@ -61,9 +61,9 @@ new (DG.getAllocator()) DIEInlineString(String, DG.getAllocator())); } else { - Die->addValue( - DG.getAllocator(), static_cast(A), Form, - DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String))); + Die->addValue(DG.getAllocator(), static_cast(A), Form, + DIEString(DG.getStringPool().getEntry( + *DG.getAsmPrinter(), String, /*Indexed*/ false))); } }