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/Twine.h"
12 #include "llvm/CodeGen/AsmPrinter.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCStreamer.h"
20 DwarfStringPool::DwarfStringPool(BumpPtrAllocator
&A
, AsmPrinter
&Asm
,
22 : Pool(A
), Prefix(Prefix
),
23 ShouldCreateSymbols(Asm
.doesDwarfUseRelocationsAcrossSections()) {}
25 StringMapEntry
<DwarfStringPool::EntryTy
> &
26 DwarfStringPool::getEntryImpl(AsmPrinter
&Asm
, StringRef Str
) {
27 auto I
= Pool
.insert(std::make_pair(Str
, EntryTy()));
28 auto &Entry
= I
.first
->second
;
30 Entry
.Index
= EntryTy::NotIndexed
;
31 Entry
.Offset
= NumBytes
;
32 Entry
.Symbol
= ShouldCreateSymbols
? Asm
.createTempSymbol(Prefix
) : nullptr;
34 NumBytes
+= Str
.size() + 1;
39 DwarfStringPool::EntryRef
DwarfStringPool::getEntry(AsmPrinter
&Asm
,
41 auto &MapEntry
= getEntryImpl(Asm
, Str
);
42 return EntryRef(MapEntry
);
45 DwarfStringPool::EntryRef
DwarfStringPool::getIndexedEntry(AsmPrinter
&Asm
,
47 auto &MapEntry
= getEntryImpl(Asm
, Str
);
48 if (!MapEntry
.getValue().isIndexed())
49 MapEntry
.getValue().Index
= NumIndexedStrings
++;
50 return EntryRef(MapEntry
);
53 void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter
&Asm
,
56 if (getNumIndexedStrings() == 0)
58 Asm
.OutStreamer
->switchSection(Section
);
59 unsigned EntrySize
= Asm
.getDwarfOffsetByteSize();
60 // We are emitting the header for a contribution to the string offsets
61 // table. The header consists of an entry with the contribution's
62 // size (not including the size of the length field), the DWARF version and
63 // 2 bytes of padding.
64 Asm
.emitDwarfUnitLength(getNumIndexedStrings() * EntrySize
+ 4,
65 "Length of String Offsets Set");
66 Asm
.emitInt16(Asm
.getDwarfVersion());
68 // Define the symbol that marks the start of the contribution. It is
69 // referenced by most unit headers via DW_AT_str_offsets_base.
70 // Split units do not use the attribute.
72 Asm
.OutStreamer
->emitLabel(StartSym
);
75 void DwarfStringPool::emit(AsmPrinter
&Asm
, MCSection
*StrSection
,
76 MCSection
*OffsetSection
, bool UseRelativeOffsets
) {
80 // Start the dwarf str section.
81 Asm
.OutStreamer
->switchSection(StrSection
);
83 // Get all of the string pool entries and sort them by their offset.
84 SmallVector
<const StringMapEntry
<EntryTy
> *, 64> Entries
;
85 Entries
.reserve(Pool
.size());
87 for (const auto &E
: Pool
)
88 Entries
.push_back(&E
);
90 llvm::sort(Entries
, [](const StringMapEntry
<EntryTy
> *A
,
91 const StringMapEntry
<EntryTy
> *B
) {
92 return A
->getValue().Offset
< B
->getValue().Offset
;
95 for (const auto &Entry
: Entries
) {
96 assert(ShouldCreateSymbols
== static_cast<bool>(Entry
->getValue().Symbol
) &&
97 "Mismatch between setting and entry");
99 // Emit a label for reference from debug information entries.
100 if (ShouldCreateSymbols
)
101 Asm
.OutStreamer
->emitLabel(Entry
->getValue().Symbol
);
103 // Emit the string itself with a terminating null byte.
104 Asm
.OutStreamer
->AddComment("string offset=" +
105 Twine(Entry
->getValue().Offset
));
106 Asm
.OutStreamer
->emitBytes(
107 StringRef(Entry
->getKeyData(), Entry
->getKeyLength() + 1));
110 // If we've got an offset section go ahead and emit that now as well.
112 // Now only take the indexed entries and put them in an array by their ID so
113 // we can emit them in order.
114 Entries
.resize(NumIndexedStrings
);
115 for (const auto &Entry
: Pool
) {
116 if (Entry
.getValue().isIndexed())
117 Entries
[Entry
.getValue().Index
] = &Entry
;
120 Asm
.OutStreamer
->switchSection(OffsetSection
);
121 unsigned size
= Asm
.getDwarfOffsetByteSize();
122 for (const auto &Entry
: Entries
)
123 if (UseRelativeOffsets
)
124 Asm
.emitDwarfStringOffset(Entry
->getValue());
126 Asm
.OutStreamer
->emitIntValue(Entry
->getValue().Offset
, size
);