xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H
100b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "ByteStreamer.h"
130b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric class AsmPrinter;
190b57cec5SDimitry Andric class DbgVariable;
200b57cec5SDimitry Andric class DwarfCompileUnit;
210b57cec5SDimitry Andric class MCSymbol;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric /// Byte stream of .debug_loc entries.
240b57cec5SDimitry Andric ///
250b57cec5SDimitry Andric /// Stores a unified stream of .debug_loc entries.  There's \a List for each
260b57cec5SDimitry Andric /// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry.
270b57cec5SDimitry Andric ///
280b57cec5SDimitry Andric /// FIXME: Do we need all these temp symbols?
290b57cec5SDimitry Andric /// FIXME: Why not output directly to the output stream?
300b57cec5SDimitry Andric class DebugLocStream {
310b57cec5SDimitry Andric public:
320b57cec5SDimitry Andric   struct List {
330b57cec5SDimitry Andric     DwarfCompileUnit *CU;
340b57cec5SDimitry Andric     MCSymbol *Label = nullptr;
350b57cec5SDimitry Andric     size_t EntryOffset;
ListList360b57cec5SDimitry Andric     List(DwarfCompileUnit *CU, size_t EntryOffset)
370b57cec5SDimitry Andric         : CU(CU), EntryOffset(EntryOffset) {}
380b57cec5SDimitry Andric   };
390b57cec5SDimitry Andric   struct Entry {
408bcb0991SDimitry Andric     const MCSymbol *Begin;
418bcb0991SDimitry Andric     const MCSymbol *End;
420b57cec5SDimitry Andric     size_t ByteOffset;
430b57cec5SDimitry Andric     size_t CommentOffset;
440b57cec5SDimitry Andric   };
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric private:
470b57cec5SDimitry Andric   SmallVector<List, 4> Lists;
480b57cec5SDimitry Andric   SmallVector<Entry, 32> Entries;
490b57cec5SDimitry Andric   SmallString<256> DWARFBytes;
508bcb0991SDimitry Andric   std::vector<std::string> Comments;
5106c3fb27SDimitry Andric   MCSymbol *Sym = nullptr;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// Only verbose textual output needs comments.  This will be set to
540b57cec5SDimitry Andric   /// true for that case, and false otherwise.
550b57cec5SDimitry Andric   bool GenerateComments;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric public:
DebugLocStream(bool GenerateComments)580b57cec5SDimitry Andric   DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { }
getNumLists()590b57cec5SDimitry Andric   size_t getNumLists() const { return Lists.size(); }
getList(size_t LI)600b57cec5SDimitry Andric   const List &getList(size_t LI) const { return Lists[LI]; }
getLists()610b57cec5SDimitry Andric   ArrayRef<List> getLists() const { return Lists; }
getSym()628bcb0991SDimitry Andric   MCSymbol *getSym() const {
638bcb0991SDimitry Andric     return Sym;
648bcb0991SDimitry Andric   }
setSym(MCSymbol * Sym)658bcb0991SDimitry Andric   void setSym(MCSymbol *Sym) {
668bcb0991SDimitry Andric     this->Sym = Sym;
678bcb0991SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   class ListBuilder;
700b57cec5SDimitry Andric   class EntryBuilder;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric private:
730b57cec5SDimitry Andric   /// Start a new .debug_loc entry list.
740b57cec5SDimitry Andric   ///
750b57cec5SDimitry Andric   /// Start a new .debug_loc entry list.  Return the new list's index so it can
760b57cec5SDimitry Andric   /// be retrieved later via \a getList().
770b57cec5SDimitry Andric   ///
780b57cec5SDimitry Andric   /// Until the next call, \a startEntry() will add entries to this list.
startList(DwarfCompileUnit * CU)790b57cec5SDimitry Andric   size_t startList(DwarfCompileUnit *CU) {
800b57cec5SDimitry Andric     size_t LI = Lists.size();
810b57cec5SDimitry Andric     Lists.emplace_back(CU, Entries.size());
820b57cec5SDimitry Andric     return LI;
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Finalize a .debug_loc entry list.
860b57cec5SDimitry Andric   ///
870b57cec5SDimitry Andric   /// If there are no entries in this list, delete it outright.  Otherwise,
880b57cec5SDimitry Andric   /// create a label with \a Asm.
890b57cec5SDimitry Andric   ///
900b57cec5SDimitry Andric   /// \return false iff the list is deleted.
910b57cec5SDimitry Andric   bool finalizeList(AsmPrinter &Asm);
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   /// Start a new .debug_loc entry.
940b57cec5SDimitry Andric   ///
950b57cec5SDimitry Andric   /// Until the next call, bytes added to the stream will be added to this
960b57cec5SDimitry Andric   /// entry.
startEntry(const MCSymbol * BeginSym,const MCSymbol * EndSym)970b57cec5SDimitry Andric   void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) {
988bcb0991SDimitry Andric     Entries.push_back({BeginSym, EndSym, DWARFBytes.size(), Comments.size()});
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   /// Finalize a .debug_loc entry, deleting if it's empty.
1020b57cec5SDimitry Andric   void finalizeEntry();
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric public:
getStreamer()1050b57cec5SDimitry Andric   BufferByteStreamer getStreamer() {
1060b57cec5SDimitry Andric     return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
getEntries(const List & L)1090b57cec5SDimitry Andric   ArrayRef<Entry> getEntries(const List &L) const {
1100b57cec5SDimitry Andric     size_t LI = getIndex(L);
111bdd1243dSDimitry Andric     return ArrayRef(Entries).slice(Lists[LI].EntryOffset, getNumEntries(LI));
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
getBytes(const Entry & E)1140b57cec5SDimitry Andric   ArrayRef<char> getBytes(const Entry &E) const {
1150b57cec5SDimitry Andric     size_t EI = getIndex(E);
116bdd1243dSDimitry Andric     return ArrayRef(DWARFBytes.begin(), DWARFBytes.end())
1170b57cec5SDimitry Andric         .slice(Entries[EI].ByteOffset, getNumBytes(EI));
1180b57cec5SDimitry Andric   }
getComments(const Entry & E)1190b57cec5SDimitry Andric   ArrayRef<std::string> getComments(const Entry &E) const {
1200b57cec5SDimitry Andric     size_t EI = getIndex(E);
121bdd1243dSDimitry Andric     return ArrayRef(Comments).slice(Entries[EI].CommentOffset,
122bdd1243dSDimitry Andric                                     getNumComments(EI));
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric private:
getIndex(const List & L)1260b57cec5SDimitry Andric   size_t getIndex(const List &L) const {
1270b57cec5SDimitry Andric     assert(&Lists.front() <= &L && &L <= &Lists.back() &&
1280b57cec5SDimitry Andric            "Expected valid list");
1290b57cec5SDimitry Andric     return &L - &Lists.front();
1300b57cec5SDimitry Andric   }
getIndex(const Entry & E)1310b57cec5SDimitry Andric   size_t getIndex(const Entry &E) const {
1320b57cec5SDimitry Andric     assert(&Entries.front() <= &E && &E <= &Entries.back() &&
1330b57cec5SDimitry Andric            "Expected valid entry");
1340b57cec5SDimitry Andric     return &E - &Entries.front();
1350b57cec5SDimitry Andric   }
getNumEntries(size_t LI)1360b57cec5SDimitry Andric   size_t getNumEntries(size_t LI) const {
1370b57cec5SDimitry Andric     if (LI + 1 == Lists.size())
1380b57cec5SDimitry Andric       return Entries.size() - Lists[LI].EntryOffset;
1390b57cec5SDimitry Andric     return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset;
1400b57cec5SDimitry Andric   }
getNumBytes(size_t EI)1410b57cec5SDimitry Andric   size_t getNumBytes(size_t EI) const {
1420b57cec5SDimitry Andric     if (EI + 1 == Entries.size())
1430b57cec5SDimitry Andric       return DWARFBytes.size() - Entries[EI].ByteOffset;
1440b57cec5SDimitry Andric     return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset;
1450b57cec5SDimitry Andric   }
getNumComments(size_t EI)1460b57cec5SDimitry Andric   size_t getNumComments(size_t EI) const {
1470b57cec5SDimitry Andric     if (EI + 1 == Entries.size())
1480b57cec5SDimitry Andric       return Comments.size() - Entries[EI].CommentOffset;
1490b57cec5SDimitry Andric     return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric };
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric /// Builder for DebugLocStream lists.
1540b57cec5SDimitry Andric class DebugLocStream::ListBuilder {
1550b57cec5SDimitry Andric   DebugLocStream &Locs;
1560b57cec5SDimitry Andric   AsmPrinter &Asm;
1570b57cec5SDimitry Andric   DbgVariable &V;
1580b57cec5SDimitry Andric   size_t ListIndex;
159bdd1243dSDimitry Andric   std::optional<uint8_t> TagOffset;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric public:
ListBuilder(DebugLocStream & Locs,DwarfCompileUnit & CU,AsmPrinter & Asm,DbgVariable & V)1620b57cec5SDimitry Andric   ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,
163*5f757f3fSDimitry Andric               DbgVariable &V)
164*5f757f3fSDimitry Andric       : Locs(Locs), Asm(Asm), V(V), ListIndex(Locs.startList(&CU)),
165bdd1243dSDimitry Andric         TagOffset(std::nullopt) {}
166480093f4SDimitry Andric 
setTagOffset(uint8_t TO)167480093f4SDimitry Andric   void setTagOffset(uint8_t TO) {
168480093f4SDimitry Andric     TagOffset = TO;
169480093f4SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   /// Finalize the list.
1720b57cec5SDimitry Andric   ///
1730b57cec5SDimitry Andric   /// If the list is empty, delete it.  Otherwise, finalize it by creating a
1740b57cec5SDimitry Andric   /// temp symbol in \a Asm and setting up the \a DbgVariable.
1750b57cec5SDimitry Andric   ~ListBuilder();
1760b57cec5SDimitry Andric 
getLocs()1770b57cec5SDimitry Andric   DebugLocStream &getLocs() { return Locs; }
1780b57cec5SDimitry Andric };
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric /// Builder for DebugLocStream entries.
1810b57cec5SDimitry Andric class DebugLocStream::EntryBuilder {
1820b57cec5SDimitry Andric   DebugLocStream &Locs;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric public:
EntryBuilder(ListBuilder & List,const MCSymbol * Begin,const MCSymbol * End)1850b57cec5SDimitry Andric   EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)
1860b57cec5SDimitry Andric       : Locs(List.getLocs()) {
1870b57cec5SDimitry Andric     Locs.startEntry(Begin, End);
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// Finalize the entry, deleting it if it's empty.
~EntryBuilder()1910b57cec5SDimitry Andric   ~EntryBuilder() { Locs.finalizeEntry(); }
1920b57cec5SDimitry Andric 
getStreamer()1930b57cec5SDimitry Andric   BufferByteStreamer getStreamer() { return Locs.getStreamer(); }
1940b57cec5SDimitry Andric };
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric } // namespace llvm
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric #endif
199