1283625Sdim//===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- C++ -*-===// 2283625Sdim// 3283625Sdim// The LLVM Compiler Infrastructure 4283625Sdim// 5283625Sdim// This file is distributed under the University of Illinois Open Source 6283625Sdim// License. See LICENSE.TXT for details. 7283625Sdim// 8283625Sdim//===----------------------------------------------------------------------===// 9283625Sdim 10283625Sdim#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H 11283625Sdim#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H 12283625Sdim 13283625Sdim#include "llvm/ADT/ArrayRef.h" 14283625Sdim#include "llvm/ADT/SmallVector.h" 15283625Sdim#include "ByteStreamer.h" 16283625Sdim 17283625Sdimnamespace llvm { 18285181Sdim 19285181Sdimclass AsmPrinter; 20285181Sdimclass DbgVariable; 21283625Sdimclass DwarfCompileUnit; 22285181Sdimclass MachineInstr; 23283625Sdimclass MCSymbol; 24283625Sdim 25283625Sdim/// \brief Byte stream of .debug_loc entries. 26283625Sdim/// 27283625Sdim/// Stores a unified stream of .debug_loc entries. There's \a List for each 28283625Sdim/// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry. 29283625Sdim/// 30283625Sdim/// FIXME: Do we need all these temp symbols? 31283625Sdim/// FIXME: Why not output directly to the output stream? 32283625Sdimclass DebugLocStream { 33283625Sdimpublic: 34283625Sdim struct List { 35283625Sdim DwarfCompileUnit *CU; 36285181Sdim MCSymbol *Label = nullptr; 37283625Sdim size_t EntryOffset; 38285181Sdim List(DwarfCompileUnit *CU, size_t EntryOffset) 39285181Sdim : CU(CU), EntryOffset(EntryOffset) {} 40283625Sdim }; 41283625Sdim struct Entry { 42283625Sdim const MCSymbol *BeginSym; 43283625Sdim const MCSymbol *EndSym; 44283625Sdim size_t ByteOffset; 45283625Sdim size_t CommentOffset; 46283625Sdim Entry(const MCSymbol *BeginSym, const MCSymbol *EndSym, size_t ByteOffset, 47283625Sdim size_t CommentOffset) 48283625Sdim : BeginSym(BeginSym), EndSym(EndSym), ByteOffset(ByteOffset), 49283625Sdim CommentOffset(CommentOffset) {} 50283625Sdim }; 51283625Sdim 52283625Sdimprivate: 53283625Sdim SmallVector<List, 4> Lists; 54283625Sdim SmallVector<Entry, 32> Entries; 55283625Sdim SmallString<256> DWARFBytes; 56283625Sdim SmallVector<std::string, 32> Comments; 57283625Sdim 58283625Sdim /// \brief Only verbose textual output needs comments. This will be set to 59283625Sdim /// true for that case, and false otherwise. 60283625Sdim bool GenerateComments; 61283625Sdim 62283625Sdimpublic: 63283625Sdim DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { } 64283625Sdim size_t getNumLists() const { return Lists.size(); } 65283625Sdim const List &getList(size_t LI) const { return Lists[LI]; } 66283625Sdim ArrayRef<List> getLists() const { return Lists; } 67283625Sdim 68285181Sdim class ListBuilder; 69285181Sdim class EntryBuilder; 70285181Sdim 71285181Sdimprivate: 72283625Sdim /// \brief Start a new .debug_loc entry list. 73283625Sdim /// 74283625Sdim /// Start a new .debug_loc entry list. Return the new list's index so it can 75283625Sdim /// be retrieved later via \a getList(). 76283625Sdim /// 77283625Sdim /// Until the next call, \a startEntry() will add entries to this list. 78285181Sdim size_t startList(DwarfCompileUnit *CU) { 79283625Sdim size_t LI = Lists.size(); 80285181Sdim Lists.emplace_back(CU, Entries.size()); 81283625Sdim return LI; 82283625Sdim } 83283625Sdim 84285181Sdim /// Finalize a .debug_loc entry list. 85285181Sdim /// 86285181Sdim /// If there are no entries in this list, delete it outright. Otherwise, 87285181Sdim /// create a label with \a Asm. 88285181Sdim /// 89285181Sdim /// \return false iff the list is deleted. 90285181Sdim bool finalizeList(AsmPrinter &Asm); 91285181Sdim 92283625Sdim /// \brief Start a new .debug_loc entry. 93283625Sdim /// 94283625Sdim /// Until the next call, bytes added to the stream will be added to this 95283625Sdim /// entry. 96283625Sdim void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) { 97283625Sdim Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size()); 98283625Sdim } 99283625Sdim 100285181Sdim /// Finalize a .debug_loc entry, deleting if it's empty. 101285181Sdim void finalizeEntry(); 102285181Sdim 103285181Sdimpublic: 104283625Sdim BufferByteStreamer getStreamer() { 105283625Sdim return BufferByteStreamer(DWARFBytes, Comments, GenerateComments); 106283625Sdim } 107283625Sdim 108283625Sdim ArrayRef<Entry> getEntries(const List &L) const { 109283625Sdim size_t LI = getIndex(L); 110283625Sdim return makeArrayRef(Entries) 111283625Sdim .slice(Lists[LI].EntryOffset, getNumEntries(LI)); 112283625Sdim } 113283625Sdim 114283625Sdim ArrayRef<char> getBytes(const Entry &E) const { 115283625Sdim size_t EI = getIndex(E); 116283625Sdim return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end()) 117283625Sdim .slice(Entries[EI].ByteOffset, getNumBytes(EI)); 118283625Sdim } 119283625Sdim ArrayRef<std::string> getComments(const Entry &E) const { 120283625Sdim size_t EI = getIndex(E); 121283625Sdim return makeArrayRef(Comments) 122283625Sdim .slice(Entries[EI].CommentOffset, getNumComments(EI)); 123283625Sdim } 124283625Sdim 125283625Sdimprivate: 126283625Sdim size_t getIndex(const List &L) const { 127283625Sdim assert(&Lists.front() <= &L && &L <= &Lists.back() && 128283625Sdim "Expected valid list"); 129283625Sdim return &L - &Lists.front(); 130283625Sdim } 131283625Sdim size_t getIndex(const Entry &E) const { 132283625Sdim assert(&Entries.front() <= &E && &E <= &Entries.back() && 133283625Sdim "Expected valid entry"); 134283625Sdim return &E - &Entries.front(); 135283625Sdim } 136283625Sdim size_t getNumEntries(size_t LI) const { 137283625Sdim if (LI + 1 == Lists.size()) 138283625Sdim return Entries.size() - Lists[LI].EntryOffset; 139283625Sdim return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset; 140283625Sdim } 141283625Sdim size_t getNumBytes(size_t EI) const { 142283625Sdim if (EI + 1 == Entries.size()) 143283625Sdim return DWARFBytes.size() - Entries[EI].ByteOffset; 144283625Sdim return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset; 145283625Sdim } 146283625Sdim size_t getNumComments(size_t EI) const { 147283625Sdim if (EI + 1 == Entries.size()) 148283625Sdim return Comments.size() - Entries[EI].CommentOffset; 149283625Sdim return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset; 150283625Sdim } 151283625Sdim}; 152285181Sdim 153285181Sdim/// Builder for DebugLocStream lists. 154285181Sdimclass DebugLocStream::ListBuilder { 155285181Sdim DebugLocStream &Locs; 156285181Sdim AsmPrinter &Asm; 157285181Sdim DbgVariable &V; 158285181Sdim const MachineInstr &MI; 159285181Sdim size_t ListIndex; 160285181Sdim 161285181Sdimpublic: 162285181Sdim ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, 163285181Sdim DbgVariable &V, const MachineInstr &MI) 164285181Sdim : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {} 165285181Sdim 166285181Sdim /// Finalize the list. 167285181Sdim /// 168285181Sdim /// If the list is empty, delete it. Otherwise, finalize it by creating a 169285181Sdim /// temp symbol in \a Asm and setting up the \a DbgVariable. 170285181Sdim ~ListBuilder(); 171285181Sdim 172285181Sdim DebugLocStream &getLocs() { return Locs; } 173285181Sdim}; 174285181Sdim 175285181Sdim/// Builder for DebugLocStream entries. 176285181Sdimclass DebugLocStream::EntryBuilder { 177285181Sdim DebugLocStream &Locs; 178285181Sdim 179285181Sdimpublic: 180285181Sdim EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End) 181285181Sdim : Locs(List.getLocs()) { 182285181Sdim Locs.startEntry(Begin, End); 183285181Sdim } 184285181Sdim 185285181Sdim /// Finalize the entry, deleting it if it's empty. 186285181Sdim ~EntryBuilder() { Locs.finalizeEntry(); } 187285181Sdim 188285181Sdim BufferByteStreamer getStreamer() { return Locs.getStreamer(); } 189285181Sdim}; 190285181Sdim 191284734Sdim} // namespace llvm 192285181Sdim 193283625Sdim#endif 194