1364a3005SDuncan P. N. Exon Smith //===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- C++ -*-===// 2364a3005SDuncan P. N. Exon Smith // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6364a3005SDuncan P. N. Exon Smith // 7364a3005SDuncan P. N. Exon Smith //===----------------------------------------------------------------------===// 8364a3005SDuncan P. N. Exon Smith 9364a3005SDuncan P. N. Exon Smith #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H 10364a3005SDuncan P. N. Exon Smith #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H 11364a3005SDuncan P. N. Exon Smith 126bda14b3SChandler Carruth #include "ByteStreamer.h" 13364a3005SDuncan P. N. Exon Smith #include "llvm/ADT/ArrayRef.h" 14364a3005SDuncan P. N. Exon Smith #include "llvm/ADT/SmallVector.h" 15364a3005SDuncan P. N. Exon Smith 16364a3005SDuncan P. N. Exon Smith namespace llvm { 173a73d9e0SDuncan P. N. Exon Smith 183a73d9e0SDuncan P. N. Exon Smith class AsmPrinter; 193a73d9e0SDuncan P. N. Exon Smith class DbgVariable; 20364a3005SDuncan P. N. Exon Smith class DwarfCompileUnit; 213a73d9e0SDuncan P. N. Exon Smith class MachineInstr; 22364a3005SDuncan P. N. Exon Smith class MCSymbol; 23364a3005SDuncan P. N. Exon Smith 245f8f34e4SAdrian Prantl /// Byte stream of .debug_loc entries. 25364a3005SDuncan P. N. Exon Smith /// 26364a3005SDuncan P. N. Exon Smith /// Stores a unified stream of .debug_loc entries. There's \a List for each 27364a3005SDuncan P. N. Exon Smith /// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry. 28364a3005SDuncan P. N. Exon Smith /// 29364a3005SDuncan P. N. Exon Smith /// FIXME: Do we need all these temp symbols? 30364a3005SDuncan P. N. Exon Smith /// FIXME: Why not output directly to the output stream? 31364a3005SDuncan P. N. Exon Smith class DebugLocStream { 32364a3005SDuncan P. N. Exon Smith public: 33364a3005SDuncan P. N. Exon Smith struct List { 34364a3005SDuncan P. N. Exon Smith DwarfCompileUnit *CU; 353a73d9e0SDuncan P. N. Exon Smith MCSymbol *Label = nullptr; 36364a3005SDuncan P. N. Exon Smith size_t EntryOffset; ListList373a73d9e0SDuncan P. N. Exon Smith List(DwarfCompileUnit *CU, size_t EntryOffset) 383a73d9e0SDuncan P. N. Exon Smith : CU(CU), EntryOffset(EntryOffset) {} 39364a3005SDuncan P. N. Exon Smith }; 40364a3005SDuncan P. N. Exon Smith struct Entry { 4111e0bcf8SDavid Blaikie const MCSymbol *Begin; 4211e0bcf8SDavid Blaikie const MCSymbol *End; 43364a3005SDuncan P. N. Exon Smith size_t ByteOffset; 44364a3005SDuncan P. N. Exon Smith size_t CommentOffset; 45364a3005SDuncan P. N. Exon Smith }; 46364a3005SDuncan P. N. Exon Smith 47364a3005SDuncan P. N. Exon Smith private: 48364a3005SDuncan P. N. Exon Smith SmallVector<List, 4> Lists; 49364a3005SDuncan P. N. Exon Smith SmallVector<Entry, 32> Entries; 50364a3005SDuncan P. N. Exon Smith SmallString<256> DWARFBytes; 51d46ac44eSDavid Stenberg std::vector<std::string> Comments; 522941cda5SDavid Blaikie MCSymbol *Sym; 53364a3005SDuncan P. N. Exon Smith 545f8f34e4SAdrian Prantl /// Only verbose textual output needs comments. This will be set to 55a05c0828SPete Cooper /// true for that case, and false otherwise. 56a05c0828SPete Cooper bool GenerateComments; 57a05c0828SPete Cooper 58364a3005SDuncan P. N. Exon Smith public: DebugLocStream(bool GenerateComments)59a05c0828SPete Cooper DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { } getNumLists()60364a3005SDuncan P. N. Exon Smith size_t getNumLists() const { return Lists.size(); } getList(size_t LI)61364a3005SDuncan P. N. Exon Smith const List &getList(size_t LI) const { return Lists[LI]; } getLists()62364a3005SDuncan P. N. Exon Smith ArrayRef<List> getLists() const { return Lists; } getSym()632941cda5SDavid Blaikie MCSymbol *getSym() const { 642941cda5SDavid Blaikie return Sym; 652941cda5SDavid Blaikie } setSym(MCSymbol * Sym)662941cda5SDavid Blaikie void setSym(MCSymbol *Sym) { 672941cda5SDavid Blaikie this->Sym = Sym; 682941cda5SDavid Blaikie } 69364a3005SDuncan P. N. Exon Smith 703a73d9e0SDuncan P. N. Exon Smith class ListBuilder; 713a73d9e0SDuncan P. N. Exon Smith class EntryBuilder; 723a73d9e0SDuncan P. N. Exon Smith 733a73d9e0SDuncan P. N. Exon Smith private: 745f8f34e4SAdrian Prantl /// Start a new .debug_loc entry list. 75364a3005SDuncan P. N. Exon Smith /// 76364a3005SDuncan P. N. Exon Smith /// Start a new .debug_loc entry list. Return the new list's index so it can 77364a3005SDuncan P. N. Exon Smith /// be retrieved later via \a getList(). 78364a3005SDuncan P. N. Exon Smith /// 79364a3005SDuncan P. N. Exon Smith /// Until the next call, \a startEntry() will add entries to this list. startList(DwarfCompileUnit * CU)803a73d9e0SDuncan P. N. Exon Smith size_t startList(DwarfCompileUnit *CU) { 81364a3005SDuncan P. N. Exon Smith size_t LI = Lists.size(); 823a73d9e0SDuncan P. N. Exon Smith Lists.emplace_back(CU, Entries.size()); 83364a3005SDuncan P. N. Exon Smith return LI; 84364a3005SDuncan P. N. Exon Smith } 85364a3005SDuncan P. N. Exon Smith 863a73d9e0SDuncan P. N. Exon Smith /// Finalize a .debug_loc entry list. 873a73d9e0SDuncan P. N. Exon Smith /// 883a73d9e0SDuncan P. N. Exon Smith /// If there are no entries in this list, delete it outright. Otherwise, 893a73d9e0SDuncan P. N. Exon Smith /// create a label with \a Asm. 903a73d9e0SDuncan P. N. Exon Smith /// 913a73d9e0SDuncan P. N. Exon Smith /// \return false iff the list is deleted. 923a73d9e0SDuncan P. N. Exon Smith bool finalizeList(AsmPrinter &Asm); 933a73d9e0SDuncan P. N. Exon Smith 945f8f34e4SAdrian Prantl /// Start a new .debug_loc entry. 95364a3005SDuncan P. N. Exon Smith /// 96364a3005SDuncan P. N. Exon Smith /// Until the next call, bytes added to the stream will be added to this 97364a3005SDuncan P. N. Exon Smith /// entry. startEntry(const MCSymbol * BeginSym,const MCSymbol * EndSym)98364a3005SDuncan P. N. Exon Smith void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) { 9911e0bcf8SDavid Blaikie Entries.push_back({BeginSym, EndSym, DWARFBytes.size(), Comments.size()}); 100364a3005SDuncan P. N. Exon Smith } 101364a3005SDuncan P. N. Exon Smith 1023a73d9e0SDuncan P. N. Exon Smith /// Finalize a .debug_loc entry, deleting if it's empty. 1033a73d9e0SDuncan P. N. Exon Smith void finalizeEntry(); 1043a73d9e0SDuncan P. N. Exon Smith 1053a73d9e0SDuncan P. N. Exon Smith public: getStreamer()106364a3005SDuncan P. N. Exon Smith BufferByteStreamer getStreamer() { 107a05c0828SPete Cooper return BufferByteStreamer(DWARFBytes, Comments, GenerateComments); 108364a3005SDuncan P. N. Exon Smith } 109364a3005SDuncan P. N. Exon Smith getEntries(const List & L)110364a3005SDuncan P. N. Exon Smith ArrayRef<Entry> getEntries(const List &L) const { 111364a3005SDuncan P. N. Exon Smith size_t LI = getIndex(L); 112364a3005SDuncan P. N. Exon Smith return makeArrayRef(Entries) 113364a3005SDuncan P. N. Exon Smith .slice(Lists[LI].EntryOffset, getNumEntries(LI)); 114364a3005SDuncan P. N. Exon Smith } 115364a3005SDuncan P. N. Exon Smith getBytes(const Entry & E)116364a3005SDuncan P. N. Exon Smith ArrayRef<char> getBytes(const Entry &E) const { 117364a3005SDuncan P. N. Exon Smith size_t EI = getIndex(E); 118364a3005SDuncan P. N. Exon Smith return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end()) 119364a3005SDuncan P. N. Exon Smith .slice(Entries[EI].ByteOffset, getNumBytes(EI)); 120364a3005SDuncan P. N. Exon Smith } getComments(const Entry & E)121364a3005SDuncan P. N. Exon Smith ArrayRef<std::string> getComments(const Entry &E) const { 122364a3005SDuncan P. N. Exon Smith size_t EI = getIndex(E); 123364a3005SDuncan P. N. Exon Smith return makeArrayRef(Comments) 124364a3005SDuncan P. N. Exon Smith .slice(Entries[EI].CommentOffset, getNumComments(EI)); 125364a3005SDuncan P. N. Exon Smith } 126364a3005SDuncan P. N. Exon Smith 127364a3005SDuncan P. N. Exon Smith private: getIndex(const List & L)128364a3005SDuncan P. N. Exon Smith size_t getIndex(const List &L) const { 129364a3005SDuncan P. N. Exon Smith assert(&Lists.front() <= &L && &L <= &Lists.back() && 130364a3005SDuncan P. N. Exon Smith "Expected valid list"); 131364a3005SDuncan P. N. Exon Smith return &L - &Lists.front(); 132364a3005SDuncan P. N. Exon Smith } getIndex(const Entry & E)133364a3005SDuncan P. N. Exon Smith size_t getIndex(const Entry &E) const { 134364a3005SDuncan P. N. Exon Smith assert(&Entries.front() <= &E && &E <= &Entries.back() && 135364a3005SDuncan P. N. Exon Smith "Expected valid entry"); 136364a3005SDuncan P. N. Exon Smith return &E - &Entries.front(); 137364a3005SDuncan P. N. Exon Smith } getNumEntries(size_t LI)138364a3005SDuncan P. N. Exon Smith size_t getNumEntries(size_t LI) const { 139364a3005SDuncan P. N. Exon Smith if (LI + 1 == Lists.size()) 140364a3005SDuncan P. N. Exon Smith return Entries.size() - Lists[LI].EntryOffset; 141364a3005SDuncan P. N. Exon Smith return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset; 142364a3005SDuncan P. N. Exon Smith } getNumBytes(size_t EI)143364a3005SDuncan P. N. Exon Smith size_t getNumBytes(size_t EI) const { 144364a3005SDuncan P. N. Exon Smith if (EI + 1 == Entries.size()) 145364a3005SDuncan P. N. Exon Smith return DWARFBytes.size() - Entries[EI].ByteOffset; 146364a3005SDuncan P. N. Exon Smith return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset; 147364a3005SDuncan P. N. Exon Smith } getNumComments(size_t EI)148364a3005SDuncan P. N. Exon Smith size_t getNumComments(size_t EI) const { 149364a3005SDuncan P. N. Exon Smith if (EI + 1 == Entries.size()) 150364a3005SDuncan P. N. Exon Smith return Comments.size() - Entries[EI].CommentOffset; 151364a3005SDuncan P. N. Exon Smith return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset; 152364a3005SDuncan P. N. Exon Smith } 153364a3005SDuncan P. N. Exon Smith }; 1543a73d9e0SDuncan P. N. Exon Smith 1553a73d9e0SDuncan P. N. Exon Smith /// Builder for DebugLocStream lists. 1563a73d9e0SDuncan P. N. Exon Smith class DebugLocStream::ListBuilder { 1573a73d9e0SDuncan P. N. Exon Smith DebugLocStream &Locs; 1583a73d9e0SDuncan P. N. Exon Smith AsmPrinter &Asm; 1593a73d9e0SDuncan P. N. Exon Smith DbgVariable &V; 1603a73d9e0SDuncan P. N. Exon Smith const MachineInstr &MI; 1613a73d9e0SDuncan P. N. Exon Smith size_t ListIndex; 162*dabd2622SEvgenii Stepanov Optional<uint8_t> TagOffset; 1633a73d9e0SDuncan P. N. Exon Smith 1643a73d9e0SDuncan P. N. Exon Smith public: ListBuilder(DebugLocStream & Locs,DwarfCompileUnit & CU,AsmPrinter & Asm,DbgVariable & V,const MachineInstr & MI)1653a73d9e0SDuncan P. N. Exon Smith ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, 1663a73d9e0SDuncan P. N. Exon Smith DbgVariable &V, const MachineInstr &MI) 167*dabd2622SEvgenii Stepanov : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)), 168*dabd2622SEvgenii Stepanov TagOffset(None) {} 169*dabd2622SEvgenii Stepanov setTagOffset(uint8_t TO)170*dabd2622SEvgenii Stepanov void setTagOffset(uint8_t TO) { 171*dabd2622SEvgenii Stepanov TagOffset = TO; 172*dabd2622SEvgenii Stepanov } 1733a73d9e0SDuncan P. N. Exon Smith 1743a73d9e0SDuncan P. N. Exon Smith /// Finalize the list. 1753a73d9e0SDuncan P. N. Exon Smith /// 1763a73d9e0SDuncan P. N. Exon Smith /// If the list is empty, delete it. Otherwise, finalize it by creating a 1773a73d9e0SDuncan P. N. Exon Smith /// temp symbol in \a Asm and setting up the \a DbgVariable. 1783a73d9e0SDuncan P. N. Exon Smith ~ListBuilder(); 1793a73d9e0SDuncan P. N. Exon Smith getLocs()1803a73d9e0SDuncan P. N. Exon Smith DebugLocStream &getLocs() { return Locs; } 1813a73d9e0SDuncan P. N. Exon Smith }; 1823a73d9e0SDuncan P. N. Exon Smith 1833a73d9e0SDuncan P. N. Exon Smith /// Builder for DebugLocStream entries. 1843a73d9e0SDuncan P. N. Exon Smith class DebugLocStream::EntryBuilder { 1853a73d9e0SDuncan P. N. Exon Smith DebugLocStream &Locs; 1863a73d9e0SDuncan P. N. Exon Smith 1873a73d9e0SDuncan P. N. Exon Smith public: EntryBuilder(ListBuilder & List,const MCSymbol * Begin,const MCSymbol * End)1883a73d9e0SDuncan P. N. Exon Smith EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End) 1893a73d9e0SDuncan P. N. Exon Smith : Locs(List.getLocs()) { 1903a73d9e0SDuncan P. N. Exon Smith Locs.startEntry(Begin, End); 1913a73d9e0SDuncan P. N. Exon Smith } 1923a73d9e0SDuncan P. N. Exon Smith 1933a73d9e0SDuncan P. N. Exon Smith /// Finalize the entry, deleting it if it's empty. ~EntryBuilder()1943a73d9e0SDuncan P. N. Exon Smith ~EntryBuilder() { Locs.finalizeEntry(); } 1953a73d9e0SDuncan P. N. Exon Smith getStreamer()1963a73d9e0SDuncan P. N. Exon Smith BufferByteStreamer getStreamer() { return Locs.getStreamer(); } 1973a73d9e0SDuncan P. N. Exon Smith }; 1983a73d9e0SDuncan P. N. Exon Smith 19970bc5f13SAlexander Kornienko } // namespace llvm 2003a73d9e0SDuncan P. N. Exon Smith 201364a3005SDuncan P. N. Exon Smith #endif 202