1 //===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains support for writing accelerator tables.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/AccelTable.h"
15 #include "DwarfCompileUnit.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/BinaryFormat/Dwarf.h"
20 #include "llvm/CodeGen/AsmPrinter.h"
21 #include "llvm/CodeGen/DIE.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSymbol.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Target/TargetLoweringObjectFile.h"
35 void AccelTableBase::computeBucketCount() {
36 // First get the number of unique hashes.
37 std::vector<uint32_t> Uniques;
38 Uniques.reserve(Entries.size());
39 for (const auto &E : Entries)
40 Uniques.push_back(E.second.HashValue);
41 array_pod_sort(Uniques.begin(), Uniques.end());
42 std::vector<uint32_t>::iterator P =
43 std::unique(Uniques.begin(), Uniques.end());
45 UniqueHashCount = std::distance(Uniques.begin(), P);
47 if (UniqueHashCount > 1024)
48 BucketCount = UniqueHashCount / 4;
49 else if (UniqueHashCount > 16)
50 BucketCount = UniqueHashCount / 2;
52 BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
55 void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) {
56 // Create the individual hash data outputs.
57 for (auto &E : Entries) {
58 // Unique the entries.
59 std::stable_sort(E.second.Values.begin(), E.second.Values.end(),
60 [](const AccelTableData *A, const AccelTableData *B) {
63 E.second.Values.erase(
64 std::unique(E.second.Values.begin(), E.second.Values.end()),
65 E.second.Values.end());
68 // Figure out how many buckets we need, then compute the bucket contents and
69 // the final ordering. The hashes and offsets can be emitted by walking these
70 // data structures. We add temporary symbols to the data so they can be
71 // referenced when emitting the offsets.
74 // Compute bucket contents and final ordering.
75 Buckets.resize(BucketCount);
76 for (auto &E : Entries) {
77 uint32_t Bucket = E.second.HashValue % BucketCount;
78 Buckets[Bucket].push_back(&E.second);
79 E.second.Sym = Asm->createTempSymbol(Prefix);
82 // Sort the contents of the buckets by hash value so that hash collisions end
83 // up together. Stable sort makes testing easier and doesn't cost much more.
84 for (auto &Bucket : Buckets)
85 std::stable_sort(Bucket.begin(), Bucket.end(),
86 [](HashData *LHS, HashData *RHS) {
87 return LHS->HashValue < RHS->HashValue;
92 /// Base class for writing out Accelerator tables. It holds the common
93 /// functionality for the two Accelerator table types.
94 class AccelTableWriter {
96 AsmPrinter *const Asm; ///< Destination.
97 const AccelTableBase &Contents; ///< Data to emit.
99 /// Controls whether to emit duplicate hash and offset table entries for names
100 /// with identical hashes. Apple tables don't emit duplicate entries, DWARF v5
102 const bool SkipIdenticalHashes;
104 void emitHashes() const;
106 /// Emit offsets to lists of entries with identical names. The offsets are
107 /// relative to the Base argument.
108 void emitOffsets(const MCSymbol *Base) const;
111 AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
112 bool SkipIdenticalHashes)
113 : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
117 class AppleAccelTableWriter : public AccelTableWriter {
118 using Atom = AppleAccelTableData::Atom;
120 /// The fixed header of an Apple Accelerator Table.
122 uint32_t Magic = MagicHash;
123 uint16_t Version = 1;
124 uint16_t HashFunction = dwarf::DW_hash_function_djb;
125 uint32_t BucketCount;
127 uint32_t HeaderDataLength;
129 /// 'HASH' magic value to detect endianness.
130 static const uint32_t MagicHash = 0x48415348;
132 Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength)
133 : BucketCount(BucketCount), HashCount(UniqueHashCount),
134 HeaderDataLength(DataLength) {}
136 void emit(AsmPrinter *Asm) const;
138 void print(raw_ostream &OS) const;
139 void dump() const { print(dbgs()); }
143 /// The HeaderData describes the structure of an Apple accelerator table
144 /// through a list of Atoms.
146 /// In the case of data that is referenced via DW_FORM_ref_* the offset
147 /// base is used to describe the offset for all forms in the list of atoms.
148 uint32_t DieOffsetBase;
150 const SmallVector<Atom, 4> Atoms;
152 HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0)
153 : DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {}
155 void emit(AsmPrinter *Asm) const;
157 void print(raw_ostream &OS) const;
158 void dump() const { print(dbgs()); }
163 HeaderData HeaderData;
164 const MCSymbol *SecBegin;
166 void emitBuckets() const;
167 void emitData() const;
170 AppleAccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
171 ArrayRef<Atom> Atoms, const MCSymbol *SecBegin)
172 : AccelTableWriter(Asm, Contents, true),
173 Header(Contents.getBucketCount(), Contents.getUniqueHashCount(),
174 8 + (Atoms.size() * 4)),
175 HeaderData(Atoms), SecBegin(SecBegin) {}
180 void print(raw_ostream &OS) const;
181 void dump() const { print(dbgs()); }
185 /// Class responsible for emitting a DWARF v5 Accelerator Table. The only
186 /// public function is emit(), which performs the actual emission.
188 /// The class is templated in its data type. This allows us to emit both dyamic
189 /// and static data entries. A callback abstract the logic to provide a CU
190 /// index for a given entry, which is different per data type, but identical
191 /// for every entry in the same table.
192 template <typename DataT>
193 class Dwarf5AccelTableWriter : public AccelTableWriter {
195 uint32_t UnitLength = 0;
196 uint16_t Version = 5;
197 uint16_t Padding = 0;
198 uint32_t CompUnitCount;
199 uint32_t LocalTypeUnitCount = 0;
200 uint32_t ForeignTypeUnitCount = 0;
201 uint32_t BucketCount;
203 uint32_t AbbrevTableSize = 0;
204 uint32_t AugmentationStringSize = sizeof(AugmentationString);
205 char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
207 Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
208 : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
209 NameCount(NameCount) {}
211 void emit(const Dwarf5AccelTableWriter &Ctx) const;
213 struct AttributeEncoding {
219 DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
220 ArrayRef<MCSymbol *> CompUnits;
221 llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
222 MCSymbol *ContributionStart = Asm->createTempSymbol("names_start");
223 MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end");
224 MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
225 MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
226 MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
228 DenseSet<uint32_t> getUniqueTags() const;
230 // Right now, we emit uniform attributes for all tags.
231 SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
233 void emitCUList() const;
234 void emitBuckets() const;
235 void emitStringOffsets() const;
236 void emitAbbrevs() const;
237 void emitEntry(const DataT &Entry) const;
238 void emitData() const;
241 Dwarf5AccelTableWriter(
242 AsmPrinter *Asm, const AccelTableBase &Contents,
243 ArrayRef<MCSymbol *> CompUnits,
244 llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
250 void AccelTableWriter::emitHashes() const {
251 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
252 unsigned BucketIdx = 0;
253 for (auto &Bucket : Contents.getBuckets()) {
254 for (auto &Hash : Bucket) {
255 uint32_t HashValue = Hash->HashValue;
256 if (SkipIdenticalHashes && PrevHash == HashValue)
258 Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
259 Asm->emitInt32(HashValue);
260 PrevHash = HashValue;
266 void AccelTableWriter::emitOffsets(const MCSymbol *Base) const {
267 const auto &Buckets = Contents.getBuckets();
268 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
269 for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
270 for (auto *Hash : Buckets[i]) {
271 uint32_t HashValue = Hash->HashValue;
272 if (SkipIdenticalHashes && PrevHash == HashValue)
274 PrevHash = HashValue;
275 Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
276 Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t));
281 void AppleAccelTableWriter::Header::emit(AsmPrinter *Asm) const {
282 Asm->OutStreamer->AddComment("Header Magic");
283 Asm->emitInt32(Magic);
284 Asm->OutStreamer->AddComment("Header Version");
285 Asm->emitInt16(Version);
286 Asm->OutStreamer->AddComment("Header Hash Function");
287 Asm->emitInt16(HashFunction);
288 Asm->OutStreamer->AddComment("Header Bucket Count");
289 Asm->emitInt32(BucketCount);
290 Asm->OutStreamer->AddComment("Header Hash Count");
291 Asm->emitInt32(HashCount);
292 Asm->OutStreamer->AddComment("Header Data Length");
293 Asm->emitInt32(HeaderDataLength);
296 void AppleAccelTableWriter::HeaderData::emit(AsmPrinter *Asm) const {
297 Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
298 Asm->emitInt32(DieOffsetBase);
299 Asm->OutStreamer->AddComment("HeaderData Atom Count");
300 Asm->emitInt32(Atoms.size());
302 for (const Atom &A : Atoms) {
303 Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type));
304 Asm->emitInt16(A.Type);
305 Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form));
306 Asm->emitInt16(A.Form);
310 void AppleAccelTableWriter::emitBuckets() const {
311 const auto &Buckets = Contents.getBuckets();
313 for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
314 Asm->OutStreamer->AddComment("Bucket " + Twine(i));
315 if (!Buckets[i].empty())
316 Asm->emitInt32(index);
318 Asm->emitInt32(std::numeric_limits<uint32_t>::max());
319 // Buckets point in the list of hashes, not to the data. Do not increment
320 // the index multiple times in case of hash collisions.
321 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
322 for (auto *HD : Buckets[i]) {
323 uint32_t HashValue = HD->HashValue;
324 if (PrevHash != HashValue)
326 PrevHash = HashValue;
331 void AppleAccelTableWriter::emitData() const {
332 const auto &Buckets = Contents.getBuckets();
333 for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
334 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
335 for (auto &Hash : Buckets[i]) {
336 // Terminate the previous entry if there is no hash collision with the
338 if (PrevHash != std::numeric_limits<uint64_t>::max() &&
339 PrevHash != Hash->HashValue)
341 // Remember to emit the label for our offset.
342 Asm->OutStreamer->EmitLabel(Hash->Sym);
343 Asm->OutStreamer->AddComment(Hash->Name.getString());
344 Asm->emitDwarfStringOffset(Hash->Name);
345 Asm->OutStreamer->AddComment("Num DIEs");
346 Asm->emitInt32(Hash->Values.size());
347 for (const auto *V : Hash->Values)
348 static_cast<const AppleAccelTableData *>(V)->emit(Asm);
349 PrevHash = Hash->HashValue;
351 // Emit the final end marker for the bucket.
352 if (!Buckets[i].empty())
357 void AppleAccelTableWriter::emit() const {
359 HeaderData.emit(Asm);
362 emitOffsets(SecBegin);
366 template <typename DataT>
367 void Dwarf5AccelTableWriter<DataT>::Header::emit(
368 const Dwarf5AccelTableWriter &Ctx) const {
369 assert(CompUnitCount > 0 && "Index must have at least one CU.");
371 AsmPrinter *Asm = Ctx.Asm;
372 Asm->OutStreamer->AddComment("Header: unit length");
373 Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
375 Asm->OutStreamer->EmitLabel(Ctx.ContributionStart);
376 Asm->OutStreamer->AddComment("Header: version");
377 Asm->emitInt16(Version);
378 Asm->OutStreamer->AddComment("Header: padding");
379 Asm->emitInt16(Padding);
380 Asm->OutStreamer->AddComment("Header: compilation unit count");
381 Asm->emitInt32(CompUnitCount);
382 Asm->OutStreamer->AddComment("Header: local type unit count");
383 Asm->emitInt32(LocalTypeUnitCount);
384 Asm->OutStreamer->AddComment("Header: foreign type unit count");
385 Asm->emitInt32(ForeignTypeUnitCount);
386 Asm->OutStreamer->AddComment("Header: bucket count");
387 Asm->emitInt32(BucketCount);
388 Asm->OutStreamer->AddComment("Header: name count");
389 Asm->emitInt32(NameCount);
390 Asm->OutStreamer->AddComment("Header: abbreviation table size");
391 Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
392 Asm->OutStreamer->AddComment("Header: augmentation string size");
393 assert(AugmentationStringSize % 4 == 0);
394 Asm->emitInt32(AugmentationStringSize);
395 Asm->OutStreamer->AddComment("Header: augmentation string");
396 Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
399 template <typename DataT>
400 DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
401 DenseSet<uint32_t> UniqueTags;
402 for (auto &Bucket : Contents.getBuckets()) {
403 for (auto *Hash : Bucket) {
404 for (auto *Value : Hash->Values) {
405 unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
406 UniqueTags.insert(Tag);
413 template <typename DataT>
414 SmallVector<typename Dwarf5AccelTableWriter<DataT>::AttributeEncoding, 2>
415 Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
416 SmallVector<AttributeEncoding, 2> UA;
417 if (CompUnits.size() > 1) {
418 size_t LargestCUIndex = CompUnits.size() - 1;
419 dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
420 UA.push_back({dwarf::DW_IDX_compile_unit, Form});
422 UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
426 template <typename DataT>
427 void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
428 for (const auto &CU : enumerate(CompUnits)) {
429 Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
430 Asm->emitDwarfSymbolReference(CU.value());
434 template <typename DataT>
435 void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
437 for (const auto &Bucket : enumerate(Contents.getBuckets())) {
438 Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
439 Asm->emitInt32(Bucket.value().empty() ? 0 : Index);
440 Index += Bucket.value().size();
444 template <typename DataT>
445 void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
446 for (const auto &Bucket : enumerate(Contents.getBuckets())) {
447 for (auto *Hash : Bucket.value()) {
448 DwarfStringPoolEntryRef String = Hash->Name;
449 Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
450 ": " + String.getString());
451 Asm->emitDwarfStringOffset(String);
456 template <typename DataT>
457 void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
458 Asm->OutStreamer->EmitLabel(AbbrevStart);
459 for (const auto &Abbrev : Abbreviations) {
460 Asm->OutStreamer->AddComment("Abbrev code");
461 assert(Abbrev.first != 0);
462 Asm->EmitULEB128(Abbrev.first);
463 Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
464 Asm->EmitULEB128(Abbrev.first);
465 for (const auto &AttrEnc : Abbrev.second) {
466 Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
467 Asm->EmitULEB128(AttrEnc.Form,
468 dwarf::FormEncodingString(AttrEnc.Form).data());
470 Asm->EmitULEB128(0, "End of abbrev");
471 Asm->EmitULEB128(0, "End of abbrev");
473 Asm->EmitULEB128(0, "End of abbrev list");
474 Asm->OutStreamer->EmitLabel(AbbrevEnd);
477 template <typename DataT>
478 void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
479 auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
480 assert(AbbrevIt != Abbreviations.end() &&
481 "Why wasn't this abbrev generated?");
483 Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code");
484 for (const auto &AttrEnc : AbbrevIt->second) {
485 Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
486 switch (AttrEnc.Index) {
487 case dwarf::DW_IDX_compile_unit: {
488 DIEInteger ID(getCUIndexForEntry(Entry));
489 ID.EmitValue(Asm, AttrEnc.Form);
492 case dwarf::DW_IDX_die_offset:
493 assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
494 Asm->emitInt32(Entry.getDieOffset());
497 llvm_unreachable("Unexpected index attribute!");
502 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
503 Asm->OutStreamer->EmitLabel(EntryPool);
504 for (auto &Bucket : Contents.getBuckets()) {
505 for (auto *Hash : Bucket) {
506 // Remember to emit the label for our offset.
507 Asm->OutStreamer->EmitLabel(Hash->Sym);
508 for (const auto *Value : Hash->Values)
509 emitEntry(*static_cast<const DataT *>(Value));
510 Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
516 template <typename DataT>
517 Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
518 AsmPrinter *Asm, const AccelTableBase &Contents,
519 ArrayRef<MCSymbol *> CompUnits,
520 llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
521 : AccelTableWriter(Asm, Contents, false),
522 Header(CompUnits.size(), Contents.getBucketCount(),
523 Contents.getUniqueNameCount()),
524 CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
525 DenseSet<uint32_t> UniqueTags = getUniqueTags();
526 SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
528 Abbreviations.reserve(UniqueTags.size());
529 for (uint32_t Tag : UniqueTags)
530 Abbreviations.try_emplace(Tag, UniformAttributes);
533 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
539 emitOffsets(EntryPool);
542 Asm->OutStreamer->EmitValueToAlignment(4, 0);
543 Asm->OutStreamer->EmitLabel(ContributionEnd);
546 void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
547 StringRef Prefix, const MCSymbol *SecBegin,
548 ArrayRef<AppleAccelTableData::Atom> Atoms) {
549 Contents.finalize(Asm, Prefix);
550 AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
553 void llvm::emitDWARF5AccelTable(
554 AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
555 const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
556 std::vector<MCSymbol *> CompUnits;
557 SmallVector<unsigned, 1> CUIndex(CUs.size());
559 for (const auto &CU : enumerate(CUs)) {
560 if (CU.value()->getCUNode()->getNameTableKind() ==
561 DICompileUnit::DebugNameTableKind::None)
563 CUIndex[CU.index()] = Count++;
564 assert(CU.index() == CU.value()->getUniqueID());
565 const DwarfCompileUnit *MainCU =
566 DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
567 CompUnits.push_back(MainCU->getLabelBegin());
570 if (CompUnits.empty())
573 Asm->OutStreamer->SwitchSection(
574 Asm->getObjFileLowering().getDwarfDebugNamesSection());
576 Contents.finalize(Asm, "names");
577 Dwarf5AccelTableWriter<DWARF5AccelTableData>(
578 Asm, Contents, CompUnits,
579 [&](const DWARF5AccelTableData &Entry) {
580 const DIE *CUDie = Entry.getDie().getUnitDie();
581 return CUIndex[DD.lookupCU(CUDie)->getUniqueID()];
586 void llvm::emitDWARF5AccelTable(
587 AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
588 ArrayRef<MCSymbol *> CUs,
589 llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
590 getCUIndexForEntry) {
591 Contents.finalize(Asm, "names");
592 Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
597 void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const {
598 Asm->emitInt32(Die.getDebugSectionOffset());
601 void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const {
602 Asm->emitInt32(Die.getDebugSectionOffset());
603 Asm->emitInt16(Die.getTag());
607 void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const {
608 Asm->emitInt32(Offset);
611 void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
612 Asm->emitInt32(Offset);
614 Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation
616 Asm->emitInt32(QualifiedNameHash);
620 // The lines below are rejected by older versions (TBD) of MSVC.
621 constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[];
622 constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[];
623 constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[];
624 constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[];
626 // FIXME: Erase this path once the minimum MSCV version has been bumped.
627 const SmallVector<AppleAccelTableData::Atom, 4>
628 AppleAccelTableOffsetData::Atoms = {
629 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
630 const SmallVector<AppleAccelTableData::Atom, 4> AppleAccelTableTypeData::Atoms =
631 {Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
632 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
633 Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
634 const SmallVector<AppleAccelTableData::Atom, 4>
635 AppleAccelTableStaticOffsetData::Atoms = {
636 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
637 const SmallVector<AppleAccelTableData::Atom, 4>
638 AppleAccelTableStaticTypeData::Atoms = {
639 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
640 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
641 Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)};
645 void AppleAccelTableWriter::Header::print(raw_ostream &OS) const {
646 OS << "Magic: " << format("0x%x", Magic) << "\n"
647 << "Version: " << Version << "\n"
648 << "Hash Function: " << HashFunction << "\n"
649 << "Bucket Count: " << BucketCount << "\n"
650 << "Header Data Length: " << HeaderDataLength << "\n";
653 void AppleAccelTableData::Atom::print(raw_ostream &OS) const {
654 OS << "Type: " << dwarf::AtomTypeString(Type) << "\n"
655 << "Form: " << dwarf::FormEncodingString(Form) << "\n";
658 void AppleAccelTableWriter::HeaderData::print(raw_ostream &OS) const {
659 OS << "DIE Offset Base: " << DieOffsetBase << "\n";
660 for (auto Atom : Atoms)
664 void AppleAccelTableWriter::print(raw_ostream &OS) const {
666 HeaderData.print(OS);
668 SecBegin->print(OS, nullptr);
671 void AccelTableBase::HashData::print(raw_ostream &OS) const {
672 OS << "Name: " << Name.getString() << "\n";
673 OS << " Hash Value: " << format("0x%x", HashValue) << "\n";
680 for (auto *Value : Values)
684 void AccelTableBase::print(raw_ostream &OS) const {
687 for (const auto &Entry : Entries) {
688 OS << "Name: " << Entry.first() << "\n";
689 for (auto *V : Entry.second.Values)
693 OS << "Buckets and Hashes: \n";
694 for (auto &Bucket : Buckets)
695 for (auto &Hash : Bucket)
699 for (auto &E : Entries)
703 void DWARF5AccelTableData::print(raw_ostream &OS) const {
704 OS << " Offset: " << getDieOffset() << "\n";
705 OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
708 void DWARF5AccelTableStaticData::print(raw_ostream &OS) const {
709 OS << " Offset: " << getDieOffset() << "\n";
710 OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
713 void AppleAccelTableOffsetData::print(raw_ostream &OS) const {
714 OS << " Offset: " << Die.getOffset() << "\n";
717 void AppleAccelTableTypeData::print(raw_ostream &OS) const {
718 OS << " Offset: " << Die.getOffset() << "\n";
719 OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n";
722 void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const {
723 OS << " Static Offset: " << Offset << "\n";
726 void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const {
727 OS << " Static Offset: " << Offset << "\n";
728 OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n";
729 OS << " Tag: " << dwarf::TagString(Tag) << "\n";
730 OS << " ObjCClassIsImplementation: "
731 << (ObjCClassIsImplementation ? "true" : "false");