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 static_assert(sizeof(AugmentationString) % 4 == 0, ""); 199 200 Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount) 201 : CompUnitCount(CompUnitCount), BucketCount(BucketCount), 202 NameCount(NameCount) {} 203 204 void emit(const Dwarf5AccelTableEmitter &Ctx) const; 205 }; 206 struct AttributeEncoding { 207 dwarf::Index Index; 208 dwarf::Form Form; 209 }; 210 211 Header Header; 212 DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations; 213 const DwarfDebug ⅅ 214 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits; 215 MCSymbol *ContributionStart = Asm->createTempSymbol("names_start"); 216 MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end"); 217 MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start"); 218 MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end"); 219 MCSymbol *EntryPool = Asm->createTempSymbol("names_entries"); 220 221 DenseSet<uint32_t> getUniqueTags() const; 222 223 // Right now, we emit uniform attributes for all tags. 224 SmallVector<AttributeEncoding, 2> getUniformAttributes() const; 225 226 void emitCUList() const; 227 void emitBuckets() const; 228 void emitStringOffsets() const; 229 void emitAbbrevs() const; 230 void emitEntry(const DWARF5AccelTableData &Data) const; 231 void emitData() const; 232 233 public: 234 Dwarf5AccelTableEmitter( 235 AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 236 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits); 237 238 void emit() const; 239 }; 240 } // namespace 241 242 void AccelTableEmitter::emitHashes() const { 243 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 244 unsigned BucketIdx = 0; 245 for (auto &Bucket : Contents.getBuckets()) { 246 for (auto &Hash : Bucket) { 247 uint32_t HashValue = Hash->HashValue; 248 if (SkipIdenticalHashes && PrevHash == HashValue) 249 continue; 250 Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx)); 251 Asm->emitInt32(HashValue); 252 PrevHash = HashValue; 253 } 254 BucketIdx++; 255 } 256 } 257 258 void AccelTableEmitter::emitOffsets(const MCSymbol *Base) const { 259 const auto &Buckets = Contents.getBuckets(); 260 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 261 for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 262 for (auto *Hash : Buckets[i]) { 263 uint32_t HashValue = Hash->HashValue; 264 if (SkipIdenticalHashes && PrevHash == HashValue) 265 continue; 266 PrevHash = HashValue; 267 Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i)); 268 Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t)); 269 } 270 } 271 } 272 273 void AppleAccelTableEmitter::Header::emit(AsmPrinter *Asm) const { 274 Asm->OutStreamer->AddComment("Header Magic"); 275 Asm->emitInt32(Magic); 276 Asm->OutStreamer->AddComment("Header Version"); 277 Asm->emitInt16(Version); 278 Asm->OutStreamer->AddComment("Header Hash Function"); 279 Asm->emitInt16(HashFunction); 280 Asm->OutStreamer->AddComment("Header Bucket Count"); 281 Asm->emitInt32(BucketCount); 282 Asm->OutStreamer->AddComment("Header Hash Count"); 283 Asm->emitInt32(HashCount); 284 Asm->OutStreamer->AddComment("Header Data Length"); 285 Asm->emitInt32(HeaderDataLength); 286 } 287 288 void AppleAccelTableEmitter::HeaderData::emit(AsmPrinter *Asm) const { 289 Asm->OutStreamer->AddComment("HeaderData Die Offset Base"); 290 Asm->emitInt32(DieOffsetBase); 291 Asm->OutStreamer->AddComment("HeaderData Atom Count"); 292 Asm->emitInt32(Atoms.size()); 293 294 for (const Atom &A : Atoms) { 295 Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type)); 296 Asm->emitInt16(A.Type); 297 Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form)); 298 Asm->emitInt16(A.Form); 299 } 300 } 301 302 void AppleAccelTableEmitter::emitBuckets() const { 303 const auto &Buckets = Contents.getBuckets(); 304 unsigned index = 0; 305 for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 306 Asm->OutStreamer->AddComment("Bucket " + Twine(i)); 307 if (!Buckets[i].empty()) 308 Asm->emitInt32(index); 309 else 310 Asm->emitInt32(std::numeric_limits<uint32_t>::max()); 311 // Buckets point in the list of hashes, not to the data. Do not increment 312 // the index multiple times in case of hash collisions. 313 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 314 for (auto *HD : Buckets[i]) { 315 uint32_t HashValue = HD->HashValue; 316 if (PrevHash != HashValue) 317 ++index; 318 PrevHash = HashValue; 319 } 320 } 321 } 322 323 void AppleAccelTableEmitter::emitData() const { 324 const auto &Buckets = Contents.getBuckets(); 325 for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 326 uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 327 for (auto &Hash : Buckets[i]) { 328 // Terminate the previous entry if there is no hash collision with the 329 // current one. 330 if (PrevHash != std::numeric_limits<uint64_t>::max() && 331 PrevHash != Hash->HashValue) 332 Asm->emitInt32(0); 333 // Remember to emit the label for our offset. 334 Asm->OutStreamer->EmitLabel(Hash->Sym); 335 Asm->OutStreamer->AddComment(Hash->Name.getString()); 336 Asm->emitDwarfStringOffset(Hash->Name); 337 Asm->OutStreamer->AddComment("Num DIEs"); 338 Asm->emitInt32(Hash->Values.size()); 339 for (const auto *V : Hash->Values) 340 static_cast<const AppleAccelTableData *>(V)->emit(Asm); 341 PrevHash = Hash->HashValue; 342 } 343 // Emit the final end marker for the bucket. 344 if (!Buckets[i].empty()) 345 Asm->emitInt32(0); 346 } 347 } 348 349 void AppleAccelTableEmitter::emit() const { 350 Header.emit(Asm); 351 HeaderData.emit(Asm); 352 emitBuckets(); 353 emitHashes(); 354 emitOffsets(SecBegin); 355 emitData(); 356 } 357 358 void Dwarf5AccelTableEmitter::Header::emit( 359 const Dwarf5AccelTableEmitter &Ctx) const { 360 AsmPrinter *Asm = Ctx.Asm; 361 Asm->OutStreamer->AddComment("Header: unit length"); 362 Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart, 363 sizeof(uint32_t)); 364 Asm->OutStreamer->EmitLabel(Ctx.ContributionStart); 365 Asm->OutStreamer->AddComment("Header: version"); 366 Asm->emitInt16(Version); 367 Asm->OutStreamer->AddComment("Header: padding"); 368 Asm->emitInt16(Padding); 369 Asm->OutStreamer->AddComment("Header: compilation unit count"); 370 Asm->emitInt32(CompUnitCount); 371 Asm->OutStreamer->AddComment("Header: local type unit count"); 372 Asm->emitInt32(LocalTypeUnitCount); 373 Asm->OutStreamer->AddComment("Header: foreign type unit count"); 374 Asm->emitInt32(ForeignTypeUnitCount); 375 Asm->OutStreamer->AddComment("Header: bucket count"); 376 Asm->emitInt32(BucketCount); 377 Asm->OutStreamer->AddComment("Header: name count"); 378 Asm->emitInt32(NameCount); 379 Asm->OutStreamer->AddComment("Header: abbreviation table size"); 380 Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t)); 381 Asm->OutStreamer->AddComment("Header: augmentation string size"); 382 Asm->emitInt32(AugmentationStringSize); 383 Asm->OutStreamer->AddComment("Header: augmentation string"); 384 Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize}); 385 } 386 387 DenseSet<uint32_t> Dwarf5AccelTableEmitter::getUniqueTags() const { 388 DenseSet<uint32_t> UniqueTags; 389 for (auto &Bucket : Contents.getBuckets()) { 390 for (auto *Hash : Bucket) { 391 for (auto *Value : Hash->Values) { 392 const DIE &Die = 393 static_cast<const DWARF5AccelTableData *>(Value)->getDie(); 394 UniqueTags.insert(Die.getTag()); 395 } 396 } 397 } 398 return UniqueTags; 399 } 400 401 SmallVector<Dwarf5AccelTableEmitter::AttributeEncoding, 2> 402 Dwarf5AccelTableEmitter::getUniformAttributes() const { 403 SmallVector<AttributeEncoding, 2> UA; 404 if (CompUnits.size() > 1) { 405 size_t LargestCUIndex = CompUnits.size() - 1; 406 dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex); 407 UA.push_back({dwarf::DW_IDX_compile_unit, Form}); 408 } 409 UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4}); 410 return UA; 411 } 412 413 void Dwarf5AccelTableEmitter::emitCUList() const { 414 for (const auto &CU : enumerate(CompUnits)) { 415 assert(CU.index() == CU.value()->getUniqueID()); 416 Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index())); 417 Asm->emitDwarfSymbolReference(CU.value()->getLabelBegin()); 418 } 419 } 420 421 void Dwarf5AccelTableEmitter::emitBuckets() const { 422 uint32_t Index = 1; 423 for (const auto &Bucket : enumerate(Contents.getBuckets())) { 424 Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index())); 425 Asm->emitInt32(Bucket.value().empty() ? 0 : Index); 426 Index += Bucket.value().size(); 427 } 428 } 429 430 void Dwarf5AccelTableEmitter::emitStringOffsets() const { 431 for (const auto &Bucket : enumerate(Contents.getBuckets())) { 432 for (auto *Hash : Bucket.value()) { 433 DwarfStringPoolEntryRef String = Hash->Name; 434 Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) + 435 ": " + String.getString()); 436 Asm->emitDwarfStringOffset(String); 437 } 438 } 439 } 440 441 void Dwarf5AccelTableEmitter::emitAbbrevs() const { 442 Asm->OutStreamer->EmitLabel(AbbrevStart); 443 for (const auto &Abbrev : Abbreviations) { 444 Asm->OutStreamer->AddComment("Abbrev code"); 445 assert(Abbrev.first != 0); 446 Asm->EmitULEB128(Abbrev.first); 447 Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first)); 448 Asm->EmitULEB128(Abbrev.first); 449 for (const auto &AttrEnc : Abbrev.second) { 450 Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); 451 Asm->EmitULEB128(AttrEnc.Form, 452 dwarf::FormEncodingString(AttrEnc.Form).data()); 453 } 454 Asm->EmitULEB128(0, "End of abbrev"); 455 Asm->EmitULEB128(0, "End of abbrev"); 456 } 457 Asm->EmitULEB128(0, "End of abbrev list"); 458 Asm->OutStreamer->EmitLabel(AbbrevEnd); 459 } 460 461 void Dwarf5AccelTableEmitter::emitEntry( 462 const DWARF5AccelTableData &Entry) const { 463 auto AbbrevIt = Abbreviations.find(Entry.getDie().getTag()); 464 assert(AbbrevIt != Abbreviations.end() && 465 "Why wasn't this abbrev generated?"); 466 467 Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code"); 468 for (const auto &AttrEnc : AbbrevIt->second) { 469 Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index)); 470 switch (AttrEnc.Index) { 471 case dwarf::DW_IDX_compile_unit: { 472 const DIE *CUDie = Entry.getDie().getUnitDie(); 473 DIEInteger ID(DD.lookupCU(CUDie)->getUniqueID()); 474 ID.EmitValue(Asm, AttrEnc.Form); 475 break; 476 } 477 case dwarf::DW_IDX_die_offset: 478 assert(AttrEnc.Form == dwarf::DW_FORM_ref4); 479 Asm->emitInt32(Entry.getDie().getOffset()); 480 break; 481 default: 482 llvm_unreachable("Unexpected index attribute!"); 483 } 484 } 485 } 486 487 void Dwarf5AccelTableEmitter::emitData() const { 488 Asm->OutStreamer->EmitLabel(EntryPool); 489 for (auto &Bucket : Contents.getBuckets()) { 490 for (auto *Hash : Bucket) { 491 // Remember to emit the label for our offset. 492 Asm->OutStreamer->EmitLabel(Hash->Sym); 493 for (const auto *Value : Hash->Values) 494 emitEntry(*static_cast<const DWARF5AccelTableData *>(Value)); 495 Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString()); 496 Asm->emitInt32(0); 497 } 498 } 499 } 500 501 Dwarf5AccelTableEmitter::Dwarf5AccelTableEmitter( 502 AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 503 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits) 504 : AccelTableEmitter(Asm, Contents, false), 505 Header(CompUnits.size(), Contents.getBucketCount(), 506 Contents.getUniqueNameCount()), 507 DD(DD), CompUnits(CompUnits) { 508 DenseSet<uint32_t> UniqueTags = getUniqueTags(); 509 SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes(); 510 511 Abbreviations.reserve(UniqueTags.size()); 512 for (uint32_t Tag : UniqueTags) 513 Abbreviations.try_emplace(Tag, UniformAttributes); 514 } 515 516 void Dwarf5AccelTableEmitter::emit() const { 517 Header.emit(*this); 518 emitCUList(); 519 emitBuckets(); 520 emitHashes(); 521 emitStringOffsets(); 522 emitOffsets(EntryPool); 523 emitAbbrevs(); 524 emitData(); 525 Asm->OutStreamer->EmitValueToAlignment(4, 0); 526 Asm->OutStreamer->EmitLabel(ContributionEnd); 527 } 528 529 void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, 530 StringRef Prefix, const MCSymbol *SecBegin, 531 ArrayRef<AppleAccelTableData::Atom> Atoms) { 532 Contents.finalize(Asm, Prefix); 533 AppleAccelTableEmitter(Asm, Contents, Atoms, SecBegin).emit(); 534 } 535 536 void llvm::emitDWARF5AccelTable( 537 AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents, 538 const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) { 539 Contents.finalize(Asm, "names"); 540 Dwarf5AccelTableEmitter(Asm, Contents, DD, CUs).emit(); 541 } 542 543 void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const { 544 Asm->emitInt32(Die->getDebugSectionOffset()); 545 } 546 547 void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const { 548 Asm->emitInt32(Die->getDebugSectionOffset()); 549 Asm->emitInt16(Die->getTag()); 550 Asm->emitInt8(0); 551 } 552 553 void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const { 554 Asm->emitInt32(Offset); 555 } 556 557 void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const { 558 Asm->emitInt32(Offset); 559 Asm->emitInt16(Tag); 560 Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation 561 : 0); 562 Asm->emitInt32(QualifiedNameHash); 563 } 564 565 #ifndef _MSC_VER 566 // The lines below are rejected by older versions (TBD) of MSVC. 567 constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[]; 568 constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[]; 569 constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[]; 570 constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[]; 571 #else 572 // FIXME: Erase this path once the minimum MSCV version has been bumped. 573 const SmallVector<AppleAccelTableData::Atom, 4> 574 AppleAccelTableOffsetData::Atoms = { 575 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 576 const SmallVector<AppleAccelTableData::Atom, 4> AppleAccelTableTypeData::Atoms = 577 {Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 578 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 579 Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; 580 const SmallVector<AppleAccelTableData::Atom, 4> 581 AppleAccelTableStaticOffsetData::Atoms = { 582 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 583 const SmallVector<AppleAccelTableData::Atom, 4> 584 AppleAccelTableStaticTypeData::Atoms = { 585 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 586 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 587 Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; 588 #endif 589 590 #ifndef NDEBUG 591 void AppleAccelTableEmitter::Header::print(raw_ostream &OS) const { 592 OS << "Magic: " << format("0x%x", Magic) << "\n" 593 << "Version: " << Version << "\n" 594 << "Hash Function: " << HashFunction << "\n" 595 << "Bucket Count: " << BucketCount << "\n" 596 << "Header Data Length: " << HeaderDataLength << "\n"; 597 } 598 599 void AppleAccelTableData::Atom::print(raw_ostream &OS) const { 600 OS << "Type: " << dwarf::AtomTypeString(Type) << "\n" 601 << "Form: " << dwarf::FormEncodingString(Form) << "\n"; 602 } 603 604 void AppleAccelTableEmitter::HeaderData::print(raw_ostream &OS) const { 605 OS << "DIE Offset Base: " << DieOffsetBase << "\n"; 606 for (auto Atom : Atoms) 607 Atom.print(OS); 608 } 609 610 void AppleAccelTableEmitter::print(raw_ostream &OS) const { 611 Header.print(OS); 612 HeaderData.print(OS); 613 Contents.print(OS); 614 SecBegin->print(OS, nullptr); 615 } 616 617 void AccelTableBase::HashData::print(raw_ostream &OS) const { 618 OS << "Name: " << Name.getString() << "\n"; 619 OS << " Hash Value: " << format("0x%x", HashValue) << "\n"; 620 OS << " Symbol: "; 621 if (Sym) 622 OS << *Sym; 623 else 624 OS << "<none>"; 625 OS << "\n"; 626 for (auto *Value : Values) 627 Value->print(OS); 628 } 629 630 void AccelTableBase::print(raw_ostream &OS) const { 631 // Print Content. 632 OS << "Entries: \n"; 633 for (const auto &Entry : Entries) { 634 OS << "Name: " << Entry.first() << "\n"; 635 for (auto *V : Entry.second.Values) 636 V->print(OS); 637 } 638 639 OS << "Buckets and Hashes: \n"; 640 for (auto &Bucket : Buckets) 641 for (auto &Hash : Bucket) 642 Hash->print(OS); 643 644 OS << "Data: \n"; 645 for (auto &E : Entries) 646 E.second.print(OS); 647 } 648 649 void DWARF5AccelTableData::print(raw_ostream &OS) const { 650 OS << " Offset: " << Die.getOffset() << "\n"; 651 OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n"; 652 } 653 654 void AppleAccelTableOffsetData::print(raw_ostream &OS) const { 655 OS << " Offset: " << Die->getOffset() << "\n"; 656 } 657 658 void AppleAccelTableTypeData::print(raw_ostream &OS) const { 659 OS << " Offset: " << Die->getOffset() << "\n"; 660 OS << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; 661 } 662 663 void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const { 664 OS << " Static Offset: " << Offset << "\n"; 665 } 666 667 void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const { 668 OS << " Static Offset: " << Offset << "\n"; 669 OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n"; 670 OS << " Tag: " << dwarf::TagString(Tag) << "\n"; 671 OS << " ObjCClassIsImplementation: " 672 << (ObjCClassIsImplementation ? "true" : "false"); 673 OS << "\n"; 674 } 675 #endif 676