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 14 #include "llvm/CodeGen/AccelTable.h" 15 #include "DwarfCompileUnit.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringMap.h" 18 #include "llvm/ADT/Twine.h" 19 #include "llvm/BinaryFormat/Dwarf.h" 20 #include "llvm/CodeGen/AsmPrinter.h" 21 #include "llvm/CodeGen/DIE.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCStreamer.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <algorithm> 26 #include <cstddef> 27 #include <cstdint> 28 #include <limits> 29 #include <vector> 30 31 using namespace llvm; 32 33 void AccelTableBase::computeBucketCount() { 34 // First get the number of unique hashes. 35 std::vector<uint32_t> Uniques; 36 Uniques.reserve(Entries.size()); 37 for (const auto &E : Entries) 38 Uniques.push_back(E.second.HashValue); 39 array_pod_sort(Uniques.begin(), Uniques.end()); 40 std::vector<uint32_t>::iterator P = 41 std::unique(Uniques.begin(), Uniques.end()); 42 43 UniqueHashCount = std::distance(Uniques.begin(), P); 44 45 if (UniqueHashCount > 1024) 46 BucketCount = UniqueHashCount / 4; 47 else if (UniqueHashCount > 16) 48 BucketCount = UniqueHashCount / 2; 49 else 50 BucketCount = std::max<uint32_t>(UniqueHashCount, 1); 51 } 52 53 void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) { 54 // Create the individual hash data outputs. 55 for (auto &E : Entries) { 56 // Unique the entries. 57 std::stable_sort(E.second.Values.begin(), E.second.Values.end(), 58 [](const AccelTableData *A, const AccelTableData *B) { 59 return *A < *B; 60 }); 61 E.second.Values.erase( 62 std::unique(E.second.Values.begin(), E.second.Values.end()), 63 E.second.Values.end()); 64 } 65 66 // Figure out how many buckets we need, then compute the bucket contents and 67 // the final ordering. The hashes and offsets can be emitted by walking these 68 // data structures. We add temporary symbols to the data so they can be 69 // referenced when emitting the offsets. 70 computeBucketCount(); 71 72 // Compute bucket contents and final ordering. 73 Buckets.resize(BucketCount); 74 for (auto &E : Entries) { 75 uint32_t Bucket = E.second.HashValue % BucketCount; 76 Buckets[Bucket].push_back(&E.second); 77 E.second.Sym = Asm->createTempSymbol(Prefix); 78 } 79 80 // Sort the contents of the buckets by hash value so that hash collisions end 81 // up together. Stable sort makes testing easier and doesn't cost much more. 82 for (auto &Bucket : Buckets) 83 std::stable_sort(Bucket.begin(), Bucket.end(), 84 [](HashData *LHS, HashData *RHS) { 85 return LHS->HashValue < RHS->HashValue; 86 }); 87 } 88 89 namespace { 90 /// Base class for writing out Accelerator tables. It holds the common 91 /// functionality for the two Accelerator table types. 92 class AccelTableEmitter { 93 protected: 94 AsmPrinter *const Asm; ///< Destination. 95 const AccelTableBase &Contents; ///< Data to emit. 96 97 /// Controls whether to emit duplicate hash and offset table entries for names 98 /// with identical hashes. Apple tables don't emit duplicate entries, DWARF v5 99 /// tables do. 100 const bool SkipIdenticalHashes; 101 102 void emitHashes() const; 103 104 /// Emit offsets to lists of entries with identical names. The offsets are 105 /// relative to the Base argument. 106 void emitOffsets(const MCSymbol *Base) const; 107 108 public: 109 AccelTableEmitter(AsmPrinter *Asm, const AccelTableBase &Contents, 110 bool SkipIdenticalHashes) 111 : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) { 112 } 113 }; 114 115 class AppleAccelTableEmitter : public AccelTableEmitter { 116 using Atom = AppleAccelTableData::Atom; 117 118 /// The fixed header of an Apple Accelerator Table. 119 struct Header { 120 uint32_t Magic = MagicHash; 121 uint16_t Version = 1; 122 uint16_t HashFunction = dwarf::DW_hash_function_djb; 123 uint32_t BucketCount; 124 uint32_t HashCount; 125 uint32_t HeaderDataLength; 126 127 /// 'HASH' magic value to detect endianness. 128 static const uint32_t MagicHash = 0x48415348; 129 130 Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength) 131 : BucketCount(BucketCount), HashCount(UniqueHashCount), 132 HeaderDataLength(DataLength) {} 133 134 void emit(AsmPrinter *Asm) const; 135 #ifndef NDEBUG 136 void print(raw_ostream &OS) const; 137 void dump() const { print(dbgs()); } 138 #endif 139 }; 140 141 /// The HeaderData describes the structure of an Apple accelerator table 142 /// through a list of Atoms. 143 struct HeaderData { 144 /// In the case of data that is referenced via DW_FORM_ref_* the offset 145 /// base is used to describe the offset for all forms in the list of atoms. 146 uint32_t DieOffsetBase; 147 148 const SmallVector<Atom, 4> Atoms; 149 150 HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0) 151 : DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {} 152 153 void emit(AsmPrinter *Asm) const; 154 #ifndef NDEBUG 155 void print(raw_ostream &OS) const; 156 void dump() const { print(dbgs()); } 157 #endif 158 }; 159 160 Header Header; 161 HeaderData HeaderData; 162 const MCSymbol *SecBegin; 163 164 void emitBuckets() const; 165 void emitData() const; 166 167 public: 168 AppleAccelTableEmitter(AsmPrinter *Asm, const AccelTableBase &Contents, 169 ArrayRef<Atom> Atoms, const MCSymbol *SecBegin) 170 : AccelTableEmitter(Asm, Contents, true), 171 Header(Contents.getBucketCount(), Contents.getUniqueHashCount(), 172 8 + (Atoms.size() * 4)), 173 HeaderData(Atoms), SecBegin(SecBegin) {} 174 175 void emit() const; 176 177 #ifndef NDEBUG 178 void print(raw_ostream &OS) const; 179 void dump() const { print(dbgs()); } 180 #endif 181 }; 182 183 /// Class responsible for emitting a DWARF v5 Accelerator Table. The only public 184 /// function is emit(), which performs the actual emission. 185 class Dwarf5AccelTableEmitter : public AccelTableEmitter { 186 struct Header { 187 uint32_t UnitLength = 0; 188 uint16_t Version = 5; 189 uint16_t Padding = 0; 190 uint32_t CompUnitCount; 191 uint32_t LocalTypeUnitCount = 0; 192 uint32_t ForeignTypeUnitCount = 0; 193 uint32_t BucketCount; 194 uint32_t NameCount; 195 uint32_t AbbrevTableSize = 0; 196 uint32_t AugmentationStringSize = sizeof(AugmentationString); 197 char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'}; 198 199 Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount) 200 : CompUnitCount(CompUnitCount), BucketCount(BucketCount), 201 NameCount(NameCount) {} 202 203 void emit(const Dwarf5AccelTableEmitter &Ctx) const; 204 }; 205 struct AttributeEncoding { 206 dwarf::Index Index; 207 dwarf::Form Form; 208 }; 209 210 Header Header; 211 DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations; 212 const DwarfDebug ⅅ 213 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits; 214 MCSymbol *ContributionStart = Asm->createTempSymbol("names_start"); 215 MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end"); 216 MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start"); 217 MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end"); 218 MCSymbol *EntryPool = Asm->createTempSymbol("names_entries"); 219 220 DenseSet<uint32_t> getUniqueTags() const; 221 222 // Right now, we emit uniform attributes for all tags. 223 SmallVector<AttributeEncoding, 2> getUniformAttributes() const; 224 225 void emitCUList() const; 226 void emitBuckets() const; 227 void emitStringOffsets() const; 228 void emitAbbrevs() const; 229 void emitEntry(const DWARF5AccelTableData &Data) const; 230 void emitData() const; 231 232 public: 233 Dwarf5AccelTableEmitter( 234 AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 235 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits); 236 237 void emit() const; 238 }; 239 } // namespace 240 241 void AccelTableEmitter::emitHashes() const { 242 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 243 unsigned BucketIdx = 0; 244 for (auto &Bucket : Contents.getBuckets()) { 245 for (auto &Hash : Bucket) { 246 uint32_t HashValue = Hash->HashValue; 247 if (SkipIdenticalHashes && PrevHash == HashValue) 248 continue; 249 Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx)); 250 Asm->emitInt32(HashValue); 251 PrevHash = HashValue; 252 } 253 BucketIdx++; 254 } 255 } 256 257 void AccelTableEmitter::emitOffsets(const MCSymbol *Base) const { 258 const auto &Buckets = Contents.getBuckets(); 259 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 260 for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 261 for (auto *Hash : Buckets[i]) { 262 uint32_t HashValue = Hash->HashValue; 263 if (SkipIdenticalHashes && PrevHash == HashValue) 264 continue; 265 PrevHash = HashValue; 266 Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i)); 267 Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t)); 268 } 269 } 270 } 271 272 void AppleAccelTableEmitter::Header::emit(AsmPrinter *Asm) const { 273 Asm->OutStreamer->AddComment("Header Magic"); 274 Asm->emitInt32(Magic); 275 Asm->OutStreamer->AddComment("Header Version"); 276 Asm->emitInt16(Version); 277 Asm->OutStreamer->AddComment("Header Hash Function"); 278 Asm->emitInt16(HashFunction); 279 Asm->OutStreamer->AddComment("Header Bucket Count"); 280 Asm->emitInt32(BucketCount); 281 Asm->OutStreamer->AddComment("Header Hash Count"); 282 Asm->emitInt32(HashCount); 283 Asm->OutStreamer->AddComment("Header Data Length"); 284 Asm->emitInt32(HeaderDataLength); 285 } 286 287 void AppleAccelTableEmitter::HeaderData::emit(AsmPrinter *Asm) const { 288 Asm->OutStreamer->AddComment("HeaderData Die Offset Base"); 289 Asm->emitInt32(DieOffsetBase); 290 Asm->OutStreamer->AddComment("HeaderData Atom Count"); 291 Asm->emitInt32(Atoms.size()); 292 293 for (const Atom &A : Atoms) { 294 Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type)); 295 Asm->emitInt16(A.Type); 296 Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form)); 297 Asm->emitInt16(A.Form); 298 } 299 } 300 301 void AppleAccelTableEmitter::emitBuckets() const { 302 const auto &Buckets = Contents.getBuckets(); 303 unsigned index = 0; 304 for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 305 Asm->OutStreamer->AddComment("Bucket " + Twine(i)); 306 if (!Buckets[i].empty()) 307 Asm->emitInt32(index); 308 else 309 Asm->emitInt32(std::numeric_limits<uint32_t>::max()); 310 // Buckets point in the list of hashes, not to the data. Do not increment 311 // the index multiple times in case of hash collisions. 312 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 313 for (auto *HD : Buckets[i]) { 314 uint32_t HashValue = HD->HashValue; 315 if (PrevHash != HashValue) 316 ++index; 317 PrevHash = HashValue; 318 } 319 } 320 } 321 322 void AppleAccelTableEmitter::emitData() const { 323 const auto &Buckets = Contents.getBuckets(); 324 for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 325 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 326 for (auto &Hash : Buckets[i]) { 327 // Terminate the previous entry if there is no hash collision with the 328 // current one. 329 if (PrevHash != std::numeric_limits<uint64_t>::max() && 330 PrevHash != Hash->HashValue) 331 Asm->emitInt32(0); 332 // Remember to emit the label for our offset. 333 Asm->OutStreamer->EmitLabel(Hash->Sym); 334 Asm->OutStreamer->AddComment(Hash->Name.getString()); 335 Asm->emitDwarfStringOffset(Hash->Name); 336 Asm->OutStreamer->AddComment("Num DIEs"); 337 Asm->emitInt32(Hash->Values.size()); 338 for (const auto *V : Hash->Values) 339 static_cast<const AppleAccelTableData *>(V)->emit(Asm); 340 PrevHash = Hash->HashValue; 341 } 342 // Emit the final end marker for the bucket. 343 if (!Buckets[i].empty()) 344 Asm->emitInt32(0); 345 } 346 } 347 348 void AppleAccelTableEmitter::emit() const { 349 Header.emit(Asm); 350 HeaderData.emit(Asm); 351 emitBuckets(); 352 emitHashes(); 353 emitOffsets(SecBegin); 354 emitData(); 355 } 356 357 void Dwarf5AccelTableEmitter::Header::emit( 358 const Dwarf5AccelTableEmitter &Ctx) const { 359 assert(CompUnitCount > 0 && "Index must have at least one CU."); 360 361 AsmPrinter *Asm = Ctx.Asm; 362 Asm->OutStreamer->AddComment("Header: unit length"); 363 Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart, 364 sizeof(uint32_t)); 365 Asm->OutStreamer->EmitLabel(Ctx.ContributionStart); 366 Asm->OutStreamer->AddComment("Header: version"); 367 Asm->emitInt16(Version); 368 Asm->OutStreamer->AddComment("Header: padding"); 369 Asm->emitInt16(Padding); 370 Asm->OutStreamer->AddComment("Header: compilation unit count"); 371 Asm->emitInt32(CompUnitCount); 372 Asm->OutStreamer->AddComment("Header: local type unit count"); 373 Asm->emitInt32(LocalTypeUnitCount); 374 Asm->OutStreamer->AddComment("Header: foreign type unit count"); 375 Asm->emitInt32(ForeignTypeUnitCount); 376 Asm->OutStreamer->AddComment("Header: bucket count"); 377 Asm->emitInt32(BucketCount); 378 Asm->OutStreamer->AddComment("Header: name count"); 379 Asm->emitInt32(NameCount); 380 Asm->OutStreamer->AddComment("Header: abbreviation table size"); 381 Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t)); 382 Asm->OutStreamer->AddComment("Header: augmentation string size"); 383 assert(AugmentationStringSize % 4 == 0); 384 Asm->emitInt32(AugmentationStringSize); 385 Asm->OutStreamer->AddComment("Header: augmentation string"); 386 Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize}); 387 } 388 389 DenseSet<uint32_t> Dwarf5AccelTableEmitter::getUniqueTags() const { 390 DenseSet<uint32_t> UniqueTags; 391 for (auto &Bucket : Contents.getBuckets()) { 392 for (auto *Hash : Bucket) { 393 for (auto *Value : Hash->Values) { 394 const DIE &Die = 395 static_cast<const DWARF5AccelTableData *>(Value)->getDie(); 396 UniqueTags.insert(Die.getTag()); 397 } 398 } 399 } 400 return UniqueTags; 401 } 402 403 SmallVector<Dwarf5AccelTableEmitter::AttributeEncoding, 2> 404 Dwarf5AccelTableEmitter::getUniformAttributes() const { 405 SmallVector<AttributeEncoding, 2> UA; 406 if (CompUnits.size() > 1) { 407 size_t LargestCUIndex = CompUnits.size() - 1; 408 dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex); 409 UA.push_back({dwarf::DW_IDX_compile_unit, Form}); 410 } 411 UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4}); 412 return UA; 413 } 414 415 void Dwarf5AccelTableEmitter::emitCUList() const { 416 for (const auto &CU : enumerate(CompUnits)) { 417 assert(CU.index() == CU.value()->getUniqueID()); 418 Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index())); 419 const DwarfCompileUnit *MainCU = 420 DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get(); 421 Asm->emitDwarfSymbolReference(MainCU->getLabelBegin()); 422 } 423 } 424 425 void Dwarf5AccelTableEmitter::emitBuckets() const { 426 uint32_t Index = 1; 427 for (const auto &Bucket : enumerate(Contents.getBuckets())) { 428 Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index())); 429 Asm->emitInt32(Bucket.value().empty() ? 0 : Index); 430 Index += Bucket.value().size(); 431 } 432 } 433 434 void Dwarf5AccelTableEmitter::emitStringOffsets() const { 435 for (const auto &Bucket : enumerate(Contents.getBuckets())) { 436 for (auto *Hash : Bucket.value()) { 437 DwarfStringPoolEntryRef String = Hash->Name; 438 Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) + 439 ": " + String.getString()); 440 Asm->emitDwarfStringOffset(String); 441 } 442 } 443 } 444 445 void Dwarf5AccelTableEmitter::emitAbbrevs() const { 446 Asm->OutStreamer->EmitLabel(AbbrevStart); 447 for (const auto &Abbrev : Abbreviations) { 448 Asm->OutStreamer->AddComment("Abbrev code"); 449 assert(Abbrev.first != 0); 450 Asm->EmitULEB128(Abbrev.first); 451 Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first)); 452 Asm->EmitULEB128(Abbrev.first); 453 for (const auto &AttrEnc : Abbrev.second) { 454 Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); 455 Asm->EmitULEB128(AttrEnc.Form, 456 dwarf::FormEncodingString(AttrEnc.Form).data()); 457 } 458 Asm->EmitULEB128(0, "End of abbrev"); 459 Asm->EmitULEB128(0, "End of abbrev"); 460 } 461 Asm->EmitULEB128(0, "End of abbrev list"); 462 Asm->OutStreamer->EmitLabel(AbbrevEnd); 463 } 464 465 void Dwarf5AccelTableEmitter::emitEntry( 466 const DWARF5AccelTableData &Entry) const { 467 auto AbbrevIt = Abbreviations.find(Entry.getDie().getTag()); 468 assert(AbbrevIt != Abbreviations.end() && 469 "Why wasn't this abbrev generated?"); 470 471 Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code"); 472 for (const auto &AttrEnc : AbbrevIt->second) { 473 Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index)); 474 switch (AttrEnc.Index) { 475 case dwarf::DW_IDX_compile_unit: { 476 const DIE *CUDie = Entry.getDie().getUnitDie(); 477 DIEInteger ID(DD.lookupCU(CUDie)->getUniqueID()); 478 ID.EmitValue(Asm, AttrEnc.Form); 479 break; 480 } 481 case dwarf::DW_IDX_die_offset: 482 assert(AttrEnc.Form == dwarf::DW_FORM_ref4); 483 Asm->emitInt32(Entry.getDie().getOffset()); 484 break; 485 default: 486 llvm_unreachable("Unexpected index attribute!"); 487 } 488 } 489 } 490 491 void Dwarf5AccelTableEmitter::emitData() const { 492 Asm->OutStreamer->EmitLabel(EntryPool); 493 for (auto &Bucket : Contents.getBuckets()) { 494 for (auto *Hash : Bucket) { 495 // Remember to emit the label for our offset. 496 Asm->OutStreamer->EmitLabel(Hash->Sym); 497 for (const auto *Value : Hash->Values) 498 emitEntry(*static_cast<const DWARF5AccelTableData *>(Value)); 499 Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString()); 500 Asm->emitInt32(0); 501 } 502 } 503 } 504 505 Dwarf5AccelTableEmitter::Dwarf5AccelTableEmitter( 506 AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 507 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits) 508 : AccelTableEmitter(Asm, Contents, false), 509 Header(CompUnits.size(), Contents.getBucketCount(), 510 Contents.getUniqueNameCount()), 511 DD(DD), CompUnits(CompUnits) { 512 DenseSet<uint32_t> UniqueTags = getUniqueTags(); 513 SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes(); 514 515 Abbreviations.reserve(UniqueTags.size()); 516 for (uint32_t Tag : UniqueTags) 517 Abbreviations.try_emplace(Tag, UniformAttributes); 518 } 519 520 void Dwarf5AccelTableEmitter::emit() const { 521 Header.emit(*this); 522 emitCUList(); 523 emitBuckets(); 524 emitHashes(); 525 emitStringOffsets(); 526 emitOffsets(EntryPool); 527 emitAbbrevs(); 528 emitData(); 529 Asm->OutStreamer->EmitValueToAlignment(4, 0); 530 Asm->OutStreamer->EmitLabel(ContributionEnd); 531 } 532 533 void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, 534 StringRef Prefix, const MCSymbol *SecBegin, 535 ArrayRef<AppleAccelTableData::Atom> Atoms) { 536 Contents.finalize(Asm, Prefix); 537 AppleAccelTableEmitter(Asm, Contents, Atoms, SecBegin).emit(); 538 } 539 540 void llvm::emitDWARF5AccelTable( 541 AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents, 542 const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) { 543 Contents.finalize(Asm, "names"); 544 Dwarf5AccelTableEmitter(Asm, Contents, DD, CUs).emit(); 545 } 546 547 void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const { 548 Asm->emitInt32(Die->getDebugSectionOffset()); 549 } 550 551 void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const { 552 Asm->emitInt32(Die->getDebugSectionOffset()); 553 Asm->emitInt16(Die->getTag()); 554 Asm->emitInt8(0); 555 } 556 557 void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const { 558 Asm->emitInt32(Offset); 559 } 560 561 void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const { 562 Asm->emitInt32(Offset); 563 Asm->emitInt16(Tag); 564 Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation 565 : 0); 566 Asm->emitInt32(QualifiedNameHash); 567 } 568 569 #ifndef _MSC_VER 570 // The lines below are rejected by older versions (TBD) of MSVC. 571 constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[]; 572 constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[]; 573 constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[]; 574 constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[]; 575 #else 576 // FIXME: Erase this path once the minimum MSCV version has been bumped. 577 const SmallVector<AppleAccelTableData::Atom, 4> 578 AppleAccelTableOffsetData::Atoms = { 579 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 580 const SmallVector<AppleAccelTableData::Atom, 4> AppleAccelTableTypeData::Atoms = 581 {Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 582 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 583 Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; 584 const SmallVector<AppleAccelTableData::Atom, 4> 585 AppleAccelTableStaticOffsetData::Atoms = { 586 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 587 const SmallVector<AppleAccelTableData::Atom, 4> 588 AppleAccelTableStaticTypeData::Atoms = { 589 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 590 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 591 Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; 592 #endif 593 594 #ifndef NDEBUG 595 void AppleAccelTableEmitter::Header::print(raw_ostream &OS) const { 596 OS << "Magic: " << format("0x%x", Magic) << "\n" 597 << "Version: " << Version << "\n" 598 << "Hash Function: " << HashFunction << "\n" 599 << "Bucket Count: " << BucketCount << "\n" 600 << "Header Data Length: " << HeaderDataLength << "\n"; 601 } 602 603 void AppleAccelTableData::Atom::print(raw_ostream &OS) const { 604 OS << "Type: " << dwarf::AtomTypeString(Type) << "\n" 605 << "Form: " << dwarf::FormEncodingString(Form) << "\n"; 606 } 607 608 void AppleAccelTableEmitter::HeaderData::print(raw_ostream &OS) const { 609 OS << "DIE Offset Base: " << DieOffsetBase << "\n"; 610 for (auto Atom : Atoms) 611 Atom.print(OS); 612 } 613 614 void AppleAccelTableEmitter::print(raw_ostream &OS) const { 615 Header.print(OS); 616 HeaderData.print(OS); 617 Contents.print(OS); 618 SecBegin->print(OS, nullptr); 619 } 620 621 void AccelTableBase::HashData::print(raw_ostream &OS) const { 622 OS << "Name: " << Name.getString() << "\n"; 623 OS << " Hash Value: " << format("0x%x", HashValue) << "\n"; 624 OS << " Symbol: "; 625 if (Sym) 626 OS << *Sym; 627 else 628 OS << "<none>"; 629 OS << "\n"; 630 for (auto *Value : Values) 631 Value->print(OS); 632 } 633 634 void AccelTableBase::print(raw_ostream &OS) const { 635 // Print Content. 636 OS << "Entries: \n"; 637 for (const auto &Entry : Entries) { 638 OS << "Name: " << Entry.first() << "\n"; 639 for (auto *V : Entry.second.Values) 640 V->print(OS); 641 } 642 643 OS << "Buckets and Hashes: \n"; 644 for (auto &Bucket : Buckets) 645 for (auto &Hash : Bucket) 646 Hash->print(OS); 647 648 OS << "Data: \n"; 649 for (auto &E : Entries) 650 E.second.print(OS); 651 } 652 653 void DWARF5AccelTableData::print(raw_ostream &OS) const { 654 OS << " Offset: " << Die.getOffset() << "\n"; 655 OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n"; 656 } 657 658 void AppleAccelTableOffsetData::print(raw_ostream &OS) const { 659 OS << " Offset: " << Die->getOffset() << "\n"; 660 } 661 662 void AppleAccelTableTypeData::print(raw_ostream &OS) const { 663 OS << " Offset: " << Die->getOffset() << "\n"; 664 OS << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; 665 } 666 667 void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const { 668 OS << " Static Offset: " << Offset << "\n"; 669 } 670 671 void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const { 672 OS << " Static Offset: " << Offset << "\n"; 673 OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n"; 674 OS << " Tag: " << dwarf::TagString(Tag) << "\n"; 675 OS << " ObjCClassIsImplementation: " 676 << (ObjCClassIsImplementation ? "true" : "false"); 677 OS << "\n"; 678 } 679 #endif 680