1855fc3bbSJonas Devlieghere //===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===// 2855fc3bbSJonas Devlieghere // 3855fc3bbSJonas Devlieghere // The LLVM Compiler Infrastructure 4855fc3bbSJonas Devlieghere // 5855fc3bbSJonas Devlieghere // This file is distributed under the University of Illinois Open Source 6855fc3bbSJonas Devlieghere // License. See LICENSE.TXT for details. 7855fc3bbSJonas Devlieghere // 8855fc3bbSJonas Devlieghere //===----------------------------------------------------------------------===// 9855fc3bbSJonas Devlieghere // 10855fc3bbSJonas Devlieghere // This file contains support for writing accelerator tables. 11855fc3bbSJonas Devlieghere // 12855fc3bbSJonas Devlieghere //===----------------------------------------------------------------------===// 13855fc3bbSJonas Devlieghere 14855fc3bbSJonas Devlieghere #include "llvm/CodeGen/AccelTable.h" 156088c234SPavel Labath #include "DwarfCompileUnit.h" 16855fc3bbSJonas Devlieghere #include "llvm/ADT/STLExtras.h" 17855fc3bbSJonas Devlieghere #include "llvm/ADT/StringMap.h" 18855fc3bbSJonas Devlieghere #include "llvm/ADT/Twine.h" 19855fc3bbSJonas Devlieghere #include "llvm/BinaryFormat/Dwarf.h" 20855fc3bbSJonas Devlieghere #include "llvm/CodeGen/AsmPrinter.h" 21855fc3bbSJonas Devlieghere #include "llvm/CodeGen/DIE.h" 22855fc3bbSJonas Devlieghere #include "llvm/MC/MCExpr.h" 23855fc3bbSJonas Devlieghere #include "llvm/MC/MCStreamer.h" 24855fc3bbSJonas Devlieghere #include "llvm/Support/raw_ostream.h" 25855fc3bbSJonas Devlieghere #include <algorithm> 26855fc3bbSJonas Devlieghere #include <cstddef> 27855fc3bbSJonas Devlieghere #include <cstdint> 28855fc3bbSJonas Devlieghere #include <limits> 29855fc3bbSJonas Devlieghere #include <vector> 30855fc3bbSJonas Devlieghere 31855fc3bbSJonas Devlieghere using namespace llvm; 32855fc3bbSJonas Devlieghere 33a7c457d2SPavel Labath void AccelTableBase::computeBucketCount() { 34a7c457d2SPavel Labath // First get the number of unique hashes. 35a7c457d2SPavel Labath std::vector<uint32_t> Uniques; 36a7c457d2SPavel Labath Uniques.reserve(Entries.size()); 37a7c457d2SPavel Labath for (const auto &E : Entries) 38a7c457d2SPavel Labath Uniques.push_back(E.second.HashValue); 39a7c457d2SPavel Labath array_pod_sort(Uniques.begin(), Uniques.end()); 40a7c457d2SPavel Labath std::vector<uint32_t>::iterator P = 41a7c457d2SPavel Labath std::unique(Uniques.begin(), Uniques.end()); 42a7c457d2SPavel Labath 43a7c457d2SPavel Labath UniqueHashCount = std::distance(Uniques.begin(), P); 44a7c457d2SPavel Labath 45a7c457d2SPavel Labath if (UniqueHashCount > 1024) 46a7c457d2SPavel Labath BucketCount = UniqueHashCount / 4; 47a7c457d2SPavel Labath else if (UniqueHashCount > 16) 48a7c457d2SPavel Labath BucketCount = UniqueHashCount / 2; 49a7c457d2SPavel Labath else 50a7c457d2SPavel Labath BucketCount = std::max<uint32_t>(UniqueHashCount, 1); 51a7c457d2SPavel Labath } 52a7c457d2SPavel Labath 53a7c457d2SPavel Labath void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) { 54a7c457d2SPavel Labath // Create the individual hash data outputs. 55a7c457d2SPavel Labath for (auto &E : Entries) { 56a7c457d2SPavel Labath // Unique the entries. 57a7c457d2SPavel Labath std::stable_sort(E.second.Values.begin(), E.second.Values.end(), 58a7c457d2SPavel Labath [](const AccelTableData *A, const AccelTableData *B) { 59a7c457d2SPavel Labath return *A < *B; 60a7c457d2SPavel Labath }); 61a7c457d2SPavel Labath E.second.Values.erase( 62a7c457d2SPavel Labath std::unique(E.second.Values.begin(), E.second.Values.end()), 63a7c457d2SPavel Labath E.second.Values.end()); 64a7c457d2SPavel Labath } 65a7c457d2SPavel Labath 66a7c457d2SPavel Labath // Figure out how many buckets we need, then compute the bucket contents and 67a7c457d2SPavel Labath // the final ordering. The hashes and offsets can be emitted by walking these 68a7c457d2SPavel Labath // data structures. We add temporary symbols to the data so they can be 69a7c457d2SPavel Labath // referenced when emitting the offsets. 70a7c457d2SPavel Labath computeBucketCount(); 71a7c457d2SPavel Labath 72a7c457d2SPavel Labath // Compute bucket contents and final ordering. 73a7c457d2SPavel Labath Buckets.resize(BucketCount); 74a7c457d2SPavel Labath for (auto &E : Entries) { 75a7c457d2SPavel Labath uint32_t Bucket = E.second.HashValue % BucketCount; 76a7c457d2SPavel Labath Buckets[Bucket].push_back(&E.second); 77a7c457d2SPavel Labath E.second.Sym = Asm->createTempSymbol(Prefix); 78a7c457d2SPavel Labath } 79a7c457d2SPavel Labath 80a7c457d2SPavel Labath // Sort the contents of the buckets by hash value so that hash collisions end 81a7c457d2SPavel Labath // up together. Stable sort makes testing easier and doesn't cost much more. 82a7c457d2SPavel Labath for (auto &Bucket : Buckets) 83a7c457d2SPavel Labath std::stable_sort(Bucket.begin(), Bucket.end(), 84a7c457d2SPavel Labath [](HashData *LHS, HashData *RHS) { 85a7c457d2SPavel Labath return LHS->HashValue < RHS->HashValue; 86a7c457d2SPavel Labath }); 87a7c457d2SPavel Labath } 88a7c457d2SPavel Labath 89a7c457d2SPavel Labath namespace { 906088c234SPavel Labath /// Base class for writing out Accelerator tables. It holds the common 916088c234SPavel Labath /// functionality for the two Accelerator table types. 92a7c457d2SPavel Labath class AccelTableEmitter { 93a7c457d2SPavel Labath protected: 94a7c457d2SPavel Labath AsmPrinter *const Asm; ///< Destination. 95a7c457d2SPavel Labath const AccelTableBase &Contents; ///< Data to emit. 96a7c457d2SPavel Labath 97a7c457d2SPavel Labath /// Controls whether to emit duplicate hash and offset table entries for names 98a7c457d2SPavel Labath /// with identical hashes. Apple tables don't emit duplicate entries, DWARF v5 99a7c457d2SPavel Labath /// tables do. 100a7c457d2SPavel Labath const bool SkipIdenticalHashes; 101a7c457d2SPavel Labath 102a7c457d2SPavel Labath void emitHashes() const; 103a7c457d2SPavel Labath 104a7c457d2SPavel Labath /// Emit offsets to lists of entries with identical names. The offsets are 105a7c457d2SPavel Labath /// relative to the Base argument. 106a7c457d2SPavel Labath void emitOffsets(const MCSymbol *Base) const; 107a7c457d2SPavel Labath 108a7c457d2SPavel Labath public: 109a7c457d2SPavel Labath AccelTableEmitter(AsmPrinter *Asm, const AccelTableBase &Contents, 110a7c457d2SPavel Labath bool SkipIdenticalHashes) 111a7c457d2SPavel Labath : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) { 112a7c457d2SPavel Labath } 113a7c457d2SPavel Labath }; 114a7c457d2SPavel Labath 115a7c457d2SPavel Labath class AppleAccelTableEmitter : public AccelTableEmitter { 116a7c457d2SPavel Labath using Atom = AppleAccelTableData::Atom; 117a7c457d2SPavel Labath 118a7c457d2SPavel Labath /// The fixed header of an Apple Accelerator Table. 119a7c457d2SPavel Labath struct Header { 120a7c457d2SPavel Labath uint32_t Magic = MagicHash; 121a7c457d2SPavel Labath uint16_t Version = 1; 122a7c457d2SPavel Labath uint16_t HashFunction = dwarf::DW_hash_function_djb; 123a7c457d2SPavel Labath uint32_t BucketCount; 124a7c457d2SPavel Labath uint32_t HashCount; 125a7c457d2SPavel Labath uint32_t HeaderDataLength; 126a7c457d2SPavel Labath 127a7c457d2SPavel Labath /// 'HASH' magic value to detect endianness. 128a7c457d2SPavel Labath static const uint32_t MagicHash = 0x48415348; 129a7c457d2SPavel Labath 130a7c457d2SPavel Labath Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength) 131a7c457d2SPavel Labath : BucketCount(BucketCount), HashCount(UniqueHashCount), 132a7c457d2SPavel Labath HeaderDataLength(DataLength) {} 133a7c457d2SPavel Labath 134a7c457d2SPavel Labath void emit(AsmPrinter *Asm) const; 135a7c457d2SPavel Labath #ifndef NDEBUG 136a7c457d2SPavel Labath void print(raw_ostream &OS) const; 137a7c457d2SPavel Labath void dump() const { print(dbgs()); } 138a7c457d2SPavel Labath #endif 139a7c457d2SPavel Labath }; 140a7c457d2SPavel Labath 141a7c457d2SPavel Labath /// The HeaderData describes the structure of an Apple accelerator table 142a7c457d2SPavel Labath /// through a list of Atoms. 143a7c457d2SPavel Labath struct HeaderData { 144a7c457d2SPavel Labath /// In the case of data that is referenced via DW_FORM_ref_* the offset 145a7c457d2SPavel Labath /// base is used to describe the offset for all forms in the list of atoms. 146a7c457d2SPavel Labath uint32_t DieOffsetBase; 147a7c457d2SPavel Labath 148a7c457d2SPavel Labath const SmallVector<Atom, 4> Atoms; 149a7c457d2SPavel Labath 150a7c457d2SPavel Labath HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0) 151a7c457d2SPavel Labath : DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {} 152a7c457d2SPavel Labath 153a7c457d2SPavel Labath void emit(AsmPrinter *Asm) const; 154a7c457d2SPavel Labath #ifndef NDEBUG 155a7c457d2SPavel Labath void print(raw_ostream &OS) const; 156a7c457d2SPavel Labath void dump() const { print(dbgs()); } 157a7c457d2SPavel Labath #endif 158a7c457d2SPavel Labath }; 159a7c457d2SPavel Labath 160a7c457d2SPavel Labath Header Header; 161a7c457d2SPavel Labath HeaderData HeaderData; 162a7c457d2SPavel Labath const MCSymbol *SecBegin; 163a7c457d2SPavel Labath 164a7c457d2SPavel Labath void emitBuckets() const; 165a7c457d2SPavel Labath void emitData() const; 166a7c457d2SPavel Labath 167a7c457d2SPavel Labath public: 168a7c457d2SPavel Labath AppleAccelTableEmitter(AsmPrinter *Asm, const AccelTableBase &Contents, 169a7c457d2SPavel Labath ArrayRef<Atom> Atoms, const MCSymbol *SecBegin) 170a7c457d2SPavel Labath : AccelTableEmitter(Asm, Contents, true), 171a7c457d2SPavel Labath Header(Contents.getBucketCount(), Contents.getUniqueHashCount(), 172a7c457d2SPavel Labath 8 + (Atoms.size() * 4)), 173a7c457d2SPavel Labath HeaderData(Atoms), SecBegin(SecBegin) {} 174a7c457d2SPavel Labath 175a7c457d2SPavel Labath void emit() const; 176a7c457d2SPavel Labath 177a7c457d2SPavel Labath #ifndef NDEBUG 178a7c457d2SPavel Labath void print(raw_ostream &OS) const; 179a7c457d2SPavel Labath void dump() const { print(dbgs()); } 180a7c457d2SPavel Labath #endif 181a7c457d2SPavel Labath }; 1826088c234SPavel Labath 1836088c234SPavel Labath /// Class responsible for emitting a DWARF v5 Accelerator Table. The only public 1846088c234SPavel Labath /// function is emit(), which performs the actual emission. 1856088c234SPavel Labath class Dwarf5AccelTableEmitter : public AccelTableEmitter { 1866088c234SPavel Labath struct Header { 1876088c234SPavel Labath uint32_t UnitLength = 0; 1886088c234SPavel Labath uint16_t Version = 5; 1896088c234SPavel Labath uint16_t Padding = 0; 1906088c234SPavel Labath uint32_t CompUnitCount; 1916088c234SPavel Labath uint32_t LocalTypeUnitCount = 0; 1926088c234SPavel Labath uint32_t ForeignTypeUnitCount = 0; 1936088c234SPavel Labath uint32_t BucketCount; 1946088c234SPavel Labath uint32_t NameCount; 1956088c234SPavel Labath uint32_t AbbrevTableSize = 0; 1966088c234SPavel Labath uint32_t AugmentationStringSize = sizeof(AugmentationString); 1976088c234SPavel Labath char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'}; 1986088c234SPavel Labath 1996088c234SPavel Labath Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount) 2006088c234SPavel Labath : CompUnitCount(CompUnitCount), BucketCount(BucketCount), 2016088c234SPavel Labath NameCount(NameCount) {} 2026088c234SPavel Labath 2036088c234SPavel Labath void emit(const Dwarf5AccelTableEmitter &Ctx) const; 2046088c234SPavel Labath }; 2056088c234SPavel Labath struct AttributeEncoding { 2066088c234SPavel Labath dwarf::Index Index; 2076088c234SPavel Labath dwarf::Form Form; 2086088c234SPavel Labath }; 2096088c234SPavel Labath 2106088c234SPavel Labath Header Header; 2116088c234SPavel Labath DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations; 2126088c234SPavel Labath const DwarfDebug ⅅ 2136088c234SPavel Labath ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits; 2146088c234SPavel Labath MCSymbol *ContributionStart = Asm->createTempSymbol("names_start"); 2156088c234SPavel Labath MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end"); 2166088c234SPavel Labath MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start"); 2176088c234SPavel Labath MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end"); 2186088c234SPavel Labath MCSymbol *EntryPool = Asm->createTempSymbol("names_entries"); 2196088c234SPavel Labath 2206088c234SPavel Labath DenseSet<uint32_t> getUniqueTags() const; 2216088c234SPavel Labath 2226088c234SPavel Labath // Right now, we emit uniform attributes for all tags. 2236088c234SPavel Labath SmallVector<AttributeEncoding, 2> getUniformAttributes() const; 2246088c234SPavel Labath 2256088c234SPavel Labath void emitCUList() const; 2266088c234SPavel Labath void emitBuckets() const; 2276088c234SPavel Labath void emitStringOffsets() const; 2286088c234SPavel Labath void emitAbbrevs() const; 2296088c234SPavel Labath void emitEntry(const DWARF5AccelTableData &Data) const; 2306088c234SPavel Labath void emitData() const; 2316088c234SPavel Labath 2326088c234SPavel Labath public: 2336088c234SPavel Labath Dwarf5AccelTableEmitter( 2346088c234SPavel Labath AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 2356088c234SPavel Labath ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits); 2366088c234SPavel Labath 2376088c234SPavel Labath void emit() const; 2386088c234SPavel Labath }; 239a7c457d2SPavel Labath } // namespace 240a7c457d2SPavel Labath 241a7c457d2SPavel Labath void AccelTableEmitter::emitHashes() const { 242a7c457d2SPavel Labath uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 243a7c457d2SPavel Labath unsigned BucketIdx = 0; 244a7c457d2SPavel Labath for (auto &Bucket : Contents.getBuckets()) { 245a7c457d2SPavel Labath for (auto &Hash : Bucket) { 246a7c457d2SPavel Labath uint32_t HashValue = Hash->HashValue; 247a7c457d2SPavel Labath if (SkipIdenticalHashes && PrevHash == HashValue) 248a7c457d2SPavel Labath continue; 249a7c457d2SPavel Labath Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx)); 2504b4d85fdSRafael Espindola Asm->emitInt32(HashValue); 251a7c457d2SPavel Labath PrevHash = HashValue; 252a7c457d2SPavel Labath } 253a7c457d2SPavel Labath BucketIdx++; 254a7c457d2SPavel Labath } 255a7c457d2SPavel Labath } 256a7c457d2SPavel Labath 257a7c457d2SPavel Labath void AccelTableEmitter::emitOffsets(const MCSymbol *Base) const { 258a7c457d2SPavel Labath const auto &Buckets = Contents.getBuckets(); 259a7c457d2SPavel Labath uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 260a7c457d2SPavel Labath for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 261a7c457d2SPavel Labath for (auto *Hash : Buckets[i]) { 262a7c457d2SPavel Labath uint32_t HashValue = Hash->HashValue; 263a7c457d2SPavel Labath if (SkipIdenticalHashes && PrevHash == HashValue) 264a7c457d2SPavel Labath continue; 265a7c457d2SPavel Labath PrevHash = HashValue; 266a7c457d2SPavel Labath Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i)); 267a7c457d2SPavel Labath Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t)); 268a7c457d2SPavel Labath } 269a7c457d2SPavel Labath } 270a7c457d2SPavel Labath } 271a7c457d2SPavel Labath 272a7c457d2SPavel Labath void AppleAccelTableEmitter::Header::emit(AsmPrinter *Asm) const { 273855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Header Magic"); 2744b4d85fdSRafael Espindola Asm->emitInt32(Magic); 275855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Header Version"); 2764b4d85fdSRafael Espindola Asm->emitInt16(Version); 277855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Header Hash Function"); 2784b4d85fdSRafael Espindola Asm->emitInt16(HashFunction); 279855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Header Bucket Count"); 2804b4d85fdSRafael Espindola Asm->emitInt32(BucketCount); 281855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Header Hash Count"); 2824b4d85fdSRafael Espindola Asm->emitInt32(HashCount); 283855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Header Data Length"); 2844b4d85fdSRafael Espindola Asm->emitInt32(HeaderDataLength); 285a7c457d2SPavel Labath } 286855fc3bbSJonas Devlieghere 287a7c457d2SPavel Labath void AppleAccelTableEmitter::HeaderData::emit(AsmPrinter *Asm) const { 288855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("HeaderData Die Offset Base"); 2894b4d85fdSRafael Espindola Asm->emitInt32(DieOffsetBase); 290855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("HeaderData Atom Count"); 2914b4d85fdSRafael Espindola Asm->emitInt32(Atoms.size()); 292855fc3bbSJonas Devlieghere 293a7c457d2SPavel Labath for (const Atom &A : Atoms) { 294855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type)); 2954b4d85fdSRafael Espindola Asm->emitInt16(A.Type); 296855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form)); 2974b4d85fdSRafael Espindola Asm->emitInt16(A.Form); 298855fc3bbSJonas Devlieghere } 299855fc3bbSJonas Devlieghere } 300855fc3bbSJonas Devlieghere 301a7c457d2SPavel Labath void AppleAccelTableEmitter::emitBuckets() const { 302a7c457d2SPavel Labath const auto &Buckets = Contents.getBuckets(); 303855fc3bbSJonas Devlieghere unsigned index = 0; 304855fc3bbSJonas Devlieghere for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 305855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Bucket " + Twine(i)); 306855fc3bbSJonas Devlieghere if (!Buckets[i].empty()) 3074b4d85fdSRafael Espindola Asm->emitInt32(index); 308855fc3bbSJonas Devlieghere else 3094b4d85fdSRafael Espindola Asm->emitInt32(std::numeric_limits<uint32_t>::max()); 310855fc3bbSJonas Devlieghere // Buckets point in the list of hashes, not to the data. Do not increment 311855fc3bbSJonas Devlieghere // the index multiple times in case of hash collisions. 312855fc3bbSJonas Devlieghere uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 313855fc3bbSJonas Devlieghere for (auto *HD : Buckets[i]) { 314855fc3bbSJonas Devlieghere uint32_t HashValue = HD->HashValue; 315855fc3bbSJonas Devlieghere if (PrevHash != HashValue) 316855fc3bbSJonas Devlieghere ++index; 317855fc3bbSJonas Devlieghere PrevHash = HashValue; 318855fc3bbSJonas Devlieghere } 319855fc3bbSJonas Devlieghere } 320855fc3bbSJonas Devlieghere } 321855fc3bbSJonas Devlieghere 322a7c457d2SPavel Labath void AppleAccelTableEmitter::emitData() const { 323a7c457d2SPavel Labath const auto &Buckets = Contents.getBuckets(); 324855fc3bbSJonas Devlieghere for (size_t i = 0, e = Buckets.size(); i < e; ++i) { 325855fc3bbSJonas Devlieghere uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); 326855fc3bbSJonas Devlieghere for (auto &Hash : Buckets[i]) { 327855fc3bbSJonas Devlieghere // Terminate the previous entry if there is no hash collision with the 328855fc3bbSJonas Devlieghere // current one. 329855fc3bbSJonas Devlieghere if (PrevHash != std::numeric_limits<uint64_t>::max() && 330855fc3bbSJonas Devlieghere PrevHash != Hash->HashValue) 3314b4d85fdSRafael Espindola Asm->emitInt32(0); 332855fc3bbSJonas Devlieghere // Remember to emit the label for our offset. 333855fc3bbSJonas Devlieghere Asm->OutStreamer->EmitLabel(Hash->Sym); 334062eb537SPavel Labath Asm->OutStreamer->AddComment(Hash->Name.getString()); 335062eb537SPavel Labath Asm->emitDwarfStringOffset(Hash->Name); 336855fc3bbSJonas Devlieghere Asm->OutStreamer->AddComment("Num DIEs"); 3374b4d85fdSRafael Espindola Asm->emitInt32(Hash->Values.size()); 338a7c457d2SPavel Labath for (const auto *V : Hash->Values) 339a7c457d2SPavel Labath static_cast<const AppleAccelTableData *>(V)->emit(Asm); 340855fc3bbSJonas Devlieghere PrevHash = Hash->HashValue; 341855fc3bbSJonas Devlieghere } 342855fc3bbSJonas Devlieghere // Emit the final end marker for the bucket. 343855fc3bbSJonas Devlieghere if (!Buckets[i].empty()) 3444b4d85fdSRafael Espindola Asm->emitInt32(0); 345855fc3bbSJonas Devlieghere } 346855fc3bbSJonas Devlieghere } 347855fc3bbSJonas Devlieghere 348a7c457d2SPavel Labath void AppleAccelTableEmitter::emit() const { 349a7c457d2SPavel Labath Header.emit(Asm); 350a7c457d2SPavel Labath HeaderData.emit(Asm); 351a7c457d2SPavel Labath emitBuckets(); 352a7c457d2SPavel Labath emitHashes(); 353a7c457d2SPavel Labath emitOffsets(SecBegin); 354a7c457d2SPavel Labath emitData(); 355855fc3bbSJonas Devlieghere } 356855fc3bbSJonas Devlieghere 3576088c234SPavel Labath void Dwarf5AccelTableEmitter::Header::emit( 3586088c234SPavel Labath const Dwarf5AccelTableEmitter &Ctx) const { 359*eadfac87SPavel Labath assert(CompUnitCount > 0 && "Index must have at least one CU."); 360*eadfac87SPavel Labath 3616088c234SPavel Labath AsmPrinter *Asm = Ctx.Asm; 3626088c234SPavel Labath Asm->OutStreamer->AddComment("Header: unit length"); 3636088c234SPavel Labath Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart, 3646088c234SPavel Labath sizeof(uint32_t)); 3656088c234SPavel Labath Asm->OutStreamer->EmitLabel(Ctx.ContributionStart); 3666088c234SPavel Labath Asm->OutStreamer->AddComment("Header: version"); 3676088c234SPavel Labath Asm->emitInt16(Version); 3686088c234SPavel Labath Asm->OutStreamer->AddComment("Header: padding"); 3696088c234SPavel Labath Asm->emitInt16(Padding); 3706088c234SPavel Labath Asm->OutStreamer->AddComment("Header: compilation unit count"); 3716088c234SPavel Labath Asm->emitInt32(CompUnitCount); 3726088c234SPavel Labath Asm->OutStreamer->AddComment("Header: local type unit count"); 3736088c234SPavel Labath Asm->emitInt32(LocalTypeUnitCount); 3746088c234SPavel Labath Asm->OutStreamer->AddComment("Header: foreign type unit count"); 3756088c234SPavel Labath Asm->emitInt32(ForeignTypeUnitCount); 3766088c234SPavel Labath Asm->OutStreamer->AddComment("Header: bucket count"); 3776088c234SPavel Labath Asm->emitInt32(BucketCount); 3786088c234SPavel Labath Asm->OutStreamer->AddComment("Header: name count"); 3796088c234SPavel Labath Asm->emitInt32(NameCount); 3806088c234SPavel Labath Asm->OutStreamer->AddComment("Header: abbreviation table size"); 3816088c234SPavel Labath Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t)); 3826088c234SPavel Labath Asm->OutStreamer->AddComment("Header: augmentation string size"); 3836088c234SPavel Labath assert(AugmentationStringSize % 4 == 0); 3846088c234SPavel Labath Asm->emitInt32(AugmentationStringSize); 3856088c234SPavel Labath Asm->OutStreamer->AddComment("Header: augmentation string"); 3866088c234SPavel Labath Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize}); 3876088c234SPavel Labath } 3886088c234SPavel Labath 3896088c234SPavel Labath DenseSet<uint32_t> Dwarf5AccelTableEmitter::getUniqueTags() const { 3906088c234SPavel Labath DenseSet<uint32_t> UniqueTags; 3916088c234SPavel Labath for (auto &Bucket : Contents.getBuckets()) { 3926088c234SPavel Labath for (auto *Hash : Bucket) { 3936088c234SPavel Labath for (auto *Value : Hash->Values) { 3946088c234SPavel Labath const DIE &Die = 3956088c234SPavel Labath static_cast<const DWARF5AccelTableData *>(Value)->getDie(); 3966088c234SPavel Labath UniqueTags.insert(Die.getTag()); 3976088c234SPavel Labath } 3986088c234SPavel Labath } 3996088c234SPavel Labath } 4006088c234SPavel Labath return UniqueTags; 4016088c234SPavel Labath } 4026088c234SPavel Labath 4036088c234SPavel Labath SmallVector<Dwarf5AccelTableEmitter::AttributeEncoding, 2> 4046088c234SPavel Labath Dwarf5AccelTableEmitter::getUniformAttributes() const { 4056088c234SPavel Labath SmallVector<AttributeEncoding, 2> UA; 4066088c234SPavel Labath if (CompUnits.size() > 1) { 4076088c234SPavel Labath size_t LargestCUIndex = CompUnits.size() - 1; 4086088c234SPavel Labath dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex); 4096088c234SPavel Labath UA.push_back({dwarf::DW_IDX_compile_unit, Form}); 4106088c234SPavel Labath } 4116088c234SPavel Labath UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4}); 4126088c234SPavel Labath return UA; 4136088c234SPavel Labath } 4146088c234SPavel Labath 4156088c234SPavel Labath void Dwarf5AccelTableEmitter::emitCUList() const { 4166088c234SPavel Labath for (const auto &CU : enumerate(CompUnits)) { 4176088c234SPavel Labath assert(CU.index() == CU.value()->getUniqueID()); 4186088c234SPavel Labath Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index())); 4196088c234SPavel Labath Asm->emitDwarfSymbolReference(CU.value()->getLabelBegin()); 4206088c234SPavel Labath } 4216088c234SPavel Labath } 4226088c234SPavel Labath 4236088c234SPavel Labath void Dwarf5AccelTableEmitter::emitBuckets() const { 4246088c234SPavel Labath uint32_t Index = 1; 4256088c234SPavel Labath for (const auto &Bucket : enumerate(Contents.getBuckets())) { 4266088c234SPavel Labath Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index())); 4276088c234SPavel Labath Asm->emitInt32(Bucket.value().empty() ? 0 : Index); 4286088c234SPavel Labath Index += Bucket.value().size(); 4296088c234SPavel Labath } 4306088c234SPavel Labath } 4316088c234SPavel Labath 4326088c234SPavel Labath void Dwarf5AccelTableEmitter::emitStringOffsets() const { 4336088c234SPavel Labath for (const auto &Bucket : enumerate(Contents.getBuckets())) { 4346088c234SPavel Labath for (auto *Hash : Bucket.value()) { 4356088c234SPavel Labath DwarfStringPoolEntryRef String = Hash->Name; 4366088c234SPavel Labath Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) + 4376088c234SPavel Labath ": " + String.getString()); 4386088c234SPavel Labath Asm->emitDwarfStringOffset(String); 4396088c234SPavel Labath } 4406088c234SPavel Labath } 4416088c234SPavel Labath } 4426088c234SPavel Labath 4436088c234SPavel Labath void Dwarf5AccelTableEmitter::emitAbbrevs() const { 4446088c234SPavel Labath Asm->OutStreamer->EmitLabel(AbbrevStart); 4456088c234SPavel Labath for (const auto &Abbrev : Abbreviations) { 4466088c234SPavel Labath Asm->OutStreamer->AddComment("Abbrev code"); 4476088c234SPavel Labath assert(Abbrev.first != 0); 4486088c234SPavel Labath Asm->EmitULEB128(Abbrev.first); 4496088c234SPavel Labath Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first)); 4506088c234SPavel Labath Asm->EmitULEB128(Abbrev.first); 4516088c234SPavel Labath for (const auto &AttrEnc : Abbrev.second) { 4526088c234SPavel Labath Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); 4536088c234SPavel Labath Asm->EmitULEB128(AttrEnc.Form, 4546088c234SPavel Labath dwarf::FormEncodingString(AttrEnc.Form).data()); 4556088c234SPavel Labath } 4566088c234SPavel Labath Asm->EmitULEB128(0, "End of abbrev"); 4576088c234SPavel Labath Asm->EmitULEB128(0, "End of abbrev"); 4586088c234SPavel Labath } 4596088c234SPavel Labath Asm->EmitULEB128(0, "End of abbrev list"); 4606088c234SPavel Labath Asm->OutStreamer->EmitLabel(AbbrevEnd); 4616088c234SPavel Labath } 4626088c234SPavel Labath 4636088c234SPavel Labath void Dwarf5AccelTableEmitter::emitEntry( 4646088c234SPavel Labath const DWARF5AccelTableData &Entry) const { 4656088c234SPavel Labath auto AbbrevIt = Abbreviations.find(Entry.getDie().getTag()); 4666088c234SPavel Labath assert(AbbrevIt != Abbreviations.end() && 4676088c234SPavel Labath "Why wasn't this abbrev generated?"); 4686088c234SPavel Labath 4696088c234SPavel Labath Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code"); 4706088c234SPavel Labath for (const auto &AttrEnc : AbbrevIt->second) { 4716088c234SPavel Labath Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index)); 4726088c234SPavel Labath switch (AttrEnc.Index) { 4736088c234SPavel Labath case dwarf::DW_IDX_compile_unit: { 4746088c234SPavel Labath const DIE *CUDie = Entry.getDie().getUnitDie(); 4756088c234SPavel Labath DIEInteger ID(DD.lookupCU(CUDie)->getUniqueID()); 4766088c234SPavel Labath ID.EmitValue(Asm, AttrEnc.Form); 4776088c234SPavel Labath break; 4786088c234SPavel Labath } 4796088c234SPavel Labath case dwarf::DW_IDX_die_offset: 4806088c234SPavel Labath assert(AttrEnc.Form == dwarf::DW_FORM_ref4); 4816088c234SPavel Labath Asm->emitInt32(Entry.getDie().getOffset()); 4826088c234SPavel Labath break; 4836088c234SPavel Labath default: 4846088c234SPavel Labath llvm_unreachable("Unexpected index attribute!"); 4856088c234SPavel Labath } 4866088c234SPavel Labath } 4876088c234SPavel Labath } 4886088c234SPavel Labath 4896088c234SPavel Labath void Dwarf5AccelTableEmitter::emitData() const { 4906088c234SPavel Labath Asm->OutStreamer->EmitLabel(EntryPool); 4916088c234SPavel Labath for (auto &Bucket : Contents.getBuckets()) { 4926088c234SPavel Labath for (auto *Hash : Bucket) { 4936088c234SPavel Labath // Remember to emit the label for our offset. 4946088c234SPavel Labath Asm->OutStreamer->EmitLabel(Hash->Sym); 4956088c234SPavel Labath for (const auto *Value : Hash->Values) 4966088c234SPavel Labath emitEntry(*static_cast<const DWARF5AccelTableData *>(Value)); 4976088c234SPavel Labath Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString()); 4986088c234SPavel Labath Asm->emitInt32(0); 4996088c234SPavel Labath } 5006088c234SPavel Labath } 5016088c234SPavel Labath } 5026088c234SPavel Labath 5036088c234SPavel Labath Dwarf5AccelTableEmitter::Dwarf5AccelTableEmitter( 5046088c234SPavel Labath AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD, 5056088c234SPavel Labath ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits) 5066088c234SPavel Labath : AccelTableEmitter(Asm, Contents, false), 5076088c234SPavel Labath Header(CompUnits.size(), Contents.getBucketCount(), 5086088c234SPavel Labath Contents.getUniqueNameCount()), 5096088c234SPavel Labath DD(DD), CompUnits(CompUnits) { 5106088c234SPavel Labath DenseSet<uint32_t> UniqueTags = getUniqueTags(); 5116088c234SPavel Labath SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes(); 5126088c234SPavel Labath 5136088c234SPavel Labath Abbreviations.reserve(UniqueTags.size()); 5146088c234SPavel Labath for (uint32_t Tag : UniqueTags) 5156088c234SPavel Labath Abbreviations.try_emplace(Tag, UniformAttributes); 5166088c234SPavel Labath } 5176088c234SPavel Labath 5186088c234SPavel Labath void Dwarf5AccelTableEmitter::emit() const { 5196088c234SPavel Labath Header.emit(*this); 5206088c234SPavel Labath emitCUList(); 5216088c234SPavel Labath emitBuckets(); 5226088c234SPavel Labath emitHashes(); 5236088c234SPavel Labath emitStringOffsets(); 5246088c234SPavel Labath emitOffsets(EntryPool); 5256088c234SPavel Labath emitAbbrevs(); 5266088c234SPavel Labath emitData(); 5276088c234SPavel Labath Asm->OutStreamer->EmitValueToAlignment(4, 0); 5286088c234SPavel Labath Asm->OutStreamer->EmitLabel(ContributionEnd); 5296088c234SPavel Labath } 5306088c234SPavel Labath 531a7c457d2SPavel Labath void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, 532a7c457d2SPavel Labath StringRef Prefix, const MCSymbol *SecBegin, 533a7c457d2SPavel Labath ArrayRef<AppleAccelTableData::Atom> Atoms) { 534a7c457d2SPavel Labath Contents.finalize(Asm, Prefix); 535a7c457d2SPavel Labath AppleAccelTableEmitter(Asm, Contents, Atoms, SecBegin).emit(); 536855fc3bbSJonas Devlieghere } 537855fc3bbSJonas Devlieghere 5386088c234SPavel Labath void llvm::emitDWARF5AccelTable( 5396088c234SPavel Labath AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents, 5406088c234SPavel Labath const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) { 5416088c234SPavel Labath Contents.finalize(Asm, "names"); 5426088c234SPavel Labath Dwarf5AccelTableEmitter(Asm, Contents, DD, CUs).emit(); 5436088c234SPavel Labath } 5446088c234SPavel Labath 545855fc3bbSJonas Devlieghere void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const { 5464b4d85fdSRafael Espindola Asm->emitInt32(Die->getDebugSectionOffset()); 547855fc3bbSJonas Devlieghere } 548855fc3bbSJonas Devlieghere 549855fc3bbSJonas Devlieghere void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const { 5504b4d85fdSRafael Espindola Asm->emitInt32(Die->getDebugSectionOffset()); 5514b4d85fdSRafael Espindola Asm->emitInt16(Die->getTag()); 5524b4d85fdSRafael Espindola Asm->emitInt8(0); 553855fc3bbSJonas Devlieghere } 5545ead3a2bSJonas Devlieghere 5555ead3a2bSJonas Devlieghere void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const { 5564b4d85fdSRafael Espindola Asm->emitInt32(Offset); 5575ead3a2bSJonas Devlieghere } 5585ead3a2bSJonas Devlieghere 5595ead3a2bSJonas Devlieghere void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const { 5604b4d85fdSRafael Espindola Asm->emitInt32(Offset); 5614b4d85fdSRafael Espindola Asm->emitInt16(Tag); 5624b4d85fdSRafael Espindola Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation 5635ead3a2bSJonas Devlieghere : 0); 5644b4d85fdSRafael Espindola Asm->emitInt32(QualifiedNameHash); 5655ead3a2bSJonas Devlieghere } 566073971b2SJonas Devlieghere 567073971b2SJonas Devlieghere #ifndef _MSC_VER 568073971b2SJonas Devlieghere // The lines below are rejected by older versions (TBD) of MSVC. 569a7c457d2SPavel Labath constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[]; 570a7c457d2SPavel Labath constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[]; 571a7c457d2SPavel Labath constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[]; 572a7c457d2SPavel Labath constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[]; 573073971b2SJonas Devlieghere #else 574073971b2SJonas Devlieghere // FIXME: Erase this path once the minimum MSCV version has been bumped. 575a7c457d2SPavel Labath const SmallVector<AppleAccelTableData::Atom, 4> 576a7c457d2SPavel Labath AppleAccelTableOffsetData::Atoms = { 577a7c457d2SPavel Labath Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 578a7c457d2SPavel Labath const SmallVector<AppleAccelTableData::Atom, 4> AppleAccelTableTypeData::Atoms = 579a7c457d2SPavel Labath {Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 580a7c457d2SPavel Labath Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 581a7c457d2SPavel Labath Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; 582a7c457d2SPavel Labath const SmallVector<AppleAccelTableData::Atom, 4> 583a7c457d2SPavel Labath AppleAccelTableStaticOffsetData::Atoms = { 584a7c457d2SPavel Labath Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; 585a7c457d2SPavel Labath const SmallVector<AppleAccelTableData::Atom, 4> 586073971b2SJonas Devlieghere AppleAccelTableStaticTypeData::Atoms = { 587a7c457d2SPavel Labath Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), 588a7c457d2SPavel Labath Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), 589a7c457d2SPavel Labath Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; 590073971b2SJonas Devlieghere #endif 5911ce64dccSJonas Devlieghere 5921ce64dccSJonas Devlieghere #ifndef NDEBUG 593a7c457d2SPavel Labath void AppleAccelTableEmitter::Header::print(raw_ostream &OS) const { 5941ce64dccSJonas Devlieghere OS << "Magic: " << format("0x%x", Magic) << "\n" 5951ce64dccSJonas Devlieghere << "Version: " << Version << "\n" 5961ce64dccSJonas Devlieghere << "Hash Function: " << HashFunction << "\n" 5971ce64dccSJonas Devlieghere << "Bucket Count: " << BucketCount << "\n" 5981ce64dccSJonas Devlieghere << "Header Data Length: " << HeaderDataLength << "\n"; 5991ce64dccSJonas Devlieghere } 6001ce64dccSJonas Devlieghere 601a7c457d2SPavel Labath void AppleAccelTableData::Atom::print(raw_ostream &OS) const { 6021ce64dccSJonas Devlieghere OS << "Type: " << dwarf::AtomTypeString(Type) << "\n" 6031ce64dccSJonas Devlieghere << "Form: " << dwarf::FormEncodingString(Form) << "\n"; 6041ce64dccSJonas Devlieghere } 6051ce64dccSJonas Devlieghere 606a7c457d2SPavel Labath void AppleAccelTableEmitter::HeaderData::print(raw_ostream &OS) const { 6071ce64dccSJonas Devlieghere OS << "DIE Offset Base: " << DieOffsetBase << "\n"; 6081ce64dccSJonas Devlieghere for (auto Atom : Atoms) 6091ce64dccSJonas Devlieghere Atom.print(OS); 6101ce64dccSJonas Devlieghere } 6111ce64dccSJonas Devlieghere 612a7c457d2SPavel Labath void AppleAccelTableEmitter::print(raw_ostream &OS) const { 6131ce64dccSJonas Devlieghere Header.print(OS); 6141ce64dccSJonas Devlieghere HeaderData.print(OS); 615a7c457d2SPavel Labath Contents.print(OS); 616a7c457d2SPavel Labath SecBegin->print(OS, nullptr); 6171ce64dccSJonas Devlieghere } 6181ce64dccSJonas Devlieghere 619a7c457d2SPavel Labath void AccelTableBase::HashData::print(raw_ostream &OS) const { 620062eb537SPavel Labath OS << "Name: " << Name.getString() << "\n"; 6211ce64dccSJonas Devlieghere OS << " Hash Value: " << format("0x%x", HashValue) << "\n"; 6221ce64dccSJonas Devlieghere OS << " Symbol: "; 6231ce64dccSJonas Devlieghere if (Sym) 6241ce64dccSJonas Devlieghere OS << *Sym; 6251ce64dccSJonas Devlieghere else 6261ce64dccSJonas Devlieghere OS << "<none>"; 6271ce64dccSJonas Devlieghere OS << "\n"; 628062eb537SPavel Labath for (auto *Value : Values) 6291ce64dccSJonas Devlieghere Value->print(OS); 6301ce64dccSJonas Devlieghere } 6311ce64dccSJonas Devlieghere 632a7c457d2SPavel Labath void AccelTableBase::print(raw_ostream &OS) const { 6331ce64dccSJonas Devlieghere // Print Content. 6341ce64dccSJonas Devlieghere OS << "Entries: \n"; 6351ce64dccSJonas Devlieghere for (const auto &Entry : Entries) { 6361ce64dccSJonas Devlieghere OS << "Name: " << Entry.first() << "\n"; 6371ce64dccSJonas Devlieghere for (auto *V : Entry.second.Values) 6381ce64dccSJonas Devlieghere V->print(OS); 6391ce64dccSJonas Devlieghere } 6401ce64dccSJonas Devlieghere 6411ce64dccSJonas Devlieghere OS << "Buckets and Hashes: \n"; 6421ce64dccSJonas Devlieghere for (auto &Bucket : Buckets) 6431ce64dccSJonas Devlieghere for (auto &Hash : Bucket) 6441ce64dccSJonas Devlieghere Hash->print(OS); 6451ce64dccSJonas Devlieghere 6461ce64dccSJonas Devlieghere OS << "Data: \n"; 647062eb537SPavel Labath for (auto &E : Entries) 648062eb537SPavel Labath E.second.print(OS); 6491ce64dccSJonas Devlieghere } 6501ce64dccSJonas Devlieghere 6516088c234SPavel Labath void DWARF5AccelTableData::print(raw_ostream &OS) const { 6526088c234SPavel Labath OS << " Offset: " << Die.getOffset() << "\n"; 6536088c234SPavel Labath OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n"; 6546088c234SPavel Labath } 6556088c234SPavel Labath 6561ce64dccSJonas Devlieghere void AppleAccelTableOffsetData::print(raw_ostream &OS) const { 6571ce64dccSJonas Devlieghere OS << " Offset: " << Die->getOffset() << "\n"; 6581ce64dccSJonas Devlieghere } 6591ce64dccSJonas Devlieghere 6601ce64dccSJonas Devlieghere void AppleAccelTableTypeData::print(raw_ostream &OS) const { 6611ce64dccSJonas Devlieghere OS << " Offset: " << Die->getOffset() << "\n"; 6621ce64dccSJonas Devlieghere OS << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; 6631ce64dccSJonas Devlieghere } 6641ce64dccSJonas Devlieghere 6651ce64dccSJonas Devlieghere void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const { 6661ce64dccSJonas Devlieghere OS << " Static Offset: " << Offset << "\n"; 6671ce64dccSJonas Devlieghere } 6681ce64dccSJonas Devlieghere 6691ce64dccSJonas Devlieghere void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const { 6701ce64dccSJonas Devlieghere OS << " Static Offset: " << Offset << "\n"; 6711ce64dccSJonas Devlieghere OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n"; 6721ce64dccSJonas Devlieghere OS << " Tag: " << dwarf::TagString(Tag) << "\n"; 6731ce64dccSJonas Devlieghere OS << " ObjCClassIsImplementation: " 6741ce64dccSJonas Devlieghere << (ObjCClassIsImplementation ? "true" : "false"); 6751ce64dccSJonas Devlieghere OS << "\n"; 6761ce64dccSJonas Devlieghere } 6771ce64dccSJonas Devlieghere #endif 678