LLVM  12.0.0git
AccelTable.cpp
Go to the documentation of this file.
1 //===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for writing accelerator tables.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "DwarfCompileUnit.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/Twine.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"
26 #include <algorithm>
27 #include <cstddef>
28 #include <cstdint>
29 #include <limits>
30 #include <vector>
31 
32 using namespace llvm;
33 
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());
43 
44  UniqueHashCount = std::distance(Uniques.begin(), P);
45 
46  if (UniqueHashCount > 1024)
48  else if (UniqueHashCount > 16)
50  else
51  BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
52 }
53 
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) {
60  return *A < *B;
61  });
62  E.second.Values.erase(
63  std::unique(E.second.Values.begin(), E.second.Values.end()),
64  E.second.Values.end());
65  }
66 
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.
72 
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);
79  }
80 
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;
86  });
87 }
88 
89 namespace {
90 /// Base class for writing out Accelerator tables. It holds the common
91 /// functionality for the two Accelerator table types.
92 class AccelTableWriter {
93 protected:
94  AsmPrinter *const Asm; ///< Destination.
95  const AccelTableBase &Contents; ///< Data to emit.
96 
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
99  /// tables do.
100  const bool SkipIdenticalHashes;
101 
102  void emitHashes() const;
103 
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;
107 
108 public:
109  AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
110  bool SkipIdenticalHashes)
111  : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
112  }
113 };
114 
115 class AppleAccelTableWriter : public AccelTableWriter {
116  using Atom = AppleAccelTableData::Atom;
117 
118  /// The fixed header of an Apple Accelerator Table.
119  struct Header {
120  uint32_t Magic = MagicHash;
121  uint16_t Version = 1;
122  uint16_t HashFunction = dwarf::DW_hash_function_djb;
123  uint32_t BucketCount;
124  uint32_t HashCount;
125  uint32_t HeaderDataLength;
126 
127  /// 'HASH' magic value to detect endianness.
128  static const uint32_t MagicHash = 0x48415348;
129 
130  Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength)
131  : BucketCount(BucketCount), HashCount(UniqueHashCount),
132  HeaderDataLength(DataLength) {}
133 
134  void emit(AsmPrinter *Asm) const;
135 #ifndef NDEBUG
136  void print(raw_ostream &OS) const;
137  void dump() const { print(dbgs()); }
138 #endif
139  };
140 
141  /// The HeaderData describes the structure of an Apple accelerator table
142  /// through a list of Atoms.
143  struct HeaderData {
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;
147 
148  const SmallVector<Atom, 4> Atoms;
149 
150  HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0)
151  : DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {}
152 
153  void emit(AsmPrinter *Asm) const;
154 #ifndef NDEBUG
155  void print(raw_ostream &OS) const;
156  void dump() const { print(dbgs()); }
157 #endif
158  };
159 
160  Header Header;
161  HeaderData HeaderData;
162  const MCSymbol *SecBegin;
163 
164  void emitBuckets() const;
165  void emitData() const;
166 
167 public:
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) {}
174 
175  void emit() const;
176 
177 #ifndef NDEBUG
178  void print(raw_ostream &OS) const;
179  void dump() const { print(dbgs()); }
180 #endif
181 };
182 
183 /// Class responsible for emitting a DWARF v5 Accelerator Table. The only
184 /// public function is emit(), which performs the actual emission.
185 ///
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 {
192  struct Header {
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;
199  uint32_t NameCount;
200  uint32_t AbbrevTableSize = 0;
201  uint32_t AugmentationStringSize = sizeof(AugmentationString);
202  char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
203 
204  Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
205  : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
206  NameCount(NameCount) {}
207 
208  void emit(const Dwarf5AccelTableWriter &Ctx) const;
209  };
210  struct AttributeEncoding {
213  };
214 
215  Header Header;
217  ArrayRef<MCSymbol *> CompUnits;
218  llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
219  MCSymbol *ContributionStart = Asm->createTempSymbol("names_start");
220  MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end");
221  MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
222  MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
223  MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
224 
225  DenseSet<uint32_t> getUniqueTags() const;
226 
227  // Right now, we emit uniform attributes for all tags.
228  SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
229 
230  void emitCUList() const;
231  void emitBuckets() const;
232  void emitStringOffsets() const;
233  void emitAbbrevs() const;
234  void emitEntry(const DataT &Entry) const;
235  void emitData() const;
236 
237 public:
238  Dwarf5AccelTableWriter(
239  AsmPrinter *Asm, const AccelTableBase &Contents,
240  ArrayRef<MCSymbol *> CompUnits,
241  llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
242 
243  void emit() const;
244 };
245 } // namespace
246 
247 void AccelTableWriter::emitHashes() const {
248  uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
249  unsigned BucketIdx = 0;
250  for (auto &Bucket : Contents.getBuckets()) {
251  for (auto &Hash : Bucket) {
252  uint32_t HashValue = Hash->HashValue;
253  if (SkipIdenticalHashes && PrevHash == HashValue)
254  continue;
255  Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
256  Asm->emitInt32(HashValue);
257  PrevHash = HashValue;
258  }
259  BucketIdx++;
260  }
261 }
262 
263 void AccelTableWriter::emitOffsets(const MCSymbol *Base) const {
264  const auto &Buckets = Contents.getBuckets();
265  uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
266  for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
267  for (auto *Hash : Buckets[i]) {
268  uint32_t HashValue = Hash->HashValue;
269  if (SkipIdenticalHashes && PrevHash == HashValue)
270  continue;
271  PrevHash = HashValue;
272  Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
273  Asm->emitLabelDifference(Hash->Sym, Base, Asm->getDwarfOffsetByteSize());
274  }
275  }
276 }
277 
278 void AppleAccelTableWriter::Header::emit(AsmPrinter *Asm) const {
279  Asm->OutStreamer->AddComment("Header Magic");
280  Asm->emitInt32(Magic);
281  Asm->OutStreamer->AddComment("Header Version");
282  Asm->emitInt16(Version);
283  Asm->OutStreamer->AddComment("Header Hash Function");
284  Asm->emitInt16(HashFunction);
285  Asm->OutStreamer->AddComment("Header Bucket Count");
286  Asm->emitInt32(BucketCount);
287  Asm->OutStreamer->AddComment("Header Hash Count");
288  Asm->emitInt32(HashCount);
289  Asm->OutStreamer->AddComment("Header Data Length");
290  Asm->emitInt32(HeaderDataLength);
291 }
292 
293 void AppleAccelTableWriter::HeaderData::emit(AsmPrinter *Asm) const {
294  Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
295  Asm->emitInt32(DieOffsetBase);
296  Asm->OutStreamer->AddComment("HeaderData Atom Count");
297  Asm->emitInt32(Atoms.size());
298 
299  for (const Atom &A : Atoms) {
300  Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type));
301  Asm->emitInt16(A.Type);
302  Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form));
303  Asm->emitInt16(A.Form);
304  }
305 }
306 
307 void AppleAccelTableWriter::emitBuckets() const {
308  const auto &Buckets = Contents.getBuckets();
309  unsigned index = 0;
310  for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
311  Asm->OutStreamer->AddComment("Bucket " + Twine(i));
312  if (!Buckets[i].empty())
313  Asm->emitInt32(index);
314  else
316  // Buckets point in the list of hashes, not to the data. Do not increment
317  // the index multiple times in case of hash collisions.
318  uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
319  for (auto *HD : Buckets[i]) {
320  uint32_t HashValue = HD->HashValue;
321  if (PrevHash != HashValue)
322  ++index;
323  PrevHash = HashValue;
324  }
325  }
326 }
327 
328 void AppleAccelTableWriter::emitData() const {
329  const auto &Buckets = Contents.getBuckets();
330  for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
331  uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
332  for (auto &Hash : Buckets[i]) {
333  // Terminate the previous entry if there is no hash collision with the
334  // current one.
335  if (PrevHash != std::numeric_limits<uint64_t>::max() &&
336  PrevHash != Hash->HashValue)
337  Asm->emitInt32(0);
338  // Remember to emit the label for our offset.
339  Asm->OutStreamer->emitLabel(Hash->Sym);
340  Asm->OutStreamer->AddComment(Hash->Name.getString());
341  Asm->emitDwarfStringOffset(Hash->Name);
342  Asm->OutStreamer->AddComment("Num DIEs");
343  Asm->emitInt32(Hash->Values.size());
344  for (const auto *V : Hash->Values)
345  static_cast<const AppleAccelTableData *>(V)->emit(Asm);
346  PrevHash = Hash->HashValue;
347  }
348  // Emit the final end marker for the bucket.
349  if (!Buckets[i].empty())
350  Asm->emitInt32(0);
351  }
352 }
353 
354 void AppleAccelTableWriter::emit() const {
355  Header.emit(Asm);
356  HeaderData.emit(Asm);
357  emitBuckets();
358  emitHashes();
359  emitOffsets(SecBegin);
360  emitData();
361 }
362 
363 template <typename DataT>
364 void Dwarf5AccelTableWriter<DataT>::Header::emit(
365  const Dwarf5AccelTableWriter &Ctx) const {
366  assert(CompUnitCount > 0 && "Index must have at least one CU.");
367 
368  AsmPrinter *Asm = Ctx.Asm;
369  Asm->emitDwarfUnitLength(Ctx.ContributionEnd, Ctx.ContributionStart,
370  "Header: unit length");
371  Asm->OutStreamer->emitLabel(Ctx.ContributionStart);
372  Asm->OutStreamer->AddComment("Header: version");
373  Asm->emitInt16(Version);
374  Asm->OutStreamer->AddComment("Header: padding");
375  Asm->emitInt16(Padding);
376  Asm->OutStreamer->AddComment("Header: compilation unit count");
377  Asm->emitInt32(CompUnitCount);
378  Asm->OutStreamer->AddComment("Header: local type unit count");
379  Asm->emitInt32(LocalTypeUnitCount);
380  Asm->OutStreamer->AddComment("Header: foreign type unit count");
381  Asm->emitInt32(ForeignTypeUnitCount);
382  Asm->OutStreamer->AddComment("Header: bucket count");
383  Asm->emitInt32(BucketCount);
384  Asm->OutStreamer->AddComment("Header: name count");
385  Asm->emitInt32(NameCount);
386  Asm->OutStreamer->AddComment("Header: abbreviation table size");
387  Asm->emitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
388  Asm->OutStreamer->AddComment("Header: augmentation string size");
389  assert(AugmentationStringSize % 4 == 0);
390  Asm->emitInt32(AugmentationStringSize);
391  Asm->OutStreamer->AddComment("Header: augmentation string");
392  Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
393 }
394 
395 template <typename DataT>
396 DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
397  DenseSet<uint32_t> UniqueTags;
398  for (auto &Bucket : Contents.getBuckets()) {
399  for (auto *Hash : Bucket) {
400  for (auto *Value : Hash->Values) {
401  unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
402  UniqueTags.insert(Tag);
403  }
404  }
405  }
406  return UniqueTags;
407 }
408 
409 template <typename DataT>
411 Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
413  if (CompUnits.size() > 1) {
414  size_t LargestCUIndex = CompUnits.size() - 1;
415  dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
416  UA.push_back({dwarf::DW_IDX_compile_unit, Form});
417  }
418  UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
419  return UA;
420 }
421 
422 template <typename DataT>
423 void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
424  for (const auto &CU : enumerate(CompUnits)) {
425  Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
426  Asm->emitDwarfSymbolReference(CU.value());
427  }
428 }
429 
430 template <typename DataT>
431 void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
432  uint32_t Index = 1;
433  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
434  Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
435  Asm->emitInt32(Bucket.value().empty() ? 0 : Index);
436  Index += Bucket.value().size();
437  }
438 }
439 
440 template <typename DataT>
441 void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
442  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
443  for (auto *Hash : Bucket.value()) {
444  DwarfStringPoolEntryRef String = Hash->Name;
445  Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
446  ": " + String.getString());
447  Asm->emitDwarfStringOffset(String);
448  }
449  }
450 }
451 
452 template <typename DataT>
453 void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
454  Asm->OutStreamer->emitLabel(AbbrevStart);
455  for (const auto &Abbrev : Abbreviations) {
456  Asm->OutStreamer->AddComment("Abbrev code");
457  assert(Abbrev.first != 0);
458  Asm->emitULEB128(Abbrev.first);
459  Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
460  Asm->emitULEB128(Abbrev.first);
461  for (const auto &AttrEnc : Abbrev.second) {
462  Asm->emitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
463  Asm->emitULEB128(AttrEnc.Form,
464  dwarf::FormEncodingString(AttrEnc.Form).data());
465  }
466  Asm->emitULEB128(0, "End of abbrev");
467  Asm->emitULEB128(0, "End of abbrev");
468  }
469  Asm->emitULEB128(0, "End of abbrev list");
470  Asm->OutStreamer->emitLabel(AbbrevEnd);
471 }
472 
473 template <typename DataT>
474 void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
475  auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
476  assert(AbbrevIt != Abbreviations.end() &&
477  "Why wasn't this abbrev generated?");
478 
479  Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");
480  for (const auto &AttrEnc : AbbrevIt->second) {
481  Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
482  switch (AttrEnc.Index) {
483  case dwarf::DW_IDX_compile_unit: {
484  DIEInteger ID(getCUIndexForEntry(Entry));
485  ID.emitValue(Asm, AttrEnc.Form);
486  break;
487  }
488  case dwarf::DW_IDX_die_offset:
489  assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
490  Asm->emitInt32(Entry.getDieOffset());
491  break;
492  default:
493  llvm_unreachable("Unexpected index attribute!");
494  }
495  }
496 }
497 
498 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
499  Asm->OutStreamer->emitLabel(EntryPool);
500  for (auto &Bucket : Contents.getBuckets()) {
501  for (auto *Hash : Bucket) {
502  // Remember to emit the label for our offset.
503  Asm->OutStreamer->emitLabel(Hash->Sym);
504  for (const auto *Value : Hash->Values)
505  emitEntry(*static_cast<const DataT *>(Value));
506  Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
507  Asm->emitInt8(0);
508  }
509  }
510 }
511 
512 template <typename DataT>
513 Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
514  AsmPrinter *Asm, const AccelTableBase &Contents,
515  ArrayRef<MCSymbol *> CompUnits,
516  llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
517  : AccelTableWriter(Asm, Contents, false),
518  Header(CompUnits.size(), Contents.getBucketCount(),
519  Contents.getUniqueNameCount()),
520  CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
521  DenseSet<uint32_t> UniqueTags = getUniqueTags();
522  SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
523 
524  Abbreviations.reserve(UniqueTags.size());
525  for (uint32_t Tag : UniqueTags)
526  Abbreviations.try_emplace(Tag, UniformAttributes);
527 }
528 
529 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
530  Header.emit(*this);
531  emitCUList();
532  emitBuckets();
533  emitHashes();
534  emitStringOffsets();
535  emitOffsets(EntryPool);
536  emitAbbrevs();
537  emitData();
538  Asm->OutStreamer->emitValueToAlignment(4, 0);
539  Asm->OutStreamer->emitLabel(ContributionEnd);
540 }
541 
543  StringRef Prefix, const MCSymbol *SecBegin,
545  Contents.finalize(Asm, Prefix);
546  AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
547 }
548 
551  const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
552  std::vector<MCSymbol *> CompUnits;
553  SmallVector<unsigned, 1> CUIndex(CUs.size());
554  int Count = 0;
555  for (const auto &CU : enumerate(CUs)) {
556  if (CU.value()->getCUNode()->getNameTableKind() !=
558  continue;
559  CUIndex[CU.index()] = Count++;
560  assert(CU.index() == CU.value()->getUniqueID());
561  const DwarfCompileUnit *MainCU =
562  DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
563  CompUnits.push_back(MainCU->getLabelBegin());
564  }
565 
566  if (CompUnits.empty())
567  return;
568 
569  Asm->OutStreamer->SwitchSection(
570  Asm->getObjFileLowering().getDwarfDebugNamesSection());
571 
572  Contents.finalize(Asm, "names");
573  Dwarf5AccelTableWriter<DWARF5AccelTableData>(
574  Asm, Contents, CompUnits,
575  [&](const DWARF5AccelTableData &Entry) {
576  const DIE *CUDie = Entry.getDie().getUnitDie();
577  return CUIndex[DD.lookupCU(CUDie)->getUniqueID()];
578  })
579  .emit();
580 }
581 
586  getCUIndexForEntry) {
587  Contents.finalize(Asm, "names");
588  Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
589  getCUIndexForEntry)
590  .emit();
591 }
592 
594  assert(Die.getDebugSectionOffset() <= UINT32_MAX &&
595  "The section offset exceeds the limit.");
596  Asm->emitInt32(Die.getDebugSectionOffset());
597 }
598 
600  assert(Die.getDebugSectionOffset() <= UINT32_MAX &&
601  "The section offset exceeds the limit.");
602  Asm->emitInt32(Die.getDebugSectionOffset());
603  Asm->emitInt16(Die.getTag());
604  Asm->emitInt8(0);
605 }
606 
608  Asm->emitInt32(Offset);
609 }
610 
612  Asm->emitInt32(Offset);
613  Asm->emitInt16(Tag);
615  : 0);
616  Asm->emitInt32(QualifiedNameHash);
617 }
618 
623 
624 #ifndef NDEBUG
626  OS << "Magic: " << format("0x%x", Magic) << "\n"
627  << "Version: " << Version << "\n"
628  << "Hash Function: " << HashFunction << "\n"
629  << "Bucket Count: " << BucketCount << "\n"
630  << "Header Data Length: " << HeaderDataLength << "\n";
631 }
632 
634  OS << "Type: " << dwarf::AtomTypeString(Type) << "\n"
635  << "Form: " << dwarf::FormEncodingString(Form) << "\n";
636 }
637 
639  OS << "DIE Offset Base: " << DieOffsetBase << "\n";
640  for (auto Atom : Atoms)
641  Atom.print(OS);
642 }
643 
645  Header.print(OS);
646  HeaderData.print(OS);
647  Contents.print(OS);
648  SecBegin->print(OS, nullptr);
649 }
650 
652  OS << "Name: " << Name.getString() << "\n";
653  OS << " Hash Value: " << format("0x%x", HashValue) << "\n";
654  OS << " Symbol: ";
655  if (Sym)
656  OS << *Sym;
657  else
658  OS << "<none>";
659  OS << "\n";
660  for (auto *Value : Values)
661  Value->print(OS);
662 }
663 
665  // Print Content.
666  OS << "Entries: \n";
667  for (const auto &Entry : Entries) {
668  OS << "Name: " << Entry.first() << "\n";
669  for (auto *V : Entry.second.Values)
670  V->print(OS);
671  }
672 
673  OS << "Buckets and Hashes: \n";
674  for (auto &Bucket : Buckets)
675  for (auto &Hash : Bucket)
676  Hash->print(OS);
677 
678  OS << "Data: \n";
679  for (auto &E : Entries)
680  E.second.print(OS);
681 }
682 
684  OS << " Offset: " << getDieOffset() << "\n";
685  OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
686 }
687 
689  OS << " Offset: " << getDieOffset() << "\n";
690  OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
691 }
692 
694  OS << " Offset: " << Die.getOffset() << "\n";
695 }
696 
698  OS << " Offset: " << Die.getOffset() << "\n";
699  OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n";
700 }
701 
703  OS << " Static Offset: " << Offset << "\n";
704 }
705 
707  OS << " Static Offset: " << Offset << "\n";
708  OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n";
709  OS << " Tag: " << dwarf::TagString(Tag) << "\n";
710  OS << " ObjCClassIsImplementation: "
711  << (ObjCClassIsImplementation ? "true" : "false");
712  OS << "\n";
713 }
714 #endif
static constexpr Atom Atoms[]
Definition: AccelTable.h:327
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:702
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:233
StringRef IndexString(unsigned Idx)
Definition: Dwarf.cpp:680
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:224
This class represents lattice values for constants.
Definition: AllocatorList.h:23
StringRef AtomTypeString(unsigned Atom)
Definition: Dwarf.cpp:584
An Atom defines the form of the data in an Apple accelerator table.
Definition: AccelTable.h:225
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:688
static constexpr Atom Atoms[]
Definition: AccelTable.h:389
Collects and handles dwarf debug information.
Definition: DwarfDebug.h:295
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition: AccelTable.h:196
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:176
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:697
bool useSplitDwarf() const
Returns whether or not to change the current debug info for the split dwarf proposal support.
Definition: DwarfDebug.h:721
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:683
Definition: BitVector.h:941
unsigned size() const
Definition: StringMap.h:93
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:105
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:611
void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, StringRef Prefix, const MCSymbol *SecBegin, ArrayRef< AppleAccelTableData::Atom > Atoms)
Definition: AccelTable.cpp:542
unsigned getUniqueID() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:599
static constexpr Atom Atoms[]
Definition: AccelTable.h:364
#define P(N)
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Definition: STLExtras.h:1397
const char Magic[]
Definition: Archive.cpp:41
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:156
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A structured debug information entry.
Definition: DIE.h:722
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
static dwarf::Form BestForm(bool IsSigned, uint64_t Int)
Choose the best form for integer.
Definition: DIE.h:170
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:82
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:593
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
Definition: AsmWriter.cpp:4577
constexpr double e
Definition: MathExtras.h:58
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
StringEntries Entries
Definition: AccelTable.h:162
BucketList Buckets
Definition: AccelTable.h:169
void emitDWARF5AccelTable(AsmPrinter *Asm, AccelTable< DWARF5AccelTableData > &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit >> CUs)
Definition: AccelTable.cpp:549
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:706
void finalize(AsmPrinter *Asm, StringRef Prefix)
Definition: AccelTable.cpp:54
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:263
Interface which the different types of accelerator table data have to conform.
Definition: AccelTable.h:114
uint64_t Offset
void print(raw_ostream &OS) const
Definition: AccelTable.cpp:664
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:350
DwarfCompileUnit * lookupCU(const DIE *Die)
Find the matching DwarfCompileUnit for the given CU DIE.
Definition: DwarfDebug.h:791
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1116
size_type size() const
Definition: DenseSet.h:81
void print(raw_ostream &OS) const
Definition: AccelTable.cpp:633
uint32_t Index
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
A base class holding non-template-dependant functionality of the AccelTable class.
Definition: AccelTable.h:135
This file contains constants used for implementing Dwarf debug support.
void print(raw_ostream &OS) const
Definition: AccelTable.cpp:651
const uint16_t Form
DWARF Form.
Definition: AccelTable.h:229
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:607
dwarf::Tag getTag() const
Definition: DIE.h:758
String pool entry reference.
basic Basic Alias true
An integer value DIE.
Definition: DIE.h:163
Represents a group of entries with identical name (and hence, hash value).
Definition: AccelTable.h:140
StringRef TagString(unsigned Tag)
Definition: Dwarf.cpp:21
The Data class implementation for DWARF v5 accelerator table.
Definition: AccelTable.h:250
static constexpr Atom Atoms[]
Definition: AccelTable.h:346
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:693
uint64_t getDebugSectionOffset() const
Get the absolute offset within the .debug_info or .debug_types section for this DIE.
Definition: DIE.cpp:197
uint32_t UniqueHashCount
Definition: AccelTable.h:166
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:152
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1479
void stable_sort(R &&Range)
Definition: STLExtras.h:1633
LLVM Value Representation.
Definition: Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1556
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
const uint64_t Version
Definition: InstrProf.h:989
detail::enumerator< R > enumerate(R &&TheRange)
Given an input range, returns a new range whose values are are pair (A,B) such that A is the 0-based ...
Definition: STLExtras.h:1916
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59