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

Generated by: LCOV version 1.13