DebugLocStream.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 makeArrayRef(Entries)
  98. .slice(Lists[LI].EntryOffset, getNumEntries(LI));
  99. }
  100. ArrayRef<char> getBytes(const Entry &E) const {
  101. size_t EI = getIndex(E);
  102. return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end())
  103. .slice(Entries[EI].ByteOffset, getNumBytes(EI));
  104. }
  105. ArrayRef<std::string> getComments(const Entry &E) const {
  106. size_t EI = getIndex(E);
  107. return makeArrayRef(Comments)
  108. .slice(Entries[EI].CommentOffset, getNumComments(EI));
  109. }
  110. private:
  111. size_t getIndex(const List &L) const {
  112. assert(&Lists.front() <= &L && &L <= &Lists.back() &&
  113. "Expected valid list");
  114. return &L - &Lists.front();
  115. }
  116. size_t getIndex(const Entry &E) const {
  117. assert(&Entries.front() <= &E && &E <= &Entries.back() &&
  118. "Expected valid entry");
  119. return &E - &Entries.front();
  120. }
  121. size_t getNumEntries(size_t LI) const {
  122. if (LI + 1 == Lists.size())
  123. return Entries.size() - Lists[LI].EntryOffset;
  124. return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset;
  125. }
  126. size_t getNumBytes(size_t EI) const {
  127. if (EI + 1 == Entries.size())
  128. return DWARFBytes.size() - Entries[EI].ByteOffset;
  129. return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset;
  130. }
  131. size_t getNumComments(size_t EI) const {
  132. if (EI + 1 == Entries.size())
  133. return Comments.size() - Entries[EI].CommentOffset;
  134. return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;
  135. }
  136. };
  137. /// Builder for DebugLocStream lists.
  138. class DebugLocStream::ListBuilder {
  139. DebugLocStream &Locs;
  140. AsmPrinter &Asm;
  141. DbgVariable &V;
  142. const MachineInstr &MI;
  143. size_t ListIndex;
  144. Optional<uint8_t> TagOffset;
  145. public:
  146. ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,
  147. DbgVariable &V, const MachineInstr &MI)
  148. : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)),
  149. TagOffset(None) {}
  150. void setTagOffset(uint8_t TO) {
  151. TagOffset = TO;
  152. }
  153. /// Finalize the list.
  154. ///
  155. /// If the list is empty, delete it. Otherwise, finalize it by creating a
  156. /// temp symbol in \a Asm and setting up the \a DbgVariable.
  157. ~ListBuilder();
  158. DebugLocStream &getLocs() { return Locs; }
  159. };
  160. /// Builder for DebugLocStream entries.
  161. class DebugLocStream::EntryBuilder {
  162. DebugLocStream &Locs;
  163. public:
  164. EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)
  165. : Locs(List.getLocs()) {
  166. Locs.startEntry(Begin, End);
  167. }
  168. /// Finalize the entry, deleting it if it's empty.
  169. ~EntryBuilder() { Locs.finalizeEntry(); }
  170. BufferByteStreamer getStreamer() { return Locs.getStreamer(); }
  171. };
  172. } // namespace llvm
  173. #endif