123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- //===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H
- #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H
- #include "ByteStreamer.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/SmallVector.h"
- namespace llvm {
- class AsmPrinter;
- class DbgVariable;
- class DwarfCompileUnit;
- class MachineInstr;
- class MCSymbol;
- /// Byte stream of .debug_loc entries.
- ///
- /// Stores a unified stream of .debug_loc entries. There's \a List for each
- /// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry.
- ///
- /// FIXME: Do we need all these temp symbols?
- /// FIXME: Why not output directly to the output stream?
- class DebugLocStream {
- public:
- struct List {
- DwarfCompileUnit *CU;
- MCSymbol *Label = nullptr;
- size_t EntryOffset;
- List(DwarfCompileUnit *CU, size_t EntryOffset)
- : CU(CU), EntryOffset(EntryOffset) {}
- };
- struct Entry {
- const MCSymbol *Begin;
- const MCSymbol *End;
- size_t ByteOffset;
- size_t CommentOffset;
- };
- private:
- SmallVector<List, 4> Lists;
- SmallVector<Entry, 32> Entries;
- SmallString<256> DWARFBytes;
- std::vector<std::string> Comments;
- MCSymbol *Sym;
- /// Only verbose textual output needs comments. This will be set to
- /// true for that case, and false otherwise.
- bool GenerateComments;
- public:
- DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { }
- size_t getNumLists() const { return Lists.size(); }
- const List &getList(size_t LI) const { return Lists[LI]; }
- ArrayRef<List> getLists() const { return Lists; }
- MCSymbol *getSym() const {
- return Sym;
- }
- void setSym(MCSymbol *Sym) {
- this->Sym = Sym;
- }
- class ListBuilder;
- class EntryBuilder;
- private:
- /// Start a new .debug_loc entry list.
- ///
- /// Start a new .debug_loc entry list. Return the new list's index so it can
- /// be retrieved later via \a getList().
- ///
- /// Until the next call, \a startEntry() will add entries to this list.
- size_t startList(DwarfCompileUnit *CU) {
- size_t LI = Lists.size();
- Lists.emplace_back(CU, Entries.size());
- return LI;
- }
- /// Finalize a .debug_loc entry list.
- ///
- /// If there are no entries in this list, delete it outright. Otherwise,
- /// create a label with \a Asm.
- ///
- /// \return false iff the list is deleted.
- bool finalizeList(AsmPrinter &Asm);
- /// Start a new .debug_loc entry.
- ///
- /// Until the next call, bytes added to the stream will be added to this
- /// entry.
- void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) {
- Entries.push_back({BeginSym, EndSym, DWARFBytes.size(), Comments.size()});
- }
- /// Finalize a .debug_loc entry, deleting if it's empty.
- void finalizeEntry();
- public:
- BufferByteStreamer getStreamer() {
- return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);
- }
- ArrayRef<Entry> getEntries(const List &L) const {
- size_t LI = getIndex(L);
- return makeArrayRef(Entries)
- .slice(Lists[LI].EntryOffset, getNumEntries(LI));
- }
- ArrayRef<char> getBytes(const Entry &E) const {
- size_t EI = getIndex(E);
- return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end())
- .slice(Entries[EI].ByteOffset, getNumBytes(EI));
- }
- ArrayRef<std::string> getComments(const Entry &E) const {
- size_t EI = getIndex(E);
- return makeArrayRef(Comments)
- .slice(Entries[EI].CommentOffset, getNumComments(EI));
- }
- private:
- size_t getIndex(const List &L) const {
- assert(&Lists.front() <= &L && &L <= &Lists.back() &&
- "Expected valid list");
- return &L - &Lists.front();
- }
- size_t getIndex(const Entry &E) const {
- assert(&Entries.front() <= &E && &E <= &Entries.back() &&
- "Expected valid entry");
- return &E - &Entries.front();
- }
- size_t getNumEntries(size_t LI) const {
- if (LI + 1 == Lists.size())
- return Entries.size() - Lists[LI].EntryOffset;
- return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset;
- }
- size_t getNumBytes(size_t EI) const {
- if (EI + 1 == Entries.size())
- return DWARFBytes.size() - Entries[EI].ByteOffset;
- return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset;
- }
- size_t getNumComments(size_t EI) const {
- if (EI + 1 == Entries.size())
- return Comments.size() - Entries[EI].CommentOffset;
- return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;
- }
- };
- /// Builder for DebugLocStream lists.
- class DebugLocStream::ListBuilder {
- DebugLocStream &Locs;
- AsmPrinter &Asm;
- DbgVariable &V;
- const MachineInstr &MI;
- size_t ListIndex;
- Optional<uint8_t> TagOffset;
- public:
- ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,
- DbgVariable &V, const MachineInstr &MI)
- : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)),
- TagOffset(None) {}
- void setTagOffset(uint8_t TO) {
- TagOffset = TO;
- }
- /// Finalize the list.
- ///
- /// If the list is empty, delete it. Otherwise, finalize it by creating a
- /// temp symbol in \a Asm and setting up the \a DbgVariable.
- ~ListBuilder();
- DebugLocStream &getLocs() { return Locs; }
- };
- /// Builder for DebugLocStream entries.
- class DebugLocStream::EntryBuilder {
- DebugLocStream &Locs;
- public:
- EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)
- : Locs(List.getLocs()) {
- Locs.startEntry(Begin, End);
- }
- /// Finalize the entry, deleting it if it's empty.
- ~EntryBuilder() { Locs.finalizeEntry(); }
- BufferByteStreamer getStreamer() { return Locs.getStreamer(); }
- };
- } // namespace llvm
- #endif
|