1*9880d681SAndroid Build Coastguard Worker //===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- 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 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H 11*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h" 14*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h" 15*9880d681SAndroid Build Coastguard Worker #include "ByteStreamer.h" 16*9880d681SAndroid Build Coastguard Worker 17*9880d681SAndroid Build Coastguard Worker namespace llvm { 18*9880d681SAndroid Build Coastguard Worker 19*9880d681SAndroid Build Coastguard Worker class AsmPrinter; 20*9880d681SAndroid Build Coastguard Worker class DbgVariable; 21*9880d681SAndroid Build Coastguard Worker class DwarfCompileUnit; 22*9880d681SAndroid Build Coastguard Worker class MachineInstr; 23*9880d681SAndroid Build Coastguard Worker class MCSymbol; 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker /// \brief Byte stream of .debug_loc entries. 26*9880d681SAndroid Build Coastguard Worker /// 27*9880d681SAndroid Build Coastguard Worker /// Stores a unified stream of .debug_loc entries. There's \a List for each 28*9880d681SAndroid Build Coastguard Worker /// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry. 29*9880d681SAndroid Build Coastguard Worker /// 30*9880d681SAndroid Build Coastguard Worker /// FIXME: Do we need all these temp symbols? 31*9880d681SAndroid Build Coastguard Worker /// FIXME: Why not output directly to the output stream? 32*9880d681SAndroid Build Coastguard Worker class DebugLocStream { 33*9880d681SAndroid Build Coastguard Worker public: 34*9880d681SAndroid Build Coastguard Worker struct List { 35*9880d681SAndroid Build Coastguard Worker DwarfCompileUnit *CU; 36*9880d681SAndroid Build Coastguard Worker MCSymbol *Label = nullptr; 37*9880d681SAndroid Build Coastguard Worker size_t EntryOffset; ListList38*9880d681SAndroid Build Coastguard Worker List(DwarfCompileUnit *CU, size_t EntryOffset) 39*9880d681SAndroid Build Coastguard Worker : CU(CU), EntryOffset(EntryOffset) {} 40*9880d681SAndroid Build Coastguard Worker }; 41*9880d681SAndroid Build Coastguard Worker struct Entry { 42*9880d681SAndroid Build Coastguard Worker const MCSymbol *BeginSym; 43*9880d681SAndroid Build Coastguard Worker const MCSymbol *EndSym; 44*9880d681SAndroid Build Coastguard Worker size_t ByteOffset; 45*9880d681SAndroid Build Coastguard Worker size_t CommentOffset; EntryEntry46*9880d681SAndroid Build Coastguard Worker Entry(const MCSymbol *BeginSym, const MCSymbol *EndSym, size_t ByteOffset, 47*9880d681SAndroid Build Coastguard Worker size_t CommentOffset) 48*9880d681SAndroid Build Coastguard Worker : BeginSym(BeginSym), EndSym(EndSym), ByteOffset(ByteOffset), 49*9880d681SAndroid Build Coastguard Worker CommentOffset(CommentOffset) {} 50*9880d681SAndroid Build Coastguard Worker }; 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Worker private: 53*9880d681SAndroid Build Coastguard Worker SmallVector<List, 4> Lists; 54*9880d681SAndroid Build Coastguard Worker SmallVector<Entry, 32> Entries; 55*9880d681SAndroid Build Coastguard Worker SmallString<256> DWARFBytes; 56*9880d681SAndroid Build Coastguard Worker SmallVector<std::string, 32> Comments; 57*9880d681SAndroid Build Coastguard Worker 58*9880d681SAndroid Build Coastguard Worker /// \brief Only verbose textual output needs comments. This will be set to 59*9880d681SAndroid Build Coastguard Worker /// true for that case, and false otherwise. 60*9880d681SAndroid Build Coastguard Worker bool GenerateComments; 61*9880d681SAndroid Build Coastguard Worker 62*9880d681SAndroid Build Coastguard Worker public: DebugLocStream(bool GenerateComments)63*9880d681SAndroid Build Coastguard Worker DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { } getNumLists()64*9880d681SAndroid Build Coastguard Worker size_t getNumLists() const { return Lists.size(); } getList(size_t LI)65*9880d681SAndroid Build Coastguard Worker const List &getList(size_t LI) const { return Lists[LI]; } getLists()66*9880d681SAndroid Build Coastguard Worker ArrayRef<List> getLists() const { return Lists; } 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker class ListBuilder; 69*9880d681SAndroid Build Coastguard Worker class EntryBuilder; 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Worker private: 72*9880d681SAndroid Build Coastguard Worker /// \brief Start a new .debug_loc entry list. 73*9880d681SAndroid Build Coastguard Worker /// 74*9880d681SAndroid Build Coastguard Worker /// Start a new .debug_loc entry list. Return the new list's index so it can 75*9880d681SAndroid Build Coastguard Worker /// be retrieved later via \a getList(). 76*9880d681SAndroid Build Coastguard Worker /// 77*9880d681SAndroid Build Coastguard Worker /// Until the next call, \a startEntry() will add entries to this list. startList(DwarfCompileUnit * CU)78*9880d681SAndroid Build Coastguard Worker size_t startList(DwarfCompileUnit *CU) { 79*9880d681SAndroid Build Coastguard Worker size_t LI = Lists.size(); 80*9880d681SAndroid Build Coastguard Worker Lists.emplace_back(CU, Entries.size()); 81*9880d681SAndroid Build Coastguard Worker return LI; 82*9880d681SAndroid Build Coastguard Worker } 83*9880d681SAndroid Build Coastguard Worker 84*9880d681SAndroid Build Coastguard Worker /// Finalize a .debug_loc entry list. 85*9880d681SAndroid Build Coastguard Worker /// 86*9880d681SAndroid Build Coastguard Worker /// If there are no entries in this list, delete it outright. Otherwise, 87*9880d681SAndroid Build Coastguard Worker /// create a label with \a Asm. 88*9880d681SAndroid Build Coastguard Worker /// 89*9880d681SAndroid Build Coastguard Worker /// \return false iff the list is deleted. 90*9880d681SAndroid Build Coastguard Worker bool finalizeList(AsmPrinter &Asm); 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker /// \brief Start a new .debug_loc entry. 93*9880d681SAndroid Build Coastguard Worker /// 94*9880d681SAndroid Build Coastguard Worker /// Until the next call, bytes added to the stream will be added to this 95*9880d681SAndroid Build Coastguard Worker /// entry. startEntry(const MCSymbol * BeginSym,const MCSymbol * EndSym)96*9880d681SAndroid Build Coastguard Worker void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) { 97*9880d681SAndroid Build Coastguard Worker Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size()); 98*9880d681SAndroid Build Coastguard Worker } 99*9880d681SAndroid Build Coastguard Worker 100*9880d681SAndroid Build Coastguard Worker /// Finalize a .debug_loc entry, deleting if it's empty. 101*9880d681SAndroid Build Coastguard Worker void finalizeEntry(); 102*9880d681SAndroid Build Coastguard Worker 103*9880d681SAndroid Build Coastguard Worker public: getStreamer()104*9880d681SAndroid Build Coastguard Worker BufferByteStreamer getStreamer() { 105*9880d681SAndroid Build Coastguard Worker return BufferByteStreamer(DWARFBytes, Comments, GenerateComments); 106*9880d681SAndroid Build Coastguard Worker } 107*9880d681SAndroid Build Coastguard Worker getEntries(const List & L)108*9880d681SAndroid Build Coastguard Worker ArrayRef<Entry> getEntries(const List &L) const { 109*9880d681SAndroid Build Coastguard Worker size_t LI = getIndex(L); 110*9880d681SAndroid Build Coastguard Worker return makeArrayRef(Entries) 111*9880d681SAndroid Build Coastguard Worker .slice(Lists[LI].EntryOffset, getNumEntries(LI)); 112*9880d681SAndroid Build Coastguard Worker } 113*9880d681SAndroid Build Coastguard Worker getBytes(const Entry & E)114*9880d681SAndroid Build Coastguard Worker ArrayRef<char> getBytes(const Entry &E) const { 115*9880d681SAndroid Build Coastguard Worker size_t EI = getIndex(E); 116*9880d681SAndroid Build Coastguard Worker return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end()) 117*9880d681SAndroid Build Coastguard Worker .slice(Entries[EI].ByteOffset, getNumBytes(EI)); 118*9880d681SAndroid Build Coastguard Worker } getComments(const Entry & E)119*9880d681SAndroid Build Coastguard Worker ArrayRef<std::string> getComments(const Entry &E) const { 120*9880d681SAndroid Build Coastguard Worker size_t EI = getIndex(E); 121*9880d681SAndroid Build Coastguard Worker return makeArrayRef(Comments) 122*9880d681SAndroid Build Coastguard Worker .slice(Entries[EI].CommentOffset, getNumComments(EI)); 123*9880d681SAndroid Build Coastguard Worker } 124*9880d681SAndroid Build Coastguard Worker 125*9880d681SAndroid Build Coastguard Worker private: getIndex(const List & L)126*9880d681SAndroid Build Coastguard Worker size_t getIndex(const List &L) const { 127*9880d681SAndroid Build Coastguard Worker assert(&Lists.front() <= &L && &L <= &Lists.back() && 128*9880d681SAndroid Build Coastguard Worker "Expected valid list"); 129*9880d681SAndroid Build Coastguard Worker return &L - &Lists.front(); 130*9880d681SAndroid Build Coastguard Worker } getIndex(const Entry & E)131*9880d681SAndroid Build Coastguard Worker size_t getIndex(const Entry &E) const { 132*9880d681SAndroid Build Coastguard Worker assert(&Entries.front() <= &E && &E <= &Entries.back() && 133*9880d681SAndroid Build Coastguard Worker "Expected valid entry"); 134*9880d681SAndroid Build Coastguard Worker return &E - &Entries.front(); 135*9880d681SAndroid Build Coastguard Worker } getNumEntries(size_t LI)136*9880d681SAndroid Build Coastguard Worker size_t getNumEntries(size_t LI) const { 137*9880d681SAndroid Build Coastguard Worker if (LI + 1 == Lists.size()) 138*9880d681SAndroid Build Coastguard Worker return Entries.size() - Lists[LI].EntryOffset; 139*9880d681SAndroid Build Coastguard Worker return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset; 140*9880d681SAndroid Build Coastguard Worker } getNumBytes(size_t EI)141*9880d681SAndroid Build Coastguard Worker size_t getNumBytes(size_t EI) const { 142*9880d681SAndroid Build Coastguard Worker if (EI + 1 == Entries.size()) 143*9880d681SAndroid Build Coastguard Worker return DWARFBytes.size() - Entries[EI].ByteOffset; 144*9880d681SAndroid Build Coastguard Worker return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset; 145*9880d681SAndroid Build Coastguard Worker } getNumComments(size_t EI)146*9880d681SAndroid Build Coastguard Worker size_t getNumComments(size_t EI) const { 147*9880d681SAndroid Build Coastguard Worker if (EI + 1 == Entries.size()) 148*9880d681SAndroid Build Coastguard Worker return Comments.size() - Entries[EI].CommentOffset; 149*9880d681SAndroid Build Coastguard Worker return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset; 150*9880d681SAndroid Build Coastguard Worker } 151*9880d681SAndroid Build Coastguard Worker }; 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker /// Builder for DebugLocStream lists. 154*9880d681SAndroid Build Coastguard Worker class DebugLocStream::ListBuilder { 155*9880d681SAndroid Build Coastguard Worker DebugLocStream &Locs; 156*9880d681SAndroid Build Coastguard Worker AsmPrinter &Asm; 157*9880d681SAndroid Build Coastguard Worker DbgVariable &V; 158*9880d681SAndroid Build Coastguard Worker const MachineInstr &MI; 159*9880d681SAndroid Build Coastguard Worker size_t ListIndex; 160*9880d681SAndroid Build Coastguard Worker 161*9880d681SAndroid Build Coastguard Worker public: ListBuilder(DebugLocStream & Locs,DwarfCompileUnit & CU,AsmPrinter & Asm,DbgVariable & V,const MachineInstr & MI)162*9880d681SAndroid Build Coastguard Worker ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, 163*9880d681SAndroid Build Coastguard Worker DbgVariable &V, const MachineInstr &MI) 164*9880d681SAndroid Build Coastguard Worker : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {} 165*9880d681SAndroid Build Coastguard Worker 166*9880d681SAndroid Build Coastguard Worker /// Finalize the list. 167*9880d681SAndroid Build Coastguard Worker /// 168*9880d681SAndroid Build Coastguard Worker /// If the list is empty, delete it. Otherwise, finalize it by creating a 169*9880d681SAndroid Build Coastguard Worker /// temp symbol in \a Asm and setting up the \a DbgVariable. 170*9880d681SAndroid Build Coastguard Worker ~ListBuilder(); 171*9880d681SAndroid Build Coastguard Worker getLocs()172*9880d681SAndroid Build Coastguard Worker DebugLocStream &getLocs() { return Locs; } 173*9880d681SAndroid Build Coastguard Worker }; 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Worker /// Builder for DebugLocStream entries. 176*9880d681SAndroid Build Coastguard Worker class DebugLocStream::EntryBuilder { 177*9880d681SAndroid Build Coastguard Worker DebugLocStream &Locs; 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker public: EntryBuilder(ListBuilder & List,const MCSymbol * Begin,const MCSymbol * End)180*9880d681SAndroid Build Coastguard Worker EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End) 181*9880d681SAndroid Build Coastguard Worker : Locs(List.getLocs()) { 182*9880d681SAndroid Build Coastguard Worker Locs.startEntry(Begin, End); 183*9880d681SAndroid Build Coastguard Worker } 184*9880d681SAndroid Build Coastguard Worker 185*9880d681SAndroid Build Coastguard Worker /// Finalize the entry, deleting it if it's empty. ~EntryBuilder()186*9880d681SAndroid Build Coastguard Worker ~EntryBuilder() { Locs.finalizeEntry(); } 187*9880d681SAndroid Build Coastguard Worker getStreamer()188*9880d681SAndroid Build Coastguard Worker BufferByteStreamer getStreamer() { return Locs.getStreamer(); } 189*9880d681SAndroid Build Coastguard Worker }; 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Worker } // namespace llvm 192*9880d681SAndroid Build Coastguard Worker 193*9880d681SAndroid Build Coastguard Worker #endif 194