From 9ff4be640fb1b3a64a8bc73020d67816f1c09ea0 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Fri, 19 Jan 2024 16:57:09 +0300 Subject: [PATCH] [DWARFLinker][NFC] Decrease DWARFLinker dependence on DwarfStreamer. (#77932) This patch is extracted from #74725. The DwarfStreamer interface looks overcomplicated and has unnecessary dependencies. This patch avoids creation of DwarfStreamer by DWARFLinker and simplifies interface. --- .../llvm/DWARFLinker/Classic/DWARFLinker.h | 24 +--- .../llvm/DWARFLinker/Classic/DWARFStreamer.h | 18 ++- .../llvm/DWARFLinker/DWARFLinkerBase.h | 47 +++++++ .../llvm/DWARFLinker/Parallel/DWARFLinker.h | 59 +++++---- llvm/lib/DWARFLinker/CMakeLists.txt | 1 + llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp | 33 ++--- .../lib/DWARFLinker/Classic/DWARFStreamer.cpp | 90 ++++++++++--- llvm/lib/DWARFLinker/DWARFLinkerBase.cpp | 64 +++++++++ .../DWARFLinker/Parallel/DWARFEmitterImpl.cpp | 66 ---------- .../DWARFLinker/Parallel/DWARFEmitterImpl.h | 23 +--- .../Parallel/DWARFLinkerCompileUnit.cpp | 14 +- .../Parallel/DWARFLinkerCompileUnit.h | 7 +- .../Parallel/DWARFLinkerGlobalData.h | 29 +++- .../DWARFLinker/Parallel/DWARFLinkerImpl.cpp | 92 +++++-------- .../DWARFLinker/Parallel/DWARFLinkerImpl.h | 23 ++-- .../Parallel/DWARFLinkerTypeUnit.cpp | 12 +- .../Parallel/DWARFLinkerTypeUnit.h | 2 +- .../DWARFLinker/Parallel/OutputSections.cpp | 53 -------- .../lib/DWARFLinker/Parallel/OutputSections.h | 124 ++++++------------ llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 36 +++-- llvm/tools/dsymutil/DwarfLinkerForBinary.h | 4 +- llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp | 25 +++- 22 files changed, 421 insertions(+), 425 deletions(-) create mode 100644 llvm/lib/DWARFLinker/DWARFLinkerBase.cpp diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h index 46d3f3148818b1..b1d3f03394f5ec 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h @@ -42,7 +42,8 @@ class DwarfEmitter { virtual ~DwarfEmitter() = default; /// Emit section named SecName with data SecData. - virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0; + virtual void emitSectionContents(StringRef SecData, + DebugSectionKind SecKind) = 0; /// Emit the abbreviation table \p Abbrevs to the .debug_abbrev section. virtual void @@ -188,17 +189,6 @@ class DwarfEmitter { /// Dump the file to the disk. virtual void finish() = 0; - - /// Emit the swift_ast section stored in \p Buffer. - virtual void emitSwiftAST(StringRef Buffer) = 0; - - /// Emit the swift reflection section stored in \p Buffer. - virtual void emitSwiftReflectionSection( - llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, - StringRef Buffer, uint32_t Alignment, uint32_t Size) = 0; - - /// Returns underlying AsmPrinter. - virtual AsmPrinter &getAsmPrinter() const = 0; }; class DwarfStreamer; @@ -232,10 +222,10 @@ class DWARFLinker : public DWARFLinkerBase { StringsTranslator); } - Error createEmitter(const Triple &TheTriple, OutputFileType FileType, - raw_pwrite_stream &OutFile); - - DwarfEmitter *getEmitter(); + /// Set output DWARF emitter. + void setOutputDWARFEmitter(DwarfEmitter *Emitter) { + TheDwarfEmitter = Emitter; + } /// Add object file to be linked. Pre-load compile unit die. Call /// \p OnCUDieLoaded for each compile unit die. If specified \p File @@ -762,7 +752,7 @@ class DWARFLinker : public DWARFLinkerBase { BumpPtrAllocator DIEAlloc; /// @} - std::unique_ptr TheDwarfEmitter; + DwarfEmitter *TheDwarfEmitter = nullptr; std::vector ObjectContexts; /// The CIEs that have been emitted in the output section. The actual CIE diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h index f010c348f12148..bebdfd5e60257e 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h @@ -45,18 +45,23 @@ class DwarfStreamer : public DwarfEmitter { public: DwarfStreamer(DWARFLinkerBase::OutputFileType OutFileType, raw_pwrite_stream &OutFile, - std::function Translator, + DWARFLinkerBase::TranslatorFuncTy Translator, DWARFLinkerBase::MessageHandlerTy Warning) : OutFile(OutFile), OutFileType(OutFileType), Translator(Translator), WarningHandler(Warning) {} virtual ~DwarfStreamer() = default; + static Expected> createStreamer( + const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, + raw_pwrite_stream &OutFile, DWARFLinkerBase::TranslatorFuncTy Translator, + DWARFLinkerBase::MessageHandlerTy Warning); + Error init(Triple TheTriple, StringRef Swift5ReflectionSegmentName); /// Dump the file to the disk. void finish() override; - AsmPrinter &getAsmPrinter() const override { return *Asm; } + AsmPrinter &getAsmPrinter() const { return *Asm; } /// Set the current output section to debug_info and change /// the MC Dwarf version to \p DwarfVersion. @@ -77,7 +82,8 @@ class DwarfStreamer : public DwarfEmitter { unsigned DwarfVersion) override; /// Emit contents of section SecName From Obj. - void emitSectionContents(StringRef SecData, StringRef SecName) override; + void emitSectionContents(StringRef SecData, + DebugSectionKind SecKind) override; /// Emit the string table described by \p Pool into .debug_str table. void emitStrings(const NonRelocatableStringpool &Pool) override; @@ -91,12 +97,12 @@ class DwarfStreamer : public DwarfEmitter { void emitLineStrings(const NonRelocatableStringpool &Pool) override; /// Emit the swift_ast section stored in \p Buffer. - void emitSwiftAST(StringRef Buffer) override; + void emitSwiftAST(StringRef Buffer); /// Emit the swift reflection section stored in \p Buffer. void emitSwiftReflectionSection( llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, - StringRef Buffer, uint32_t Alignment, uint32_t Size) override; + StringRef Buffer, uint32_t Alignment, uint32_t Size); /// Emit debug ranges(.debug_ranges, .debug_rnglists) header. MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) override; @@ -215,6 +221,8 @@ class DwarfStreamer : public DwarfEmitter { WarningHandler(Warning, Context, nullptr); } + MCSection *getMCSection(DebugSectionKind SecKind); + void emitMacroTableImpl(const DWARFDebugMacro *MacroTable, const Offset2UnitMap &UnitMacroMap, OffsetsStringPool &StringPool, uint64_t &OutOffset); diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h index 626fb53d90f9fa..5c811b668f0a31 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h @@ -23,6 +23,53 @@ class DWARFUnit; namespace dwarf_linker { +/// List of tracked debug tables. +enum class DebugSectionKind : uint8_t { + DebugInfo = 0, + DebugLine, + DebugFrame, + DebugRange, + DebugRngLists, + DebugLoc, + DebugLocLists, + DebugARanges, + DebugAbbrev, + DebugMacinfo, + DebugMacro, + DebugAddr, + DebugStr, + DebugLineStr, + DebugStrOffsets, + DebugPubNames, + DebugPubTypes, + DebugNames, + AppleNames, + AppleNamespaces, + AppleObjC, + AppleTypes, + NumberOfEnumEntries // must be last +}; + +static constexpr size_t SectionKindsNum = + static_cast(DebugSectionKind::NumberOfEnumEntries); + +static constexpr StringLiteral SectionNames[SectionKindsNum] = { + "debug_info", "debug_line", "debug_frame", "debug_ranges", + "debug_rnglists", "debug_loc", "debug_loclists", "debug_aranges", + "debug_abbrev", "debug_macinfo", "debug_macro", "debug_addr", + "debug_str", "debug_line_str", "debug_str_offsets", "debug_pubnames", + "debug_pubtypes", "debug_names", "apple_names", "apple_namespac", + "apple_objc", "apple_types"}; + +/// Return the name of the section. +static constexpr const StringLiteral & +getSectionName(DebugSectionKind SectionKind) { + return SectionNames[static_cast(SectionKind)]; +} + +/// Recognise the table name and match it with the DebugSectionKind. +std::optional parseDebugTableName(StringRef Name); + /// The base interface for DWARFLinker implementations. class DWARFLinkerBase { public: diff --git a/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h index c38a9906940ec5..5312712a4a5b81 100644 --- a/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h @@ -89,30 +89,34 @@ namespace llvm { namespace dwarf_linker { namespace parallel { -/// ExtraDwarfEmitter allows adding extra data to the DWARFLinker output. -/// The finish() method should be called after all extra data are emitted. -class ExtraDwarfEmitter { -public: - virtual ~ExtraDwarfEmitter() = default; - - /// Dump the file to the disk. - virtual void finish() = 0; - - /// Emit section named SecName with data SecData. - virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0; - - /// Emit the swift_ast section stored in \p Buffer. - virtual void emitSwiftAST(StringRef Buffer) = 0; - - /// Emit the swift reflection section stored in \p Buffer. - virtual void emitSwiftReflectionSection( - llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, - StringRef Buffer, uint32_t Alignment, uint32_t Size) = 0; - - /// Returns underlying AsmPrinter. - virtual AsmPrinter &getAsmPrinter() const = 0; +/// This structure keeps data of the concrete section. +struct SectionDescriptorBase { + SectionDescriptorBase(DebugSectionKind SectionKind, dwarf::FormParams Format, + llvm::endianness Endianess) + : SectionKind(SectionKind), Format(Format), Endianess(Endianess) {} + virtual ~SectionDescriptorBase() = default; + /// Returns section content. + virtual StringRef getContents() = 0; + /// Returns section kind. + DebugSectionKind getKind() { return SectionKind; } + /// Returns section name. + const StringLiteral &getName() const { return getSectionName(SectionKind); } + /// Returns endianess used by section. + llvm::endianness getEndianess() const { return Endianess; } + /// Returns FormParams used by section. + dwarf::FormParams getFormParams() const { return Format; } + +protected: + /// The section kind. + DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries; + /// Output format. + dwarf::FormParams Format = {4, 4, dwarf::DWARF32}; + llvm::endianness Endianess = llvm::endianness::little; }; +using SectionHandlerTy = + std::function Section)>; + class DWARFLinker : public DWARFLinkerBase { public: virtual ~DWARFLinker() = default; @@ -122,12 +126,11 @@ class DWARFLinker : public DWARFLinkerBase { createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler, TranslatorFuncTy StringsTranslator = nullptr); - /// Creates emitter for output dwarf. - virtual Error createEmitter(const Triple &TheTriple, OutputFileType FileType, - raw_pwrite_stream &OutFile) = 0; - - /// Returns previously created dwarf emitter. May be nullptr. - virtual ExtraDwarfEmitter *getEmitter() = 0; + /// Set output DWARF handler. Result of linking DWARF is set of sections + /// containing final debug info. DWARFLinkerBase::link() pass generated + /// sections using specified \p SectionHandler. + virtual void setOutputDWARFHandler(const Triple &TargetTriple, + SectionHandlerTy SectionHandler) = 0; }; } // end of namespace parallel diff --git a/llvm/lib/DWARFLinker/CMakeLists.txt b/llvm/lib/DWARFLinker/CMakeLists.txt index 66bbf72165d642..f9d523757cd7c8 100644 --- a/llvm/lib/DWARFLinker/CMakeLists.txt +++ b/llvm/lib/DWARFLinker/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_component_library(LLVMDWARFLinker + DWARFLinkerBase.cpp Utils.cpp ADDITIONAL_HEADER_DIRS diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index db294169ceb9b8..d2b4db3b0c6fb2 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -2644,19 +2644,22 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) { TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data, - "debug_loc"); + DebugSectionKind::DebugLoc); TheDwarfEmitter->emitSectionContents( - Dwarf.getDWARFObj().getRangesSection().Data, "debug_ranges"); + Dwarf.getDWARFObj().getRangesSection().Data, + DebugSectionKind::DebugRange); TheDwarfEmitter->emitSectionContents( - Dwarf.getDWARFObj().getFrameSection().Data, "debug_frame"); + Dwarf.getDWARFObj().getFrameSection().Data, DebugSectionKind::DebugFrame); TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(), - "debug_aranges"); + DebugSectionKind::DebugARanges); TheDwarfEmitter->emitSectionContents( - Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr"); + Dwarf.getDWARFObj().getAddrSection().Data, DebugSectionKind::DebugAddr); TheDwarfEmitter->emitSectionContents( - Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists"); + Dwarf.getDWARFObj().getRnglistsSection().Data, + DebugSectionKind::DebugRngLists); TheDwarfEmitter->emitSectionContents( - Dwarf.getDWARFObj().getLoclistsSection().Data, "debug_loclists"); + Dwarf.getDWARFObj().getLoclistsSection().Data, + DebugSectionKind::DebugLocLists); } void DWARFLinker::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader, @@ -2848,7 +2851,7 @@ Error DWARFLinker::link() { SizeByObject[OptContext.File.FileName].Input = getDebugInfoSize(*OptContext.File.Dwarf); SizeByObject[OptContext.File.FileName].Output = - DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc, + DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc, OptContext.CompileUnits, Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool) .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File, @@ -3011,7 +3014,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit, UnitListTy CompileUnits; CompileUnits.emplace_back(std::move(Unit.Unit)); assert(TheDwarfEmitter); - DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits, + DIECloner(*this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits, Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool) .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File, Unit.File.Dwarf->isLittleEndian()); @@ -3030,16 +3033,4 @@ void DWARFLinker::verifyInput(const DWARFFile &File) { } } -Error DWARFLinker::createEmitter(const Triple &TheTriple, - OutputFileType FileType, - raw_pwrite_stream &OutFile) { - - TheDwarfEmitter = std::make_unique( - FileType, OutFile, StringsTranslator, WarningHandler); - - return TheDwarfEmitter->init(TheTriple, "__DWARF"); -} - -DwarfEmitter *DWARFLinker::getEmitter() { return TheDwarfEmitter.get(); } - } // namespace llvm diff --git a/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp index 020bbb06449d3a..6d522370e440d1 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp @@ -30,6 +30,18 @@ using namespace llvm; using namespace dwarf_linker; using namespace dwarf_linker::classic; +Expected> DwarfStreamer::createStreamer( + const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, + raw_pwrite_stream &OutFile, DWARFLinkerBase::TranslatorFuncTy Translator, + DWARFLinkerBase::MessageHandlerTy Warning) { + std::unique_ptr Streamer = + std::make_unique(FileType, OutFile, Translator, Warning); + if (Error Err = Streamer->init(TheTriple, "__DWARF")) + return std::move(Err); + + return std::move(Streamer); +} + Error DwarfStreamer::init(Triple TheTriple, StringRef Swift5ReflectionSegmentName) { std::string ErrorStr; @@ -212,30 +224,72 @@ void DwarfStreamer::emitDIE(DIE &Die) { } /// Emit contents of section SecName From Obj. -void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) { - MCSection *Section = - StringSwitch(SecName) - .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection()) - .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection()) - .Case("debug_ranges", - MC->getObjectFileInfo()->getDwarfRangesSection()) - .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection()) - .Case("debug_aranges", - MC->getObjectFileInfo()->getDwarfARangesSection()) - .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection()) - .Case("debug_rnglists", - MC->getObjectFileInfo()->getDwarfRnglistsSection()) - .Case("debug_loclists", - MC->getObjectFileInfo()->getDwarfLoclistsSection()) - .Default(nullptr); - - if (Section) { +void DwarfStreamer::emitSectionContents(StringRef SecData, + DebugSectionKind SecKind) { + if (SecData.empty()) + return; + + if (MCSection *Section = getMCSection(SecKind)) { MS->switchSection(Section); MS->emitBytes(SecData); } } +MCSection *DwarfStreamer::getMCSection(DebugSectionKind SecKind) { + switch (SecKind) { + case DebugSectionKind::DebugInfo: + return MC->getObjectFileInfo()->getDwarfInfoSection(); + case DebugSectionKind::DebugLine: + return MC->getObjectFileInfo()->getDwarfLineSection(); + case DebugSectionKind::DebugFrame: + return MC->getObjectFileInfo()->getDwarfFrameSection(); + case DebugSectionKind::DebugRange: + return MC->getObjectFileInfo()->getDwarfRangesSection(); + case DebugSectionKind::DebugRngLists: + return MC->getObjectFileInfo()->getDwarfRnglistsSection(); + case DebugSectionKind::DebugLoc: + return MC->getObjectFileInfo()->getDwarfLocSection(); + case DebugSectionKind::DebugLocLists: + return MC->getObjectFileInfo()->getDwarfLoclistsSection(); + case DebugSectionKind::DebugARanges: + return MC->getObjectFileInfo()->getDwarfARangesSection(); + case DebugSectionKind::DebugAbbrev: + return MC->getObjectFileInfo()->getDwarfAbbrevSection(); + case DebugSectionKind::DebugMacinfo: + return MC->getObjectFileInfo()->getDwarfMacinfoSection(); + case DebugSectionKind::DebugMacro: + return MC->getObjectFileInfo()->getDwarfMacroSection(); + case DebugSectionKind::DebugAddr: + return MC->getObjectFileInfo()->getDwarfAddrSection(); + case DebugSectionKind::DebugStr: + return MC->getObjectFileInfo()->getDwarfStrSection(); + case DebugSectionKind::DebugLineStr: + return MC->getObjectFileInfo()->getDwarfLineStrSection(); + case DebugSectionKind::DebugStrOffsets: + return MC->getObjectFileInfo()->getDwarfStrOffSection(); + case DebugSectionKind::DebugPubNames: + return MC->getObjectFileInfo()->getDwarfPubNamesSection(); + case DebugSectionKind::DebugPubTypes: + return MC->getObjectFileInfo()->getDwarfPubTypesSection(); + case DebugSectionKind::DebugNames: + return MC->getObjectFileInfo()->getDwarfDebugNamesSection(); + case DebugSectionKind::AppleNames: + return MC->getObjectFileInfo()->getDwarfAccelNamesSection(); + case DebugSectionKind::AppleNamespaces: + return MC->getObjectFileInfo()->getDwarfAccelNamespaceSection(); + case DebugSectionKind::AppleObjC: + return MC->getObjectFileInfo()->getDwarfAccelObjCSection(); + case DebugSectionKind::AppleTypes: + return MC->getObjectFileInfo()->getDwarfAccelTypesSection(); + case DebugSectionKind::NumberOfEnumEntries: + llvm_unreachable("Unknown DebugSectionKind value"); + break; + } + + return nullptr; +} + /// Emit the debug_str section stored in \p Pool. void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) { Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection()); diff --git a/llvm/lib/DWARFLinker/DWARFLinkerBase.cpp b/llvm/lib/DWARFLinker/DWARFLinkerBase.cpp new file mode 100644 index 00000000000000..7ba98d43274fa3 --- /dev/null +++ b/llvm/lib/DWARFLinker/DWARFLinkerBase.cpp @@ -0,0 +1,64 @@ +//=== DWARFLinkerBase.cpp -------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/DWARFLinker/DWARFLinkerBase.h" +#include "llvm/ADT/StringSwitch.h" + +using namespace llvm; +using namespace llvm::dwarf_linker; + +std::optional +llvm::dwarf_linker::parseDebugTableName(llvm::StringRef SecName) { + return llvm::StringSwitch>( + SecName.substr(SecName.find_first_not_of("._"))) + .Case(getSectionName(DebugSectionKind::DebugInfo), + DebugSectionKind::DebugInfo) + .Case(getSectionName(DebugSectionKind::DebugLine), + DebugSectionKind::DebugLine) + .Case(getSectionName(DebugSectionKind::DebugFrame), + DebugSectionKind::DebugFrame) + .Case(getSectionName(DebugSectionKind::DebugRange), + DebugSectionKind::DebugRange) + .Case(getSectionName(DebugSectionKind::DebugRngLists), + DebugSectionKind::DebugRngLists) + .Case(getSectionName(DebugSectionKind::DebugLoc), + DebugSectionKind::DebugLoc) + .Case(getSectionName(DebugSectionKind::DebugLocLists), + DebugSectionKind::DebugLocLists) + .Case(getSectionName(DebugSectionKind::DebugARanges), + DebugSectionKind::DebugARanges) + .Case(getSectionName(DebugSectionKind::DebugAbbrev), + DebugSectionKind::DebugAbbrev) + .Case(getSectionName(DebugSectionKind::DebugMacinfo), + DebugSectionKind::DebugMacinfo) + .Case(getSectionName(DebugSectionKind::DebugMacro), + DebugSectionKind::DebugMacro) + .Case(getSectionName(DebugSectionKind::DebugAddr), + DebugSectionKind::DebugAddr) + .Case(getSectionName(DebugSectionKind::DebugStr), + DebugSectionKind::DebugStr) + .Case(getSectionName(DebugSectionKind::DebugLineStr), + DebugSectionKind::DebugLineStr) + .Case(getSectionName(DebugSectionKind::DebugStrOffsets), + DebugSectionKind::DebugStrOffsets) + .Case(getSectionName(DebugSectionKind::DebugPubNames), + DebugSectionKind::DebugPubNames) + .Case(getSectionName(DebugSectionKind::DebugPubTypes), + DebugSectionKind::DebugPubTypes) + .Case(getSectionName(DebugSectionKind::DebugNames), + DebugSectionKind::DebugNames) + .Case(getSectionName(DebugSectionKind::AppleNames), + DebugSectionKind::AppleNames) + .Case(getSectionName(DebugSectionKind::AppleNamespaces), + DebugSectionKind::AppleNamespaces) + .Case(getSectionName(DebugSectionKind::AppleObjC), + DebugSectionKind::AppleObjC) + .Case(getSectionName(DebugSectionKind::AppleTypes), + DebugSectionKind::AppleTypes) + .Default(std::nullopt); +} diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp index 115167f0c7dc9a..b9edcb63a34015 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp @@ -120,72 +120,6 @@ Error DwarfEmitterImpl::init(Triple TheTriple, return Error::success(); } -void DwarfEmitterImpl::emitSwiftAST(StringRef Buffer) { - MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection(); - SwiftASTSection->setAlignment(Align(32)); - MS->switchSection(SwiftASTSection); - MS->emitBytes(Buffer); -} - -/// Emit the swift reflection section stored in \p Buffer. -void DwarfEmitterImpl::emitSwiftReflectionSection( - llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, - StringRef Buffer, uint32_t Alignment, uint32_t) { - MCSection *ReflectionSection = - MOFI->getSwift5ReflectionSection(ReflSectionKind); - if (ReflectionSection == nullptr) - return; - ReflectionSection->setAlignment(Align(Alignment)); - MS->switchSection(ReflectionSection); - MS->emitBytes(Buffer); -} - -void DwarfEmitterImpl::emitSectionContents(StringRef SecData, - StringRef SecName) { - if (SecData.empty()) - return; - - if (MCSection *Section = switchSection(SecName)) { - MS->switchSection(Section); - - MS->emitBytes(SecData); - } -} - -MCSection *DwarfEmitterImpl::switchSection(StringRef SecName) { - return StringSwitch(SecName) - .Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection()) - .Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection()) - .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection()) - .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection()) - .Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection()) - .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection()) - .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection()) - .Case("debug_rnglists", - MC->getObjectFileInfo()->getDwarfRnglistsSection()) - .Case("debug_loclists", - MC->getObjectFileInfo()->getDwarfLoclistsSection()) - .Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection()) - .Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection()) - .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection()) - .Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection()) - .Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection()) - .Case("debug_str_offsets", - MC->getObjectFileInfo()->getDwarfStrOffSection()) - .Case("debug_pubnames", - MC->getObjectFileInfo()->getDwarfPubNamesSection()) - .Case("debug_pubtypes", - MC->getObjectFileInfo()->getDwarfPubTypesSection()) - .Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection()) - .Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection()) - .Case("apple_namespac", - MC->getObjectFileInfo()->getDwarfAccelNamespaceSection()) - .Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection()) - .Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection()) - - .Default(nullptr); -} - void DwarfEmitterImpl::emitAbbrevs( const SmallVector> &Abbrevs, unsigned DwarfVersion) { diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.h b/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.h index 89a33fe9419153..71351f1d8c1cee 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.h @@ -45,7 +45,7 @@ using CompUnitIDToIdx = DenseMap; /// This class emits DWARF data to the output stream. It emits already /// generated section data and specific data, which could not be generated /// by CompileUnit. -class DwarfEmitterImpl : public ExtraDwarfEmitter { +class DwarfEmitterImpl { public: DwarfEmitterImpl(DWARFLinker::OutputFileType OutFileType, raw_pwrite_stream &OutFile) @@ -58,21 +58,7 @@ class DwarfEmitterImpl : public ExtraDwarfEmitter { const Triple &getTargetTriple() { return MC->getTargetTriple(); } /// Dump the file to the disk. - void finish() override { MS->finish(); } - - /// Returns AsmPrinter. - AsmPrinter &getAsmPrinter() const override { return *Asm; } - - /// Emit the swift_ast section stored in \p Buffer. - void emitSwiftAST(StringRef Buffer) override; - - /// Emit the swift reflection section stored in \p Buffer. - void emitSwiftReflectionSection( - llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, - StringRef Buffer, uint32_t Alignment, uint32_t) override; - - /// Emit specified section data. - void emitSectionContents(StringRef SecData, StringRef SecName) override; + void finish() { MS->finish(); } /// Emit abbreviations. void emitAbbrevs(const SmallVector> &Abbrevs, @@ -115,8 +101,6 @@ class DwarfEmitterImpl : public ExtraDwarfEmitter { const StringEntryToDwarfStringPoolEntryMap &Strings, uint64_t &NextOffset, MCSection *OutSection); - MCSection *switchSection(StringRef SecName); - /// \defgroup MCObjects MC layer objects constructed by the streamer /// @{ std::unique_ptr MRI; @@ -135,7 +119,8 @@ class DwarfEmitterImpl : public ExtraDwarfEmitter { /// The output file we stream the linked Dwarf to. raw_pwrite_stream &OutFile; - DWARFLinker::OutputFileType OutFileType = DWARFLinker::OutputFileType::Object; + DWARFLinkerBase::OutputFileType OutFileType = + DWARFLinkerBase::OutputFileType::Object; uint64_t DebugInfoSectionSize = 0; }; diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp index 6ed284a66a8561..212264714c2a57 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp @@ -1229,8 +1229,9 @@ void CompileUnit::cloneDieAttrExpression( } } -Error CompileUnit::cloneAndEmit(std::optional TargetTriple, - TypeUnit *ArtificialTypeUnit) { +Error CompileUnit::cloneAndEmit( + std::optional> TargetTriple, + TypeUnit *ArtificialTypeUnit) { BumpPtrAllocator Allocator; DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE(); @@ -1247,18 +1248,17 @@ Error CompileUnit::cloneAndEmit(std::optional TargetTriple, std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit); setOutUnitDIE(OutCUDie.first); - if (getGlobalData().getOptions().NoOutput || (OutCUDie.first == nullptr)) + if (!TargetTriple.has_value() || (OutCUDie.first == nullptr)) return Error::success(); - assert(TargetTriple.has_value()); - if (Error Err = cloneAndEmitLineTable(*TargetTriple)) + if (Error Err = cloneAndEmitLineTable((*TargetTriple).get())) return Err; if (Error Err = cloneAndEmitDebugMacro()) return Err; getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); - if (Error Err = emitDebugInfo(*TargetTriple)) + if (Error Err = emitDebugInfo((*TargetTriple).get())) return Err; // ASSUMPTION: .debug_info section should already be emitted at this point. @@ -1514,7 +1514,7 @@ TypeEntry *CompileUnit::createTypeDIEandCloneAttributes( return Entry; } -Error CompileUnit::cloneAndEmitLineTable(Triple &TargetTriple) { +Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) { const DWARFDebugLine::LineTable *InputLineTable = getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit()); if (InputLineTable == nullptr) { diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h index abd978e7c0e4bb..20e20222a4ac0a 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h @@ -401,8 +401,9 @@ class alignas(8) CompileUnit : public DwarfUnit { const RangesTy &getFunctionRanges() const { return Ranges; } /// Clone and emit this compilation unit. - Error cloneAndEmit(std::optional TargetTriple, - TypeUnit *ArtificialTypeUnit); + Error + cloneAndEmit(std::optional> TargetTriple, + TypeUnit *ArtificialTypeUnit); /// Clone and emit debug locations(.debug_loc/.debug_loclists). Error cloneAndEmitDebugLocations(); @@ -422,7 +423,7 @@ class alignas(8) CompileUnit : public DwarfUnit { BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit); // Clone and emit line table. - Error cloneAndEmitLineTable(Triple &TargetTriple); + Error cloneAndEmitLineTable(const Triple &TargetTriple); /// Clone attribute location axpression. void cloneDieAttrExpression(const DWARFExpression &InputExpression, diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h index b641343ac808c7..38c261a8106fcd 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h @@ -39,9 +39,6 @@ struct DWARFLinkerOptions { /// Verify the input DWARF. bool VerifyInputDWARF = false; - /// Do not emit output. - bool NoOutput = false; - /// Do not unique types according to ODR bool NoODR = false; @@ -59,13 +56,14 @@ struct DWARFLinkerOptions { unsigned Threads = 1; /// The accelerator table kinds - SmallVector AccelTables; + SmallVector AccelTables; /// Prepend path for the clang modules. std::string PrependPath; /// input verification handler(it might be called asynchronously). - DWARFLinker::InputVerificationHandlerTy InputVerificationHandler = nullptr; + DWARFLinkerBase::InputVerificationHandlerTy InputVerificationHandler = + nullptr; /// A list of all .swiftinterface files referenced by the debug /// info, mapping Module name to path on disk. The entries need to @@ -74,12 +72,12 @@ struct DWARFLinkerOptions { /// this is dsymutil specific fag. /// /// (it might be called asynchronously). - DWARFLinker::SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr; + DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr; /// A list of remappings to apply to file paths. /// /// (it might be called asynchronously). - DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap = nullptr; + DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap = nullptr; }; class DWARFLinkerImpl; @@ -147,6 +145,19 @@ class LinkingGlobalData { }); } + /// Set target triple. + void setTargetTriple(const Triple &TargetTriple) { + this->TargetTriple = TargetTriple; + } + + /// Optionally return target triple. + std::optional> getTargetTriple() { + if (TargetTriple) + return std::cref(*TargetTriple); + + return std::nullopt; + } + protected: llvm::parallel::PerThreadBumpPtrAllocator Allocator; StringPool Strings; @@ -154,6 +165,10 @@ class LinkingGlobalData { DWARFLinkerOptions Options; MessageHandlerTy WarningHandler; MessageHandlerTy ErrorHandler; + + /// Triple for output data. May be not set if generation of output + /// data is not requested. + std::optional TargetTriple; }; } // end of namespace parallel diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp index b0b819cf977850..f127214927a5d3 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp @@ -32,11 +32,9 @@ DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler, DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File, StringMap &ClangModules, - std::atomic &UniqueUnitID, - std::optional TargetTriple) + std::atomic &UniqueUnitID) : OutputSections(GlobalData), InputDWARFFile(File), - ClangModules(ClangModules), TargetTriple(TargetTriple), - UniqueUnitID(UniqueUnitID) { + ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) { if (File.Dwarf) { if (!File.Dwarf->compile_units().empty()) @@ -63,25 +61,10 @@ void DWARFLinkerImpl::LinkContext::addModulesCompileUnit( ModulesCompileUnits.emplace_back(std::move(Unit)); } -Error DWARFLinkerImpl::createEmitter(const Triple &TheTriple, - OutputFileType FileType, - raw_pwrite_stream &OutFile) { - - TheDwarfEmitter = std::make_unique(FileType, OutFile); - - return TheDwarfEmitter->init(TheTriple, "__DWARF"); -} - -ExtraDwarfEmitter *DWARFLinkerImpl::getEmitter() { - return TheDwarfEmitter.get(); -} - void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader, CompileUnitHandlerTy OnCUDieLoaded) { ObjectContexts.emplace_back(std::make_unique( - GlobalData, File, ClangModules, UniqueUnitID, - (TheDwarfEmitter.get() == nullptr ? std::optional(std::nullopt) - : TheDwarfEmitter->getTargetTriple()))); + GlobalData, File, ClangModules, UniqueUnitID)); if (ObjectContexts.back()->InputDWARFFile.Dwarf) { for (const std::unique_ptr &CU : @@ -117,8 +100,9 @@ Error DWARFLinkerImpl::link() { 0, dwarf::DwarfFormat::DWARF32}; llvm::endianness GlobalEndianness = llvm::endianness::native; - if (TheDwarfEmitter) { - GlobalEndianness = TheDwarfEmitter->getTargetTriple().isLittleEndian() + if (std::optional> CurTriple = + GlobalData.getTargetTriple()) { + GlobalEndianness = (*CurTriple).get().isLittleEndian() ? llvm::endianness::little : llvm::endianness::big; } @@ -147,7 +131,7 @@ Error DWARFLinkerImpl::link() { if (GlobalData.getOptions().VerifyInputDWARF) verifyInput(Context->InputDWARFFile); - if (!TheDwarfEmitter) + if (!GlobalData.getTargetTriple()) GlobalEndianness = Context->getEndianness(); GlobalFormat.AddrSize = std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize); @@ -173,9 +157,9 @@ Error DWARFLinkerImpl::link() { } if (GlobalFormat.AddrSize == 0) { - if (TheDwarfEmitter) - GlobalFormat.AddrSize = - TheDwarfEmitter->getTargetTriple().isArch32Bit() ? 4 : 8; + if (std::optional> TargetTriple = + GlobalData.getTargetTriple()) + GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8; else GlobalFormat.AddrSize = 8; } @@ -225,12 +209,10 @@ Error DWARFLinkerImpl::link() { ->getValue() .load() ->Children.empty()) { - std::optional OutTriple = TheDwarfEmitter.get() == nullptr - ? std::optional(std::nullopt) - : TheDwarfEmitter->getTargetTriple(); - - if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit(OutTriple)) - return Err; + if (GlobalData.getTargetTriple().has_value()) + if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit( + (*GlobalData.getTargetTriple()).get())) + return Err; } // At this stage each compile units are cloned to their own set of debug @@ -258,8 +240,6 @@ Error DWARFLinkerImpl::validateAndUpdateOptions() { return createStringError(std::errc::invalid_argument, "target DWARF version is not set"); - GlobalData.Options.NoOutput = TheDwarfEmitter.get() == nullptr; - if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) { GlobalData.Options.Threads = 1; GlobalData.warn( @@ -690,7 +670,8 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit( if (CU.isClangModule() || GlobalData.getOptions().UpdateIndexTablesOnly || CU.getContaingFile().Addresses->hasValidRelocs()) { - if (Error Err = CU.cloneAndEmit(TargetTriple, ArtificialTypeUnit)) + if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(), + ArtificialTypeUnit)) return std::move(Err); } @@ -727,7 +708,7 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit( } Error DWARFLinkerImpl::LinkContext::emitInvariantSections() { - if (GlobalData.getOptions().NoOutput) + if (!GlobalData.getTargetTriple().has_value()) return Error::success(); getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS @@ -749,7 +730,7 @@ Error DWARFLinkerImpl::LinkContext::emitInvariantSections() { } Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() { - if (GlobalData.getOptions().NoOutput) + if (!GlobalData.getTargetTriple().has_value()) return Error::success(); if (InputDWARFFile.Dwarf.get() == nullptr) @@ -870,8 +851,9 @@ void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset, } void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() { - if (GlobalData.getOptions().NoOutput) + if (!GlobalData.getTargetTriple().has_value()) return; + assert(SectionHandler); // Go through all object files, all compile units and assign // offsets to them. @@ -1154,21 +1136,23 @@ void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() { AccelTableKind::DebugNames)) CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames); - const Triple &TargetTriple = TheDwarfEmitter->getTargetTriple(); - // Emit .debug_str and .debug_line_str sections. TG.spawn([&]() { emitStringSections(); }); if (llvm::is_contained(GlobalData.Options.AccelTables, AccelTableKind::Apple)) { // Emit apple accelerator sections. - TG.spawn([&]() { emitAppleAcceleratorSections(TargetTriple); }); + TG.spawn([&]() { + emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get()); + }); } if (llvm::is_contained(GlobalData.Options.AccelTables, AccelTableKind::DebugNames)) { // Emit .debug_names section. - TG.spawn([&]() { emitDWARFv5DebugNamesSection(TargetTriple); }); + TG.spawn([&]() { + emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get()); + }); } // Write compile units to the output file. @@ -1419,33 +1403,17 @@ void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() { } void DWARFLinkerImpl::writeCompileUnitsToTheOutput() { - bool HasAbbreviations = false; - // Enumerate all sections and store them into the final emitter. forEachObjectSectionsSet([&](OutputSections &Sections) { - Sections.forEach([&](SectionDescriptor &OutSection) { - if (!HasAbbreviations && !OutSection.getContents().empty() && - OutSection.getKind() == DebugSectionKind::DebugAbbrev) - HasAbbreviations = true; - + Sections.forEach([&](std::shared_ptr OutSection) { // Emit section content. - TheDwarfEmitter->emitSectionContents(OutSection.getContents(), - OutSection.getName()); - OutSection.clearSectionContent(); + SectionHandler(OutSection); }); }); - - if (!HasAbbreviations) { - const SmallVector> Abbreviations; - TheDwarfEmitter->emitAbbrevs(Abbreviations, 3); - } } void DWARFLinkerImpl::writeCommonSectionsToTheOutput() { - CommonSections.forEach([&](SectionDescriptor &OutSection) { - // Emit section content. - TheDwarfEmitter->emitSectionContents(OutSection.getContents(), - OutSection.getName()); - OutSection.clearSectionContent(); + CommonSections.forEach([&](std::shared_ptr OutSection) { + SectionHandler(OutSection); }); } diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h index b4331df5e323d7..527c7a0ec3642f 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h @@ -29,12 +29,6 @@ class DWARFLinkerImpl : public DWARFLinker { MessageHandlerTy WarningHandler, TranslatorFuncTy StringsTranslator); - /// Create debug info emitter. - Error createEmitter(const Triple &TheTriple, OutputFileType FileType, - raw_pwrite_stream &OutFile) override; - - ExtraDwarfEmitter *getEmitter() override; - /// Add object file to be linked. Pre-load compile unit die. Call /// \p OnCUDieLoaded for each compile unit die. If specified \p File /// has reference to the Clang module then such module would be @@ -49,6 +43,14 @@ class DWARFLinkerImpl : public DWARFLinker { /// Link debug info for added files. Error link() override; + /// Set output DWARF handler. May be not set if output generation is not + /// necessary. + void setOutputDWARFHandler(const Triple &TargetTriple, + SectionHandlerTy SectionHandler) override { + GlobalData.setTargetTriple(TargetTriple); + this->SectionHandler = SectionHandler; + } + /// \defgroup Methods setting various linking options: /// /// @{ @@ -190,8 +192,6 @@ class DWARFLinkerImpl : public DWARFLinker { StringMap &ClangModules; - std::optional TargetTriple; - /// Flag indicating that new inter-connected compilation units were /// discovered. It is used for restarting units processing /// if new inter-connected units were found. @@ -204,8 +204,7 @@ class DWARFLinkerImpl : public DWARFLinker { LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File, StringMap &ClangModules, - std::atomic &UniqueUnitID, - std::optional TargetTriple); + std::atomic &UniqueUnitID); /// Check whether specified \p CUDie is a Clang module reference. /// if \p Quiet is false then display error messages. @@ -364,8 +363,8 @@ class DWARFLinkerImpl : public DWARFLinker { /// Common sections. OutputSections CommonSections; - /// The emitter of final dwarf file. - std::unique_ptr TheDwarfEmitter; + /// Hanler for output sections. + SectionHandlerTy SectionHandler = nullptr; /// Overall compile units number. uint64_t OverallNumberOfCU = 0; diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.cpp index 397411895a8e3e..3030aa2c39b234 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.cpp @@ -337,11 +337,11 @@ uint8_t TypeUnit::getSizeByAttrForm(dwarf::Form Form) const { llvm_unreachable("Unsupported Attr Form"); } -Error TypeUnit::finishCloningAndEmit(std::optional TargetTriple) { +Error TypeUnit::finishCloningAndEmit(const Triple &TargetTriple) { BumpPtrAllocator Allocator; createDIETree(Allocator); - if (getGlobalData().getOptions().NoOutput || (getOutUnitDIE() == nullptr)) + if (getOutUnitDIE() == nullptr) return Error::success(); // Create sections ahead so that they should not be created asynchronously @@ -360,14 +360,12 @@ Error TypeUnit::finishCloningAndEmit(std::optional TargetTriple) { // Add task for emitting .debug_line section. if (!LineTable.Prologue.FileNames.empty()) { - Tasks.push_back([&]() -> Error { - assert(TargetTriple.has_value()); - return emitDebugLine(*TargetTriple, LineTable); - }); + Tasks.push_back( + [&]() -> Error { return emitDebugLine(TargetTriple, LineTable); }); } // Add task for emitting .debug_info section. - Tasks.push_back([&]() -> Error { return emitDebugInfo(*TargetTriple); }); + Tasks.push_back([&]() -> Error { return emitDebugInfo(TargetTriple); }); // Add task for emitting Pub accelerator sections. if (llvm::is_contained(GlobalData.getOptions().AccelTables, diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.h index 0944de8d1315a9..328da5c0570b16 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.h @@ -31,7 +31,7 @@ class TypeUnit : public DwarfUnit { void createDIETree(BumpPtrAllocator &Allocator); /// Emits resulting dwarf based on information from DIE tree. - Error finishCloningAndEmit(std::optional TargetTriple); + Error finishCloningAndEmit(const Triple &TargetTriple); /// Returns global type pool. TypePool &getTypePool() { return Types; } diff --git a/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp b/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp index cd1205b60f85ba..d03f9b40d49021 100644 --- a/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp +++ b/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp @@ -15,59 +15,6 @@ using namespace llvm; using namespace dwarf_linker; using namespace dwarf_linker::parallel; -std::optional -dwarf_linker::parallel::parseDebugTableName(llvm::StringRef SecName) { - return llvm::StringSwitch>( - SecName.substr(SecName.find_first_not_of("._"))) - .Case(getSectionName(DebugSectionKind::DebugInfo), - DebugSectionKind::DebugInfo) - .Case(getSectionName(DebugSectionKind::DebugLine), - DebugSectionKind::DebugLine) - .Case(getSectionName(DebugSectionKind::DebugFrame), - DebugSectionKind::DebugFrame) - .Case(getSectionName(DebugSectionKind::DebugRange), - DebugSectionKind::DebugRange) - .Case(getSectionName(DebugSectionKind::DebugRngLists), - DebugSectionKind::DebugRngLists) - .Case(getSectionName(DebugSectionKind::DebugLoc), - DebugSectionKind::DebugLoc) - .Case(getSectionName(DebugSectionKind::DebugLocLists), - DebugSectionKind::DebugLocLists) - .Case(getSectionName(DebugSectionKind::DebugARanges), - DebugSectionKind::DebugARanges) - .Case(getSectionName(DebugSectionKind::DebugAbbrev), - DebugSectionKind::DebugAbbrev) - .Case(getSectionName(DebugSectionKind::DebugMacinfo), - DebugSectionKind::DebugMacinfo) - .Case(getSectionName(DebugSectionKind::DebugMacro), - DebugSectionKind::DebugMacro) - .Case(getSectionName(DebugSectionKind::DebugAddr), - DebugSectionKind::DebugAddr) - .Case(getSectionName(DebugSectionKind::DebugStr), - DebugSectionKind::DebugStr) - .Case(getSectionName(DebugSectionKind::DebugLineStr), - DebugSectionKind::DebugLineStr) - .Case(getSectionName(DebugSectionKind::DebugStrOffsets), - DebugSectionKind::DebugStrOffsets) - .Case(getSectionName(DebugSectionKind::DebugPubNames), - DebugSectionKind::DebugPubNames) - .Case(getSectionName(DebugSectionKind::DebugPubTypes), - DebugSectionKind::DebugPubTypes) - .Case(getSectionName(DebugSectionKind::DebugNames), - DebugSectionKind::DebugNames) - .Case(getSectionName(DebugSectionKind::AppleNames), - DebugSectionKind::AppleNames) - .Case(getSectionName(DebugSectionKind::AppleNamespaces), - DebugSectionKind::AppleNamespaces) - .Case(getSectionName(DebugSectionKind::AppleObjC), - DebugSectionKind::AppleObjC) - .Case(getSectionName(DebugSectionKind::AppleTypes), - DebugSectionKind::AppleTypes) - .Default(std::nullopt); - - return std::nullopt; -} - DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, uint32_t RefIdx) : SectionPatch({PatchOffset}), diff --git a/llvm/lib/DWARFLinker/Parallel/OutputSections.h b/llvm/lib/DWARFLinker/Parallel/OutputSections.h index b9df2228920a94..a21e4b2b75a503 100644 --- a/llvm/lib/DWARFLinker/Parallel/OutputSections.h +++ b/llvm/lib/DWARFLinker/Parallel/OutputSections.h @@ -34,51 +34,6 @@ namespace parallel { class TypeUnit; -/// List of tracked debug tables. -enum class DebugSectionKind : uint8_t { - DebugInfo = 0, - DebugLine, - DebugFrame, - DebugRange, - DebugRngLists, - DebugLoc, - DebugLocLists, - DebugARanges, - DebugAbbrev, - DebugMacinfo, - DebugMacro, - DebugAddr, - DebugStr, - DebugLineStr, - DebugStrOffsets, - DebugPubNames, - DebugPubTypes, - DebugNames, - AppleNames, - AppleNamespaces, - AppleObjC, - AppleTypes, - NumberOfEnumEntries // must be last -}; -constexpr static size_t SectionKindsNum = - static_cast(DebugSectionKind::NumberOfEnumEntries); - -static constexpr StringLiteral SectionNames[SectionKindsNum] = { - "debug_info", "debug_line", "debug_frame", "debug_ranges", - "debug_rnglists", "debug_loc", "debug_loclists", "debug_aranges", - "debug_abbrev", "debug_macinfo", "debug_macro", "debug_addr", - "debug_str", "debug_line_str", "debug_str_offsets", "debug_pubnames", - "debug_pubtypes", "debug_names", "apple_names", "apple_namespac", - "apple_objc", "apple_types"}; - -static constexpr const StringLiteral & -getSectionName(DebugSectionKind SectionKind) { - return SectionNames[static_cast(SectionKind)]; -} - -/// Recognise the table name and match it with the DebugSectionKind. -std::optional parseDebugTableName(StringRef Name); - /// There are fields(sizes, offsets) which should be updated after /// sections are generated. To remember offsets and related data /// the descendants of SectionPatch structure should be used. @@ -194,12 +149,13 @@ class OutputSections; /// This structure is used to keep data of the concrete section. /// Like data bits, list of patches, format. -struct SectionDescriptor { +struct SectionDescriptor : SectionDescriptorBase { friend OutputSections; SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData, dwarf::FormParams Format, llvm::endianness Endianess) - : OS(Contents), ListDebugStrPatch(&GlobalData.getAllocator()), + : SectionDescriptorBase(SectionKind, Format, Endianess), OS(Contents), + ListDebugStrPatch(&GlobalData.getAllocator()), ListDebugLineStrPatch(&GlobalData.getAllocator()), ListDebugRangePatch(&GlobalData.getAllocator()), ListDebugLocPatch(&GlobalData.getAllocator()), @@ -211,10 +167,9 @@ struct SectionDescriptor { ListDebugTypeStrPatch(&GlobalData.getAllocator()), ListDebugTypeLineStrPatch(&GlobalData.getAllocator()), ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()), - GlobalData(GlobalData), SectionKind(SectionKind), Format(Format), - Endianess(Endianess) {} + GlobalData(GlobalData) {} - /// Erase whole section contents(data bits, list of patches). + /// Erase whole section content(data bits, list of patches). void clearAllSectionData(); /// Erase only section output data bits. @@ -263,7 +218,7 @@ struct SectionDescriptor { void setSizesForSectionCreatedByAsmPrinter(); /// Returns section content. - StringRef getContents() { + StringRef getContents() override { if (SectionOffsetInsideAsmPrinterOutputStart == 0) return StringRef(Contents.data(), Contents.size()); @@ -311,18 +266,6 @@ struct SectionDescriptor { /// Write specified \p Value of \p AttrForm to the \p PatchOffset. void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val); - /// Returns section kind. - DebugSectionKind getKind() { return SectionKind; } - - /// Returns section name. - const StringLiteral &getName() const { return getSectionName(SectionKind); } - - /// Returns endianess used by section. - llvm::endianness getEndianess() const { return Endianess; } - - /// Returns FormParams used by section. - dwarf::FormParams getFormParams() const { return Format; } - /// Returns integer value of \p Size located by specified \p PatchOffset. uint64_t getIntVal(uint64_t PatchOffset, unsigned Size); @@ -344,9 +287,6 @@ struct SectionDescriptor { LinkingGlobalData &GlobalData; - /// The section kind. - DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries; - /// Section data bits. OutSectionDataTy Contents; @@ -355,10 +295,6 @@ struct SectionDescriptor { /// real section content inside elf file. size_t SectionOffsetInsideAsmPrinterOutputStart = 0; size_t SectionOffsetInsideAsmPrinterOutputEnd = 0; - - /// Output format. - dwarf::FormParams Format = {4, 4, dwarf::DWARF32}; - llvm::endianness Endianess = llvm::endianness::little; }; /// This class keeps contents and offsets to the debug sections. Any objects @@ -387,7 +323,7 @@ class OutputSections { .str() .c_str()); - return It->second; + return *It->second; } /// Returns descriptor for the specified section of \p SectionKind. @@ -402,7 +338,9 @@ class OutputSections { .str() .c_str()); - return It->second; + assert(It->second.get() != nullptr); + + return *It->second; } /// Returns descriptor for the specified section of \p SectionKind. @@ -414,7 +352,7 @@ class OutputSections { if (It == SectionDescriptors.end()) return std::nullopt; - return &It->second; + return It->second.get(); } /// Returns descriptor for the specified section of \p SectionKind. @@ -426,26 +364,44 @@ class OutputSections { if (It == SectionDescriptors.end()) return std::nullopt; - return &It->second; + return It->second.get(); } /// Returns descriptor for the specified section of \p SectionKind. /// If descriptor does not exist then creates it. SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind) { - return SectionDescriptors - .try_emplace(SectionKind, SectionKind, GlobalData, Format, Endianness) - .first->second; + SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind); + + if (It == SectionDescriptors.end()) { + SectionDescriptor *Section = + new SectionDescriptor(SectionKind, GlobalData, Format, Endianness); + auto Result = SectionDescriptors.try_emplace(SectionKind, Section); + assert(Result.second); + + It = Result.first; + } + + return *It->second; } /// Erases data of all sections. void eraseSections() { for (auto &Section : SectionDescriptors) - Section.second.clearAllSectionData(); + Section.second->clearAllSectionData(); } /// Enumerate all sections and call \p Handler for each. void forEach(function_ref Handler) { + for (auto &Section : SectionDescriptors) { + assert(Section.second.get() != nullptr); + Handler(*(Section.second)); + } + } + + /// Enumerate all sections and call \p Handler for each. + void forEach( + function_ref Section)> Handler) { for (auto &Section : SectionDescriptors) Handler(Section.second); } @@ -456,10 +412,11 @@ class OutputSections { void assignSectionsOffsetAndAccumulateSize( std::array &SectionSizesAccumulator) { for (auto &Section : SectionDescriptors) { - Section.second.StartOffset = SectionSizesAccumulator[static_cast( - Section.second.getKind())]; - SectionSizesAccumulator[static_cast(Section.second.getKind())] += - Section.second.getContents().size(); + Section.second->StartOffset = + SectionSizesAccumulator[static_cast( + Section.second->getKind())]; + SectionSizesAccumulator[static_cast( + Section.second->getKind())] += Section.second->getContents().size(); } } @@ -505,7 +462,8 @@ class OutputSections { llvm::endianness Endianness = llvm::endianness::native; /// All keeping sections. - using SectionsSetTy = std::map; + using SectionsSetTy = + std::map>; SectionsSetTy SectionDescriptors; }; diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 4ad188b0796f53..d09dcf678e1e99 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -533,9 +533,8 @@ Error DwarfLinkerForBinary::copySwiftInterfaces(StringRef Architecture) const { return Error::success(); } -template void DwarfLinkerForBinary::copySwiftReflectionMetadata( - const llvm::dsymutil::DebugMapObject *Obj, OutStreamer *Streamer, + const llvm::dsymutil::DebugMapObject *Obj, classic::DwarfStreamer *Streamer, std::vector &SectionToOffsetInDwarf, std::vector &RelocationsToApply) { @@ -649,14 +648,32 @@ bool DwarfLinkerForBinary::linkImpl( }, Options.Translator ? TranslationLambda : nullptr); + std::unique_ptr Streamer; if (!Options.NoOutput) { - if (Error Err = GeneralLinker->createEmitter(Map.getTriple(), ObjectType, - OutFile)) { - handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) { + if (Expected> StreamerOrErr = + classic::DwarfStreamer::createStreamer( + Map.getTriple(), ObjectType, OutFile, Options.Translator, + [&](const Twine &Warning, StringRef Context, + const DWARFDie *DIE) { + reportWarning(Warning, Context, DIE); + })) + Streamer = std::move(*StreamerOrErr); + else { + handleAllErrors(StreamerOrErr.takeError(), [&](const ErrorInfoBase &EI) { reportError(EI.message(), "dwarf streamer init"); }); return false; } + + if constexpr (std::is_same::value) { + GeneralLinker->setOutputDWARFHandler( + Map.getTriple(), + [&](std::shared_ptr Section) { + Streamer->emitSectionContents(Section->getContents(), + Section->getKind()); + }); + } else + GeneralLinker->setOutputDWARFEmitter(Streamer.get()); } remarks::RemarkLinker RL; @@ -749,7 +766,7 @@ bool DwarfLinkerForBinary::linkImpl( auto SectionToOffsetInDwarf = calculateStartOfStrippableReflectionSections(Map); for (const auto &Obj : Map.objects()) - copySwiftReflectionMetadata(Obj.get(), GeneralLinker->getEmitter(), + copySwiftReflectionMetadata(Obj.get(), Streamer.get(), SectionToOffsetInDwarf, RelocationsToApply); } @@ -796,7 +813,7 @@ bool DwarfLinkerForBinary::linkImpl( // Copy the module into the .swift_ast section. if (!Options.NoOutput) - GeneralLinker->getEmitter()->emitSwiftAST((*ErrorOrMem)->getBuffer()); + Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer()); continue; } @@ -850,10 +867,9 @@ bool DwarfLinkerForBinary::linkImpl( ObjectType == Linker::OutputFileType::Object) return MachOUtils::generateDsymCompanion( Options.VFS, Map, Options.Translator, - *GeneralLinker->getEmitter()->getAsmPrinter().OutStreamer, OutFile, - RelocationsToApply); + *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply); - GeneralLinker->getEmitter()->finish(); + Streamer->finish(); return true; } diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h index 052c6a899fd76a..14b9625117c2d6 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h @@ -253,9 +253,9 @@ class DwarfLinkerForBinary { Error copySwiftInterfaces(StringRef Architecture) const; - template void copySwiftReflectionMetadata( - const llvm::dsymutil::DebugMapObject *Obj, OutStreamer *Streamer, + const llvm::dsymutil::DebugMapObject *Obj, + classic::DwarfStreamer *Streamer, std::vector &SectionToOffsetInDwarf, std::vector &RelocationsToApply); diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp index d677bb0962669f..19eb1bed7578bb 100644 --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -336,9 +336,26 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, Linker::createLinker(ReportErr, ReportWarn); Triple TargetTriple = File.makeTriple(); - if (Error Err = DebugInfoLinker->createEmitter( - TargetTriple, Linker::OutputFileType::Object, OutStream)) - return Err; + std::unique_ptr Streamer; + if (Expected> StreamerOrErr = + classic::DwarfStreamer::createStreamer( + TargetTriple, Linker::OutputFileType::Object, OutStream, nullptr, + ReportWarn)) + Streamer = std::move(*StreamerOrErr); + else + return StreamerOrErr.takeError(); + + if constexpr (std::is_same::value) { + DebugInfoLinker->setOutputDWARFHandler( + TargetTriple, + [&](std::shared_ptr + Section) { + Streamer->emitSectionContents(Section->getContents(), + Section->getKind()); + }); + } else + DebugInfoLinker->setOutputDWARFEmitter(Streamer.get()); DebugInfoLinker->setEstimatedObjfilesAmount(1); DebugInfoLinker->setNumThreads(Options.NumThreads); @@ -445,7 +462,7 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, if (Error Err = DebugInfoLinker->link()) return Err; - DebugInfoLinker->getEmitter()->finish(); + Streamer->finish(); return Error::success(); }