DebugLocStream.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 *BeginSym;
  37. const MCSymbol *EndSym;
  38. size_t ByteOffset;
  39. size_t CommentOffset;
  40. Entry(const MCSymbol *BeginSym, const MCSymbol *EndSym, size_t ByteOffset,
  41. size_t CommentOffset)
  42. : BeginSym(BeginSym), EndSym(EndSym), ByteOffset(ByteOffset),
  43. CommentOffset(CommentOffset) {}
  44. };
  45. private:
  46. SmallVector<List, 4> Lists;
  47. SmallVector<Entry, 32> Entries;
  48. SmallString<256> DWARFBytes;
  49. SmallVector<std::string, 32> Comments;
  50. /// Only verbose textual output needs comments. This will be set to
  51. /// true for that case, and false otherwise.
  52. bool GenerateComments;
  53. public:
  54. DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { }
  55. size_t getNumLists() const { return Lists.size(); }
  56. const List &getList(size_t LI) const { return Lists[LI]; }
  57. ArrayRef<List> getLists() const { return Lists; }
  58. class ListBuilder;
  59. class EntryBuilder;
  60. private:
  61. /// Start a new .debug_loc entry list.
  62. ///
  63. /// Start a new .debug_loc entry list. Return the new list's index so it can
  64. /// be retrieved later via \a getList().
  65. ///
  66. /// Until the next call, \a startEntry() will add entries to this list.
  67. size_t startList(DwarfCompileUnit *CU) {
  68. size_t LI = Lists.size();
  69. Lists.emplace_back(CU, Entries.size());
  70. return LI;
  71. }
  72. /// Finalize a .debug_loc entry list.
  73. ///
  74. /// If there are no entries in this list, delete it outright. Otherwise,
  75. /// create a label with \a Asm.
  76. ///
  77. /// \return false iff the list is deleted.
  78. bool finalizeList(AsmPrinter &Asm);
  79. /// Start a new .debug_loc entry.
  80. ///
  81. /// Until the next call, bytes added to the stream will be added to this
  82. /// entry.
  83. void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) {
  84. Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size());
  85. }
  86. /// Finalize a .debug_loc entry, deleting if it's empty.
  87. void finalizeEntry();
  88. public:
  89. BufferByteStreamer getStreamer() {
  90. return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);
  91. }
  92. ArrayRef<Entry> getEntries(const List &L) const {
  93. size_t LI = getIndex(L);
  94. return makeArrayRef(Entries)
  95. .slice(Lists[LI].EntryOffset, getNumEntries(LI));
  96. }
  97. ArrayRef<char> getBytes(const Entry &E) const {
  98. size_t EI = getIndex(E);
  99. return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end())
  100. .slice(Entries[EI].ByteOffset, getNumBytes(EI));
  101. }
  102. ArrayRef<std::string> getComments(const Entry &E) const {
  103. size_t EI = getIndex(E);
  104. return makeArrayRef(Comments)
  105. .slice(Entries[EI].CommentOffset, getNumComments(EI));
  106. }
  107. private:
  108. size_t getIndex(const List &L) const {
  109. assert(&Lists.front() <= &L && &L <= &Lists.back() &&
  110. "Expected valid list");
  111. return &L - &Lists.front();
  112. }
  113. size_t getIndex(const Entry &E) const {
  114. assert(&Entries.front() <= &E && &E <= &Entries.back() &&
  115. "Expected valid entry");
  116. return &E - &Entries.front();
  117. }
  118. size_t getNumEntries(size_t LI) const {
  119. if (LI + 1 == Lists.size())
  120. return Entries.size() - Lists[LI].EntryOffset;
  121. return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset;
  122. }
  123. size_t getNumBytes(size_t EI) const {
  124. if (EI + 1 == Entries.size())
  125. return DWARFBytes.size() - Entries[EI].ByteOffset;
  126. return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset;
  127. }
  128. size_t getNumComments(size_t EI) const {
  129. if (EI + 1 == Entries.size())
  130. return Comments.size() - Entries[EI].CommentOffset;
  131. return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;
  132. }
  133. };
  134. /// Builder for DebugLocStream lists.
  135. class DebugLocStream::ListBuilder {
  136. DebugLocStream &Locs;
  137. AsmPrinter &Asm;
  138. DbgVariable &V;
  139. const MachineInstr &MI;
  140. size_t ListIndex;
  141. public:
  142. ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,
  143. DbgVariable &V, const MachineInstr &MI)
  144. : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {}
  145. /// Finalize the list.
  146. ///
  147. /// If the list is empty, delete it. Otherwise, finalize it by creating a
  148. /// temp symbol in \a Asm and setting up the \a DbgVariable.
  149. ~ListBuilder();
  150. DebugLocStream &getLocs() { return Locs; }
  151. };
  152. /// Builder for DebugLocStream entries.
  153. class DebugLocStream::EntryBuilder {
  154. DebugLocStream &Locs;
  155. public:
  156. EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)
  157. : Locs(List.getLocs()) {
  158. Locs.startEntry(Begin, End);
  159. }
  160. /// Finalize the entry, deleting it if it's empty.
  161. ~EntryBuilder() { Locs.finalizeEntry(); }
  162. BufferByteStreamer getStreamer() { return Locs.getStreamer(); }
  163. };
  164. } // namespace llvm
  165. #endif