DebugLocStream.h 5.8 KB

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