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