LCOV - code coverage report
Current view: top level - lib/CodeGen/AsmPrinter - DwarfAccelTable.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 12 12 100.0 %
Date: 2017-09-14 15:23:50 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //==- llvm/CodeGen/DwarfAccelTable.h - Dwarf Accelerator Tables --*- C++ -*-==//
       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 dwarf accelerator tables.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
      15             : #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
      16             : 
      17             : #include "llvm/ADT/ArrayRef.h"
      18             : #include "llvm/ADT/SmallVector.h"
      19             : #include "llvm/ADT/StringMap.h"
      20             : #include "llvm/ADT/StringRef.h"
      21             : #include "llvm/BinaryFormat/Dwarf.h"
      22             : #include "llvm/CodeGen/DIE.h"
      23             : #include "llvm/CodeGen/DwarfStringPoolEntry.h"
      24             : #include "llvm/MC/MCSymbol.h"
      25             : #include "llvm/Support/Allocator.h"
      26             : #include "llvm/Support/Debug.h"
      27             : #include "llvm/Support/Format.h"
      28             : #include "llvm/Support/raw_ostream.h"
      29             : #include <cstddef>
      30             : #include <cstdint>
      31             : #include <vector>
      32             : 
      33             : // The dwarf accelerator tables are an indirect hash table optimized
      34             : // for null lookup rather than access to known data. They are output into
      35             : // an on-disk format that looks like this:
      36             : //
      37             : // .-------------.
      38             : // |  HEADER     |
      39             : // |-------------|
      40             : // |  BUCKETS    |
      41             : // |-------------|
      42             : // |  HASHES     |
      43             : // |-------------|
      44             : // |  OFFSETS    |
      45             : // |-------------|
      46             : // |  DATA       |
      47             : // `-------------'
      48             : //
      49             : // where the header contains a magic number, version, type of hash function,
      50             : // the number of buckets, total number of hashes, and room for a special
      51             : // struct of data and the length of that struct.
      52             : //
      53             : // The buckets contain an index (e.g. 6) into the hashes array. The hashes
      54             : // section contains all of the 32-bit hash values in contiguous memory, and
      55             : // the offsets contain the offset into the data area for the particular
      56             : // hash.
      57             : //
      58             : // For a lookup example, we could hash a function name and take it modulo the
      59             : // number of buckets giving us our bucket. From there we take the bucket value
      60             : // as an index into the hashes table and look at each successive hash as long
      61             : // as the hash value is still the same modulo result (bucket value) as earlier.
      62             : // If we have a match we look at that same entry in the offsets table and
      63             : // grab the offset in the data for our final match.
      64             : 
      65             : namespace llvm {
      66             : 
      67             : class AsmPrinter;
      68             : class DwarfDebug;
      69             : 
      70      262046 : class DwarfAccelTable {
      71             :   static uint32_t HashDJB(StringRef Str) {
      72         906 :     uint32_t h = 5381;
      73        7476 :     for (unsigned i = 0, e = Str.size(); i != e; ++i)
      74       13140 :       h = ((h << 5) + h) + Str[i];
      75             :     return h;
      76             :   }
      77             : 
      78             :   // Helper function to compute the number of buckets needed based on
      79             :   // the number of unique hashes.
      80             :   void ComputeBucketCount();
      81             : 
      82             :   struct TableHeader {
      83             :     uint32_t magic = MagicHash; // 'HASH' magic value to allow endian detection
      84             :     uint16_t version = 1;       // Version number.
      85             :     uint16_t hash_function = dwarf::DW_hash_function_djb;
      86             :     // The hash function enumeration that was used.
      87             :     uint32_t bucket_count = 0;  // The number of buckets in this hash table.
      88             :     uint32_t hashes_count = 0;  // The total number of unique hash values
      89             :                                 // and hash data offsets in this table.
      90             :     uint32_t header_data_len;   // The bytes to skip to get to the hash
      91             :                                 // indexes (buckets) for correct alignment.
      92             :     // Also written to disk is the implementation specific header data.
      93             : 
      94             :     static const uint32_t MagicHash = 0x48415348;
      95             : 
      96       65896 :     TableHeader(uint32_t data_len) : header_data_len(data_len) {}
      97             : 
      98             : #ifndef NDEBUG
      99             :     void print(raw_ostream &OS) {
     100             :       OS << "Magic: " << format("0x%x", magic) << "\n"
     101             :          << "Version: " << version << "\n"
     102             :          << "Hash Function: " << hash_function << "\n"
     103             :          << "Bucket Count: " << bucket_count << "\n"
     104             :          << "Header Data Length: " << header_data_len << "\n";
     105             :     }
     106             : 
     107             :     void dump() { print(dbgs()); }
     108             : #endif
     109             :   };
     110             : 
     111             : public:
     112             :   // The HeaderData describes the form of each set of data. In general this
     113             :   // is as a list of atoms (atom_count) where each atom contains a type
     114             :   // (AtomType type) of data, and an encoding form (form). In the case of
     115             :   // data that is referenced via DW_FORM_ref_* the die_offset_base is
     116             :   // used to describe the offset for all forms in the list of atoms.
     117             :   // This also serves as a public interface of sorts.
     118             :   // When written to disk this will have the form:
     119             :   //
     120             :   // uint32_t die_offset_base
     121             :   // uint32_t atom_count
     122             :   // atom_count Atoms
     123             : 
     124             :   // Make these public so that they can be used as a general interface to
     125             :   // the class.
     126             :   struct Atom {
     127             :     uint16_t type; // enum AtomType
     128             :     uint16_t form; // DWARF DW_FORM_ defines
     129             : 
     130       49422 :     constexpr Atom(uint16_t type, uint16_t form) : type(type), form(form) {}
     131             : 
     132             : #ifndef NDEBUG
     133             :     void print(raw_ostream &OS) {
     134             :       OS << "Type: " << dwarf::AtomTypeString(type) << "\n"
     135             :          << "Form: " << dwarf::FormEncodingString(form) << "\n";
     136             :     }
     137             : 
     138             :     void dump() { print(dbgs()); }
     139             : #endif
     140             :   };
     141             : 
     142             : private:
     143      131024 :   struct TableHeaderData {
     144             :     uint32_t die_offset_base;
     145             :     SmallVector<Atom, 3> Atoms;
     146             : 
     147             :     TableHeaderData(ArrayRef<Atom> AtomList, uint32_t offset = 0)
     148      197687 :         : die_offset_base(offset), Atoms(AtomList.begin(), AtomList.end()) {}
     149             : 
     150             : #ifndef NDEBUG
     151             :     void print(raw_ostream &OS) {
     152             :       OS << "die_offset_base: " << die_offset_base << "\n";
     153             :       for (size_t i = 0; i < Atoms.size(); i++)
     154             :         Atoms[i].print(OS);
     155             :     }
     156             : 
     157             :     void dump() { print(dbgs()); }
     158             : #endif
     159             :   };
     160             : 
     161             :   // The data itself consists of a str_offset, a count of the DIEs in the
     162             :   // hash and the offsets to the DIEs themselves.
     163             :   // On disk each data section is ended with a 0 KeyType as the end of the
     164             :   // hash chain.
     165             :   // On output this looks like:
     166             :   // uint32_t str_offset
     167             :   // uint32_t hash_data_count
     168             :   // HashData[hash_data_count]
     169             : public:
     170             :   struct HashDataContents {
     171             :     const DIE *Die;   // Offsets
     172             :     char Flags; // Specific flags to output
     173             : 
     174         961 :     HashDataContents(const DIE *D, char Flags) : Die(D), Flags(Flags) {}
     175             : 
     176             : #ifndef NDEBUG
     177             :     void print(raw_ostream &OS) const {
     178             :       OS << "  Offset: " << Die->getOffset() << "\n"
     179             :          << "  Tag: " << dwarf::TagString(Die->getTag()) << "\n"
     180             :          << "  Flags: " << Flags << "\n";
     181             :     }
     182             : #endif
     183             :   };
     184             : 
     185             : private:
     186             :   // String Data
     187        3624 :   struct DataArray {
     188             :     DwarfStringPoolEntryRef Name;
     189             :     std::vector<HashDataContents *> Values;
     190             :   };
     191             : 
     192             :   friend struct HashData;
     193             : 
     194             :   struct HashData {
     195             :     StringRef Str;
     196             :     uint32_t HashValue;
     197             :     MCSymbol *Sym;
     198             :     DwarfAccelTable::DataArray &Data; // offsets
     199             : 
     200             :     HashData(StringRef S, DwarfAccelTable::DataArray &Data)
     201         906 :         : Str(S), Data(Data) {
     202         906 :       HashValue = DwarfAccelTable::HashDJB(S);
     203             :     }
     204             : 
     205             : #ifndef NDEBUG
     206             :     void print(raw_ostream &OS) {
     207             :       OS << "Name: " << Str << "\n";
     208             :       OS << "  Hash Value: " << format("0x%x", HashValue) << "\n";
     209             :       OS << "  Symbol: ";
     210             :       if (Sym)
     211             :         OS << *Sym;
     212             :       else
     213             :         OS << "<none>";
     214             :       OS << "\n";
     215             :       for (HashDataContents *C : Data.Values) {
     216             :         OS << "  Offset: " << C->Die->getOffset() << "\n";
     217             :         OS << "  Tag: " << dwarf::TagString(C->Die->getTag()) << "\n";
     218             :         OS << "  Flags: " << C->Flags << "\n";
     219             :       }
     220             :     }
     221             : 
     222             :     void dump() { print(dbgs()); }
     223             : #endif
     224             :   };
     225             : 
     226             :   // Internal Functions
     227             :   void EmitHeader(AsmPrinter *);
     228             :   void EmitBuckets(AsmPrinter *);
     229             :   void EmitHashes(AsmPrinter *);
     230             :   void emitOffsets(AsmPrinter *, const MCSymbol *);
     231             :   void EmitData(AsmPrinter *, DwarfDebug *D);
     232             : 
     233             :   // Allocator for HashData and HashDataContents.
     234             :   BumpPtrAllocator Allocator;
     235             : 
     236             :   // Output Variables
     237             :   TableHeader Header;
     238             :   TableHeaderData HeaderData;
     239             :   std::vector<HashData *> Data;
     240             : 
     241             :   using StringEntries = StringMap<DataArray, BumpPtrAllocator &>;
     242             : 
     243             :   StringEntries Entries;
     244             : 
     245             :   // Buckets/Hashes/Offsets
     246             :   using HashList = std::vector<HashData *>;
     247             :   using BucketList = std::vector<HashList>;
     248             :   BucketList Buckets;
     249             :   HashList Hashes;
     250             : 
     251             :   // Public Implementation
     252             : public:
     253             :   DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>);
     254             :   DwarfAccelTable(const DwarfAccelTable &) = delete;
     255             :   DwarfAccelTable &operator=(const DwarfAccelTable &) = delete;
     256             : 
     257             :   void AddName(DwarfStringPoolEntryRef Name, const DIE *Die, char Flags = 0);
     258             :   void FinalizeTable(AsmPrinter *, StringRef);
     259             :   void emit(AsmPrinter *, const MCSymbol *, DwarfDebug *);
     260             : #ifndef NDEBUG
     261             :   void print(raw_ostream &OS);
     262             :   void dump() { print(dbgs()); }
     263             : #endif
     264             : };
     265             : 
     266             : } // end namespace llvm
     267             : 
     268             : #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H

Generated by: LCOV version 1.13