35 std::vector<uint32_t> Uniques;
38 Uniques.push_back(
E.second.HashValue);
40 std::vector<uint32_t>::iterator
P =
61 E.second.Values.erase(
63 E.second.Values.end());
76 Buckets[Bucket].push_back(&
E.second);
84 return LHS->HashValue <
RHS->HashValue;
91 class AccelTableWriter {
99 const bool SkipIdenticalHashes;
101 void emitHashes()
const;
105 void emitOffsets(
const MCSymbol *Base)
const;
109 bool SkipIdenticalHashes)
110 :
Asm(
Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
114 class 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) {}
189 template <
typename DataT>
190 class 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(
245 void AccelTableWriter::emitHashes()
const {
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;
261 void AccelTableWriter::emitOffsets(
const MCSymbol *Base)
const {
262 const auto &Buckets = Contents.getBuckets();
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());
277 Asm->OutStreamer->AddComment(
"Header Magic");
279 Asm->OutStreamer->AddComment(
"Header 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);
292 Asm->OutStreamer->AddComment(
"HeaderData Die Offset Base");
293 Asm->emitInt32(DieOffsetBase);
294 Asm->OutStreamer->AddComment(
"HeaderData Atom Count");
295 Asm->emitInt32(Atoms.size());
297 for (
const Atom &A : Atoms) {
299 Asm->emitInt16(
A.Type);
301 Asm->emitInt16(
A.Form);
305 void 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())
317 for (
auto *HD : Buckets[
i]) {
319 if (PrevHash != HashValue)
321 PrevHash = HashValue;
326 void AppleAccelTableWriter::emitData()
const {
327 const auto &Buckets = Contents.getBuckets();
330 for (
const auto &Hash : Bucket) {
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;
354 HeaderData.emit(
Asm);
357 emitOffsets(SecBegin);
361 template <
typename DataT>
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");
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});
391 template <
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();
405 template <
typename DataT>
407 Dwarf5AccelTableWriter<DataT>::getUniformAttributes()
const {
409 if (CompUnits.
size() > 1) {
410 size_t LargestCUIndex = CompUnits.
size() - 1;
412 UA.push_back({dwarf::DW_IDX_compile_unit,
Form});
414 UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
418 template <
typename DataT>
419 void Dwarf5AccelTableWriter<DataT>::emitCUList()
const {
421 Asm->OutStreamer->AddComment(
"Compilation unit " +
Twine(
CU.index()));
422 Asm->emitDwarfSymbolReference(
CU.value());
426 template <
typename DataT>
427 void 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();
436 template <
typename DataT>
437 void 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());
443 Asm->emitDwarfStringOffset(String);
448 template <
typename DataT>
449 void 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);
469 template <
typename DataT>
470 void 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());
494 template <
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());
508 template <
typename DataT>
509 Dwarf5AccelTableWriter<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);
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();
582 getCUIndexForEntry) {
584 Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(
Asm, Contents, CUs,
591 "The section offset exceeds the limit.");
597 "The section offset exceeds the limit.");
623 <<
"Version: " <<
Version <<
"\n"
624 <<
"Hash Function: " << HashFunction <<
"\n"
625 <<
"Bucket Count: " << BucketCount <<
"\n"
626 <<
"Header Data Length: " << HeaderDataLength <<
"\n";
635 OS <<
"DIE Offset Base: " << DieOffsetBase <<
"\n";
636 for (
auto Atom : Atoms)
642 HeaderData.print(OS);
644 SecBegin->
print(OS,
nullptr);
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");