diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h')
-rw-r--r-- | contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h b/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h new file mode 100644 index 000000000000..b4331df5e323 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h @@ -0,0 +1,382 @@ +//===- DWARFLinkerImpl.h ----------------------------------------*- 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_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H +#define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H + +#include "DWARFEmitterImpl.h" +#include "DWARFLinkerCompileUnit.h" +#include "DWARFLinkerTypeUnit.h" +#include "StringEntryToDwarfStringPoolEntryMap.h" +#include "llvm/ADT/AddressRanges.h" +#include "llvm/CodeGen/AccelTable.h" +#include "llvm/DWARFLinker/Parallel/DWARFLinker.h" +#include "llvm/DWARFLinker/StringPool.h" + +namespace llvm { +namespace dwarf_linker { +namespace parallel { + +/// This class links debug info. +class DWARFLinkerImpl : public DWARFLinker { +public: + DWARFLinkerImpl(MessageHandlerTy ErrorHandler, + 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 + /// pre-loaded by \p Loader for !Update case. + /// + /// \pre NoODR, Update options should be set before call to addObjectFile. + void addObjectFile( + DWARFFile &File, ObjFileLoaderTy Loader = nullptr, + + CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override; + + /// Link debug info for added files. + Error link() override; + + /// \defgroup Methods setting various linking options: + /// + /// @{ + /// + + /// Allows to generate log of linking process to the standard output. + void setVerbosity(bool Verbose) override { + GlobalData.Options.Verbose = Verbose; + } + + /// Print statistics to standard output. + void setStatistics(bool Statistics) override { + GlobalData.Options.Statistics = Statistics; + } + + /// Verify the input DWARF. + void setVerifyInputDWARF(bool Verify) override { + GlobalData.Options.VerifyInputDWARF = Verify; + } + + /// Do not unique types according to ODR. + void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; } + + /// Update index tables only(do not modify rest of DWARF). + void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override { + GlobalData.Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly; + } + + /// Allow generating valid, but non-deterministic output. + void + setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) override { + GlobalData.Options.AllowNonDeterministicOutput = + AllowNonDeterministicOutput; + } + + /// Set to keep the enclosing function for a static variable. + void setKeepFunctionForStatic(bool KeepFunctionForStatic) override { + GlobalData.Options.KeepFunctionForStatic = KeepFunctionForStatic; + } + + /// Use specified number of threads for parallel files linking. + void setNumThreads(unsigned NumThreads) override { + GlobalData.Options.Threads = NumThreads; + } + + /// Add kind of accelerator tables to be generated. + void addAccelTableKind(AccelTableKind Kind) override { + assert(!llvm::is_contained(GlobalData.getOptions().AccelTables, Kind)); + GlobalData.Options.AccelTables.emplace_back(Kind); + } + + /// Set prepend path for clang modules. + void setPrependPath(StringRef Ppath) override { + GlobalData.Options.PrependPath = Ppath; + } + + /// Set estimated objects files amount, for preliminary data allocation. + void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override; + + /// Set verification handler which would be used to report verification + /// errors. + void + setInputVerificationHandler(InputVerificationHandlerTy Handler) override { + GlobalData.Options.InputVerificationHandler = Handler; + } + + /// Set map for Swift interfaces. + void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override { + GlobalData.Options.ParseableSwiftInterfaces = Map; + } + + /// Set prefix map for objects. + void setObjectPrefixMap(ObjectPrefixMapTy *Map) override { + GlobalData.Options.ObjectPrefixMap = Map; + } + + /// Set target DWARF version. + Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override { + if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5)) + return createStringError(std::errc::invalid_argument, + "unsupported DWARF version: %d", + TargetDWARFVersion); + + GlobalData.Options.TargetDWARFVersion = TargetDWARFVersion; + return Error::success(); + } + /// @} + +protected: + /// Verify input DWARF file. + void verifyInput(const DWARFFile &File); + + /// Validate specified options. + Error validateAndUpdateOptions(); + + /// Take already linked compile units and glue them into single file. + void glueCompileUnitsAndWriteToTheOutput(); + + /// Hold the input and output of the debug info size in bytes. + struct DebugInfoSize { + uint64_t Input; + uint64_t Output; + }; + + friend class DependencyTracker; + /// Keeps track of data associated with one object during linking. + /// i.e. source file descriptor, compilation units, output data + /// for compilation units common tables. + struct LinkContext : public OutputSections { + using UnitListTy = SmallVector<std::unique_ptr<CompileUnit>>; + + /// Keep information for referenced clang module: already loaded DWARF info + /// of the clang module and a CompileUnit of the module. + struct RefModuleUnit { + RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit); + RefModuleUnit(RefModuleUnit &&Other); + RefModuleUnit(const RefModuleUnit &) = delete; + + DWARFFile &File; + std::unique_ptr<CompileUnit> Unit; + }; + using ModuleUnitListTy = SmallVector<RefModuleUnit>; + + /// Object file descriptor. + DWARFFile &InputDWARFFile; + + /// Set of Compilation Units(may be accessed asynchroniously for reading). + UnitListTy CompileUnits; + + /// Set of Compile Units for modules. + ModuleUnitListTy ModulesCompileUnits; + + /// Size of Debug info before optimizing. + uint64_t OriginalDebugInfoSize = 0; + + /// Flag indicating that all inter-connected units are loaded + /// and the dwarf linking process for these units is started. + bool InterCUProcessingStarted = false; + + StringMap<uint64_t> &ClangModules; + + std::optional<Triple> 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. + std::atomic<bool> HasNewInterconnectedCUs = {false}; + + std::atomic<bool> HasNewGlobalDependency = {false}; + + /// Counter for compile units ID. + std::atomic<size_t> &UniqueUnitID; + + LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File, + StringMap<uint64_t> &ClangModules, + std::atomic<size_t> &UniqueUnitID, + std::optional<Triple> TargetTriple); + + /// Check whether specified \p CUDie is a Clang module reference. + /// if \p Quiet is false then display error messages. + /// \return first == true if CUDie is a Clang module reference. + /// second == true if module is already loaded. + std::pair<bool, bool> isClangModuleRef(const DWARFDie &CUDie, + std::string &PCMFile, + unsigned Indent, bool Quiet); + + /// If this compile unit is really a skeleton CU that points to a + /// clang module, register it in ClangModules and return true. + /// + /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name + /// pointing to the module, and a DW_AT_gnu_dwo_id with the module + /// hash. + bool registerModuleReference(const DWARFDie &CUDie, ObjFileLoaderTy Loader, + CompileUnitHandlerTy OnCUDieLoaded, + unsigned Indent = 0); + + /// Recursively add the debug info in this clang module .pcm + /// file (and all the modules imported by it in a bottom-up fashion) + /// to ModuleUnits. + Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie, + const std::string &PCMFile, + CompileUnitHandlerTy OnCUDieLoaded, + unsigned Indent = 0); + + /// Add Compile Unit corresponding to the module. + void addModulesCompileUnit(RefModuleUnit &&Unit); + + /// Computes the total size of the debug info. + uint64_t getInputDebugInfoSize() const { + uint64_t Size = 0; + + if (InputDWARFFile.Dwarf == nullptr) + return Size; + + for (auto &Unit : InputDWARFFile.Dwarf->compile_units()) + Size += Unit->getLength(); + + return Size; + } + + /// Link compile units for this context. + Error link(TypeUnit *ArtificialTypeUnit); + + /// Link specified compile unit until specified stage. + void linkSingleCompileUnit( + CompileUnit &CU, TypeUnit *ArtificialTypeUnit, + enum CompileUnit::Stage DoUntilStage = CompileUnit::Stage::Cleaned); + + /// Emit invariant sections. + Error emitInvariantSections(); + + /// Clone and emit .debug_frame. + Error cloneAndEmitDebugFrame(); + + /// Emit FDE record. + void emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint64_t Address, + StringRef FDEBytes, SectionDescriptor &Section); + + std::function<CompileUnit *(uint64_t)> getUnitForOffset = + [&](uint64_t Offset) -> CompileUnit * { + auto CU = llvm::upper_bound( + CompileUnits, Offset, + [](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) { + return LHS < RHS->getOrigUnit().getNextUnitOffset(); + }); + + return CU != CompileUnits.end() ? CU->get() : nullptr; + }; + }; + + /// Enumerate all compile units and assign offsets to their sections and + /// strings. + void assignOffsets(); + + /// Enumerate all compile units and assign offsets to their sections. + void assignOffsetsToSections(); + + /// Enumerate all compile units and assign offsets to their strings. + void assignOffsetsToStrings(); + + /// Print statistic for processed Debug Info. + void printStatistic(); + + enum StringDestinationKind : uint8_t { DebugStr, DebugLineStr }; + + /// Enumerates all strings. + void forEachOutputString( + function_ref<void(StringDestinationKind, const StringEntry *)> + StringHandler); + + /// Enumerates sections for modules, invariant for object files, compile + /// units. + void forEachObjectSectionsSet( + function_ref<void(OutputSections &SectionsSet)> SectionsSetHandler); + + /// Enumerates all compile and type units. + void forEachCompileAndTypeUnit(function_ref<void(DwarfUnit *CU)> UnitHandler); + + /// Enumerates all comple units. + void forEachCompileUnit(function_ref<void(CompileUnit *CU)> UnitHandler); + + /// Enumerates all patches and update them with the correct values. + void patchOffsetsAndSizes(); + + /// Emit debug sections common for all input files. + void emitCommonSectionsAndWriteCompileUnitsToTheOutput(); + + /// Emit apple accelerator sections. + void emitAppleAcceleratorSections(const Triple &TargetTriple); + + /// Emit .debug_names section. + void emitDWARFv5DebugNamesSection(const Triple &TargetTriple); + + /// Emit string sections. + void emitStringSections(); + + /// Cleanup data(string pools) after output sections are generated. + void cleanupDataAfterDWARFOutputIsWritten(); + + /// Enumerate all compile units and put their data into the output stream. + void writeCompileUnitsToTheOutput(); + + /// Enumerate common sections and put their data into the output stream. + void writeCommonSectionsToTheOutput(); + + /// \defgroup Data members accessed asinchroniously. + /// + /// @{ + + /// Unique ID for compile unit. + std::atomic<size_t> UniqueUnitID; + + /// Mapping the PCM filename to the DwoId. + StringMap<uint64_t> ClangModules; + std::mutex ClangModulesMutex; + + /// Type unit. + std::unique_ptr<TypeUnit> ArtificialTypeUnit; + /// @} + + /// \defgroup Data members accessed sequentially. + /// + /// @{ + /// DwarfStringPoolEntries for .debug_str section. + StringEntryToDwarfStringPoolEntryMap DebugStrStrings; + + /// DwarfStringPoolEntries for .debug_line_str section. + StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings; + + /// Keeps all linking contexts. + SmallVector<std::unique_ptr<LinkContext>> ObjectContexts; + + /// Common sections. + OutputSections CommonSections; + + /// The emitter of final dwarf file. + std::unique_ptr<DwarfEmitterImpl> TheDwarfEmitter; + + /// Overall compile units number. + uint64_t OverallNumberOfCU = 0; + + /// Data global for the whole linking process. + LinkingGlobalData GlobalData; + /// @} +}; + +} // end of namespace parallel +} // end of namespace dwarf_linker +} // end of namespace llvm + +#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H |