37 std::vector<uint32_t> Uniques;
40 Uniques.push_back(
E.second.HashValue);
42 std::vector<uint32_t>::iterator
P =
43 std::unique(Uniques.begin(), Uniques.end());
47 if (UniqueHashCount > 1024)
49 else if (UniqueHashCount > 16)
59 std::stable_sort(
E.second.Values.begin(),
E.second.Values.end(),
63 E.second.Values.erase(
64 std::unique(
E.second.Values.begin(),
E.second.Values.end()),
65 E.second.Values.end());
76 for (
auto &
E : Entries) {
78 Buckets[Bucket].push_back(&
E.second);
85 std::stable_sort(Bucket.begin(), Bucket.end(),
94 class AccelTableWriter {
102 const bool SkipIdenticalHashes;
104 void emitHashes()
const;
112 bool SkipIdenticalHashes)
113 :
Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
117 class AppleAccelTableWriter :
public AccelTableWriter {
130 static const uint32_t MagicHash = 0x48415348;
133 :
BucketCount(BucketCount), HashCount(UniqueHashCount),
134 HeaderDataLength(DataLength) {}
153 : DieOffsetBase(
Offset), Atoms(AtomList.
begin(), AtomList.
end()) {}
163 HeaderData HeaderData;
166 void emitBuckets()
const;
167 void emitData()
const;
172 : AccelTableWriter(Asm, Contents,
true),
174 8 + (Atoms.
size() * 4)),
175 HeaderData(Atoms), SecBegin(SecBegin) {}
192 template <
typename DataT>
193 class Dwarf5AccelTableWriter :
public AccelTableWriter {
197 uint16_t Padding = 0;
204 uint32_t AugmentationStringSize =
sizeof(AugmentationString);
205 char AugmentationString[8] = {
'L',
'L',
'V',
'M',
'0',
'7',
'0',
'0'};
208 : CompUnitCount(CompUnitCount),
BucketCount(BucketCount),
209 NameCount(NameCount) {}
211 void emit(
const Dwarf5AccelTableWriter &Ctx)
const;
213 struct AttributeEncoding {
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");
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(
250 void AccelTableWriter::emitHashes()
const {
252 unsigned BucketIdx = 0;
253 for (
auto &Bucket : Contents.getBuckets()) {
254 for (
auto &
Hash : Bucket) {
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();
269 for (
size_t i = 0, e =
Buckets.size(); i < e; ++i) {
272 if (SkipIdenticalHashes && PrevHash == HashValue)
274 PrevHash = HashValue;
275 Asm->OutStreamer->AddComment(
"Offset in Bucket " +
Twine(i));
281 void AppleAccelTableWriter::Header::emit(
AsmPrinter *
Asm)
const {
286 Asm->
OutStreamer->AddComment(
"Header Hash Function");
288 Asm->
OutStreamer->AddComment(
"Header Bucket Count");
292 Asm->
OutStreamer->AddComment(
"Header Data Length");
296 void AppleAccelTableWriter::HeaderData::emit(
AsmPrinter *Asm)
const {
297 Asm->
OutStreamer->AddComment(
"HeaderData Die Offset Base");
299 Asm->
OutStreamer->AddComment(
"HeaderData Atom Count");
302 for (
const Atom &A : Atoms) {
310 void AppleAccelTableWriter::emitBuckets()
const {
311 const auto &
Buckets = Contents.getBuckets();
313 for (
size_t i = 0, e =
Buckets.size(); i < e; ++i) {
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) {
339 PrevHash !=
Hash->HashValue)
347 for (
const auto *V :
Hash->Values)
349 PrevHash =
Hash->HashValue;
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.");
372 Asm->
OutStreamer->AddComment(
"Header: unit length");
375 Asm->
OutStreamer->EmitLabel(Ctx.ContributionStart);
380 Asm->
OutStreamer->AddComment(
"Header: compilation unit count");
382 Asm->
OutStreamer->AddComment(
"Header: local type unit count");
384 Asm->
OutStreamer->AddComment(
"Header: foreign type unit count");
386 Asm->
OutStreamer->AddComment(
"Header: bucket count");
388 Asm->
OutStreamer->AddComment(
"Header: name count");
390 Asm->
OutStreamer->AddComment(
"Header: abbreviation table size");
392 Asm->
OutStreamer->AddComment(
"Header: augmentation string size");
393 assert(AugmentationStringSize % 4 == 0);
395 Asm->
OutStreamer->AddComment(
"Header: augmentation string");
396 Asm->
OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
399 template <
typename DataT>
402 for (
auto &Bucket : Contents.getBuckets()) {
403 for (
auto *
Hash : Bucket) {
405 unsigned Tag =
static_cast<const DataT *
>(
Value)->getDieTag();
413 template <
typename DataT>
415 Dwarf5AccelTableWriter<DataT>::getUniformAttributes()
const {
417 if (CompUnits.size() > 1) {
418 size_t LargestCUIndex = CompUnits.
size() - 1;
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 {
434 template <
typename DataT>
435 void Dwarf5AccelTableWriter<DataT>::emitBuckets()
const {
437 for (
const auto &Bucket :
enumerate(Contents.getBuckets())) {
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()) {
456 template <
typename DataT>
457 void Dwarf5AccelTableWriter<DataT>::emitAbbrevs()
const {
459 for (
const auto &Abbrev : Abbreviations) {
461 assert(Abbrev.first != 0);
465 for (
const auto &AttrEnc : Abbrev.second) {
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) {
486 switch (AttrEnc.Index) {
487 case dwarf::DW_IDX_compile_unit: {
492 case dwarf::DW_IDX_die_offset:
493 assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
502 template <
typename DataT>
void Dwarf5AccelTableWriter<DataT>::emitData()
const {
504 for (
auto &Bucket : Contents.getBuckets()) {
505 for (
auto *
Hash : Bucket) {
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(
521 : AccelTableWriter(Asm, Contents,
false),
524 CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
528 Abbreviations.reserve(UniqueTags.
size());
530 Abbreviations.try_emplace(
Tag, UniformAttributes);
533 template <
typename DataT>
void Dwarf5AccelTableWriter<DataT>::emit()
const {
539 emitOffsets(EntryPool);
550 AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
556 std::vector<MCSymbol *> CompUnits;
560 if (
CU.value()->getCUNode()->getNameTableKind() ==
563 CUIndex[
CU.index()] = Count++;
564 assert(
CU.index() ==
CU.value()->getUniqueID());
567 CompUnits.push_back(MainCU->getLabelBegin());
570 if (CompUnits.empty())
577 Dwarf5AccelTableWriter<DWARF5AccelTableData>(
578 Asm, Contents, CompUnits,
590 getCUIndexForEntry) {
592 Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(
Asm, Contents, CUs,
598 Asm->
emitInt32(Die.getDebugSectionOffset());
602 Asm->
emitInt32(Die.getDebugSectionOffset());
628 AppleAccelTableOffsetData::Atoms = {
635 AppleAccelTableStaticOffsetData::Atoms = {
638 AppleAccelTableStaticTypeData::Atoms = {
641 Atom(5, dwarf::DW_FORM_data1),
Atom(6, dwarf::DW_FORM_data4)};
647 <<
"Version: " <<
Version <<
"\n" 648 <<
"Hash Function: " << HashFunction <<
"\n" 650 <<
"Header Data Length: " << HeaderDataLength <<
"\n";
659 OS <<
"DIE Offset Base: " << DieOffsetBase <<
"\n";
660 for (
auto Atom : Atoms)
666 HeaderData.print(OS);
668 SecBegin->print(OS,
nullptr);
672 OS <<
"Name: " <<
Name.getString() <<
"\n";
673 OS <<
" Hash Value: " <<
format(
"0x%x", HashValue) <<
"\n";
680 for (
auto *
Value : Values)
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";
695 for (
auto &
Hash : Bucket)
699 for (
auto &
E : Entries)
704 OS <<
" Offset: " << getDieOffset() <<
"\n";
709 OS <<
" Offset: " << getDieOffset() <<
"\n";
714 OS <<
" Offset: " << Die.getOffset() <<
"\n";
718 OS <<
" Offset: " << Die.getOffset() <<
"\n";
723 OS <<
" Static Offset: " <<
Offset <<
"\n";
727 OS <<
" Static Offset: " <<
Offset <<
"\n";
728 OS <<
" QualifiedNameHash: " <<
format(
"%x\n", QualifiedNameHash) <<
"\n";
730 OS <<
" ObjCClassIsImplementation: " 731 << (ObjCClassIsImplementation ?
"true" :
"false");
StringRef getString() const
static constexpr Atom Atoms[]
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
void print(raw_ostream &OS) const override
StringRef IndexString(unsigned Idx)
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
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 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
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).
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
amdgpu Simplify well known AMD library false Value Value const Twine & Name
uint32_t getUniqueHashCount() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
const DIE * getUnitDie() const
Climb up the parent chain to get the compile unit or type unit DIE that this DIE belongs to...
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")
uint32_t getUniqueNameCount() const
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)
A base class for different implementations of Data classes for Apple Accelerator Tables.
#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)
static const char *const Magic
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Interface which the different types of accelerator table data have to conform.
void print(raw_ostream &OS) const
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.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void print(raw_ostream &OS) const
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.
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
void emit(AsmPrinter *Asm) const override
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
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...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void emitInt8(int Value) const
Emit a byte directive and value.
LLVM Value Representation.
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...
StringRef - Represent a constant reference to a string, i.e.
void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const
EmitValue - Emit integer of appropriate size.
Marker as the end of a list of atoms.
MCSymbol * createTempSymbol(const Twine &Name) const
uint32_t getBucketCount() const
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 ...