36 std::vector<uint32_t> Uniques;
39 Uniques.push_back(
E.second.HashValue);
41 std::vector<uint32_t>::iterator
P =
42 std::unique(Uniques.begin(), Uniques.end());
62 E.second.Values.erase(
63 std::unique(
E.second.Values.begin(),
E.second.Values.end()),
64 E.second.Values.end());
77 Buckets[Bucket].push_back(&
E.second);
92 class AccelTableWriter {
100 const bool SkipIdenticalHashes;
102 void emitHashes()
const;
110 bool SkipIdenticalHashes)
111 :
Asm(
Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
115 class AppleAccelTableWriter :
public AccelTableWriter {
128 static const uint32_t MagicHash = 0x48415348;
131 : BucketCount(BucketCount), HashCount(UniqueHashCount),
132 HeaderDataLength(DataLength) {}
151 : DieOffsetBase(
Offset), Atoms(AtomList.
begin(), AtomList.
end()) {}
161 HeaderData HeaderData;
164 void emitBuckets()
const;
165 void emitData()
const;
170 : AccelTableWriter(
Asm, Contents,
true),
171 Header(Contents.getBucketCount(), Contents.getUniqueHashCount(),
172 8 + (Atoms.
size() * 4)),
173 HeaderData(Atoms), SecBegin(SecBegin) {}
190 template <
typename DataT>
191 class Dwarf5AccelTableWriter :
public AccelTableWriter {
201 uint32_t AugmentationStringSize =
sizeof(AugmentationString);
202 char AugmentationString[8] = {
'L',
'L',
'V',
'M',
'0',
'7',
'0',
'0'};
205 : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
206 NameCount(NameCount) {}
208 void emit(
const Dwarf5AccelTableWriter &Ctx)
const;
210 struct AttributeEncoding {
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");
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;
238 Dwarf5AccelTableWriter(
247 void AccelTableWriter::emitHashes()
const {
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)
255 Asm->OutStreamer->AddComment(
"Hash in Bucket " +
Twine(BucketIdx));
256 Asm->emitInt32(HashValue);
257 PrevHash = HashValue;
263 void AccelTableWriter::emitOffsets(
const MCSymbol *
Base)
const {
264 const auto &Buckets = Contents.getBuckets();
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)
271 PrevHash = HashValue;
272 Asm->OutStreamer->AddComment(
"Offset in Bucket " +
Twine(i));
273 Asm->emitLabelDifference(Hash->Sym,
Base,
Asm->getDwarfOffsetByteSize());
278 void AppleAccelTableWriter::Header::emit(
AsmPrinter *
Asm)
const {
279 Asm->OutStreamer->AddComment(
"Header Magic");
281 Asm->OutStreamer->AddComment(
"Header 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);
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");
299 for (
const Atom &A : Atoms) {
301 Asm->emitInt16(
A.Type);
303 Asm->emitInt16(
A.Form);
307 void AppleAccelTableWriter::emitBuckets()
const {
308 const auto &Buckets = Contents.getBuckets();
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);
319 for (
auto *HD : Buckets[i]) {
321 if (PrevHash != HashValue)
323 PrevHash = HashValue;
328 void AppleAccelTableWriter::emitData()
const {
329 const auto &Buckets = Contents.getBuckets();
330 for (
size_t i = 0,
e = Buckets.size(); i <
e; ++i) {
332 for (
auto &Hash : Buckets[i]) {
336 PrevHash != Hash->HashValue)
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;
349 if (!Buckets[i].
empty())
354 void AppleAccelTableWriter::emit()
const {
356 HeaderData.emit(
Asm);
359 emitOffsets(SecBegin);
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.");
369 Asm->emitDwarfUnitLength(Ctx.ContributionEnd, Ctx.ContributionStart,
370 "Header: unit length");
371 Asm->OutStreamer->emitLabel(Ctx.ContributionStart);
372 Asm->OutStreamer->AddComment(
"Header: 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});
395 template <
typename DataT>
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();
409 template <
typename DataT>
411 Dwarf5AccelTableWriter<DataT>::getUniformAttributes()
const {
413 if (CompUnits.
size() > 1) {
414 size_t LargestCUIndex = CompUnits.
size() - 1;
418 UA.
push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
422 template <
typename DataT>
423 void Dwarf5AccelTableWriter<DataT>::emitCUList()
const {
425 Asm->OutStreamer->AddComment(
"Compilation unit " +
Twine(
CU.index()));
426 Asm->emitDwarfSymbolReference(
CU.value());
430 template <
typename DataT>
431 void Dwarf5AccelTableWriter<DataT>::emitBuckets()
const {
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();
440 template <
typename DataT>
441 void Dwarf5AccelTableWriter<DataT>::emitStringOffsets()
const {
442 for (
const auto &Bucket :
enumerate(Contents.getBuckets())) {
443 for (
auto *Hash : Bucket.value()) {
445 Asm->OutStreamer->AddComment(
"String in Bucket " +
Twine(Bucket.index()) +
446 ": " +
String.getString());
447 Asm->emitDwarfStringOffset(String);
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);
460 Asm->emitULEB128(Abbrev.first);
461 for (
const auto &AttrEnc : Abbrev.second) {
463 Asm->emitULEB128(AttrEnc.Form,
466 Asm->emitULEB128(0,
"End of abbrev");
467 Asm->emitULEB128(0,
"End of abbrev");
469 Asm->emitULEB128(0,
"End of abbrev list");
470 Asm->OutStreamer->emitLabel(AbbrevEnd);
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?");
479 Asm->emitULEB128(AbbrevIt->first,
"Abbreviation code");
480 for (
const auto &AttrEnc : AbbrevIt->second) {
482 switch (AttrEnc.Index) {
483 case dwarf::DW_IDX_compile_unit: {
485 ID.emitValue(
Asm, AttrEnc.Form);
488 case dwarf::DW_IDX_die_offset:
489 assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
490 Asm->emitInt32(Entry.getDieOffset());
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) {
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());
512 template <
typename DataT>
513 Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
517 : AccelTableWriter(
Asm, Contents,
false),
518 Header(CompUnits.
size(), Contents.getBucketCount(),
519 Contents.getUniqueNameCount()),
520 CompUnits(CompUnits), getCUIndexForEntry(
std::
move(getCUIndexForEntry)) {
524 Abbreviations.reserve(UniqueTags.
size());
526 Abbreviations.try_emplace(
Tag, UniformAttributes);
529 template <
typename DataT>
void Dwarf5AccelTableWriter<DataT>::emit()
const {
535 emitOffsets(EntryPool);
538 Asm->OutStreamer->emitValueToAlignment(4, 0);
539 Asm->OutStreamer->emitLabel(ContributionEnd);
546 AppleAccelTableWriter(
Asm, Contents, Atoms, SecBegin).emit();
552 std::vector<MCSymbol *> CompUnits;
556 if (
CU.value()->getCUNode()->getNameTableKind() !=
559 CUIndex[
CU.index()] = Count++;
560 assert(
CU.index() ==
CU.value()->getUniqueID());
563 CompUnits.push_back(MainCU->getLabelBegin());
566 if (CompUnits.empty())
569 Asm->OutStreamer->SwitchSection(
570 Asm->getObjFileLowering().getDwarfDebugNamesSection());
573 Dwarf5AccelTableWriter<DWARF5AccelTableData>(
574 Asm, Contents, CompUnits,
576 const DIE *CUDie = Entry.getDie().getUnitDie();
586 getCUIndexForEntry) {
588 Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(
Asm, Contents, CUs,
595 "The section offset exceeds the limit.");
601 "The section offset exceeds the limit.");
627 <<
"Version: " <<
Version <<
"\n" 628 <<
"Hash Function: " << HashFunction <<
"\n" 629 <<
"Bucket Count: " << BucketCount <<
"\n" 630 <<
"Header Data Length: " << HeaderDataLength <<
"\n";
639 OS <<
"DIE Offset Base: " << DieOffsetBase <<
"\n";
640 for (
auto Atom : Atoms)
646 HeaderData.print(OS);
648 SecBegin->
print(OS,
nullptr);
652 OS <<
"Name: " <<
Name.getString() <<
"\n";
653 OS <<
" Hash Value: " <<
format(
"0x%x", HashValue) <<
"\n";
660 for (
auto *
Value : Values)
667 for (
const auto &Entry : Entries) {
668 OS <<
"Name: " << Entry.first() <<
"\n";
669 for (
auto *V : Entry.second.Values)
673 OS <<
"Buckets and Hashes: \n";
674 for (
auto &Bucket : Buckets)
675 for (
auto &Hash : Bucket)
679 for (
auto &
E : Entries)
684 OS <<
" Offset: " << getDieOffset() <<
"\n";
689 OS <<
" Offset: " << getDieOffset() <<
"\n";
694 OS <<
" Offset: " << Die.getOffset() <<
"\n";
698 OS <<
" Offset: " << Die.getOffset() <<
"\n";
703 OS <<
" Static Offset: " <<
Offset <<
"\n";
707 OS <<
" Static Offset: " <<
Offset <<
"\n";
708 OS <<
" QualifiedNameHash: " <<
format(
"%x\n", QualifiedNameHash) <<
"\n";
710 OS <<
" ObjCClassIsImplementation: " 711 << (ObjCClassIsImplementation ?
"true" :
"false");
static constexpr Atom Atoms[]
void print(raw_ostream &OS) const override
const_iterator end(StringRef path)
Get end iterator over path.
StringRef IndexString(unsigned Idx)
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
This class represents lattice values for constants.
StringRef AtomTypeString(unsigned Atom)
An Atom defines the form of the data in an Apple accelerator table.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
void print(raw_ostream &OS) const override
void push_back(const T &Elt)
static constexpr Atom Atoms[]
Collects and handles dwarf debug information.
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
An efficient, type-erasing, non-owning reference to a callable.
void print(raw_ostream &OS) const override
bool useSplitDwarf() const
Returns whether or not to change the current debug info for the split dwarf proposal support.
void print(raw_ostream &OS) const override
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
StringRef FormEncodingString(unsigned Encoding)
void emit(AsmPrinter *Asm) const override
void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, StringRef Prefix, const MCSymbol *SecBegin, ArrayRef< AppleAccelTableData::Atom > Atoms)
void computeBucketCount()
unsigned getUniqueID() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
void emit(AsmPrinter *Asm) const override
static constexpr Atom Atoms[]
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
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.
size_t size() const
size - Get the array size.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A structured debug information entry.
std::pair< iterator, bool > insert(const ValueT &V)
static dwarf::Form BestForm(bool IsSigned, uint64_t Int)
Choose the best form for integer.
This class is intended to be used as a driving class for all asm writers.
void emit(AsmPrinter *Asm) const override
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
void emitDWARF5AccelTable(AsmPrinter *Asm, AccelTable< DWARF5AccelTableData > &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit >> CUs)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void print(raw_ostream &OS) const override
void finalize(AsmPrinter *Asm, StringRef Prefix)
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
uint32_t QualifiedNameHash
Interface which the different types of accelerator table data have to conform.
void print(raw_ostream &OS) const
Align max(MaybeAlign Lhs, Align Rhs)
DwarfCompileUnit * lookupCU(const DIE *Die)
Find the matching DwarfCompileUnit for the given CU DIE.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void print(raw_ostream &OS) const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
A base class holding non-template-dependant functionality of the AccelTable class.
This file contains constants used for implementing Dwarf debug support.
void print(raw_ostream &OS) const
const uint16_t Form
DWARF Form.
void emit(AsmPrinter *Asm) const override
dwarf::Tag getTag() const
String pool entry reference.
Represents a group of entries with identical name (and hence, hash value).
StringRef TagString(unsigned Tag)
The Data class implementation for DWARF v5 accelerator table.
static constexpr Atom Atoms[]
void print(raw_ostream &OS) const override
uint64_t getDebugSectionOffset() const
Get the absolute offset within the .debug_info or .debug_types section for this DIE.
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
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.
void stable_sort(R &&Range)
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
bool ObjCClassIsImplementation
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 ...
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.