//===- 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_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H #define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H #include "DWARFEmitterImpl.h" #include "DWARFLinkerCompileUnit.h" #include "llvm/ADT/AddressRanges.h" #include "llvm/CodeGen/AccelTable.h" #include "llvm/DWARFLinkerParallel/DWARFLinker.h" #include "llvm/DWARFLinkerParallel/StringPool.h" #include "llvm/DWARFLinkerParallel/StringTable.h" namespace llvm { namespace dwarflinker_parallel { using Offset2UnitMapTy = DenseMap; struct RangeAttrPatch; struct LocAttrPatch; class DWARFLinkerImpl : public DWARFLinker { public: DWARFLinkerImpl(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler, TranslatorFuncTy StringsTranslator) : UniqueUnitID(0), ErrorHandler(ErrorHandler), WarningHandler(WarningHandler), OutputStrings(Strings, StringsTranslator) {} 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 { reportWarning("LLVM parallel dwarflinker is not implemented yet.", ""); return Error::success(); } /// \defgroup Methods setting various linking options: /// /// @{ /// /// Allows to generate log of linking process to the standard output. void setVerbosity(bool Verbose) override { Options.Verbose = Verbose; } /// Print statistics to standard output. void setStatistics(bool Statistics) override { Options.Statistics = Statistics; } /// Verify the input DWARF. void setVerifyInputDWARF(bool Verify) override { Options.VerifyInputDWARF = Verify; } /// Do not unique types according to ODR. void setNoODR(bool NoODR) override { Options.NoODR = NoODR; } /// Update index tables only(do not modify rest of DWARF). void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override { Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly; } /// Allow generating valid, but non-deterministic output. void setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) override { Options.AllowNonDeterministicOutput = AllowNonDeterministicOutput; } /// Set to keep the enclosing function for a static variable. void setKeepFunctionForStatic(bool KeepFunctionForStatic) override { Options.KeepFunctionForStatic = KeepFunctionForStatic; } /// Use specified number of threads for parallel files linking. void setNumThreads(unsigned NumThreads) override { Options.Threads = NumThreads; } /// Add kind of accelerator tables to be generated. void addAccelTableKind(AccelTableKind Kind) override { assert(!llvm::is_contained(Options.AccelTables, Kind)); Options.AccelTables.emplace_back(Kind); } /// Set prepend path for clang modules. void setPrependPath(const std::string &Ppath) override { Options.PrependPath = Ppath; } /// Set estimated objects files amount, for preliminary data allocation. void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override { ObjectContexts.reserve(ObjFilesNum); } /// Set verification handler which would be used to report verification /// errors. void setInputVerificationHandler(InputVerificationHandlerTy Handler) override { Options.InputVerificationHandler = Handler; } /// Set map for Swift interfaces. void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override { Options.ParseableSwiftInterfaces = Map; } /// Set prefix map for objects. void setObjectPrefixMap(ObjectPrefixMapTy *Map) override { 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); Options.TargetDWARFVersion = TargetDWARFVersion; return Error::success(); } /// @} protected: /// Reports Warning. void reportWarning(const Twine &Warning, const DWARFFile &File, const DWARFDie *DIE = nullptr) const { if (WarningHandler != nullptr) WarningHandler(Warning, File.FileName, DIE); } /// Reports Warning. void reportWarning(const Twine &Warning, StringRef FileName, const DWARFDie *DIE = nullptr) const { if (WarningHandler != nullptr) WarningHandler(Warning, FileName, DIE); } /// Reports Error. void reportError(const Twine &Warning, StringRef FileName, const DWARFDie *DIE = nullptr) const { if (ErrorHandler != nullptr) ErrorHandler(Warning, FileName, DIE); } /// Returns next available unique Compile Unit ID. unsigned getNextUniqueUnitID() { return UniqueUnitID.fetch_add(1); } /// 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>; /// 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 Unit) : File(File), Unit(std::move(Unit)) {} RefModuleUnit(RefModuleUnit &&Other) : File(Other.File), Unit(std::move(Other.Unit)) {} RefModuleUnit(const RefModuleUnit &) = delete; DWARFFile &File; std::unique_ptr Unit; }; using ModuleUnitListTy = SmallVector; /// Object file descriptor. DWARFFile &File; /// 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; /// Output sections, common for all compilation units. OutTablesFileTy OutDebugInfoBytes; /// Endianness for the final file. support::endianness Endianess = support::endianness::little; LinkContext(DWARFFile &File) : File(File) { if (File.Dwarf) { if (!File.Dwarf->compile_units().empty()) CompileUnits.reserve(File.Dwarf->getNumCompileUnits()); Endianess = File.Dwarf->isLittleEndian() ? support::endianness::little : support::endianness::big; } } /// Add Compile Unit corresponding to the module. void addModulesCompileUnit(RefModuleUnit &&Unit) { ModulesCompileUnits.emplace_back(std::move(Unit)); } /// Return Endiannes of the source DWARF information. support::endianness getEndianness() { return Endianess; } /// \returns pointer to compilation unit which corresponds \p Offset. CompileUnit *getUnitForOffset(CompileUnit &CU, uint64_t Offset) const; }; /// linking options struct DWARFLinkerOptions { /// DWARF version for the output. uint16_t TargetDWARFVersion = 0; /// Generate processing log to the standard output. bool Verbose = false; /// Print statistics. bool Statistics = false; /// Verify the input DWARF. bool VerifyInputDWARF = false; /// Do not unique types according to ODR bool NoODR = false; /// Update index tables. bool UpdateIndexTablesOnly = false; /// Whether we want a static variable to force us to keep its enclosing /// function. bool KeepFunctionForStatic = false; /// Allow to generate valid, but non deterministic output. bool AllowNonDeterministicOutput = false; /// Number of threads. unsigned Threads = 1; /// The accelerator table kinds SmallVector AccelTables; /// Prepend path for the clang modules. std::string PrependPath; /// input verification handler(it might be called asynchronously). 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 /// be uniqued and sorted and there are only few entries expected /// per compile unit, which is why this is a std::map. /// this is dsymutil specific fag. /// /// (it might be called asynchronously). SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr; /// A list of remappings to apply to file paths. /// /// (it might be called asynchronously). ObjectPrefixMapTy *ObjectPrefixMap = nullptr; } Options; /// \defgroup Data members accessed asinchroniously. /// /// @{ /// Unique ID for compile unit. std::atomic UniqueUnitID; /// Strings pool. Keeps all strings. StringPool Strings; /// error handler(it might be called asynchronously). MessageHandlerTy ErrorHandler = nullptr; /// warning handler(it might be called asynchronously). MessageHandlerTy WarningHandler = nullptr; /// @} /// \defgroup Data members accessed sequentially. /// /// @{ /// Set of strings which should be emitted. StringTable OutputStrings; /// Keeps all linking contexts. SmallVector> ObjectContexts; /// The emitter of final dwarf file. std::unique_ptr TheDwarfEmitter; /// @} }; } // end namespace dwarflinker_parallel } // end namespace llvm #endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H