<div dir="ltr">Any idea if there's work to add str_index support to the name tables?<br><br>I guess the idea is that it's more efficient to have one fewer indirections for strings, and worth the cost in duplicate relocations/bytes/etc? *shrug*<br><br>(also one question inline \/)<br><br><div class="gmail_quote"><div dir="ltr">On Tue, Aug 21, 2018 at 11:22 AM Pavel Labath via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: labath<br>
Date: Tue Aug 7 02:54:52 2018<br>
New Revision: 339122<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=339122&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=339122&view=rev</a><br>
Log:<br>
[DebugInfo] Reduce debug_str_offsets section size<br>
<br>
Summary:<br>
The accelerator tables use the debug_str section to store their strings.<br>
However, they do not support the indirect method of access that is<br>
available for the debug_info section (DW_FORM_strx et al.).<br>
<br>
Currently our code is assuming that all strings can/will be referenced<br>
indirectly, and puts all of them into the debug_str_offsets section.<br>
This is generally true for regular (unsplit) dwarf, but in the DWO case,<br>
most of the strings in the debug_str section will only be used from the<br>
accelerator tables. Therefore the contents of the debug_str_offsets<br>
section will be largely unused and bloating the main executable.<br>
<br>
This patch rectifies this by teaching the DwarfStringPool to<br>
differentiate between strings accessed directly and indirectly. When a<br>
user inserts a string into the pool it has to declare whether that<br>
string will be referenced directly or not. If at least one user requsts<br>
indirect access, that string will be assigned an index ID and put into<br>
debug_str_offsets table. Otherwise, the offset table is skipped.<br>
<br>
This approach reduces the overall binary size (when compiled with<br>
-gdwarf-5 -gsplit-dwarf) in my tests by about 2% (debug_str_offsets is<br>
shrunk by 99%).<br>
<br>
Reviewers: probinson, dblaikie, JDevlieghere<br>
<br>
Subscribers: aprantl, mgrang, llvm-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D49493" rel="noreferrer" target="_blank">https://reviews.llvm.org/D49493</a><br>
<br>
Added:<br>
llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll<br>
Modified:<br>
llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp<br>
llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll<br>
llvm/trunk/tools/dsymutil/DwarfStreamer.cpp<br>
llvm/trunk/tools/dsymutil/MachOUtils.cpp<br>
llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp<br>
llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h<br>
llvm/trunk/unittests/CodeGen/DIEHashTest.cpp<br>
llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp<br>
llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h Tue Aug 7 02:54:52 2018<br>
@@ -10,6 +10,7 @@<br>
#ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H<br>
#define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H<br>
<br>
+#include "llvm/ADT/PointerIntPair.h"<br>
#include "llvm/ADT/StringMap.h"<br>
<br>
namespace llvm {<br>
@@ -18,34 +19,52 @@ class MCSymbol;<br>
<br>
/// Data for a string pool entry.<br>
struct DwarfStringPoolEntry {<br>
+ static constexpr unsigned NotIndexed = -1;<br>
+<br>
MCSymbol *Symbol;<br>
unsigned Offset;<br>
unsigned Index;<br>
+<br>
+ bool isIndexed() const { return Index != NotIndexed; }<br>
};<br>
<br>
/// String pool entry reference.<br>
-struct DwarfStringPoolEntryRef {<br>
- const StringMapEntry<DwarfStringPoolEntry> *I = nullptr;<br>
+class DwarfStringPoolEntryRef {<br>
+ PointerIntPair<const StringMapEntry<DwarfStringPoolEntry> *, 1, bool><br>
+ MapEntryAndIndexed;<br>
+<br>
+ const StringMapEntry<DwarfStringPoolEntry> *getMapEntry() const {<br>
+ return MapEntryAndIndexed.getPointer();<br>
+ }<br>
<br>
public:<br>
DwarfStringPoolEntryRef() = default;<br>
- explicit DwarfStringPoolEntryRef(<br>
- const StringMapEntry<DwarfStringPoolEntry> &I)<br>
- : I(&I) {}<br>
+ DwarfStringPoolEntryRef(const StringMapEntry<DwarfStringPoolEntry> &Entry,<br>
+ bool Indexed)<br>
+ : MapEntryAndIndexed(&Entry, Indexed) {}<br>
<br>
- explicit operator bool() const { return I; }<br>
+ explicit operator bool() const { return getMapEntry(); }<br>
MCSymbol *getSymbol() const {<br>
- assert(I->second.Symbol && "No symbol available!");<br>
- return I->second.Symbol;<br>
+ assert(getMapEntry()->second.Symbol && "No symbol available!");<br>
+ return getMapEntry()->second.Symbol;<br>
}<br>
- unsigned getOffset() const { return I->second.Offset; }<br>
- unsigned getIndex() const { return I->second.Index; }<br>
- StringRef getString() const { return I->first(); }<br>
+ unsigned getOffset() const { return getMapEntry()->second.Offset; }<br>
+ bool isIndexed() const { return MapEntryAndIndexed.getInt(); }<br>
+ unsigned getIndex() const {<br>
+ assert(isIndexed());<br>
+ assert(getMapEntry()->getValue().isIndexed());<br>
+ return getMapEntry()->second.Index;<br>
+ }<br>
+ StringRef getString() const { return getMapEntry()->first(); }<br>
/// Return the entire string pool entry for convenience.<br>
- DwarfStringPoolEntry getEntry() const { return I->getValue(); }<br>
+ DwarfStringPoolEntry getEntry() const { return getMapEntry()->getValue(); }<br>
<br>
- bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; }<br>
- bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; }<br>
+ bool operator==(const DwarfStringPoolEntryRef &X) const {<br>
+ return getMapEntry() == X.getMapEntry();<br>
+ }<br>
+ bool operator!=(const DwarfStringPoolEntryRef &X) const {<br>
+ return getMapEntry() != X.getMapEntry();<br>
+ }<br>
};<br>
<br>
} // end namespace llvm<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Aug 7 02:54:52 2018<br>
@@ -2437,8 +2437,7 @@ void DwarfDebug::addAccelNameImpl(AccelT<br>
return;<br>
<br>
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;<br>
- DwarfStringPoolEntryRef Ref =<br>
- Holder.getStringPool().getEntry(*Asm, Name);<br>
+ DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm, Name);<br>
<br>
switch (getAccelTableKind()) {<br>
case AccelTableKind::Apple:<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp Tue Aug 7 02:54:52 2018<br>
@@ -24,25 +24,39 @@ DwarfStringPool::DwarfStringPool(BumpPtr<br>
: Pool(A), Prefix(Prefix),<br>
ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}<br>
<br>
-DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,<br>
- StringRef Str) {<br>
+StringMapEntry<DwarfStringPool::EntryTy> &<br>
+DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {<br>
auto I = Pool.insert(std::make_pair(Str, EntryTy()));<br>
+ auto &Entry = I.first->second;<br>
if (I.second) {<br>
- auto &Entry = I.first->second;<br>
- Entry.Index = Pool.size() - 1;<br>
+ Entry.Index = EntryTy::NotIndexed;<br>
Entry.Offset = NumBytes;<br>
Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;<br>
<br>
NumBytes += Str.size() + 1;<br>
assert(NumBytes > Entry.Offset && "Unexpected overflow");<br>
}<br>
- return EntryRef(*I.first);<br>
+ return *I.first;<br>
+}<br>
+<br>
+DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,<br>
+ StringRef Str) {<br>
+ auto &MapEntry = getEntryImpl(Asm, Str);<br>
+ return EntryRef(MapEntry, false);<br>
+}<br>
+<br>
+DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm,<br>
+ StringRef Str) {<br>
+ auto &MapEntry = getEntryImpl(Asm, Str);<br>
+ if (!MapEntry.getValue().isIndexed())<br>
+ MapEntry.getValue().Index = NumIndexedStrings++;<br>
+ return EntryRef(MapEntry, true);<br>
}<br>
<br>
void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,<br>
MCSection *Section,<br>
MCSymbol *StartSym) {<br>
- if (empty())<br>
+ if (getNumIndexedStrings() == 0)<br>
return;<br>
Asm.OutStreamer->SwitchSection(Section);<br>
unsigned EntrySize = 4;<br>
@@ -51,7 +65,7 @@ void DwarfStringPool::emitStringOffsetsT<br>
// table. The header consists of an entry with the contribution's<br>
// size (not including the size of the length field), the DWARF version and<br>
// 2 bytes of padding.<br>
- Asm.emitInt32(size() * EntrySize + 4);<br>
+ Asm.emitInt32(getNumIndexedStrings() * EntrySize + 4);<br>
Asm.emitInt16(Asm.getDwarfVersion());<br>
Asm.emitInt16(0);<br>
// Define the symbol that marks the start of the contribution. It is<br>
@@ -69,12 +83,18 @@ void DwarfStringPool::emit(AsmPrinter &A<br>
// Start the dwarf str section.<br>
Asm.OutStreamer->SwitchSection(StrSection);<br>
<br>
- // Get all of the string pool entries and put them in an array by their ID so<br>
- // we can sort them.<br>
- SmallVector<const StringMapEntry<EntryTy> *, 64> Entries(Pool.size());<br>
+ // Get all of the string pool entries and sort them by their offset.<br>
+ SmallVector<const StringMapEntry<EntryTy> *, 64> Entries;<br>
+ Entries.reserve(Pool.size());<br>
<br>
for (const auto &E : Pool)<br>
- Entries[E.getValue().Index] = &E;<br>
+ Entries.push_back(&E);<br>
+<br>
+ llvm::sort(<br>
+ Entries.begin(), Entries.end(),<br>
+ [](const StringMapEntry<EntryTy> *A, const StringMapEntry<EntryTy> *B) {<br>
+ return A->getValue().Offset < B->getValue().Offset;<br>
+ });<br>
<br>
for (const auto &Entry : Entries) {<br>
assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&<br>
@@ -93,6 +113,14 @@ void DwarfStringPool::emit(AsmPrinter &A<br>
<br>
// If we've got an offset section go ahead and emit that now as well.<br>
if (OffsetSection) {<br>
+ // Now only take the indexed entries and put them in an array by their ID so<br>
+ // we can emit them in order.<br>
+ Entries.resize(NumIndexedStrings);<br>
+ for (const auto &Entry : Pool) {<br>
+ if (Entry.getValue().isIndexed())<br>
+ Entries[Entry.getValue().Index] = &Entry;<br>
+ }<br>
+<br>
Asm.OutStreamer->SwitchSection(OffsetSection);<br>
unsigned size = 4; // FIXME: DWARF64 is 8.<br>
for (const auto &Entry : Entries)<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h Tue Aug 7 02:54:52 2018<br>
@@ -30,8 +30,11 @@ class DwarfStringPool {<br>
StringMap<EntryTy, BumpPtrAllocator &> Pool;<br>
StringRef Prefix;<br>
unsigned NumBytes = 0;<br>
+ unsigned NumIndexedStrings = 0;<br>
bool ShouldCreateSymbols;<br>
<br>
+ StringMapEntry<EntryTy> &getEntryImpl(AsmPrinter &Asm, StringRef Str);<br>
+<br>
public:<br>
using EntryRef = DwarfStringPoolEntryRef;<br>
<br>
@@ -48,8 +51,15 @@ public:<br>
<br>
unsigned size() const { return Pool.size(); }<br>
<br>
+ unsigned getNumIndexedStrings() const { return NumIndexedStrings; }<br>
+<br>
/// Get a reference to an entry in the string pool.<br>
EntryRef getEntry(AsmPrinter &Asm, StringRef Str);<br>
+<br>
+ /// Same as getEntry, except that you can use EntryRef::getIndex to obtain a<br>
+ /// unique ID of this entry (e.g., for use in indexed forms like<br>
+ /// DW_FORM_strx).<br>
+ EntryRef getIndexedEntry(AsmPrinter &Asm, StringRef Str);<br>
};<br>
<br>
} // end namespace llvm<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Tue Aug 7 02:54:52 2018<br>
@@ -243,9 +243,14 @@ void DwarfUnit::addString(DIE &Die, dwar<br>
DIEInlineString(String, DIEValueAllocator));<br>
return;<br>
}<br>
- auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String);<br>
dwarf::Form IxForm =<br>
isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp;<br>
+<br>
+ auto StringPoolEntry =<br>
+ useSegmentedStringOffsetsTable() || IxForm == dwarf::DW_FORM_GNU_str_index<br>
+ ? DU->getStringPool().getIndexedEntry(*Asm, String)<br>
+ : DU->getStringPool().getEntry(*Asm, String);<br>
+<br>
// For DWARF v5 and beyond, use the smallest strx? form possible.<br>
if (useSegmentedStringOffsetsTable()) {<br>
IxForm = dwarf::DW_FORM_strx1;<br>
<br>
Added: llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll?rev=339122&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll?rev=339122&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll (added)<br>
+++ llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll Tue Aug 7 02:54:52 2018<br>
@@ -0,0 +1,79 @@<br>
+; REQUIRES: object-emission<br>
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=foo.dwo -filetype=obj < %s \<br>
+; RUN: | llvm-dwarfdump -v - | FileCheck %s<br>
+<br>
+; This triggers a situation where the order of entries in the .debug_str and<br>
+; .debug_str_offsets sections does not match and makes sure that all entries are<br>
+; still wired up correctly.<br>
+<br>
+; Produced with "clang -S -emit-llvm -gdwarf-5" from source "int X;", copied<br>
+; three times and modified by hand.<br></blockquote><div><br>Could you describe in the comment what modifications were necessary?<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+; CHECK: .debug_info contents:<br>
+; CHECK: DW_TAG_compile_unit<br>
+; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string = "X3")<br>
+; CHECK: DW_TAG_compile_unit<br>
+; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000002) string = "X2")<br>
+; CHECK: DW_TAG_compile_unit<br>
+; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000003) string = "X1")<br>
+; CHECK: .debug_info.dwo contents:<br>
+<br>
+; CHECK: .debug_str contents:<br>
+; CHECK: 0x[[X3:[0-9a-f]*]]: "X3"<br>
+; CHECK: 0x[[X1:[0-9a-f]*]]: "X1"<br>
+; CHECK: 0x[[X2:[0-9a-f]*]]: "X2"<br>
+<br>
+; CHECK: .debug_str_offsets contents:<br>
+; CHECK: Format = DWARF32, Version = 5<br>
+; CHECK-NEXT: 00000000 "foo.dwo"<br>
+; CHECK-NEXT: [[X3]] "X3"<br>
+; CHECK-NEXT: [[X2]] "X2"<br>
+; CHECK-NEXT: [[X1]] "X1"<br>
+; CHECK-EMPTY:<br>
+<br>
+<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!10, !20, !30}<br>
+!llvm.module.flags = !{!0, !1, !2}<br>
+!llvm.ident = !{!3}<br>
+<br>
+!0 = !{i32 2, !"Dwarf Version", i32 5}<br>
+!1 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!2 = !{i32 1, !"wchar_size", i32 4}<br>
+!3 = !{!"clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)"}<br>
+<br>
+<br>
+@X1 = dso_local global i32 0, align 4, !dbg !11<br>
+<br>
+!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !13, producer: "clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !14, globals: !15)<br>
+!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression())<br>
+!12 = distinct !DIGlobalVariable(name: "X1", scope: !10, file: !16, line: 1, type: !17, isLocal: false, isDefinition: true)<br>
+!13 = !DIFile(filename: "-", directory: "X3", checksumkind: CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")<br>
+!14 = !{}<br>
+!15 = !{!11}<br>
+!16 = !DIFile(filename: "<stdin>", directory: "X3", checksumkind: CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")<br>
+!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+<br>
+<br>
+@X2 = dso_local global i32 0, align 4, !dbg !21<br>
+<br>
+!20 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !23, producer: "clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !24, globals: !25)<br>
+!21 = !DIGlobalVariableExpression(var: !22, expr: !DIExpression())<br>
+!22 = distinct !DIGlobalVariable(name: "X2", scope: !20, file: !26, line: 1, type: !27, isLocal: false, isDefinition: true)<br>
+!23 = !DIFile(filename: "-", directory: "X2", checksumkind: CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")<br>
+!24 = !{}<br>
+!25 = !{!21}<br>
+!26 = !DIFile(filename: "<stdin>", directory: "X2", checksumkind: CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")<br>
+!27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+<br>
+<br>
+@X3 = dso_local global i32 0, align 4, !dbg !31<br>
+<br>
+!30 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !33, producer: "clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !34, globals: !35)<br>
+!31 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression())<br>
+!32 = distinct !DIGlobalVariable(name: "X3", scope: !30, file: !36, line: 1, type: !37, isLocal: false, isDefinition: true)<br>
+!33 = !DIFile(filename: "-", directory: "X1", checksumkind: CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")<br>
+!34 = !{}<br>
+!35 = !{!31}<br>
+!36 = !DIFile(filename: "<stdin>", directory: "X1", checksumkind: CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")<br>
+!37 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
<br>
Modified: llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll Tue Aug 7 02:54:52 2018<br>
@@ -1,7 +1,7 @@<br>
; REQUIRES: object-emission<br>
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj < %s | llvm-dwarfdump -v - \<br>
; RUN: | FileCheck --check-prefix=MONOLITHIC %s<br>
-; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=%t.dwo -filetype=obj < %s \<br>
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=foo.dwo -filetype=obj < %s \<br>
; RUN: | llvm-dwarfdump -v - | FileCheck --check-prefix=SPLIT %s<br>
<br>
; This basic test checks the emission of a DWARF v5 string offsets table in<br>
@@ -59,6 +59,8 @@<br>
; SPLIT: DW_TAG_compile_unit<br>
; SPLIT-NOT: {{DW_TAG|contents:}}<br>
; SPLIT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)<br>
+; SPLIT: DW_AT_GNU_dwo_name [DW_FORM_strx1] ( indexed (00000000) string = "foo.dwo")<br>
+; SPLIT: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string = "/home/test")<br>
<br>
; Check for the split CU in .debug_info.dwo.<br>
; SPLIT: .debug_info.dwo contents:<br>
@@ -79,10 +81,10 @@<br>
;<br>
; Extract the string offsets referenced in the main file by the skeleton unit.<br>
; SPLIT: .debug_str contents:<br>
-; SPLIT-NEXT: 0x00000000:{{.*}}<br>
-; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]{{.*}}<br>
-; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]{{.*}}<br>
-; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]{{.*}}<br>
+; SPLIT-NEXT: 0x00000000: "foo.dwo"<br>
+; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]: "/home/test"<br>
+; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]: "E"<br>
+; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]: "glob"<br>
;<br>
; Extract the string offsets referenced in the .dwo file by the split unit.<br>
; SPLIT: .debug_str.dwo contents:<br>
@@ -91,13 +93,15 @@<br>
; SPLIT-NEXT: 0x[[STRING3DWO:[0-9a-f]*]]{{.*}}<br>
;<br>
; Check the string offsets sections in both the main and the .dwo files and<br>
-; verify that the extracted string offsets are referenced correctly.<br>
+; verify that the extracted string offsets are referenced correctly. The<br>
+; sections should contain only the offsets of strings that are actually<br>
+; referenced by the debug info.<br>
; SPLIT: .debug_str_offsets contents:<br>
-; SPLIT-NEXT: 0x00000000: Contribution size = 20, Format = DWARF32, Version = 5<br>
-; SPLIT-NEXT: 0x00000008: 00000000{{.*}}<br>
-; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]]<br>
-; SPLIT-NEXT: 0x00000010: [[STRING3SPLIT]]<br>
-; SPLIT-NEXT: 0x00000014: [[STRING4SPLIT]]<br>
+; SPLIT-NEXT: 0x00000000: Contribution size = 12, Format = DWARF32, Version = 5<br>
+; SPLIT-NEXT: 0x00000008: 00000000 "foo.dwo"<br>
+; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]] "/home/test"<br>
+; SPLIT-EMPTY:<br>
+<br>
; SPLIT: .debug_str_offsets.dwo contents:<br>
; SPLIT-NEXT: 0x00000000: Contribution size = 36, Format = DWARF32, Version = 5<br>
; SPLIT-NEXT: 0x00000008: 00000000{{.*}}<br>
<br>
Modified: llvm/trunk/tools/dsymutil/DwarfStreamer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/dsymutil/DwarfStreamer.cpp (original)<br>
+++ llvm/trunk/tools/dsymutil/DwarfStreamer.cpp Tue Aug 7 02:54:52 2018<br>
@@ -190,10 +190,8 @@ void DwarfStreamer::emitDIE(DIE &Die) {<br>
/// Emit the debug_str section stored in \p Pool.<br>
void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {<br>
Asm->OutStreamer->SwitchSection(MOFI->getDwarfStrSection());<br>
- std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntries();<br>
+ std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();<br>
for (auto Entry : Entries) {<br>
- if (Entry.getIndex() == -1U)<br>
- break;<br>
// Emit the string itself.<br>
Asm->OutStreamer->EmitBytes(Entry.getString());<br>
// Emit a null terminator.<br>
<br>
Modified: llvm/trunk/tools/dsymutil/MachOUtils.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachOUtils.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachOUtils.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/dsymutil/MachOUtils.cpp (original)<br>
+++ llvm/trunk/tools/dsymutil/MachOUtils.cpp Tue Aug 7 02:54:52 2018<br>
@@ -514,10 +514,9 @@ bool generateDsymCompanion(const DebugMa<br>
// Reproduce that behavior for now (there is corresponding code in<br>
// transferSymbol).<br>
OutFile << '\0';<br>
- std::vector<DwarfStringPoolEntryRef> Strings = NewStrings.getEntries();<br>
+ std::vector<DwarfStringPoolEntryRef> Strings =<br>
+ NewStrings.getEntriesForEmission();<br>
for (auto EntryRef : Strings) {<br>
- if (EntryRef.getIndex() == -1U)<br>
- break;<br>
OutFile.write(EntryRef.getString().data(),<br>
EntryRef.getString().size() + 1);<br>
}<br>
<br>
Modified: llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp (original)<br>
+++ llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp Tue Aug 7 02:54:52 2018<br>
@@ -18,27 +18,28 @@ DwarfStringPoolEntryRef NonRelocatableSt<br>
<br>
auto I = Strings.insert({S, DwarfStringPoolEntry()});<br>
auto &Entry = I.first->second;<br>
- if (I.second || Entry.Index == -1U) {<br>
+ if (I.second || !Entry.isIndexed()) {<br>
Entry.Index = NumEntries++;<br>
Entry.Offset = CurrentEndOffset;<br>
Entry.Symbol = nullptr;<br>
CurrentEndOffset += S.size() + 1;<br>
}<br>
- return DwarfStringPoolEntryRef(*I.first);<br>
+ return DwarfStringPoolEntryRef(*I.first, true);<br>
}<br>
<br>
StringRef NonRelocatableStringpool::internString(StringRef S) {<br>
- DwarfStringPoolEntry Entry{nullptr, 0, -1U};<br>
+ DwarfStringPoolEntry Entry{nullptr, 0, DwarfStringPoolEntry::NotIndexed};<br>
auto InsertResult = Strings.insert({S, Entry});<br>
return InsertResult.first->getKey();<br>
}<br>
<br>
std::vector<DwarfStringPoolEntryRef><br>
-NonRelocatableStringpool::getEntries() const {<br>
+NonRelocatableStringpool::getEntriesForEmission() const {<br>
std::vector<DwarfStringPoolEntryRef> Result;<br>
Result.reserve(Strings.size());<br>
for (const auto &E : Strings)<br>
- Result.emplace_back(E);<br>
+ if (E.getValue().isIndexed())<br>
+ Result.emplace_back(E, true);<br>
llvm::sort(<br>
Result.begin(), Result.end(),<br>
[](const DwarfStringPoolEntryRef A, const DwarfStringPoolEntryRef B) {<br>
<br>
Modified: llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h (original)<br>
+++ llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h Tue Aug 7 02:54:52 2018<br>
@@ -53,7 +53,9 @@ public:<br>
<br>
uint64_t getSize() { return CurrentEndOffset; }<br>
<br>
- std::vector<DwarfStringPoolEntryRef> getEntries() const;<br>
+ /// Return the list of strings to be emitted. This does not contain the<br>
+ /// strings which were added via internString only.<br>
+ std::vector<DwarfStringPoolEntryRef> getEntriesForEmission() const;<br>
<br>
private:<br>
MapTy Strings;<br>
<br>
Modified: llvm/trunk/unittests/CodeGen/DIEHashTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/DIEHashTest.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/DIEHashTest.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/CodeGen/DIEHashTest.cpp (original)<br>
+++ llvm/trunk/unittests/CodeGen/DIEHashTest.cpp Tue Aug 7 02:54:52 2018<br>
@@ -31,8 +31,8 @@ private:<br>
public:<br>
DIEString getString(StringRef S) {<br>
DwarfStringPoolEntry Entry = {nullptr, 1, 1};<br>
- return DIEString(<br>
- DwarfStringPoolEntryRef(*Pool.insert(std::make_pair(S, Entry)).first));<br>
+ return DIEString(DwarfStringPoolEntryRef(<br>
+ *Pool.insert(std::make_pair(S, Entry)).first, Entry.isIndexed()));<br>
}<br>
};<br>
<br>
<br>
Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)<br>
+++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Tue Aug 7 02:54:52 2018<br>
@@ -1007,6 +1007,99 @@ TEST(DWARFDebugInfo, TestDWARF32Version4<br>
TestAddresses<4, AddrType>();<br>
}<br>
<br>
+TEST(DWARFDebugInfo, TestStringOffsets) {<br>
+ Triple Triple = getHostTripleForAddrSize(sizeof(void *));<br>
+ if (!isConfigurationSupported(Triple))<br>
+ return;<br>
+<br>
+ const char *String1 = "Hello";<br>
+ const char *String2 = "World";<br>
+<br>
+ auto ExpectedDG = dwarfgen::Generator::create(Triple, 5);<br>
+ ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());<br>
+ dwarfgen::Generator *DG = ExpectedDG.get().get();<br>
+ dwarfgen::CompileUnit &CU = DG->addCompileUnit();<br>
+ dwarfgen::DIE CUDie = CU.getUnitDIE();<br>
+<br>
+ CUDie.addStrOffsetsBaseAttribute();<br>
+<br>
+ uint16_t Attr = DW_AT_lo_user;<br>
+<br>
+ // Create our strings. First we create a non-indexed reference to String1,<br>
+ // followed by an indexed String2. Finally, we add an indexed reference to<br>
+ // String1.<br>
+ const auto Attr1 = static_cast<dwarf::Attribute>(Attr++);<br>
+ CUDie.addAttribute(Attr1, DW_FORM_strp, String1);<br>
+<br>
+ const auto Attr2 = static_cast<dwarf::Attribute>(Attr++);<br>
+ CUDie.addAttribute(Attr2, DW_FORM_strx, String2);<br>
+<br>
+ const auto Attr3 = static_cast<dwarf::Attribute>(Attr++);<br>
+ CUDie.addAttribute(Attr3, DW_FORM_strx, String1);<br>
+<br>
+ // Generate the DWARF<br>
+ StringRef FileBytes = DG->generate();<br>
+ MemoryBufferRef FileBuffer(FileBytes, "dwarf");<br>
+ auto Obj = object::ObjectFile::createObjectFile(FileBuffer);<br>
+ ASSERT_TRUE((bool)Obj);<br>
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);<br>
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();<br>
+ ASSERT_EQ(NumCUs, 1u);<br>
+ DWARFUnit *U = DwarfContext->getUnitAtIndex(0);<br>
+ auto DieDG = U->getUnitDIE(false);<br>
+ ASSERT_TRUE(DieDG.isValid());<br>
+<br>
+ // Now make sure the string offsets came out properly. Attr2 should have index<br>
+ // 0 (because it was the first indexed string) even though the string itself<br>
+ // was added eariler.<br>
+ auto Extracted1 = toString(DieDG.find(Attr1));<br>
+ ASSERT_TRUE((bool)Extracted1);<br>
+ EXPECT_STREQ(String1, *Extracted1);<br>
+<br>
+ Optional<DWARFFormValue> Form2 = DieDG.find(Attr2);<br>
+ ASSERT_TRUE((bool)Form2);<br>
+ EXPECT_EQ(0u, Form2->getRawUValue());<br>
+ auto Extracted2 = toString(Form2);<br>
+ ASSERT_TRUE((bool)Extracted2);<br>
+ EXPECT_STREQ(String2, *Extracted2);<br>
+<br>
+ Optional<DWARFFormValue> Form3 = DieDG.find(Attr3);<br>
+ ASSERT_TRUE((bool)Form3);<br>
+ EXPECT_EQ(1u, Form3->getRawUValue());<br>
+ auto Extracted3 = toString(Form3);<br>
+ ASSERT_TRUE((bool)Extracted3);<br>
+ EXPECT_STREQ(String1, *Extracted3);<br>
+}<br>
+<br>
+TEST(DWARFDebugInfo, TestEmptyStringOffsets) {<br>
+ Triple Triple = getHostTripleForAddrSize(sizeof(void *));<br>
+ if (!isConfigurationSupported(Triple))<br>
+ return;<br>
+<br>
+ const char *String1 = "Hello";<br>
+<br>
+ auto ExpectedDG = dwarfgen::Generator::create(Triple, 5);<br>
+ ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());<br>
+ dwarfgen::Generator *DG = ExpectedDG.get().get();<br>
+ dwarfgen::CompileUnit &CU = DG->addCompileUnit();<br>
+ dwarfgen::DIE CUDie = CU.getUnitDIE();<br>
+<br>
+ uint16_t Attr = DW_AT_lo_user;<br>
+<br>
+ // We shall insert only one string. It will be referenced directly.<br>
+ const auto Attr1 = static_cast<dwarf::Attribute>(Attr++);<br>
+ CUDie.addAttribute(Attr1, DW_FORM_strp, String1);<br>
+<br>
+ // Generate the DWARF<br>
+ StringRef FileBytes = DG->generate();<br>
+ MemoryBufferRef FileBuffer(FileBytes, "dwarf");<br>
+ auto Obj = object::ObjectFile::createObjectFile(FileBuffer);<br>
+ ASSERT_TRUE((bool)Obj);<br>
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);<br>
+ EXPECT_TRUE(<br>
+ DwarfContext->getDWARFObj().getStringOffsetSection().Data.empty());<br>
+}<br>
+<br>
TEST(DWARFDebugInfo, TestRelations) {<br>
Triple Triple = getHostTripleForAddrSize(sizeof(void *));<br>
if (!isConfigurationSupported(Triple))<br>
<br>
Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp?rev=339122&r1=339121&r2=339122&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp?rev=339122&r1=339121&r2=339122&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp (original)<br>
+++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp Tue Aug 7 02:54:52 2018<br>
@@ -71,15 +71,20 @@ void dwarfgen::DIE::addAttribute(uint16_<br>
break;<br>
<br>
case DW_FORM_strp:<br>
+ Die->addValue(<br>
+ DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,<br>
+ DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));<br>
+ break;<br>
+<br>
case DW_FORM_GNU_str_index:<br>
case DW_FORM_strx:<br>
case DW_FORM_strx1:<br>
case DW_FORM_strx2:<br>
case DW_FORM_strx3:<br>
case DW_FORM_strx4:<br>
- Die->addValue(<br>
- DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,<br>
- DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));<br>
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,<br>
+ DIEString(DG.getStringPool().getIndexedEntry(<br>
+ *DG.getAsmPrinter(), String)));<br>
break;<br>
<br>
default:<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>