LLVM  8.0.1
AccelTable.cpp
Go to the documentation of this file.
1 //===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains support for writing accelerator tables.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "DwarfCompileUnit.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/Twine.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"
27 #include <algorithm>
28 #include <cstddef>
29 #include <cstdint>
30 #include <limits>
31 #include <vector>
32 
33 using namespace llvm;
34 
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());
44 
45  UniqueHashCount = std::distance(Uniques.begin(), P);
46 
47  if (UniqueHashCount > 1024)
48  BucketCount = UniqueHashCount / 4;
49  else if (UniqueHashCount > 16)
50  BucketCount = UniqueHashCount / 2;
51  else
52  BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
53 }
54 
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) {
61  return *A < *B;
62  });
63  E.second.Values.erase(
64  std::unique(E.second.Values.begin(), E.second.Values.end()),
65  E.second.Values.end());
66  }
67 
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.
73 
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);
80  }
81 
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;
88  });
89 }
90 
91 namespace {
92 /// Base class for writing out Accelerator tables. It holds the common
93 /// functionality for the two Accelerator table types.
94 class AccelTableWriter {
95 protected:
96  AsmPrinter *const Asm; ///< Destination.
97  const AccelTableBase &Contents; ///< Data to emit.
98 
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
101  /// tables do.
102  const bool SkipIdenticalHashes;
103 
104  void emitHashes() const;
105 
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;
109 
110 public:
111  AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
112  bool SkipIdenticalHashes)
113  : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
114  }
115 };
116 
117 class AppleAccelTableWriter : public AccelTableWriter {
118  using Atom = AppleAccelTableData::Atom;
119 
120  /// The fixed header of an Apple Accelerator Table.
121  struct Header {
122  uint32_t Magic = MagicHash;
123  uint16_t Version = 1;
124  uint16_t HashFunction = dwarf::DW_hash_function_djb;
126  uint32_t HashCount;
127  uint32_t HeaderDataLength;
128 
129  /// 'HASH' magic value to detect endianness.
130  static const uint32_t MagicHash = 0x48415348;
131 
132  Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength)
133  : BucketCount(BucketCount), HashCount(UniqueHashCount),
134  HeaderDataLength(DataLength) {}
135 
136  void emit(AsmPrinter *Asm) const;
137 #ifndef NDEBUG
138  void print(raw_ostream &OS) const;
139  void dump() const { print(dbgs()); }
140 #endif
141  };
142 
143  /// The HeaderData describes the structure of an Apple accelerator table
144  /// through a list of Atoms.
145  struct HeaderData {
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;
149 
150  const SmallVector<Atom, 4> Atoms;
151 
152  HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0)
153  : DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {}
154 
155  void emit(AsmPrinter *Asm) const;
156 #ifndef NDEBUG
157  void print(raw_ostream &OS) const;
158  void dump() const { print(dbgs()); }
159 #endif
160  };
161 
162  Header Header;
163  HeaderData HeaderData;
164  const MCSymbol *SecBegin;
165 
166  void emitBuckets() const;
167  void emitData() const;
168 
169 public:
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) {}
176 
177  void emit() const;
178 
179 #ifndef NDEBUG
180  void print(raw_ostream &OS) const;
181  void dump() const { print(dbgs()); }
182 #endif
183 };
184 
185 /// Class responsible for emitting a DWARF v5 Accelerator Table. The only
186 /// public function is emit(), which performs the actual emission.
187 ///
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 {
194  struct Header {
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;
202  uint32_t NameCount;
203  uint32_t AbbrevTableSize = 0;
204  uint32_t AugmentationStringSize = sizeof(AugmentationString);
205  char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
206 
207  Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
208  : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
209  NameCount(NameCount) {}
210 
211  void emit(const Dwarf5AccelTableWriter &Ctx) const;
212  };
213  struct AttributeEncoding {
216  };
217 
218  Header Header;
220  ArrayRef<MCSymbol *> CompUnits;
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");
227 
228  DenseSet<uint32_t> getUniqueTags() const;
229 
230  // Right now, we emit uniform attributes for all tags.
231  SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
232 
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;
239 
240 public:
241  Dwarf5AccelTableWriter(
242  AsmPrinter *Asm, const AccelTableBase &Contents,
243  ArrayRef<MCSymbol *> CompUnits,
244  llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
245 
246  void emit() const;
247 };
248 } // namespace
249 
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)
257  continue;
258  Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
259  Asm->emitInt32(HashValue);
260  PrevHash = HashValue;
261  }
262  BucketIdx++;
263  }
264 }
265 
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)
273  continue;
274  PrevHash = HashValue;
275  Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
276  Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t));
277  }
278  }
279 }
280 
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);
294 }
295 
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());
301 
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);
307  }
308 }
309 
310 void AppleAccelTableWriter::emitBuckets() const {
311  const auto &Buckets = Contents.getBuckets();
312  unsigned index = 0;
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);
317  else
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)
325  ++index;
326  PrevHash = HashValue;
327  }
328  }
329 }
330 
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
337  // current one.
338  if (PrevHash != std::numeric_limits<uint64_t>::max() &&
339  PrevHash != Hash->HashValue)
340  Asm->emitInt32(0);
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;
350  }
351  // Emit the final end marker for the bucket.
352  if (!Buckets[i].empty())
353  Asm->emitInt32(0);
354  }
355 }
356 
357 void AppleAccelTableWriter::emit() const {
358  Header.emit(Asm);
359  HeaderData.emit(Asm);
360  emitBuckets();
361  emitHashes();
362  emitOffsets(SecBegin);
363  emitData();
364 }
365 
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.");
370 
371  AsmPrinter *Asm = Ctx.Asm;
372  Asm->OutStreamer->AddComment("Header: unit length");
373  Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
374  sizeof(uint32_t));
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});
397 }
398 
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);
407  }
408  }
409  }
410  return UniqueTags;
411 }
412 
413 template <typename DataT>
415 Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
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});
421  }
422  UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
423  return UA;
424 }
425 
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());
431  }
432 }
433 
434 template <typename DataT>
435 void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
436  uint32_t Index = 1;
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();
441  }
442 }
443 
444 template <typename DataT>
445 void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
446  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
447  for (auto *Hash : Bucket.value()) {
449  Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
450  ": " + String.getString());
451  Asm->emitDwarfStringOffset(String);
452  }
453  }
454 }
455 
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());
469  }
470  Asm->EmitULEB128(0, "End of abbrev");
471  Asm->EmitULEB128(0, "End of abbrev");
472  }
473  Asm->EmitULEB128(0, "End of abbrev list");
474  Asm->OutStreamer->EmitLabel(AbbrevEnd);
475 }
476 
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?");
482 
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);
490  break;
491  }
492  case dwarf::DW_IDX_die_offset:
493  assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
494  Asm->emitInt32(Entry.getDieOffset());
495  break;
496  default:
497  llvm_unreachable("Unexpected index attribute!");
498  }
499  }
500 }
501 
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());
511  Asm->emitInt32(0);
512  }
513  }
514 }
515 
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();
527 
528  Abbreviations.reserve(UniqueTags.size());
529  for (uint32_t Tag : UniqueTags)
530  Abbreviations.try_emplace(Tag, UniformAttributes);
531 }
532 
533 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
534  Header.emit(*this);
535  emitCUList();
536  emitBuckets();
537  emitHashes();
538  emitStringOffsets();
539  emitOffsets(EntryPool);
540  emitAbbrevs();
541  emitData();
542  Asm->OutStreamer->EmitValueToAlignment(4, 0);
543  Asm->OutStreamer->EmitLabel(ContributionEnd);
544 }
545 
547  StringRef Prefix, const MCSymbol *SecBegin,
549  Contents.finalize(Asm, Prefix);
550  AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
551 }
552 
555  const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
556  std::vector<MCSymbol *> CompUnits;
557  SmallVector<unsigned, 1> CUIndex(CUs.size());
558  int Count = 0;
559  for (const auto &CU : enumerate(CUs)) {
560  if (CU.value()->getCUNode()->getNameTableKind() ==
562  continue;
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());
568  }
569 
570  if (CompUnits.empty())
571  return;
572 
573  Asm->OutStreamer->SwitchSection(
575 
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()];
582  })
583  .emit();
584 }
585 
590  getCUIndexForEntry) {
591  Contents.finalize(Asm, "names");
592  Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
593  getCUIndexForEntry)
594  .emit();
595 }
596 
598  Asm->emitInt32(Die.getDebugSectionOffset());
599 }
600 
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);
614  Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation
615  : 0);
616  Asm->emitInt32(QualifiedNameHash);
617 }
618 
619 #ifndef _MSC_VER
620 // The lines below are rejected by older versions (TBD) of MSVC.
625 #else
626 // FIXME: Erase this path once the minimum MSCV version has been bumped.
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)};
635  AppleAccelTableStaticOffsetData::Atoms = {
636  Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
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)};
642 #endif
643 
644 #ifndef NDEBUG
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";
651 }
652 
654  OS << "Type: " << dwarf::AtomTypeString(Type) << "\n"
655  << "Form: " << dwarf::FormEncodingString(Form) << "\n";
656 }
657 
659  OS << "DIE Offset Base: " << DieOffsetBase << "\n";
660  for (auto Atom : Atoms)
661  Atom.print(OS);
662 }
663 
665  Header.print(OS);
666  HeaderData.print(OS);
667  Contents.print(OS);
668  SecBegin->print(OS, nullptr);
669 }
670 
672  OS << "Name: " << Name.getString() << "\n";
673  OS << " Hash Value: " << format("0x%x", HashValue) << "\n";
674  OS << " Symbol: ";
675  if (Sym)
676  OS << *Sym;
677  else
678  OS << "<none>";
679  OS << "\n";
680  for (auto *Value : Values)
681  Value->print(OS);
682 }
683 
685  // Print Content.
686  OS << "Entries: \n";
687  for (const auto &Entry : Entries) {
688  OS << "Name: " << Entry.first() << "\n";
689  for (auto *V : Entry.second.Values)
690  V->print(OS);
691  }
692 
693  OS << "Buckets and Hashes: \n";
694  for (auto &Bucket : Buckets)
695  for (auto &Hash : Bucket)
696  Hash->print(OS);
697 
698  OS << "Data: \n";
699  for (auto &E : Entries)
700  E.second.print(OS);
701 }
702 
704  OS << " Offset: " << getDieOffset() << "\n";
705  OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
706 }
707 
709  OS << " Offset: " << getDieOffset() << "\n";
710  OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
711 }
712 
714  OS << " Offset: " << Die.getOffset() << "\n";
715 }
716 
718  OS << " Offset: " << Die.getOffset() << "\n";
719  OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n";
720 }
721 
723  OS << " Static Offset: " << Offset << "\n";
724 }
725 
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");
732  OS << "\n";
733 }
734 #endif
static constexpr Atom Atoms[]
Definition: AccelTable.h:332
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:212
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:722
StringRef IndexString(unsigned Idx)
Definition: Dwarf.cpp:615
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:94
This class represents lattice values for constants.
Definition: AllocatorList.h:24
StringRef AtomTypeString(unsigned Atom)
Definition: Dwarf.cpp:521
An Atom defines the form of the data in an Apple accelerator table.
Definition: AccelTable.h:228
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
iterator begin() const
Definition: ArrayRef.h:137
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:708
static constexpr Atom Atoms[]
Definition: AccelTable.h:412
Collects and handles dwarf debug information.
Definition: DwarfDebug.h:281
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition: AccelTable.h:199
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:117
void emitDwarfSymbolReference(const MCSymbol *Label, bool ForceOffset=false) const
Emit a reference to a symbol for use in dwarf.
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:717
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
bool useSplitDwarf() const
Returns whether or not to change the current debug info for the split dwarf proposal support...
Definition: DwarfDebug.h:656
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:703
amdgpu Simplify well known AMD library false Value Value const Twine & Name
uint32_t getUniqueHashCount() const
Definition: AccelTable.h:182
unsigned size() const
Definition: StringMap.h:112
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
const DIE * getUnitDie() const
Climb up the parent chain to get the compile unit or type unit DIE that this DIE belongs to...
Definition: DIE.cpp:204
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:106
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:546
unsigned getUniqueID() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:601
static constexpr Atom Atoms[]
Definition: AccelTable.h:381
#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:1083
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
uint32_t getUniqueNameCount() const
Definition: AccelTable.h:183
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:149
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A structured debug information entry.
Definition: DIE.h:662
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:188
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:79
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:597
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
Definition: AsmWriter.cpp:4148
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
StringEntries Entries
Definition: AccelTable.h:165
BucketList Buckets
Definition: AccelTable.h:172
void emitDWARF5AccelTable(AsmPrinter *Asm, AccelTable< DWARF5AccelTableData > &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit >> CUs)
Definition: AccelTable.cpp:553
size_t size() const
Definition: SmallVector.h:53
A base class for different implementations of Data classes for Apple Accelerator Tables.
Definition: AccelTable.h:223
#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:726
void finalize(AsmPrinter *Asm, StringRef Prefix)
Definition: AccelTable.cpp:55
static const char *const Magic
Definition: Archive.cpp:42
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:210
Interface which the different types of accelerator table data have to conform.
Definition: AccelTable.h:117
void dump() const
Definition: AccelTable.h:187
void print(raw_ostream &OS) const
Definition: AccelTable.cpp:684
void emitDwarfStringOffset(DwarfStringPoolEntry S) const
Emit the 4-byte offset of a string from the start of its section.
DwarfCompileUnit * lookupCU(const DIE *Die)
Find the matching DwarfCompileUnit for the given CU DIE.
Definition: DwarfDebug.h:715
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
size_type size() const
Definition: DenseSet.h:76
void print(raw_ostream &OS) const
Definition: AccelTable.cpp:653
iterator end() const
Definition: ArrayRef.h:138
void emitInt32(int Value) const
Emit a long directive and value.
MCSection * getDwarfDebugNamesSection() const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
A base class holding non-template-dependant functionality of the AccelTable class.
Definition: AccelTable.h:138
This file contains constants used for implementing Dwarf debug support.
void print(raw_ostream &OS) const
Definition: AccelTable.cpp:671
void emit(AsmPrinter *Asm) const override
Definition: AccelTable.cpp:607
String pool entry reference.
An integer value DIE.
Definition: DIE.h:163
Represents a group of entries with identical name (and hence, hash value).
Definition: AccelTable.h:143
StringRef TagString(unsigned Tag)
Definition: Dwarf.cpp:22
The Data class implementation for DWARF v5 accelerator table.
Definition: AccelTable.h:253
static constexpr Atom Atoms[]
Definition: AccelTable.h:357
void print(raw_ostream &OS) const override
Definition: AccelTable.cpp:713
void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const
Emit something like ".long Hi-Lo" where the size in bytes of the directive is specified by Size and H...
uint32_t UniqueHashCount
Definition: AccelTable.h:169
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void emitInt8(int Value) const
Emit a byte directive and value.
LLVM Value Representation.
Definition: Value.h:73
void EmitULEB128(uint64_t Value, const char *Desc=nullptr) const
Emit the specified unsigned leb128 value.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const
EmitValue - Emit integer of appropriate size.
Definition: DIE.cpp:376
Marker as the end of a list of atoms.
Definition: Dwarf.h:374
MCSymbol * createTempSymbol(const Twine &Name) const
const uint64_t Version
Definition: InstrProf.h:895
uint32_t getBucketCount() const
Definition: AccelTable.h:181
void emitInt16(int Value) const
Emit a short directive and value.
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:1517