1 //===- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework -----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "DwarfStringPool.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/CodeGen/AsmPrinter.h"
14 #include "llvm/MC/MCAsmInfo.h"
15 #include "llvm/MC/MCStreamer.h"
21 DwarfStringPool::DwarfStringPool(BumpPtrAllocator
&A
, AsmPrinter
&Asm
,
23 : Pool(A
), Prefix(Prefix
),
24 ShouldCreateSymbols(Asm
.MAI
->doesDwarfUseRelocationsAcrossSections()) {}
26 StringMapEntry
<DwarfStringPool::EntryTy
> &
27 DwarfStringPool::getEntryImpl(AsmPrinter
&Asm
, StringRef Str
) {
28 auto I
= Pool
.insert(std::make_pair(Str
, EntryTy()));
29 auto &Entry
= I
.first
->second
;
31 Entry
.Index
= EntryTy::NotIndexed
;
32 Entry
.Offset
= NumBytes
;
33 Entry
.Symbol
= ShouldCreateSymbols
? Asm
.createTempSymbol(Prefix
) : nullptr;
35 NumBytes
+= Str
.size() + 1;
36 assert(NumBytes
> Entry
.Offset
&& "Unexpected overflow");
41 DwarfStringPool::EntryRef
DwarfStringPool::getEntry(AsmPrinter
&Asm
,
43 auto &MapEntry
= getEntryImpl(Asm
, Str
);
44 return EntryRef(MapEntry
, false);
47 DwarfStringPool::EntryRef
DwarfStringPool::getIndexedEntry(AsmPrinter
&Asm
,
49 auto &MapEntry
= getEntryImpl(Asm
, Str
);
50 if (!MapEntry
.getValue().isIndexed())
51 MapEntry
.getValue().Index
= NumIndexedStrings
++;
52 return EntryRef(MapEntry
, true);
55 void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter
&Asm
,
58 if (getNumIndexedStrings() == 0)
60 Asm
.OutStreamer
->SwitchSection(Section
);
61 unsigned EntrySize
= 4;
63 // We are emitting the header for a contribution to the string offsets
64 // table. The header consists of an entry with the contribution's
65 // size (not including the size of the length field), the DWARF version and
66 // 2 bytes of padding.
67 Asm
.emitInt32(getNumIndexedStrings() * EntrySize
+ 4);
68 Asm
.emitInt16(Asm
.getDwarfVersion());
70 // Define the symbol that marks the start of the contribution. It is
71 // referenced by most unit headers via DW_AT_str_offsets_base.
72 // Split units do not use the attribute.
74 Asm
.OutStreamer
->EmitLabel(StartSym
);
77 void DwarfStringPool::emit(AsmPrinter
&Asm
, MCSection
*StrSection
,
78 MCSection
*OffsetSection
, bool UseRelativeOffsets
) {
82 // Start the dwarf str section.
83 Asm
.OutStreamer
->SwitchSection(StrSection
);
85 // Get all of the string pool entries and sort them by their offset.
86 SmallVector
<const StringMapEntry
<EntryTy
> *, 64> Entries
;
87 Entries
.reserve(Pool
.size());
89 for (const auto &E
: Pool
)
90 Entries
.push_back(&E
);
92 llvm::sort(Entries
, [](const StringMapEntry
<EntryTy
> *A
,
93 const StringMapEntry
<EntryTy
> *B
) {
94 return A
->getValue().Offset
< B
->getValue().Offset
;
97 for (const auto &Entry
: Entries
) {
98 assert(ShouldCreateSymbols
== static_cast<bool>(Entry
->getValue().Symbol
) &&
99 "Mismatch between setting and entry");
101 // Emit a label for reference from debug information entries.
102 if (ShouldCreateSymbols
)
103 Asm
.OutStreamer
->EmitLabel(Entry
->getValue().Symbol
);
105 // Emit the string itself with a terminating null byte.
106 Asm
.OutStreamer
->AddComment("string offset=" +
107 Twine(Entry
->getValue().Offset
));
108 Asm
.OutStreamer
->EmitBytes(
109 StringRef(Entry
->getKeyData(), Entry
->getKeyLength() + 1));
112 // If we've got an offset section go ahead and emit that now as well.
114 // Now only take the indexed entries and put them in an array by their ID so
115 // we can emit them in order.
116 Entries
.resize(NumIndexedStrings
);
117 for (const auto &Entry
: Pool
) {
118 if (Entry
.getValue().isIndexed())
119 Entries
[Entry
.getValue().Index
] = &Entry
;
122 Asm
.OutStreamer
->SwitchSection(OffsetSection
);
123 unsigned size
= 4; // FIXME: DWARF64 is 8.
124 for (const auto &Entry
: Entries
)
125 if (UseRelativeOffsets
)
126 Asm
.emitDwarfStringOffset(Entry
->getValue());
128 Asm
.OutStreamer
->EmitIntValue(Entry
->getValue().Offset
, size
);