LCOV - code coverage report
Current view: top level - lib/CodeGen/AsmPrinter - AccelTable.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 266 269 98.9 %
Date: 2018-07-13 00:08:38 Functions: 27 27 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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        1213 : void AccelTableBase::computeBucketCount() {
      34             :   // First get the number of unique hashes.
      35             :   std::vector<uint32_t> Uniques;
      36        1213 :   Uniques.reserve(Entries.size());
      37        4431 :   for (const auto &E : Entries)
      38        2005 :     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        1213 :   UniqueHashCount = std::distance(Uniques.begin(), P);
      44             : 
      45        1213 :   if (UniqueHashCount > 1024)
      46           0 :     BucketCount = UniqueHashCount / 4;
      47        1213 :   else if (UniqueHashCount > 16)
      48           5 :     BucketCount = UniqueHashCount / 2;
      49             :   else
      50        2416 :     BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
      51        1213 : }
      52             : 
      53        1213 : void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) {
      54             :   // Create the individual hash data outputs.
      55        4431 :   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        2005 :         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        1213 :   computeBucketCount();
      71             : 
      72             :   // Compute bucket contents and final ordering.
      73        1213 :   Buckets.resize(BucketCount);
      74        4431 :   for (auto &E : Entries) {
      75        2005 :     uint32_t Bucket = E.second.HashValue % BucketCount;
      76        6015 :     Buckets[Bucket].push_back(&E.second);
      77        2005 :     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        3669 :   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        1213 : }
      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 AccelTableWriter {
      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             :   AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
     110             :                    bool SkipIdenticalHashes)
     111        1213 :       : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
     112             :   }
     113             : };
     114             : 
     115             : class AppleAccelTableWriter : public AccelTableWriter {
     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        1188 :         : BucketCount(BucketCount), HashCount(UniqueHashCount),
     132        1188 :           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        1188 :         : 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        1188 :   AppleAccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
     169             :                         ArrayRef<Atom> Atoms, const MCSymbol *SecBegin)
     170        1188 :       : AccelTableWriter(Asm, Contents, true),
     171             :         Header(Contents.getBucketCount(), Contents.getUniqueHashCount(),
     172             :                8 + (Atoms.size() * 4)),
     173        2376 :         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 Dwarf5AccelTableWriter : public AccelTableWriter {
     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          25 :         : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
     201          25 :           NameCount(NameCount) {}
     202             : 
     203             :     void emit(const Dwarf5AccelTableWriter &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 &DD;
     213             :   ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits;
     214          75 :   MCSymbol *ContributionStart = Asm->createTempSymbol("names_start");
     215          75 :   MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end");
     216          75 :   MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
     217          75 :   MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
     218          75 :   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             :   Dwarf5AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
     234             :                          const DwarfDebug &DD,
     235             :                          ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits);
     236             : 
     237             :   void emit() const;
     238             : };
     239             : } // namespace
     240             : 
     241        1213 : void AccelTableWriter::emitHashes() const {
     242             :   uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
     243             :   unsigned BucketIdx = 0;
     244        7338 :   for (auto &Bucket : Contents.getBuckets()) {
     245        2456 :     for (auto &Hash : Bucket) {
     246        2005 :       uint32_t HashValue = Hash->HashValue;
     247        2005 :       if (SkipIdenticalHashes && PrevHash == HashValue)
     248           6 :         continue;
     249        5997 :       Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
     250        1999 :       Asm->emitInt32(HashValue);
     251        1999 :       PrevHash = HashValue;
     252             :     }
     253        2456 :     BucketIdx++;
     254             :   }
     255        1213 : }
     256             : 
     257        1213 : void AccelTableWriter::emitOffsets(const MCSymbol *Base) const {
     258        1213 :   const auto &Buckets = Contents.getBuckets();
     259             :   uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
     260        3669 :   for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
     261        2456 :     for (auto *Hash : Buckets[i]) {
     262        2005 :       uint32_t HashValue = Hash->HashValue;
     263        2005 :       if (SkipIdenticalHashes && PrevHash == HashValue)
     264           6 :         continue;
     265        1999 :       PrevHash = HashValue;
     266        5997 :       Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
     267        1999 :       Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t));
     268             :     }
     269             :   }
     270        1213 : }
     271             : 
     272        1188 : void AppleAccelTableWriter::Header::emit(AsmPrinter *Asm) const {
     273        2376 :   Asm->OutStreamer->AddComment("Header Magic");
     274        1188 :   Asm->emitInt32(Magic);
     275        2376 :   Asm->OutStreamer->AddComment("Header Version");
     276        1188 :   Asm->emitInt16(Version);
     277        2376 :   Asm->OutStreamer->AddComment("Header Hash Function");
     278        1188 :   Asm->emitInt16(HashFunction);
     279        2376 :   Asm->OutStreamer->AddComment("Header Bucket Count");
     280        1188 :   Asm->emitInt32(BucketCount);
     281        2376 :   Asm->OutStreamer->AddComment("Header Hash Count");
     282        1188 :   Asm->emitInt32(HashCount);
     283        2376 :   Asm->OutStreamer->AddComment("Header Data Length");
     284        1188 :   Asm->emitInt32(HeaderDataLength);
     285        1188 : }
     286             : 
     287        1188 : void AppleAccelTableWriter::HeaderData::emit(AsmPrinter *Asm) const {
     288        2376 :   Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
     289        1188 :   Asm->emitInt32(DieOffsetBase);
     290        2376 :   Asm->OutStreamer->AddComment("HeaderData Atom Count");
     291        1188 :   Asm->emitInt32(Atoms.size());
     292             : 
     293        4920 :   for (const Atom &A : Atoms) {
     294        3732 :     Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type));
     295        1866 :     Asm->emitInt16(A.Type);
     296        3732 :     Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form));
     297        1866 :     Asm->emitInt16(A.Form);
     298             :   }
     299        1188 : }
     300             : 
     301        1188 : void AppleAccelTableWriter::emitBuckets() const {
     302        1188 :   const auto &Buckets = Contents.getBuckets();
     303             :   unsigned index = 0;
     304        3401 :   for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
     305        6639 :     Asm->OutStreamer->AddComment("Bucket " + Twine(i));
     306        4426 :     if (!Buckets[i].empty())
     307        1166 :       Asm->emitInt32(index);
     308             :     else
     309        1047 :       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        4426 :     for (auto *HD : Buckets[i]) {
     314        1605 :       uint32_t HashValue = HD->HashValue;
     315        1605 :       if (PrevHash != HashValue)
     316        1599 :         ++index;
     317             :       PrevHash = HashValue;
     318             :     }
     319             :   }
     320        1188 : }
     321             : 
     322        1188 : void AppleAccelTableWriter::emitData() const {
     323        1188 :   const auto &Buckets = Contents.getBuckets();
     324        5614 :   for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
     325             :     uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
     326        2213 :     for (auto &Hash : Buckets[i]) {
     327             :       // Terminate the previous entry if there is no hash collision with the
     328             :       // current one.
     329        2044 :       if (PrevHash != std::numeric_limits<uint64_t>::max() &&
     330         439 :           PrevHash != Hash->HashValue)
     331         433 :         Asm->emitInt32(0);
     332             :       // Remember to emit the label for our offset.
     333        3210 :       Asm->OutStreamer->EmitLabel(Hash->Sym);
     334        6420 :       Asm->OutStreamer->AddComment(Hash->Name.getString());
     335        1605 :       Asm->emitDwarfStringOffset(Hash->Name);
     336        4815 :       Asm->OutStreamer->AddComment("Num DIEs");
     337        3210 :       Asm->emitInt32(Hash->Values.size());
     338        5055 :       for (const auto *V : Hash->Values)
     339        1845 :         static_cast<const AppleAccelTableData *>(V)->emit(Asm);
     340        1605 :       PrevHash = Hash->HashValue;
     341             :     }
     342             :     // Emit the final end marker for the bucket.
     343        2213 :     if (!Buckets[i].empty())
     344        1166 :       Asm->emitInt32(0);
     345             :   }
     346        1188 : }
     347             : 
     348        1188 : void AppleAccelTableWriter::emit() const {
     349        1188 :   Header.emit(Asm);
     350        1188 :   HeaderData.emit(Asm);
     351        1188 :   emitBuckets();
     352        1188 :   emitHashes();
     353        1188 :   emitOffsets(SecBegin);
     354        1188 :   emitData();
     355        1188 : }
     356             : 
     357          25 : void Dwarf5AccelTableWriter::Header::emit(
     358             :     const Dwarf5AccelTableWriter &Ctx) const {
     359             :   assert(CompUnitCount > 0 && "Index must have at least one CU.");
     360             : 
     361          25 :   AsmPrinter *Asm = Ctx.Asm;
     362          50 :   Asm->OutStreamer->AddComment("Header: unit length");
     363          25 :   Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
     364             :                            sizeof(uint32_t));
     365          25 :   Asm->OutStreamer->EmitLabel(Ctx.ContributionStart);
     366          50 :   Asm->OutStreamer->AddComment("Header: version");
     367          25 :   Asm->emitInt16(Version);
     368          50 :   Asm->OutStreamer->AddComment("Header: padding");
     369          25 :   Asm->emitInt16(Padding);
     370          50 :   Asm->OutStreamer->AddComment("Header: compilation unit count");
     371          25 :   Asm->emitInt32(CompUnitCount);
     372          50 :   Asm->OutStreamer->AddComment("Header: local type unit count");
     373          25 :   Asm->emitInt32(LocalTypeUnitCount);
     374          50 :   Asm->OutStreamer->AddComment("Header: foreign type unit count");
     375          25 :   Asm->emitInt32(ForeignTypeUnitCount);
     376          50 :   Asm->OutStreamer->AddComment("Header: bucket count");
     377          25 :   Asm->emitInt32(BucketCount);
     378          50 :   Asm->OutStreamer->AddComment("Header: name count");
     379          25 :   Asm->emitInt32(NameCount);
     380          50 :   Asm->OutStreamer->AddComment("Header: abbreviation table size");
     381          25 :   Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
     382          50 :   Asm->OutStreamer->AddComment("Header: augmentation string size");
     383             :   assert(AugmentationStringSize % 4 == 0);
     384          25 :   Asm->emitInt32(AugmentationStringSize);
     385          50 :   Asm->OutStreamer->AddComment("Header: augmentation string");
     386          50 :   Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
     387          25 : }
     388             : 
     389          25 : DenseSet<uint32_t> Dwarf5AccelTableWriter::getUniqueTags() const {
     390             :   DenseSet<uint32_t> UniqueTags;
     391         536 :   for (auto &Bucket : Contents.getBuckets()) {
     392         243 :     for (auto *Hash : Bucket) {
     393         823 :       for (auto *Value : Hash->Values) {
     394             :         const DIE &Die =
     395         423 :             static_cast<const DWARF5AccelTableData *>(Value)->getDie();
     396         846 :         UniqueTags.insert(Die.getTag());
     397             :       }
     398             :     }
     399             :   }
     400          25 :   return UniqueTags;
     401             : }
     402             : 
     403             : SmallVector<Dwarf5AccelTableWriter::AttributeEncoding, 2>
     404          25 : Dwarf5AccelTableWriter::getUniformAttributes() const {
     405             :   SmallVector<AttributeEncoding, 2> UA;
     406          25 :   if (CompUnits.size() > 1) {
     407           2 :     size_t LargestCUIndex = CompUnits.size() - 1;
     408             :     dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
     409           2 :     UA.push_back({dwarf::DW_IDX_compile_unit, Form});
     410             :   }
     411          25 :   UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
     412          25 :   return UA;
     413             : }
     414             : 
     415          25 : void Dwarf5AccelTableWriter::emitCUList() const {
     416         332 :   for (const auto &CU : enumerate(CompUnits)) {
     417             :     assert(CU.index() == CU.value()->getUniqueID());
     418         846 :     Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
     419             :     const DwarfCompileUnit *MainCU =
     420         285 :         DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
     421         282 :     Asm->emitDwarfSymbolReference(MainCU->getLabelBegin());
     422             :   }
     423          25 : }
     424             : 
     425          25 : void Dwarf5AccelTableWriter::emitBuckets() const {
     426             :   uint32_t Index = 1;
     427         293 :   for (const auto &Bucket : enumerate(Contents.getBuckets())) {
     428         729 :     Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
     429         486 :     Asm->emitInt32(Bucket.value().empty() ? 0 : Index);
     430         486 :     Index += Bucket.value().size();
     431             :   }
     432          25 : }
     433             : 
     434          25 : void Dwarf5AccelTableWriter::emitStringOffsets() const {
     435         293 :   for (const auto &Bucket : enumerate(Contents.getBuckets())) {
     436         243 :     for (auto *Hash : Bucket.value()) {
     437         400 :       DwarfStringPoolEntryRef String = Hash->Name;
     438        1600 :       Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
     439        1600 :                                    ": " + String.getString());
     440         400 :       Asm->emitDwarfStringOffset(String);
     441             :     }
     442             :   }
     443          25 : }
     444             : 
     445          25 : void Dwarf5AccelTableWriter::emitAbbrevs() const {
     446          50 :   Asm->OutStreamer->EmitLabel(AbbrevStart);
     447         123 :   for (const auto &Abbrev : Abbreviations) {
     448         219 :     Asm->OutStreamer->AddComment("Abbrev code");
     449             :     assert(Abbrev.first != 0);
     450          73 :     Asm->EmitULEB128(Abbrev.first);
     451         219 :     Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
     452          73 :     Asm->EmitULEB128(Abbrev.first);
     453         223 :     for (const auto &AttrEnc : Abbrev.second) {
     454         150 :       Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
     455         150 :       Asm->EmitULEB128(AttrEnc.Form,
     456         150 :                        dwarf::FormEncodingString(AttrEnc.Form).data());
     457             :     }
     458          73 :     Asm->EmitULEB128(0, "End of abbrev");
     459          73 :     Asm->EmitULEB128(0, "End of abbrev");
     460             :   }
     461          25 :   Asm->EmitULEB128(0, "End of abbrev list");
     462          50 :   Asm->OutStreamer->EmitLabel(AbbrevEnd);
     463          25 : }
     464             : 
     465         423 : void Dwarf5AccelTableWriter::emitEntry(
     466             :     const DWARF5AccelTableData &Entry) const {
     467         423 :   auto AbbrevIt = Abbreviations.find(Entry.getDie().getTag());
     468             :   assert(AbbrevIt != Abbreviations.end() &&
     469             :          "Why wasn't this abbrev generated?");
     470             : 
     471         423 :   Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code");
     472        1787 :   for (const auto &AttrEnc : AbbrevIt->second) {
     473        2046 :     Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
     474         682 :     switch (AttrEnc.Index) {
     475         259 :     case dwarf::DW_IDX_compile_unit: {
     476         259 :       const DIE *CUDie = Entry.getDie().getUnitDie();
     477         518 :       DIEInteger ID(DD.lookupCU(CUDie)->getUniqueID());
     478         259 :       ID.EmitValue(Asm, AttrEnc.Form);
     479             :       break;
     480             :     }
     481         423 :     case dwarf::DW_IDX_die_offset:
     482             :       assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
     483         423 :       Asm->emitInt32(Entry.getDie().getOffset());
     484         423 :       break;
     485           0 :     default:
     486           0 :       llvm_unreachable("Unexpected index attribute!");
     487             :     }
     488             :   }
     489         423 : }
     490             : 
     491          25 : void Dwarf5AccelTableWriter::emitData() const {
     492          50 :   Asm->OutStreamer->EmitLabel(EntryPool);
     493         536 :   for (auto &Bucket : Contents.getBuckets()) {
     494         243 :     for (auto *Hash : Bucket) {
     495             :       // Remember to emit the label for our offset.
     496         800 :       Asm->OutStreamer->EmitLabel(Hash->Sym);
     497         823 :       for (const auto *Value : Hash->Values)
     498         423 :         emitEntry(*static_cast<const DWARF5AccelTableData *>(Value));
     499        1600 :       Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
     500         400 :       Asm->emitInt32(0);
     501             :     }
     502             :   }
     503          25 : }
     504             : 
     505          25 : Dwarf5AccelTableWriter::Dwarf5AccelTableWriter(
     506             :     AsmPrinter *Asm, const AccelTableBase &Contents, const DwarfDebug &DD,
     507          25 :     ArrayRef<std::unique_ptr<DwarfCompileUnit>> CompUnits)
     508             :     : AccelTableWriter(Asm, Contents, false),
     509          25 :       Header(CompUnits.size(), Contents.getBucketCount(),
     510             :              Contents.getUniqueNameCount()),
     511         225 :       DD(DD), CompUnits(CompUnits) {
     512          25 :   DenseSet<uint32_t> UniqueTags = getUniqueTags();
     513          25 :   SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
     514             : 
     515          25 :   Abbreviations.reserve(UniqueTags.size());
     516          98 :   for (uint32_t Tag : UniqueTags)
     517          73 :     Abbreviations.try_emplace(Tag, UniformAttributes);
     518          25 : }
     519             : 
     520          25 : void Dwarf5AccelTableWriter::emit() const {
     521          25 :   Header.emit(*this);
     522          25 :   emitCUList();
     523          25 :   emitBuckets();
     524          25 :   emitHashes();
     525          25 :   emitStringOffsets();
     526          25 :   emitOffsets(EntryPool);
     527          25 :   emitAbbrevs();
     528          25 :   emitData();
     529          50 :   Asm->OutStreamer->EmitValueToAlignment(4, 0);
     530          50 :   Asm->OutStreamer->EmitLabel(ContributionEnd);
     531          25 : }
     532             : 
     533        1188 : void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
     534             :                                    StringRef Prefix, const MCSymbol *SecBegin,
     535             :                                    ArrayRef<AppleAccelTableData::Atom> Atoms) {
     536        1188 :   Contents.finalize(Asm, Prefix);
     537        2376 :   AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
     538        1188 : }
     539             : 
     540          25 : void llvm::emitDWARF5AccelTable(
     541             :     AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
     542             :     const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
     543          50 :   Contents.finalize(Asm, "names");
     544          50 :   Dwarf5AccelTableWriter(Asm, Contents, DD, CUs).emit();
     545          25 : }
     546             : 
     547         632 : void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const {
     548         632 :   Asm->emitInt32(Die->getDebugSectionOffset());
     549         632 : }
     550             : 
     551         504 : void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const {
     552         504 :   Asm->emitInt32(Die->getDebugSectionOffset());
     553         504 :   Asm->emitInt16(Die->getTag());
     554         504 :   Asm->emitInt8(0);
     555         504 : }
     556             : 
     557         435 : void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const {
     558         435 :   Asm->emitInt32(Offset);
     559         435 : }
     560             : 
     561         274 : void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
     562         274 :   Asm->emitInt32(Offset);
     563         274 :   Asm->emitInt16(Tag);
     564         274 :   Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation
     565             :                                           : 0);
     566         274 :   Asm->emitInt32(QualifiedNameHash);
     567         274 : }
     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 AppleAccelTableWriter::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 AppleAccelTableWriter::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 AppleAccelTableWriter::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

Generated by: LCOV version 1.13