DebugLocStream.h 5.8 KB

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