1 //===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
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 // This file contains support for writing accelerator tables.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/CodeGen/AccelTable.h"
14 #include "DwarfCompileUnit.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/BinaryFormat/Dwarf.h"
19 #include "llvm/CodeGen/AsmPrinter.h"
20 #include "llvm/CodeGen/DIE.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCStreamer.h"
23 #include "llvm/MC/MCSymbol.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Target/TargetLoweringObjectFile.h"
34 void AccelTableBase::computeBucketCount() {
35 // First get the number of unique hashes.
36 std::vector
<uint32_t> Uniques
;
37 Uniques
.reserve(Entries
.size());
38 for (const auto &E
: Entries
)
39 Uniques
.push_back(E
.second
.HashValue
);
40 array_pod_sort(Uniques
.begin(), Uniques
.end());
41 std::vector
<uint32_t>::iterator P
=
42 std::unique(Uniques
.begin(), Uniques
.end());
44 UniqueHashCount
= std::distance(Uniques
.begin(), P
);
46 if (UniqueHashCount
> 1024)
47 BucketCount
= UniqueHashCount
/ 4;
48 else if (UniqueHashCount
> 16)
49 BucketCount
= UniqueHashCount
/ 2;
51 BucketCount
= std::max
<uint32_t>(UniqueHashCount
, 1);
54 void AccelTableBase::finalize(AsmPrinter
*Asm
, StringRef Prefix
) {
55 // Create the individual hash data outputs.
56 for (auto &E
: Entries
) {
57 // Unique the entries.
58 llvm::stable_sort(E
.second
.Values
,
59 [](const AccelTableData
*A
, const AccelTableData
*B
) {
62 E
.second
.Values
.erase(
63 std::unique(E
.second
.Values
.begin(), E
.second
.Values
.end()),
64 E
.second
.Values
.end());
67 // Figure out how many buckets we need, then compute the bucket contents and
68 // the final ordering. The hashes and offsets can be emitted by walking these
69 // data structures. We add temporary symbols to the data so they can be
70 // referenced when emitting the offsets.
73 // Compute bucket contents and final ordering.
74 Buckets
.resize(BucketCount
);
75 for (auto &E
: Entries
) {
76 uint32_t Bucket
= E
.second
.HashValue
% BucketCount
;
77 Buckets
[Bucket
].push_back(&E
.second
);
78 E
.second
.Sym
= Asm
->createTempSymbol(Prefix
);
81 // Sort the contents of the buckets by hash value so that hash collisions end
82 // up together. Stable sort makes testing easier and doesn't cost much more.
83 for (auto &Bucket
: Buckets
)
84 llvm::stable_sort(Bucket
, [](HashData
*LHS
, HashData
*RHS
) {
85 return LHS
->HashValue
< RHS
->HashValue
;
90 /// Base class for writing out Accelerator tables. It holds the common
91 /// functionality for the two Accelerator table types.
92 class AccelTableWriter
{
94 AsmPrinter
*const Asm
; ///< Destination.
95 const AccelTableBase
&Contents
; ///< Data to emit.
97 /// Controls whether to emit duplicate hash and offset table entries for names
98 /// with identical hashes. Apple tables don't emit duplicate entries, DWARF v5
100 const bool SkipIdenticalHashes
;
102 void emitHashes() const;
104 /// Emit offsets to lists of entries with identical names. The offsets are
105 /// relative to the Base argument.
106 void emitOffsets(const MCSymbol
*Base
) const;
109 AccelTableWriter(AsmPrinter
*Asm
, const AccelTableBase
&Contents
,
110 bool SkipIdenticalHashes
)
111 : Asm(Asm
), Contents(Contents
), SkipIdenticalHashes(SkipIdenticalHashes
) {
115 class AppleAccelTableWriter
: public AccelTableWriter
{
116 using Atom
= AppleAccelTableData::Atom
;
118 /// The fixed header of an Apple Accelerator Table.
120 uint32_t Magic
= MagicHash
;
121 uint16_t Version
= 1;
122 uint16_t HashFunction
= dwarf::DW_hash_function_djb
;
123 uint32_t BucketCount
;
125 uint32_t HeaderDataLength
;
127 /// 'HASH' magic value to detect endianness.
128 static const uint32_t MagicHash
= 0x48415348;
130 Header(uint32_t BucketCount
, uint32_t UniqueHashCount
, uint32_t DataLength
)
131 : BucketCount(BucketCount
), HashCount(UniqueHashCount
),
132 HeaderDataLength(DataLength
) {}
134 void emit(AsmPrinter
*Asm
) const;
136 void print(raw_ostream
&OS
) const;
137 void dump() const { print(dbgs()); }
141 /// The HeaderData describes the structure of an Apple accelerator table
142 /// through a list of Atoms.
144 /// In the case of data that is referenced via DW_FORM_ref_* the offset
145 /// base is used to describe the offset for all forms in the list of atoms.
146 uint32_t DieOffsetBase
;
148 const SmallVector
<Atom
, 4> Atoms
;
150 HeaderData(ArrayRef
<Atom
> AtomList
, uint32_t Offset
= 0)
151 : DieOffsetBase(Offset
), Atoms(AtomList
.begin(), AtomList
.end()) {}
153 void emit(AsmPrinter
*Asm
) const;
155 void print(raw_ostream
&OS
) const;
156 void dump() const { print(dbgs()); }
161 HeaderData HeaderData
;
162 const MCSymbol
*SecBegin
;
164 void emitBuckets() const;
165 void emitData() const;
168 AppleAccelTableWriter(AsmPrinter
*Asm
, const AccelTableBase
&Contents
,
169 ArrayRef
<Atom
> Atoms
, const MCSymbol
*SecBegin
)
170 : AccelTableWriter(Asm
, Contents
, true),
171 Header(Contents
.getBucketCount(), Contents
.getUniqueHashCount(),
172 8 + (Atoms
.size() * 4)),
173 HeaderData(Atoms
), SecBegin(SecBegin
) {}
178 void print(raw_ostream
&OS
) const;
179 void dump() const { print(dbgs()); }
183 /// Class responsible for emitting a DWARF v5 Accelerator Table. The only
184 /// public function is emit(), which performs the actual emission.
186 /// The class is templated in its data type. This allows us to emit both dyamic
187 /// and static data entries. A callback abstract the logic to provide a CU
188 /// index for a given entry, which is different per data type, but identical
189 /// for every entry in the same table.
190 template <typename DataT
>
191 class Dwarf5AccelTableWriter
: public AccelTableWriter
{
193 uint16_t Version
= 5;
194 uint16_t Padding
= 0;
195 uint32_t CompUnitCount
;
196 uint32_t LocalTypeUnitCount
= 0;
197 uint32_t ForeignTypeUnitCount
= 0;
198 uint32_t BucketCount
;
200 uint32_t AbbrevTableSize
= 0;
201 uint32_t AugmentationStringSize
= sizeof(AugmentationString
);
202 char AugmentationString
[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
204 Header(uint32_t CompUnitCount
, uint32_t BucketCount
, uint32_t NameCount
)
205 : CompUnitCount(CompUnitCount
), BucketCount(BucketCount
),
206 NameCount(NameCount
) {}
208 void emit(Dwarf5AccelTableWriter
&Ctx
);
210 struct AttributeEncoding
{
216 DenseMap
<uint32_t, SmallVector
<AttributeEncoding
, 2>> Abbreviations
;
217 ArrayRef
<MCSymbol
*> CompUnits
;
218 llvm::function_ref
<unsigned(const DataT
&)> getCUIndexForEntry
;
219 MCSymbol
*ContributionEnd
= nullptr;
220 MCSymbol
*AbbrevStart
= Asm
->createTempSymbol("names_abbrev_start");
221 MCSymbol
*AbbrevEnd
= Asm
->createTempSymbol("names_abbrev_end");
222 MCSymbol
*EntryPool
= Asm
->createTempSymbol("names_entries");
224 DenseSet
<uint32_t> getUniqueTags() const;
226 // Right now, we emit uniform attributes for all tags.
227 SmallVector
<AttributeEncoding
, 2> getUniformAttributes() const;
229 void emitCUList() const;
230 void emitBuckets() const;
231 void emitStringOffsets() const;
232 void emitAbbrevs() const;
233 void emitEntry(const DataT
&Entry
) const;
234 void emitData() const;
237 Dwarf5AccelTableWriter(
238 AsmPrinter
*Asm
, const AccelTableBase
&Contents
,
239 ArrayRef
<MCSymbol
*> CompUnits
,
240 llvm::function_ref
<unsigned(const DataT
&)> GetCUIndexForEntry
);
246 void AccelTableWriter::emitHashes() const {
247 uint64_t PrevHash
= std::numeric_limits
<uint64_t>::max();
248 unsigned BucketIdx
= 0;
249 for (auto &Bucket
: Contents
.getBuckets()) {
250 for (auto &Hash
: Bucket
) {
251 uint32_t HashValue
= Hash
->HashValue
;
252 if (SkipIdenticalHashes
&& PrevHash
== HashValue
)
254 Asm
->OutStreamer
->AddComment("Hash in Bucket " + Twine(BucketIdx
));
255 Asm
->emitInt32(HashValue
);
256 PrevHash
= HashValue
;
262 void AccelTableWriter::emitOffsets(const MCSymbol
*Base
) const {
263 const auto &Buckets
= Contents
.getBuckets();
264 uint64_t PrevHash
= std::numeric_limits
<uint64_t>::max();
265 for (size_t i
= 0, e
= Buckets
.size(); i
< e
; ++i
) {
266 for (auto *Hash
: Buckets
[i
]) {
267 uint32_t HashValue
= Hash
->HashValue
;
268 if (SkipIdenticalHashes
&& PrevHash
== HashValue
)
270 PrevHash
= HashValue
;
271 Asm
->OutStreamer
->AddComment("Offset in Bucket " + Twine(i
));
272 Asm
->emitLabelDifference(Hash
->Sym
, Base
, Asm
->getDwarfOffsetByteSize());
277 void AppleAccelTableWriter::Header::emit(AsmPrinter
*Asm
) const {
278 Asm
->OutStreamer
->AddComment("Header Magic");
279 Asm
->emitInt32(Magic
);
280 Asm
->OutStreamer
->AddComment("Header Version");
281 Asm
->emitInt16(Version
);
282 Asm
->OutStreamer
->AddComment("Header Hash Function");
283 Asm
->emitInt16(HashFunction
);
284 Asm
->OutStreamer
->AddComment("Header Bucket Count");
285 Asm
->emitInt32(BucketCount
);
286 Asm
->OutStreamer
->AddComment("Header Hash Count");
287 Asm
->emitInt32(HashCount
);
288 Asm
->OutStreamer
->AddComment("Header Data Length");
289 Asm
->emitInt32(HeaderDataLength
);
292 void AppleAccelTableWriter::HeaderData::emit(AsmPrinter
*Asm
) const {
293 Asm
->OutStreamer
->AddComment("HeaderData Die Offset Base");
294 Asm
->emitInt32(DieOffsetBase
);
295 Asm
->OutStreamer
->AddComment("HeaderData Atom Count");
296 Asm
->emitInt32(Atoms
.size());
298 for (const Atom
&A
: Atoms
) {
299 Asm
->OutStreamer
->AddComment(dwarf::AtomTypeString(A
.Type
));
300 Asm
->emitInt16(A
.Type
);
301 Asm
->OutStreamer
->AddComment(dwarf::FormEncodingString(A
.Form
));
302 Asm
->emitInt16(A
.Form
);
306 void AppleAccelTableWriter::emitBuckets() const {
307 const auto &Buckets
= Contents
.getBuckets();
309 for (size_t i
= 0, e
= Buckets
.size(); i
< e
; ++i
) {
310 Asm
->OutStreamer
->AddComment("Bucket " + Twine(i
));
311 if (!Buckets
[i
].empty())
312 Asm
->emitInt32(index
);
314 Asm
->emitInt32(std::numeric_limits
<uint32_t>::max());
315 // Buckets point in the list of hashes, not to the data. Do not increment
316 // the index multiple times in case of hash collisions.
317 uint64_t PrevHash
= std::numeric_limits
<uint64_t>::max();
318 for (auto *HD
: Buckets
[i
]) {
319 uint32_t HashValue
= HD
->HashValue
;
320 if (PrevHash
!= HashValue
)
322 PrevHash
= HashValue
;
327 void AppleAccelTableWriter::emitData() const {
328 const auto &Buckets
= Contents
.getBuckets();
329 for (const AccelTableBase::HashList
&Bucket
: Buckets
) {
330 uint64_t PrevHash
= std::numeric_limits
<uint64_t>::max();
331 for (auto &Hash
: Bucket
) {
332 // Terminate the previous entry if there is no hash collision with the
334 if (PrevHash
!= std::numeric_limits
<uint64_t>::max() &&
335 PrevHash
!= Hash
->HashValue
)
337 // Remember to emit the label for our offset.
338 Asm
->OutStreamer
->emitLabel(Hash
->Sym
);
339 Asm
->OutStreamer
->AddComment(Hash
->Name
.getString());
340 Asm
->emitDwarfStringOffset(Hash
->Name
);
341 Asm
->OutStreamer
->AddComment("Num DIEs");
342 Asm
->emitInt32(Hash
->Values
.size());
343 for (const auto *V
: Hash
->Values
)
344 static_cast<const AppleAccelTableData
*>(V
)->emit(Asm
);
345 PrevHash
= Hash
->HashValue
;
347 // Emit the final end marker for the bucket.
353 void AppleAccelTableWriter::emit() const {
355 HeaderData
.emit(Asm
);
358 emitOffsets(SecBegin
);
362 template <typename DataT
>
363 void Dwarf5AccelTableWriter
<DataT
>::Header::emit(Dwarf5AccelTableWriter
&Ctx
) {
364 assert(CompUnitCount
> 0 && "Index must have at least one CU.");
366 AsmPrinter
*Asm
= Ctx
.Asm
;
367 Ctx
.ContributionEnd
=
368 Asm
->emitDwarfUnitLength("names", "Header: unit length");
369 Asm
->OutStreamer
->AddComment("Header: version");
370 Asm
->emitInt16(Version
);
371 Asm
->OutStreamer
->AddComment("Header: padding");
372 Asm
->emitInt16(Padding
);
373 Asm
->OutStreamer
->AddComment("Header: compilation unit count");
374 Asm
->emitInt32(CompUnitCount
);
375 Asm
->OutStreamer
->AddComment("Header: local type unit count");
376 Asm
->emitInt32(LocalTypeUnitCount
);
377 Asm
->OutStreamer
->AddComment("Header: foreign type unit count");
378 Asm
->emitInt32(ForeignTypeUnitCount
);
379 Asm
->OutStreamer
->AddComment("Header: bucket count");
380 Asm
->emitInt32(BucketCount
);
381 Asm
->OutStreamer
->AddComment("Header: name count");
382 Asm
->emitInt32(NameCount
);
383 Asm
->OutStreamer
->AddComment("Header: abbreviation table size");
384 Asm
->emitLabelDifference(Ctx
.AbbrevEnd
, Ctx
.AbbrevStart
, sizeof(uint32_t));
385 Asm
->OutStreamer
->AddComment("Header: augmentation string size");
386 assert(AugmentationStringSize
% 4 == 0);
387 Asm
->emitInt32(AugmentationStringSize
);
388 Asm
->OutStreamer
->AddComment("Header: augmentation string");
389 Asm
->OutStreamer
->emitBytes({AugmentationString
, AugmentationStringSize
});
392 template <typename DataT
>
393 DenseSet
<uint32_t> Dwarf5AccelTableWriter
<DataT
>::getUniqueTags() const {
394 DenseSet
<uint32_t> UniqueTags
;
395 for (auto &Bucket
: Contents
.getBuckets()) {
396 for (auto *Hash
: Bucket
) {
397 for (auto *Value
: Hash
->Values
) {
398 unsigned Tag
= static_cast<const DataT
*>(Value
)->getDieTag();
399 UniqueTags
.insert(Tag
);
406 template <typename DataT
>
407 SmallVector
<typename Dwarf5AccelTableWriter
<DataT
>::AttributeEncoding
, 2>
408 Dwarf5AccelTableWriter
<DataT
>::getUniformAttributes() const {
409 SmallVector
<AttributeEncoding
, 2> UA
;
410 if (CompUnits
.size() > 1) {
411 size_t LargestCUIndex
= CompUnits
.size() - 1;
412 dwarf::Form Form
= DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex
);
413 UA
.push_back({dwarf::DW_IDX_compile_unit
, Form
});
415 UA
.push_back({dwarf::DW_IDX_die_offset
, dwarf::DW_FORM_ref4
});
419 template <typename DataT
>
420 void Dwarf5AccelTableWriter
<DataT
>::emitCUList() const {
421 for (const auto &CU
: enumerate(CompUnits
)) {
422 Asm
->OutStreamer
->AddComment("Compilation unit " + Twine(CU
.index()));
423 Asm
->emitDwarfSymbolReference(CU
.value());
427 template <typename DataT
>
428 void Dwarf5AccelTableWriter
<DataT
>::emitBuckets() const {
430 for (const auto &Bucket
: enumerate(Contents
.getBuckets())) {
431 Asm
->OutStreamer
->AddComment("Bucket " + Twine(Bucket
.index()));
432 Asm
->emitInt32(Bucket
.value().empty() ? 0 : Index
);
433 Index
+= Bucket
.value().size();
437 template <typename DataT
>
438 void Dwarf5AccelTableWriter
<DataT
>::emitStringOffsets() const {
439 for (const auto &Bucket
: enumerate(Contents
.getBuckets())) {
440 for (auto *Hash
: Bucket
.value()) {
441 DwarfStringPoolEntryRef String
= Hash
->Name
;
442 Asm
->OutStreamer
->AddComment("String in Bucket " + Twine(Bucket
.index()) +
443 ": " + String
.getString());
444 Asm
->emitDwarfStringOffset(String
);
449 template <typename DataT
>
450 void Dwarf5AccelTableWriter
<DataT
>::emitAbbrevs() const {
451 Asm
->OutStreamer
->emitLabel(AbbrevStart
);
452 for (const auto &Abbrev
: Abbreviations
) {
453 Asm
->OutStreamer
->AddComment("Abbrev code");
454 assert(Abbrev
.first
!= 0);
455 Asm
->emitULEB128(Abbrev
.first
);
456 Asm
->OutStreamer
->AddComment(dwarf::TagString(Abbrev
.first
));
457 Asm
->emitULEB128(Abbrev
.first
);
458 for (const auto &AttrEnc
: Abbrev
.second
) {
459 Asm
->emitULEB128(AttrEnc
.Index
, dwarf::IndexString(AttrEnc
.Index
).data());
460 Asm
->emitULEB128(AttrEnc
.Form
,
461 dwarf::FormEncodingString(AttrEnc
.Form
).data());
463 Asm
->emitULEB128(0, "End of abbrev");
464 Asm
->emitULEB128(0, "End of abbrev");
466 Asm
->emitULEB128(0, "End of abbrev list");
467 Asm
->OutStreamer
->emitLabel(AbbrevEnd
);
470 template <typename DataT
>
471 void Dwarf5AccelTableWriter
<DataT
>::emitEntry(const DataT
&Entry
) const {
472 auto AbbrevIt
= Abbreviations
.find(Entry
.getDieTag());
473 assert(AbbrevIt
!= Abbreviations
.end() &&
474 "Why wasn't this abbrev generated?");
476 Asm
->emitULEB128(AbbrevIt
->first
, "Abbreviation code");
477 for (const auto &AttrEnc
: AbbrevIt
->second
) {
478 Asm
->OutStreamer
->AddComment(dwarf::IndexString(AttrEnc
.Index
));
479 switch (AttrEnc
.Index
) {
480 case dwarf::DW_IDX_compile_unit
: {
481 DIEInteger
ID(getCUIndexForEntry(Entry
));
482 ID
.emitValue(Asm
, AttrEnc
.Form
);
485 case dwarf::DW_IDX_die_offset
:
486 assert(AttrEnc
.Form
== dwarf::DW_FORM_ref4
);
487 Asm
->emitInt32(Entry
.getDieOffset());
490 llvm_unreachable("Unexpected index attribute!");
495 template <typename DataT
> void Dwarf5AccelTableWriter
<DataT
>::emitData() const {
496 Asm
->OutStreamer
->emitLabel(EntryPool
);
497 for (auto &Bucket
: Contents
.getBuckets()) {
498 for (auto *Hash
: Bucket
) {
499 // Remember to emit the label for our offset.
500 Asm
->OutStreamer
->emitLabel(Hash
->Sym
);
501 for (const auto *Value
: Hash
->Values
)
502 emitEntry(*static_cast<const DataT
*>(Value
));
503 Asm
->OutStreamer
->AddComment("End of list: " + Hash
->Name
.getString());
509 template <typename DataT
>
510 Dwarf5AccelTableWriter
<DataT
>::Dwarf5AccelTableWriter(
511 AsmPrinter
*Asm
, const AccelTableBase
&Contents
,
512 ArrayRef
<MCSymbol
*> CompUnits
,
513 llvm::function_ref
<unsigned(const DataT
&)> getCUIndexForEntry
)
514 : AccelTableWriter(Asm
, Contents
, false),
515 Header(CompUnits
.size(), Contents
.getBucketCount(),
516 Contents
.getUniqueNameCount()),
517 CompUnits(CompUnits
), getCUIndexForEntry(std::move(getCUIndexForEntry
)) {
518 DenseSet
<uint32_t> UniqueTags
= getUniqueTags();
519 SmallVector
<AttributeEncoding
, 2> UniformAttributes
= getUniformAttributes();
521 Abbreviations
.reserve(UniqueTags
.size());
522 for (uint32_t Tag
: UniqueTags
)
523 Abbreviations
.try_emplace(Tag
, UniformAttributes
);
526 template <typename DataT
> void Dwarf5AccelTableWriter
<DataT
>::emit() {
532 emitOffsets(EntryPool
);
535 Asm
->OutStreamer
->emitValueToAlignment(4, 0);
536 Asm
->OutStreamer
->emitLabel(ContributionEnd
);
539 void llvm::emitAppleAccelTableImpl(AsmPrinter
*Asm
, AccelTableBase
&Contents
,
540 StringRef Prefix
, const MCSymbol
*SecBegin
,
541 ArrayRef
<AppleAccelTableData::Atom
> Atoms
) {
542 Contents
.finalize(Asm
, Prefix
);
543 AppleAccelTableWriter(Asm
, Contents
, Atoms
, SecBegin
).emit();
546 void llvm::emitDWARF5AccelTable(
547 AsmPrinter
*Asm
, AccelTable
<DWARF5AccelTableData
> &Contents
,
548 const DwarfDebug
&DD
, ArrayRef
<std::unique_ptr
<DwarfCompileUnit
>> CUs
) {
549 std::vector
<MCSymbol
*> CompUnits
;
550 SmallVector
<unsigned, 1> CUIndex(CUs
.size());
552 for (const auto &CU
: enumerate(CUs
)) {
553 if (CU
.value()->getCUNode()->getNameTableKind() !=
554 DICompileUnit::DebugNameTableKind::Default
)
556 CUIndex
[CU
.index()] = Count
++;
557 assert(CU
.index() == CU
.value()->getUniqueID());
558 const DwarfCompileUnit
*MainCU
=
559 DD
.useSplitDwarf() ? CU
.value()->getSkeleton() : CU
.value().get();
560 CompUnits
.push_back(MainCU
->getLabelBegin());
563 if (CompUnits
.empty())
566 Asm
->OutStreamer
->SwitchSection(
567 Asm
->getObjFileLowering().getDwarfDebugNamesSection());
569 Contents
.finalize(Asm
, "names");
570 Dwarf5AccelTableWriter
<DWARF5AccelTableData
>(
571 Asm
, Contents
, CompUnits
,
572 [&](const DWARF5AccelTableData
&Entry
) {
573 const DIE
*CUDie
= Entry
.getDie().getUnitDie();
574 return CUIndex
[DD
.lookupCU(CUDie
)->getUniqueID()];
579 void llvm::emitDWARF5AccelTable(
580 AsmPrinter
*Asm
, AccelTable
<DWARF5AccelTableStaticData
> &Contents
,
581 ArrayRef
<MCSymbol
*> CUs
,
582 llvm::function_ref
<unsigned(const DWARF5AccelTableStaticData
&)>
583 getCUIndexForEntry
) {
584 Contents
.finalize(Asm
, "names");
585 Dwarf5AccelTableWriter
<DWARF5AccelTableStaticData
>(Asm
, Contents
, CUs
,
590 void AppleAccelTableOffsetData::emit(AsmPrinter
*Asm
) const {
591 assert(Die
.getDebugSectionOffset() <= UINT32_MAX
&&
592 "The section offset exceeds the limit.");
593 Asm
->emitInt32(Die
.getDebugSectionOffset());
596 void AppleAccelTableTypeData::emit(AsmPrinter
*Asm
) const {
597 assert(Die
.getDebugSectionOffset() <= UINT32_MAX
&&
598 "The section offset exceeds the limit.");
599 Asm
->emitInt32(Die
.getDebugSectionOffset());
600 Asm
->emitInt16(Die
.getTag());
604 void AppleAccelTableStaticOffsetData::emit(AsmPrinter
*Asm
) const {
605 Asm
->emitInt32(Offset
);
608 void AppleAccelTableStaticTypeData::emit(AsmPrinter
*Asm
) const {
609 Asm
->emitInt32(Offset
);
611 Asm
->emitInt8(ObjCClassIsImplementation
? dwarf::DW_FLAG_type_implementation
613 Asm
->emitInt32(QualifiedNameHash
);
616 constexpr AppleAccelTableData::Atom
AppleAccelTableTypeData::Atoms
[];
617 constexpr AppleAccelTableData::Atom
AppleAccelTableOffsetData::Atoms
[];
618 constexpr AppleAccelTableData::Atom
AppleAccelTableStaticOffsetData::Atoms
[];
619 constexpr AppleAccelTableData::Atom
AppleAccelTableStaticTypeData::Atoms
[];
622 void AppleAccelTableWriter::Header::print(raw_ostream
&OS
) const {
623 OS
<< "Magic: " << format("0x%x", Magic
) << "\n"
624 << "Version: " << Version
<< "\n"
625 << "Hash Function: " << HashFunction
<< "\n"
626 << "Bucket Count: " << BucketCount
<< "\n"
627 << "Header Data Length: " << HeaderDataLength
<< "\n";
630 void AppleAccelTableData::Atom::print(raw_ostream
&OS
) const {
631 OS
<< "Type: " << dwarf::AtomTypeString(Type
) << "\n"
632 << "Form: " << dwarf::FormEncodingString(Form
) << "\n";
635 void AppleAccelTableWriter::HeaderData::print(raw_ostream
&OS
) const {
636 OS
<< "DIE Offset Base: " << DieOffsetBase
<< "\n";
637 for (auto Atom
: Atoms
)
641 void AppleAccelTableWriter::print(raw_ostream
&OS
) const {
643 HeaderData
.print(OS
);
645 SecBegin
->print(OS
, nullptr);
648 void AccelTableBase::HashData::print(raw_ostream
&OS
) const {
649 OS
<< "Name: " << Name
.getString() << "\n";
650 OS
<< " Hash Value: " << format("0x%x", HashValue
) << "\n";
657 for (auto *Value
: Values
)
661 void AccelTableBase::print(raw_ostream
&OS
) const {
664 for (const auto &Entry
: Entries
) {
665 OS
<< "Name: " << Entry
.first() << "\n";
666 for (auto *V
: Entry
.second
.Values
)
670 OS
<< "Buckets and Hashes: \n";
671 for (auto &Bucket
: Buckets
)
672 for (auto &Hash
: Bucket
)
676 for (auto &E
: Entries
)
680 void DWARF5AccelTableData::print(raw_ostream
&OS
) const {
681 OS
<< " Offset: " << getDieOffset() << "\n";
682 OS
<< " Tag: " << dwarf::TagString(getDieTag()) << "\n";
685 void DWARF5AccelTableStaticData::print(raw_ostream
&OS
) const {
686 OS
<< " Offset: " << getDieOffset() << "\n";
687 OS
<< " Tag: " << dwarf::TagString(getDieTag()) << "\n";
690 void AppleAccelTableOffsetData::print(raw_ostream
&OS
) const {
691 OS
<< " Offset: " << Die
.getOffset() << "\n";
694 void AppleAccelTableTypeData::print(raw_ostream
&OS
) const {
695 OS
<< " Offset: " << Die
.getOffset() << "\n";
696 OS
<< " Tag: " << dwarf::TagString(Die
.getTag()) << "\n";
699 void AppleAccelTableStaticOffsetData::print(raw_ostream
&OS
) const {
700 OS
<< " Static Offset: " << Offset
<< "\n";
703 void AppleAccelTableStaticTypeData::print(raw_ostream
&OS
) const {
704 OS
<< " Static Offset: " << Offset
<< "\n";
705 OS
<< " QualifiedNameHash: " << format("%x\n", QualifiedNameHash
) << "\n";
706 OS
<< " Tag: " << dwarf::TagString(Tag
) << "\n";
707 OS
<< " ObjCClassIsImplementation: "
708 << (ObjCClassIsImplementation
? "true" : "false");