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