Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h
35271 views
//===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H9#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H1011#include "ByteStreamer.h"12#include "llvm/ADT/ArrayRef.h"13#include "llvm/ADT/SmallVector.h"1415namespace llvm {1617class AsmPrinter;18class DbgVariable;19class DwarfCompileUnit;20class MCSymbol;2122/// Byte stream of .debug_loc entries.23///24/// Stores a unified stream of .debug_loc entries. There's \a List for each25/// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry.26///27/// FIXME: Do we need all these temp symbols?28/// FIXME: Why not output directly to the output stream?29class DebugLocStream {30public:31struct List {32DwarfCompileUnit *CU;33MCSymbol *Label = nullptr;34size_t EntryOffset;35List(DwarfCompileUnit *CU, size_t EntryOffset)36: CU(CU), EntryOffset(EntryOffset) {}37};38struct Entry {39const MCSymbol *Begin;40const MCSymbol *End;41size_t ByteOffset;42size_t CommentOffset;43};4445private:46SmallVector<List, 4> Lists;47SmallVector<Entry, 32> Entries;48SmallString<256> DWARFBytes;49std::vector<std::string> Comments;50MCSymbol *Sym = nullptr;5152/// Only verbose textual output needs comments. This will be set to53/// true for that case, and false otherwise.54bool GenerateComments;5556public:57DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { }58size_t getNumLists() const { return Lists.size(); }59const List &getList(size_t LI) const { return Lists[LI]; }60ArrayRef<List> getLists() const { return Lists; }61MCSymbol *getSym() const {62return Sym;63}64void setSym(MCSymbol *Sym) {65this->Sym = Sym;66}6768class ListBuilder;69class EntryBuilder;7071private:72/// Start a new .debug_loc entry list.73///74/// Start a new .debug_loc entry list. Return the new list's index so it can75/// be retrieved later via \a getList().76///77/// Until the next call, \a startEntry() will add entries to this list.78size_t startList(DwarfCompileUnit *CU) {79size_t LI = Lists.size();80Lists.emplace_back(CU, Entries.size());81return LI;82}8384/// 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.90bool finalizeList(AsmPrinter &Asm);9192/// Start a new .debug_loc entry.93///94/// Until the next call, bytes added to the stream will be added to this95/// entry.96void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) {97Entries.push_back({BeginSym, EndSym, DWARFBytes.size(), Comments.size()});98}99100/// Finalize a .debug_loc entry, deleting if it's empty.101void finalizeEntry();102103public:104BufferByteStreamer getStreamer() {105return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);106}107108ArrayRef<Entry> getEntries(const List &L) const {109size_t LI = getIndex(L);110return ArrayRef(Entries).slice(Lists[LI].EntryOffset, getNumEntries(LI));111}112113ArrayRef<char> getBytes(const Entry &E) const {114size_t EI = getIndex(E);115return ArrayRef(DWARFBytes.begin(), DWARFBytes.end())116.slice(Entries[EI].ByteOffset, getNumBytes(EI));117}118ArrayRef<std::string> getComments(const Entry &E) const {119size_t EI = getIndex(E);120return ArrayRef(Comments).slice(Entries[EI].CommentOffset,121getNumComments(EI));122}123124private:125size_t getIndex(const List &L) const {126assert(&Lists.front() <= &L && &L <= &Lists.back() &&127"Expected valid list");128return &L - &Lists.front();129}130size_t getIndex(const Entry &E) const {131assert(&Entries.front() <= &E && &E <= &Entries.back() &&132"Expected valid entry");133return &E - &Entries.front();134}135size_t getNumEntries(size_t LI) const {136if (LI + 1 == Lists.size())137return Entries.size() - Lists[LI].EntryOffset;138return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset;139}140size_t getNumBytes(size_t EI) const {141if (EI + 1 == Entries.size())142return DWARFBytes.size() - Entries[EI].ByteOffset;143return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset;144}145size_t getNumComments(size_t EI) const {146if (EI + 1 == Entries.size())147return Comments.size() - Entries[EI].CommentOffset;148return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;149}150};151152/// Builder for DebugLocStream lists.153class DebugLocStream::ListBuilder {154DebugLocStream &Locs;155AsmPrinter &Asm;156DbgVariable &V;157size_t ListIndex;158std::optional<uint8_t> TagOffset;159160public:161ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,162DbgVariable &V)163: Locs(Locs), Asm(Asm), V(V), ListIndex(Locs.startList(&CU)),164TagOffset(std::nullopt) {}165166void setTagOffset(uint8_t TO) {167TagOffset = TO;168}169170/// Finalize the list.171///172/// If the list is empty, delete it. Otherwise, finalize it by creating a173/// temp symbol in \a Asm and setting up the \a DbgVariable.174~ListBuilder();175176DebugLocStream &getLocs() { return Locs; }177};178179/// Builder for DebugLocStream entries.180class DebugLocStream::EntryBuilder {181DebugLocStream &Locs;182183public:184EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)185: Locs(List.getLocs()) {186Locs.startEntry(Begin, End);187}188189/// Finalize the entry, deleting it if it's empty.190~EntryBuilder() { Locs.finalizeEntry(); }191192BufferByteStreamer getStreamer() { return Locs.getStreamer(); }193};194195} // namespace llvm196197#endif198199200