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