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 Asm->emitDwarfSymbolReference(CU.value()->getLabelBegin()); 420 } 421 } 422 423 void Dwarf5AccelTableEmitter::emitBuckets() const { 424 uint32_t Index = 1; 425 for (const auto &Bucket : enumerate(Contents.getBuckets())) { 426 Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index())); 427 Asm->emitInt32(Bucket.value().empty() ? 0 : Index); 428 Index += Bucket.value().size(); 429 } 430 } 431 432 void Dwarf5AccelTableEmitter::emitStringOffsets() const { 433 for (const auto &Bucket : enumerate(Contents.getBuckets())) { 434 for (auto *Hash : Bucket.value()) { 435 DwarfStringPoolEntryRef String = Hash->Name; 436 Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) + 437 ": " + String.getString()); 438 Asm->emitDwarfStringOffset(String); 439 } 440 } 441 } 442 443 void Dwarf5AccelTableEmitter::emitAbbrevs() const { 444 Asm->OutStreamer->EmitLabel(AbbrevStart); 445 for (const auto &Abbrev : Abbreviations) { 446 Asm->OutStreamer->AddComment("Abbrev code"); 447 assert(Abbrev.first != 0); 448 Asm->EmitULEB128(Abbrev.first); 449 Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first)); 450 Asm->EmitULEB128(Abbrev.first); 451 for (const auto &AttrEnc : Abbrev.second) { 452 Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); 453 Asm->EmitULEB128(AttrEnc.Form, 454 dwarf::FormEncodingString(AttrEnc.Form).data()); 455 } 456 Asm->EmitULEB128(0, "End of abbrev"); 457 Asm->EmitULEB128(0, "End of abbrev"); 458 } 459 Asm->EmitULEB128(0, "End of abbrev list"); 460 Asm->OutStreamer->EmitLabel(AbbrevEnd); 461 } 462 463 void Dwarf5AccelTableEmitter::emitEntry( 464 const DWARF5AccelTableData &Entry) const { 465 auto AbbrevIt = Abbreviations.find(Entry.getDie().getTag()); 466 assert(AbbrevIt != Abbreviations.end() && 467 "Why wasn't this abbrev generated?"); 468 469 Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code"); 470 for (const auto &AttrEnc : AbbrevIt->second) { 471 Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index)); 472 switch (AttrEnc.Index) { 473 case dwarf::DW_IDX_compile_unit: { 474 const DIE *CUDie = Entry.getDie().getUnitDie(); 475 DIEInteger ID(DD.lookupCU(CUDie)->getUniqueID()); 476 ID.EmitValue(Asm, AttrEnc.Form); 477 break; 478 } 479 case dwarf::DW_IDX_die_offset: 480 assert(AttrEnc.Form == dwarf::DW_FORM_ref4); 481 Asm->emitInt32(Entry.getDie().getOffset()); 482 break; 483 default: 484 llvm_unreachable("Unexpected index attribute!"); 485 } 486 } 487 } 488 489 void Dwarf5AccelTableEmitter::emitData() const { 490 Asm->OutStreamer->EmitLabel(EntryPool); 491 for (auto &Bucket : Contents.getBuckets()) { 492 for (auto *Hash : Bucket) { 493 // Remember to emit the label for our offset. 494 Asm->OutStreamer->EmitLabel(Hash->Sym); 495 for (const auto *Value : Hash->Values) 496 emitEntry(*static_cast<const DWARF5AccelTableData *>(Value)); 497 Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString()); 498 Asm->emitInt32(0); 499 } 500 } 501 } 502 503 Dwarf5AccelTableEmitter::Dwarf5AccelTableEmitter( 504 AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 505 ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits) 506 : AccelTableEmitter(Asm, Contents, false), 507 Header(CompUnits.size(), Contents.getBucketCount(), 508 Contents.getUniqueNameCount()), 509 DD(DD), CompUnits(CompUnits) { 510 DenseSet<uint32_t> UniqueTags = getUniqueTags(); 511 SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes(); 512 513 Abbreviations.reserve(UniqueTags.size()); 514 for (uint32_t Tag : UniqueTags) 515 Abbreviations.try_emplace(Tag, UniformAttributes); 516 } 517 518 void Dwarf5AccelTableEmitter::emit() const { 519 Header.emit(*this); 520 emitCUList(); 521 emitBuckets(); 522 emitHashes(); 523 emitStringOffsets(); 524 emitOffsets(EntryPool); 525 emitAbbrevs(); 526 emitData(); 527 Asm->OutStreamer->EmitValueToAlignment(4, 0); 528 Asm->OutStreamer->EmitLabel(ContributionEnd); 529 } 530 531 void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, 532 StringRef Prefix, const MCSymbol *SecBegin, 533 ArrayRef<AppleAccelTableData::Atom> Atoms) { 534 Contents.finalize(Asm, Prefix); 535 AppleAccelTableEmitter(Asm, Contents, Atoms, SecBegin).emit(); 536 } 537 538 void llvm::emitDWARF5AccelTable( 539 AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents, 540 const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) { 541 Contents.finalize(Asm, "names"); 542 Dwarf5AccelTableEmitter(Asm, Contents, DD, CUs).emit(); 543 } 544 545 void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const { 546 Asm->emitInt32(Die->getDebugSectionOffset()); 547 } 548 549 void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const { 550 Asm->emitInt32(Die->getDebugSectionOffset()); 551 Asm->emitInt16(Die->getTag()); 552 Asm->emitInt8(0); 553 } 554 555 void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const { 556 Asm->emitInt32(Offset); 557 } 558 559 void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const { 560 Asm->emitInt32(Offset); 561 Asm->emitInt16(Tag); 562 Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation 563 : 0); 564 Asm->emitInt32(QualifiedNameHash); 565 } 566 567 #ifndef _MSC_VER 568 // The lines below are rejected by older versions (TBD) of MSVC. 569 constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[]; 570 constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[]; 571 constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[]; 572 constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[]; 573 #else 574 // FIXME: Erase this path once the minimum MSCV version has been bumped. 575 const SmallVector<AppleAccelTableData::Atom, 4> 576 AppleAccelTableOffsetData::Atoms = { 577 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 578 const SmallVector<AppleAccelTableData::Atom, 4> AppleAccelTableTypeData::Atoms = 579 {Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 580 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 581 Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; 582 const SmallVector<AppleAccelTableData::Atom, 4> 583 AppleAccelTableStaticOffsetData::Atoms = { 584 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 585 const SmallVector<AppleAccelTableData::Atom, 4> 586 AppleAccelTableStaticTypeData::Atoms = { 587 Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 588 Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 589 Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; 590 #endif 591 592 #ifndef NDEBUG 593 void AppleAccelTableEmitter::Header::print(raw_ostream &OS) const { 594 OS << "Magic: " << format("0x%x", Magic) << "\n" 595 << "Version: " << Version << "\n" 596 << "Hash Function: " << HashFunction << "\n" 597 << "Bucket Count: " << BucketCount << "\n" 598 << "Header Data Length: " << HeaderDataLength << "\n"; 599 } 600 601 void AppleAccelTableData::Atom::print(raw_ostream &OS) const { 602 OS << "Type: " << dwarf::AtomTypeString(Type) << "\n" 603 << "Form: " << dwarf::FormEncodingString(Form) << "\n"; 604 } 605 606 void AppleAccelTableEmitter::HeaderData::print(raw_ostream &OS) const { 607 OS << "DIE Offset Base: " << DieOffsetBase << "\n"; 608 for (auto Atom : Atoms) 609 Atom.print(OS); 610 } 611 612 void AppleAccelTableEmitter::print(raw_ostream &OS) const { 613 Header.print(OS); 614 HeaderData.print(OS); 615 Contents.print(OS); 616 SecBegin->print(OS, nullptr); 617 } 618 619 void AccelTableBase::HashData::print(raw_ostream &OS) const { 620 OS << "Name: " << Name.getString() << "\n"; 621 OS << " Hash Value: " << format("0x%x", HashValue) << "\n"; 622 OS << " Symbol: "; 623 if (Sym) 624 OS << *Sym; 625 else 626 OS << "<none>"; 627 OS << "\n"; 628 for (auto *Value : Values) 629 Value->print(OS); 630 } 631 632 void AccelTableBase::print(raw_ostream &OS) const { 633 // Print Content. 634 OS << "Entries: \n"; 635 for (const auto &Entry : Entries) { 636 OS << "Name: " << Entry.first() << "\n"; 637 for (auto *V : Entry.second.Values) 638 V->print(OS); 639 } 640 641 OS << "Buckets and Hashes: \n"; 642 for (auto &Bucket : Buckets) 643 for (auto &Hash : Bucket) 644 Hash->print(OS); 645 646 OS << "Data: \n"; 647 for (auto &E : Entries) 648 E.second.print(OS); 649 } 650 651 void DWARF5AccelTableData::print(raw_ostream &OS) const { 652 OS << " Offset: " << Die.getOffset() << "\n"; 653 OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n"; 654 } 655 656 void AppleAccelTableOffsetData::print(raw_ostream &OS) const { 657 OS << " Offset: " << Die->getOffset() << "\n"; 658 } 659 660 void AppleAccelTableTypeData::print(raw_ostream &OS) const { 661 OS << " Offset: " << Die->getOffset() << "\n"; 662 OS << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; 663 } 664 665 void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const { 666 OS << " Static Offset: " << Offset << "\n"; 667 } 668 669 void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const { 670 OS << " Static Offset: " << Offset << "\n"; 671 OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n"; 672 OS << " Tag: " << dwarf::TagString(Tag) << "\n"; 673 OS << " ObjCClassIsImplementation: " 674 << (ObjCClassIsImplementation ? "true" : "false"); 675 OS << "\n"; 676 } 677 #endif 678