blob: 88e284f89678bc007b60be82f92916e4d0f8c367 [file] [log] [blame]
//===- 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<uint64_t, CompileUnit *>;
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(std::find(Options.AccelTables.begin(), Options.AccelTables.end(),
Kind) == Options.AccelTables.end());
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<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)
: 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<CompileUnit> Unit;
};
using ModuleUnitListTy = SmallVector<RefModuleUnit>;
/// 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<AccelTableKind, 1> 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<unsigned> 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<std::unique_ptr<LinkContext>> ObjectContexts;
/// The emitter of final dwarf file.
std::unique_ptr<DwarfEmitterImpl> TheDwarfEmitter;
/// @}
};
} // end namespace dwarflinker_parallel
} // end namespace llvm
#endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H