xref: /src/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1044eb2f6SDimitry Andric //===- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework -----------===//
25ca98fd9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ca98fd9SDimitry Andric //
75ca98fd9SDimitry Andric //===----------------------------------------------------------------------===//
85ca98fd9SDimitry Andric 
95ca98fd9SDimitry Andric #include "DwarfStringPool.h"
10044eb2f6SDimitry Andric #include "llvm/ADT/SmallVector.h"
11044eb2f6SDimitry Andric #include "llvm/ADT/Twine.h"
125a5ac124SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
135a5ac124SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
145ca98fd9SDimitry Andric #include "llvm/MC/MCStreamer.h"
15044eb2f6SDimitry Andric #include <cassert>
16044eb2f6SDimitry Andric #include <utility>
175ca98fd9SDimitry Andric 
185ca98fd9SDimitry Andric using namespace llvm;
195ca98fd9SDimitry Andric 
DwarfStringPool(BumpPtrAllocator & A,AsmPrinter & Asm,StringRef Prefix)205a5ac124SDimitry Andric DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,
215a5ac124SDimitry Andric                                  StringRef Prefix)
225a5ac124SDimitry Andric     : Pool(A), Prefix(Prefix),
23e3b55780SDimitry Andric       ShouldCreateSymbols(Asm.doesDwarfUseRelocationsAcrossSections()) {}
245a5ac124SDimitry Andric 
25d8e91e46SDimitry Andric StringMapEntry<DwarfStringPool::EntryTy> &
getEntryImpl(AsmPrinter & Asm,StringRef Str)26d8e91e46SDimitry Andric DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {
275a5ac124SDimitry Andric   auto I = Pool.insert(std::make_pair(Str, EntryTy()));
285a5ac124SDimitry Andric   auto &Entry = I.first->second;
29d8e91e46SDimitry Andric   if (I.second) {
30d8e91e46SDimitry Andric     Entry.Index = EntryTy::NotIndexed;
315a5ac124SDimitry Andric     Entry.Offset = NumBytes;
325a5ac124SDimitry Andric     Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;
335a5ac124SDimitry Andric 
345a5ac124SDimitry Andric     NumBytes += Str.size() + 1;
355ca98fd9SDimitry Andric   }
36d8e91e46SDimitry Andric   return *I.first;
37d8e91e46SDimitry Andric }
38d8e91e46SDimitry Andric 
getEntry(AsmPrinter & Asm,StringRef Str)39d8e91e46SDimitry Andric DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
40d8e91e46SDimitry Andric                                                     StringRef Str) {
41d8e91e46SDimitry Andric   auto &MapEntry = getEntryImpl(Asm, Str);
42145449b1SDimitry Andric   return EntryRef(MapEntry);
43d8e91e46SDimitry Andric }
44d8e91e46SDimitry Andric 
getIndexedEntry(AsmPrinter & Asm,StringRef Str)45d8e91e46SDimitry Andric DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm,
46d8e91e46SDimitry Andric                                                            StringRef Str) {
47d8e91e46SDimitry Andric   auto &MapEntry = getEntryImpl(Asm, Str);
48d8e91e46SDimitry Andric   if (!MapEntry.getValue().isIndexed())
49d8e91e46SDimitry Andric     MapEntry.getValue().Index = NumIndexedStrings++;
50145449b1SDimitry Andric   return EntryRef(MapEntry);
515ca98fd9SDimitry Andric }
525ca98fd9SDimitry Andric 
emitStringOffsetsTableHeader(AsmPrinter & Asm,MCSection * Section,MCSymbol * StartSym)53eb11fae6SDimitry Andric void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
54eb11fae6SDimitry Andric                                                    MCSection *Section,
55eb11fae6SDimitry Andric                                                    MCSymbol *StartSym) {
56d8e91e46SDimitry Andric   if (getNumIndexedStrings() == 0)
57eb11fae6SDimitry Andric     return;
58145449b1SDimitry Andric   Asm.OutStreamer->switchSection(Section);
59b60736ecSDimitry Andric   unsigned EntrySize = Asm.getDwarfOffsetByteSize();
60eb11fae6SDimitry Andric   // We are emitting the header for a contribution to the string offsets
61eb11fae6SDimitry Andric   // table. The header consists of an entry with the contribution's
62eb11fae6SDimitry Andric   // size (not including the size of the length field), the DWARF version and
63eb11fae6SDimitry Andric   // 2 bytes of padding.
64b60736ecSDimitry Andric   Asm.emitDwarfUnitLength(getNumIndexedStrings() * EntrySize + 4,
65b60736ecSDimitry Andric                           "Length of String Offsets Set");
66eb11fae6SDimitry Andric   Asm.emitInt16(Asm.getDwarfVersion());
67eb11fae6SDimitry Andric   Asm.emitInt16(0);
68eb11fae6SDimitry Andric   // Define the symbol that marks the start of the contribution. It is
69eb11fae6SDimitry Andric   // referenced by most unit headers via DW_AT_str_offsets_base.
70eb11fae6SDimitry Andric   // Split units do not use the attribute.
71eb11fae6SDimitry Andric   if (StartSym)
72cfca06d7SDimitry Andric     Asm.OutStreamer->emitLabel(StartSym);
73eb11fae6SDimitry Andric }
74eb11fae6SDimitry Andric 
emit(AsmPrinter & Asm,MCSection * StrSection,MCSection * OffsetSection,bool UseRelativeOffsets)755a5ac124SDimitry Andric void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
76eb11fae6SDimitry Andric                            MCSection *OffsetSection, bool UseRelativeOffsets) {
775ca98fd9SDimitry Andric   if (Pool.empty())
785ca98fd9SDimitry Andric     return;
795ca98fd9SDimitry Andric 
805ca98fd9SDimitry Andric   // Start the dwarf str section.
81145449b1SDimitry Andric   Asm.OutStreamer->switchSection(StrSection);
825ca98fd9SDimitry Andric 
83d8e91e46SDimitry Andric   // Get all of the string pool entries and sort them by their offset.
84d8e91e46SDimitry Andric   SmallVector<const StringMapEntry<EntryTy> *, 64> Entries;
85d8e91e46SDimitry Andric   Entries.reserve(Pool.size());
865ca98fd9SDimitry Andric 
875ca98fd9SDimitry Andric   for (const auto &E : Pool)
88d8e91e46SDimitry Andric     Entries.push_back(&E);
89d8e91e46SDimitry Andric 
90d8e91e46SDimitry Andric   llvm::sort(Entries, [](const StringMapEntry<EntryTy> *A,
91d8e91e46SDimitry Andric                          const StringMapEntry<EntryTy> *B) {
92d8e91e46SDimitry Andric     return A->getValue().Offset < B->getValue().Offset;
93d8e91e46SDimitry Andric   });
945ca98fd9SDimitry Andric 
955ca98fd9SDimitry Andric   for (const auto &Entry : Entries) {
965a5ac124SDimitry Andric     assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&
975a5ac124SDimitry Andric            "Mismatch between setting and entry");
985a5ac124SDimitry Andric 
995ca98fd9SDimitry Andric     // Emit a label for reference from debug information entries.
1005a5ac124SDimitry Andric     if (ShouldCreateSymbols)
101cfca06d7SDimitry Andric       Asm.OutStreamer->emitLabel(Entry->getValue().Symbol);
1025ca98fd9SDimitry Andric 
1035ca98fd9SDimitry Andric     // Emit the string itself with a terminating null byte.
1045a5ac124SDimitry Andric     Asm.OutStreamer->AddComment("string offset=" +
1055a5ac124SDimitry Andric                                 Twine(Entry->getValue().Offset));
106cfca06d7SDimitry Andric     Asm.OutStreamer->emitBytes(
1075ca98fd9SDimitry Andric         StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1));
1085ca98fd9SDimitry Andric   }
1095ca98fd9SDimitry Andric 
1105ca98fd9SDimitry Andric   // If we've got an offset section go ahead and emit that now as well.
1115ca98fd9SDimitry Andric   if (OffsetSection) {
112d8e91e46SDimitry Andric     // Now only take the indexed entries and put them in an array by their ID so
113d8e91e46SDimitry Andric     // we can emit them in order.
114d8e91e46SDimitry Andric     Entries.resize(NumIndexedStrings);
115d8e91e46SDimitry Andric     for (const auto &Entry : Pool) {
116d8e91e46SDimitry Andric       if (Entry.getValue().isIndexed())
117d8e91e46SDimitry Andric         Entries[Entry.getValue().Index] = &Entry;
118d8e91e46SDimitry Andric     }
119d8e91e46SDimitry Andric 
120145449b1SDimitry Andric     Asm.OutStreamer->switchSection(OffsetSection);
121b60736ecSDimitry Andric     unsigned size = Asm.getDwarfOffsetByteSize();
1225a5ac124SDimitry Andric     for (const auto &Entry : Entries)
123eb11fae6SDimitry Andric       if (UseRelativeOffsets)
124eb11fae6SDimitry Andric         Asm.emitDwarfStringOffset(Entry->getValue());
125eb11fae6SDimitry Andric       else
126cfca06d7SDimitry Andric         Asm.OutStreamer->emitIntValue(Entry->getValue().Offset, size);
1275ca98fd9SDimitry Andric   }
1285ca98fd9SDimitry Andric }
129