35 std::vector<uint32_t> Uniques;
38 Uniques.push_back(
E.second.HashValue);
40 std::vector<uint32_t>::iterator
P =
41 std::unique(Uniques.begin(), Uniques.end());
61 E.second.Values.erase(
62 std::unique(
E.second.Values.begin(),
E.second.Values.end()),
63 E.second.Values.end());
76 Buckets[Bucket].push_back(&
E.second);
77 E.second.Sym = Asm->createTempSymbol(Prefix);
84 return LHS->HashValue <
RHS->HashValue;
91class AccelTableWriter {
99 const bool SkipIdenticalHashes;
101 void emitHashes()
const;
109 bool SkipIdenticalHashes)
110 : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
114class AppleAccelTableWriter :
public AccelTableWriter {
127 static const uint32_t MagicHash = 0x48415348;
130 : BucketCount(BucketCount), HashCount(UniqueHashCount),
131 HeaderDataLength(DataLength) {}
150 : DieOffsetBase(
Offset), Atoms(AtomList.
begin(), AtomList.
end()) {}
160 HeaderData HeaderData;
163 void emitBuckets()
const;
164 void emitData()
const;
169 : AccelTableWriter(
Asm, Contents,
true),
170 Header(Contents.getBucketCount(), Contents.getUniqueHashCount(),
171 8 + (Atoms.
size() * 4)),
172 HeaderData(Atoms), SecBegin(SecBegin) {}
189template <
typename DataT>
190class Dwarf5AccelTableWriter :
public AccelTableWriter {
200 uint32_t AugmentationStringSize =
sizeof(AugmentationString);
201 char AugmentationString[8] = {
'L',
'L',
'V',
'M',
'0',
'7',
'0',
'0'};
204 : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
205 NameCount(NameCount) {}
207 void emit(Dwarf5AccelTableWriter &Ctx);
209 struct AttributeEncoding {
218 MCSymbol *ContributionEnd =
nullptr;
219 MCSymbol *AbbrevStart =
Asm->createTempSymbol(
"names_abbrev_start");
220 MCSymbol *AbbrevEnd =
Asm->createTempSymbol(
"names_abbrev_end");
221 MCSymbol *EntryPool =
Asm->createTempSymbol(
"names_entries");
228 void emitCUList()
const;
229 void emitBuckets()
const;
230 void emitStringOffsets()
const;
231 void emitAbbrevs()
const;
232 void emitEntry(
const DataT &Entry)
const;
233 void emitData()
const;
236 Dwarf5AccelTableWriter(
245void AccelTableWriter::emitHashes()
const {
246 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
247 unsigned BucketIdx = 0;
248 for (
const auto &Bucket : Contents.getBuckets()) {
249 for (
const auto &Hash : Bucket) {
250 uint32_t HashValue = Hash->HashValue;
251 if (SkipIdenticalHashes && PrevHash == HashValue)
253 Asm->OutStreamer->AddComment(
"Hash in Bucket " +
Twine(BucketIdx));
254 Asm->emitInt32(HashValue);
255 PrevHash = HashValue;
261void AccelTableWriter::emitOffsets(
const MCSymbol *
Base)
const {
262 const auto &Buckets = Contents.getBuckets();
263 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
264 for (
size_t i = 0, e = Buckets.size(); i < e; ++i) {
265 for (
auto *Hash : Buckets[i]) {
266 uint32_t HashValue = Hash->HashValue;
267 if (SkipIdenticalHashes && PrevHash == HashValue)
269 PrevHash = HashValue;
270 Asm->OutStreamer->AddComment(
"Offset in Bucket " +
Twine(i));
271 Asm->emitLabelDifference(Hash->Sym,
Base,
Asm->getDwarfOffsetByteSize());
276void AppleAccelTableWriter::Header::emit(
AsmPrinter *Asm)
const {
277 Asm->OutStreamer->AddComment(
"Header Magic");
278 Asm->emitInt32(Magic);
279 Asm->OutStreamer->AddComment(
"Header Version");
280 Asm->emitInt16(Version);
281 Asm->OutStreamer->AddComment(
"Header Hash Function");
282 Asm->emitInt16(HashFunction);
283 Asm->OutStreamer->AddComment(
"Header Bucket Count");
284 Asm->emitInt32(BucketCount);
285 Asm->OutStreamer->AddComment(
"Header Hash Count");
286 Asm->emitInt32(HashCount);
287 Asm->OutStreamer->AddComment(
"Header Data Length");
288 Asm->emitInt32(HeaderDataLength);
291void AppleAccelTableWriter::HeaderData::emit(
AsmPrinter *Asm)
const {
292 Asm->OutStreamer->AddComment(
"HeaderData Die Offset Base");
293 Asm->emitInt32(DieOffsetBase);
294 Asm->OutStreamer->AddComment(
"HeaderData Atom Count");
297 for (
const Atom &
A : Atoms) {
299 Asm->emitInt16(
A.Type);
301 Asm->emitInt16(
A.Form);
305void AppleAccelTableWriter::emitBuckets()
const {
306 const auto &Buckets = Contents.getBuckets();
308 for (
size_t i = 0, e = Buckets.size(); i < e; ++i) {
309 Asm->OutStreamer->AddComment(
"Bucket " +
Twine(i));
310 if (!Buckets[i].empty())
311 Asm->emitInt32(index);
313 Asm->emitInt32(std::numeric_limits<uint32_t>::max());
316 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
317 for (
auto *HD : Buckets[i]) {
319 if (PrevHash != HashValue)
321 PrevHash = HashValue;
326void AppleAccelTableWriter::emitData()
const {
327 const auto &Buckets = Contents.getBuckets();
329 uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
330 for (
const auto &Hash : Bucket) {
333 if (PrevHash != std::numeric_limits<uint64_t>::max() &&
334 PrevHash != Hash->HashValue)
337 Asm->OutStreamer->emitLabel(Hash->Sym);
338 Asm->OutStreamer->AddComment(Hash->Name.getString());
339 Asm->emitDwarfStringOffset(Hash->Name);
340 Asm->OutStreamer->AddComment(
"Num DIEs");
341 Asm->emitInt32(Hash->Values.size());
342 for (
const auto *V : Hash->Values)
344 PrevHash = Hash->HashValue;
352void AppleAccelTableWriter::emit()
const {
354 HeaderData.emit(Asm);
357 emitOffsets(SecBegin);
361template <
typename DataT>
362void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
363 assert(CompUnitCount > 0 &&
"Index must have at least one CU.");
366 Ctx.ContributionEnd =
367 Asm->emitDwarfUnitLength(
"names",
"Header: unit length");
368 Asm->OutStreamer->AddComment(
"Header: version");
369 Asm->emitInt16(Version);
370 Asm->OutStreamer->AddComment(
"Header: padding");
371 Asm->emitInt16(Padding);
372 Asm->OutStreamer->AddComment(
"Header: compilation unit count");
373 Asm->emitInt32(CompUnitCount);
374 Asm->OutStreamer->AddComment(
"Header: local type unit count");
375 Asm->emitInt32(LocalTypeUnitCount);
376 Asm->OutStreamer->AddComment(
"Header: foreign type unit count");
377 Asm->emitInt32(ForeignTypeUnitCount);
378 Asm->OutStreamer->AddComment(
"Header: bucket count");
379 Asm->emitInt32(BucketCount);
380 Asm->OutStreamer->AddComment(
"Header: name count");
381 Asm->emitInt32(NameCount);
382 Asm->OutStreamer->AddComment(
"Header: abbreviation table size");
383 Asm->emitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart,
sizeof(
uint32_t));
384 Asm->OutStreamer->AddComment(
"Header: augmentation string size");
385 assert(AugmentationStringSize % 4 == 0);
386 Asm->emitInt32(AugmentationStringSize);
387 Asm->OutStreamer->AddComment(
"Header: augmentation string");
388 Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
391template <
typename DataT>
394 for (
auto &Bucket : Contents.getBuckets()) {
395 for (
auto *Hash : Bucket) {
396 for (
auto *
Value : Hash->Values) {
397 unsigned Tag =
static_cast<const DataT *
>(
Value)->getDieTag();
405template <
typename DataT>
407Dwarf5AccelTableWriter<DataT>::getUniformAttributes()
const {
409 if (CompUnits.
size() > 1) {
410 size_t LargestCUIndex = CompUnits.
size() - 1;
414 UA.
push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
418template <
typename DataT>
419void Dwarf5AccelTableWriter<DataT>::emitCUList()
const {
421 Asm->OutStreamer->AddComment(
"Compilation unit " +
Twine(
CU.index()));
422 Asm->emitDwarfSymbolReference(
CU.value());
426template <
typename DataT>
427void Dwarf5AccelTableWriter<DataT>::emitBuckets()
const {
429 for (
const auto &Bucket :
enumerate(Contents.getBuckets())) {
430 Asm->OutStreamer->AddComment(
"Bucket " +
Twine(Bucket.index()));
431 Asm->emitInt32(Bucket.value().empty() ? 0 :
Index);
432 Index += Bucket.value().size();
436template <
typename DataT>
437void Dwarf5AccelTableWriter<DataT>::emitStringOffsets()
const {
438 for (
const auto &Bucket :
enumerate(Contents.getBuckets())) {
439 for (
auto *Hash : Bucket.value()) {
441 Asm->OutStreamer->AddComment(
"String in Bucket " +
Twine(Bucket.index()) +
442 ": " +
String.getString());
448template <
typename DataT>
449void Dwarf5AccelTableWriter<DataT>::emitAbbrevs()
const {
450 Asm->OutStreamer->emitLabel(AbbrevStart);
451 for (
const auto &Abbrev : Abbreviations) {
452 Asm->OutStreamer->AddComment(
"Abbrev code");
453 assert(Abbrev.first != 0);
454 Asm->emitULEB128(Abbrev.first);
456 Asm->emitULEB128(Abbrev.first);
457 for (
const auto &AttrEnc : Abbrev.second) {
459 Asm->emitULEB128(AttrEnc.Form,
462 Asm->emitULEB128(0,
"End of abbrev");
463 Asm->emitULEB128(0,
"End of abbrev");
465 Asm->emitULEB128(0,
"End of abbrev list");
466 Asm->OutStreamer->emitLabel(AbbrevEnd);
469template <
typename DataT>
470void Dwarf5AccelTableWriter<DataT>::emitEntry(
const DataT &Entry)
const {
471 auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
472 assert(AbbrevIt != Abbreviations.end() &&
473 "Why wasn't this abbrev generated?");
475 Asm->emitULEB128(AbbrevIt->first,
"Abbreviation code");
476 for (
const auto &AttrEnc : AbbrevIt->second) {
478 switch (AttrEnc.Index) {
479 case dwarf::DW_IDX_compile_unit: {
481 ID.emitValue(Asm, AttrEnc.Form);
484 case dwarf::DW_IDX_die_offset:
485 assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
486 Asm->emitInt32(Entry.getDieOffset());
494template <
typename DataT>
void Dwarf5AccelTableWriter<DataT>::emitData()
const {
495 Asm->OutStreamer->emitLabel(EntryPool);
496 for (
auto &Bucket : Contents.getBuckets()) {
497 for (
auto *Hash : Bucket) {
499 Asm->OutStreamer->emitLabel(Hash->Sym);
500 for (
const auto *
Value : Hash->Values)
501 emitEntry(*
static_cast<const DataT *
>(
Value));
502 Asm->OutStreamer->AddComment(
"End of list: " + Hash->Name.getString());
508template <
typename DataT>
509Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
513 : AccelTableWriter(
Asm, Contents,
false),
514 Header(CompUnits.
size(), Contents.getBucketCount(),
515 Contents.getUniqueNameCount()),
516 CompUnits(CompUnits), getCUIndexForEntry(
std::
move(getCUIndexForEntry)) {
520 Abbreviations.reserve(UniqueTags.
size());
522 Abbreviations.try_emplace(
Tag, UniformAttributes);
525template <
typename DataT>
void Dwarf5AccelTableWriter<DataT>::emit() {
531 emitOffsets(EntryPool);
534 Asm->OutStreamer->emitValueToAlignment(
Align(4), 0);
535 Asm->OutStreamer->emitLabel(ContributionEnd);
542 AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
548 std::vector<MCSymbol *> CompUnits;
552 if (
CU.value()->getCUNode()->getNameTableKind() !=
555 CUIndex[
CU.index()] = Count++;
556 assert(
CU.index() ==
CU.value()->getUniqueID());
562 if (CompUnits.empty())
565 Asm->OutStreamer->switchSection(
566 Asm->getObjFileLowering().getDwarfDebugNamesSection());
569 Dwarf5AccelTableWriter<DWARF5AccelTableData>(
570 Asm, Contents, CompUnits,
572 const DIE *CUDie = Entry.getDie().getUnitDie();
573 return CUIndex[DD.
lookupCU(CUDie)->getUniqueID()];
582 getCUIndexForEntry) {
584 Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
591 "The section offset exceeds the limit.");
597 "The section offset exceeds the limit.");
621void AppleAccelTableWriter::Header::print(
raw_ostream &
OS)
const {
622 OS <<
"Magic: " <<
format(
"0x%x", Magic) <<
"\n"
623 <<
"Version: " << Version <<
"\n"
624 <<
"Hash Function: " << HashFunction <<
"\n"
625 <<
"Bucket Count: " << BucketCount <<
"\n"
626 <<
"Header Data Length: " << HeaderDataLength <<
"\n";
634void AppleAccelTableWriter::HeaderData::print(
raw_ostream &
OS)
const {
635 OS <<
"DIE Offset Base: " << DieOffsetBase <<
"\n";
636 for (
auto Atom : Atoms)
642 HeaderData.print(
OS);
648 OS <<
"Name: " <<
Name.getString() <<
"\n";
649 OS <<
" Hash Value: " <<
format(
"0x%x", HashValue) <<
"\n";
656 for (
auto *
Value : Values)
663 for (
const auto &Entry : Entries) {
664 OS <<
"Name: " << Entry.first() <<
"\n";
665 for (
auto *V : Entry.second.Values)
669 OS <<
"Buckets and Hashes: \n";
670 for (
const auto &Bucket : Buckets)
671 for (
const auto &Hash : Bucket)
675 for (
const auto &
E : Entries)
680 OS <<
" Offset: " << getDieOffset() <<
"\n";
685 OS <<
" Offset: " << getDieOffset() <<
"\n";
690 OS <<
" Offset: " << Die.getOffset() <<
"\n";
694 OS <<
" Offset: " << Die.getOffset() <<
"\n";
699 OS <<
" Static Offset: " <<
Offset <<
"\n";
703 OS <<
" Static Offset: " <<
Offset <<
"\n";
704 OS <<
" QualifiedNameHash: " <<
format(
"%x\n", QualifiedNameHash) <<
"\n";
706 OS <<
" ObjCClassIsImplementation: "
707 << (ObjCClassIsImplementation ?
"true" :
"false");
This file defines the StringMap class.
This file contains support for writing accelerator tables.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A base class holding non-template-dependant functionality of the AccelTable class.
std::vector< HashData * > HashList
void computeBucketCount()
void finalize(AsmPrinter *Asm, StringRef Prefix)
void print(raw_ostream &OS) const
Interface which the different types of accelerator table data have to conform.
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
A base class for different implementations of Data classes for Apple Accelerator Tables.
void emit(AsmPrinter *Asm) const override
void print(raw_ostream &OS) const override
static constexpr Atom Atoms[]
static constexpr Atom Atoms[]
void emit(AsmPrinter *Asm) const override
void print(raw_ostream &OS) const override
uint32_t QualifiedNameHash
void emit(AsmPrinter *Asm) const override
void print(raw_ostream &OS) const override
bool ObjCClassIsImplementation
static constexpr Atom Atoms[]
void print(raw_ostream &OS) const override
void emit(AsmPrinter *Asm) const override
static constexpr Atom Atoms[]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
static dwarf::Form BestForm(bool IsSigned, uint64_t Int)
Choose the best form for integer.
A structured debug information entry.
uint64_t getDebugSectionOffset() const
Get the absolute offset within the .debug_info or .debug_types section for this DIE.
dwarf::Tag getTag() const
The Data class implementation for DWARF v5 accelerator table.
void print(raw_ostream &OS) const override
void print(raw_ostream &OS) const override
Implements a dense probed hash-table based set.
MCSymbol * getLabelBegin() const
Collects and handles dwarf debug information.
DwarfCompileUnit * lookupCU(const DIE *Die)
Find the matching DwarfCompileUnit for the given CU DIE.
bool useSplitDwarf() const
Returns whether or not to change the current debug info for the split dwarf proposal support.
DwarfStringPoolEntryRef: Dwarf string pool entry reference.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
std::pair< iterator, bool > insert(const ValueT &V)
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
StringRef FormEncodingString(unsigned Encoding)
StringRef IndexString(unsigned Idx)
StringRef AtomTypeString(unsigned Atom)
StringRef TagString(unsigned Tag)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ DW_FLAG_type_implementation
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void stable_sort(R &&Range)
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.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are are tuples (A,...
void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, StringRef Prefix, const MCSymbol *SecBegin, ArrayRef< AppleAccelTableData::Atom > Atoms)
void emitDWARF5AccelTable(AsmPrinter *Asm, AccelTable< DWARF5AccelTableData > &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit > > CUs)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Represents a group of entries with identical name (and hence, hash value).
void print(raw_ostream &OS) const
This struct is a compact representation of a valid (non-zero power of two) alignment.
An Atom defines the form of the data in an Apple accelerator table.
void print(raw_ostream &OS) const