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