summaryrefslogtreecommitdiff
path: root/include/lld
diff options
context:
space:
mode:
Diffstat (limited to 'include/lld')
-rw-r--r--include/lld/Common/Args.h35
-rw-r--r--include/lld/Common/Driver.h (renamed from include/lld/Driver/Driver.h)16
-rw-r--r--include/lld/Common/ErrorHandler.h112
-rw-r--r--include/lld/Common/LLVM.h (renamed from include/lld/Core/LLVM.h)4
-rw-r--r--include/lld/Common/Memory.h60
-rw-r--r--include/lld/Common/Reproduce.h (renamed from include/lld/Core/Reproduce.h)8
-rw-r--r--include/lld/Common/Strings.h23
-rw-r--r--include/lld/Common/TargetOptionsCommandFlags.h (renamed from include/lld/Core/TargetOptionsCommandFlags.h)3
-rw-r--r--include/lld/Common/Threads.h86
-rw-r--r--include/lld/Common/Version.h (renamed from include/lld/Config/Version.h)4
-rw-r--r--include/lld/Common/Version.inc.in (renamed from include/lld/Config/Version.inc.in)0
-rw-r--r--include/lld/Core/Atom.h2
-rw-r--r--include/lld/Core/DefinedAtom.h2
-rw-r--r--include/lld/Core/Error.h2
-rw-r--r--include/lld/Core/LinkingContext.h4
-rw-r--r--include/lld/Core/PassManager.h2
-rw-r--r--include/lld/Core/Reader.h2
-rw-r--r--include/lld/Core/SymbolTable.h2
-rw-r--r--include/lld/Core/Writer.h2
-rw-r--r--include/lld/ReaderWriter/YamlContext.h3
20 files changed, 350 insertions, 22 deletions
diff --git a/include/lld/Common/Args.h b/include/lld/Common/Args.h
new file mode 100644
index 0000000000000..c49a6a7e17e75
--- /dev/null
+++ b/include/lld/Common/Args.h
@@ -0,0 +1,35 @@
+//===- Args.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ARGS_H
+#define LLD_ARGS_H
+
+#include "lld/Common/LLVM.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <vector>
+
+namespace llvm {
+namespace opt {
+class InputArgList;
+}
+} // namespace llvm
+
+namespace lld {
+namespace args {
+int getInteger(llvm::opt::InputArgList &Args, unsigned Key, int Default);
+std::vector<StringRef> getStrings(llvm::opt::InputArgList &Args, int Id);
+
+uint64_t getZOptionValue(llvm::opt::InputArgList &Args, int Id, StringRef Key,
+ uint64_t Default);
+
+std::vector<StringRef> getLines(MemoryBufferRef MB);
+} // namespace args
+} // namespace lld
+
+#endif
diff --git a/include/lld/Driver/Driver.h b/include/lld/Common/Driver.h
index 4ba0994e88b9b..15ec3cd44cb55 100644
--- a/include/lld/Driver/Driver.h
+++ b/include/lld/Common/Driver.h
@@ -1,4 +1,4 @@
-//===- lld/Driver/Driver.h - Linker Driver Emulator -----------------------===//
+//===- lld/Common/Driver.h - Linker Driver Emulator -----------------------===//
//
// The LLVM Linker
//
@@ -7,14 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_DRIVER_DRIVER_H
-#define LLD_DRIVER_DRIVER_H
+#ifndef LLD_COMMON_DRIVER_H
+#define LLD_COMMON_DRIVER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/raw_ostream.h"
namespace lld {
namespace coff {
+bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
+ llvm::raw_ostream &Diag = llvm::errs());
+}
+
+namespace mingw {
bool link(llvm::ArrayRef<const char *> Args,
llvm::raw_ostream &Diag = llvm::errs());
}
@@ -28,6 +33,11 @@ namespace mach_o {
bool link(llvm::ArrayRef<const char *> Args,
llvm::raw_ostream &Diag = llvm::errs());
}
+
+namespace wasm {
+bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
+ llvm::raw_ostream &Diag = llvm::errs());
+}
}
#endif
diff --git a/include/lld/Common/ErrorHandler.h b/include/lld/Common/ErrorHandler.h
new file mode 100644
index 0000000000000..8ae6f46ac59e1
--- /dev/null
+++ b/include/lld/Common/ErrorHandler.h
@@ -0,0 +1,112 @@
+//===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// In LLD, we have three levels of errors: fatal, error or warn.
+//
+// Fatal makes the program exit immediately with an error message.
+// You shouldn't use it except for reporting a corrupted input file.
+//
+// Error prints out an error message and increment a global variable
+// ErrorCount to record the fact that we met an error condition. It does
+// not exit, so it is safe for a lld-as-a-library use case. It is generally
+// useful because it can report more than one error in a single run.
+//
+// Warn doesn't do anything but printing out a given message.
+//
+// It is not recommended to use llvm::outs() or llvm::errs() directly
+// in LLD because they are not thread-safe. The functions declared in
+// this file are mutually excluded, so you want to use them instead.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COMMON_ERRORHANDLER_H
+#define LLD_COMMON_ERRORHANDLER_H
+
+#include "lld/Common/LLVM.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
+
+namespace lld {
+
+class ErrorHandler {
+public:
+ uint64_t ErrorCount = 0;
+ uint64_t ErrorLimit = 20;
+ StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now";
+ StringRef LogName = "lld";
+ llvm::raw_ostream *ErrorOS = &llvm::errs();
+ bool ColorDiagnostics = llvm::errs().has_colors();
+ bool ExitEarly = true;
+ bool FatalWarnings = false;
+ bool Verbose = false;
+
+ void error(const Twine &Msg);
+ LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
+ void log(const Twine &Msg);
+ void message(const Twine &Msg);
+ void warn(const Twine &Msg);
+
+ std::unique_ptr<llvm::FileOutputBuffer> OutputBuffer;
+
+private:
+ void print(StringRef S, raw_ostream::Colors C);
+};
+
+/// Returns the default error handler.
+ErrorHandler &errorHandler();
+
+inline void error(const Twine &Msg) { errorHandler().error(Msg); }
+inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) {
+ errorHandler().fatal(Msg);
+}
+inline void log(const Twine &Msg) { errorHandler().log(Msg); }
+inline void message(const Twine &Msg) { errorHandler().message(Msg); }
+inline void warn(const Twine &Msg) { errorHandler().warn(Msg); }
+inline uint64_t errorCount() { return errorHandler().ErrorCount; }
+
+LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
+
+// check functions are convenient functions to strip errors
+// from error-or-value objects.
+template <class T> T check(ErrorOr<T> E) {
+ if (auto EC = E.getError())
+ fatal(EC.message());
+ return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E) {
+ if (!E)
+ fatal(llvm::toString(E.takeError()));
+ return std::move(*E);
+}
+
+template <class T>
+T check2(ErrorOr<T> E, llvm::function_ref<std::string()> Prefix) {
+ if (auto EC = E.getError())
+ fatal(Prefix() + ": " + EC.message());
+ return std::move(*E);
+}
+
+template <class T>
+T check2(Expected<T> E, llvm::function_ref<std::string()> Prefix) {
+ if (!E)
+ fatal(Prefix() + ": " + toString(E.takeError()));
+ return std::move(*E);
+}
+
+inline std::string toString(const Twine &S) { return S.str(); }
+
+// To evaluate the second argument lazily, we use C macro.
+#define CHECK(E, S) check2(E, [&] { return toString(S); })
+
+} // namespace lld
+
+#endif
diff --git a/include/lld/Core/LLVM.h b/include/lld/Common/LLVM.h
index ccf08859f4aeb..b5d0e2bffb038 100644
--- a/include/lld/Core/LLVM.h
+++ b/include/lld/Common/LLVM.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_CORE_LLVM_H
-#define LLD_CORE_LLVM_H
+#ifndef LLD_COMMON_LLVM_H
+#define LLD_COMMON_LLVM_H
// This should be the only #include, force #includes of all the others on
// clients.
diff --git a/include/lld/Common/Memory.h b/include/lld/Common/Memory.h
new file mode 100644
index 0000000000000..699f7c1654cd3
--- /dev/null
+++ b/include/lld/Common/Memory.h
@@ -0,0 +1,60 @@
+//===- Memory.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines arena allocators.
+//
+// Almost all large objects, such as files, sections or symbols, are
+// used for the entire lifetime of the linker once they are created.
+// This usage characteristic makes arena allocator an attractive choice
+// where the entire linker is one arena. With an arena, newly created
+// objects belong to the arena and freed all at once when everything is done.
+// Arena allocators are efficient and easy to understand.
+// Most objects are allocated using the arena allocators defined by this file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COMMON_MEMORY_H
+#define LLD_COMMON_MEMORY_H
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/StringSaver.h"
+#include <vector>
+
+namespace lld {
+
+// Use this arena if your object doesn't have a destructor.
+extern llvm::BumpPtrAllocator BAlloc;
+extern llvm::StringSaver Saver;
+
+void freeArena();
+
+// These two classes are hack to keep track of all
+// SpecificBumpPtrAllocator instances.
+struct SpecificAllocBase {
+ SpecificAllocBase() { Instances.push_back(this); }
+ virtual ~SpecificAllocBase() = default;
+ virtual void reset() = 0;
+ static std::vector<SpecificAllocBase *> Instances;
+};
+
+template <class T> struct SpecificAlloc : public SpecificAllocBase {
+ void reset() override { Alloc.DestroyAll(); }
+ llvm::SpecificBumpPtrAllocator<T> Alloc;
+};
+
+// Use this arena if your object has a destructor.
+// Your destructor will be invoked from freeArena().
+template <typename T, typename... U> T *make(U &&... Args) {
+ static SpecificAlloc<T> Alloc;
+ return new (Alloc.Alloc.Allocate()) T(std::forward<U>(Args)...);
+}
+
+} // namespace lld
+
+#endif
diff --git a/include/lld/Core/Reproduce.h b/include/lld/Common/Reproduce.h
index 6e1d36a549160..0f425de269c7f 100644
--- a/include/lld/Core/Reproduce.h
+++ b/include/lld/Common/Reproduce.h
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_CORE_REPRODUCE_H
-#define LLD_CORE_REPRODUCE_H
+#ifndef LLD_COMMON_REPRODUCE_H
+#define LLD_COMMON_REPRODUCE_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -33,7 +33,7 @@ std::string quote(StringRef S);
std::string rewritePath(StringRef S);
// Returns the string form of the given argument.
-std::string toString(llvm::opt::Arg *Arg);
+std::string toString(const llvm::opt::Arg &Arg);
}
#endif
diff --git a/include/lld/Common/Strings.h b/include/lld/Common/Strings.h
new file mode 100644
index 0000000000000..1a63f75f9ecfe
--- /dev/null
+++ b/include/lld/Common/Strings.h
@@ -0,0 +1,23 @@
+//===- Strings.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_STRINGS_H
+#define LLD_STRINGS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace lld {
+// Returns a demangled C++ symbol name. If Name is not a mangled
+// name, it returns Optional::None.
+llvm::Optional<std::string> demangleItanium(llvm::StringRef Name);
+}
+
+#endif
diff --git a/include/lld/Core/TargetOptionsCommandFlags.h b/include/lld/Common/TargetOptionsCommandFlags.h
index 9ba99d94b9572..9c4ff7cea3fb8 100644
--- a/include/lld/Core/TargetOptionsCommandFlags.h
+++ b/include/lld/Common/TargetOptionsCommandFlags.h
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetOptions.h"
namespace lld {
llvm::TargetOptions InitTargetOptionsFromCodeGenFlags();
-llvm::CodeModel::Model GetCodeModelFromCMModel();
+llvm::Optional<llvm::CodeModel::Model> GetCodeModelFromCMModel();
}
diff --git a/include/lld/Common/Threads.h b/include/lld/Common/Threads.h
new file mode 100644
index 0000000000000..8545907531433
--- /dev/null
+++ b/include/lld/Common/Threads.h
@@ -0,0 +1,86 @@
+//===- Threads.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// LLD supports threads to distribute workloads to multiple cores. Using
+// multicore is most effective when more than one core are idle. At the
+// last step of a build, it is often the case that a linker is the only
+// active process on a computer. So, we are naturally interested in using
+// threads wisely to reduce latency to deliver results to users.
+//
+// That said, we don't want to do "too clever" things using threads.
+// Complex multi-threaded algorithms are sometimes extremely hard to
+// reason about and can easily mess up the entire design.
+//
+// Fortunately, when a linker links large programs (when the link time is
+// most critical), it spends most of the time to work on massive number of
+// small pieces of data of the same kind, and there are opportunities for
+// large parallelism there. Here are examples:
+//
+// - We have hundreds of thousands of input sections that need to be
+// copied to a result file at the last step of link. Once we fix a file
+// layout, each section can be copied to its destination and its
+// relocations can be applied independently.
+//
+// - We have tens of millions of small strings when constructing a
+// mergeable string section.
+//
+// For the cases such as the former, we can just use parallelForEach
+// instead of std::for_each (or a plain for loop). Because tasks are
+// completely independent from each other, we can run them in parallel
+// without any coordination between them. That's very easy to understand
+// and reason about.
+//
+// For the cases such as the latter, we can use parallel algorithms to
+// deal with massive data. We have to write code for a tailored algorithm
+// for each problem, but the complexity of multi-threading is isolated in
+// a single pass and doesn't affect the linker's overall design.
+//
+// The above approach seems to be working fairly well. As an example, when
+// linking Chromium (output size 1.6 GB), using 4 cores reduces latency to
+// 75% compared to single core (from 12.66 seconds to 9.55 seconds) on my
+// Ivy Bridge Xeon 2.8 GHz machine. Using 40 cores reduces it to 63% (from
+// 12.66 seconds to 7.95 seconds). Because of the Amdahl's law, the
+// speedup is not linear, but as you add more cores, it gets faster.
+//
+// On a final note, if you are trying to optimize, keep the axiom "don't
+// guess, measure!" in mind. Some important passes of the linker are not
+// that slow. For example, resolving all symbols is not a very heavy pass,
+// although it would be very hard to parallelize it. You want to first
+// identify a slow pass and then optimize it.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COMMON_THREADS_H
+#define LLD_COMMON_THREADS_H
+
+#include "llvm/Support/Parallel.h"
+#include <functional>
+
+namespace lld {
+
+extern bool ThreadsEnabled;
+
+template <typename R, class FuncTy> void parallelForEach(R &&Range, FuncTy Fn) {
+ if (ThreadsEnabled)
+ for_each(llvm::parallel::par, std::begin(Range), std::end(Range), Fn);
+ else
+ for_each(llvm::parallel::seq, std::begin(Range), std::end(Range), Fn);
+}
+
+inline void parallelForEachN(size_t Begin, size_t End,
+ std::function<void(size_t)> Fn) {
+ if (ThreadsEnabled)
+ for_each_n(llvm::parallel::par, Begin, End, Fn);
+ else
+ for_each_n(llvm::parallel::seq, Begin, End, Fn);
+}
+
+} // namespace lld
+
+#endif
diff --git a/include/lld/Config/Version.h b/include/lld/Common/Version.h
index 1cec3cc7678c4..93de77df5804e 100644
--- a/include/lld/Config/Version.h
+++ b/include/lld/Common/Version.h
@@ -1,4 +1,4 @@
-//===- lld/Config/Version.h - LLD Version Number ----------------*- C++ -*-===//
+//===- lld/Common/Version.h - LLD Version Number ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,7 +14,7 @@
#ifndef LLD_VERSION_H
#define LLD_VERSION_H
-#include "lld/Config/Version.inc"
+#include "lld/Common/Version.inc"
#include "llvm/ADT/StringRef.h"
namespace lld {
diff --git a/include/lld/Config/Version.inc.in b/include/lld/Common/Version.inc.in
index 2789a5c460892..2789a5c460892 100644
--- a/include/lld/Config/Version.inc.in
+++ b/include/lld/Common/Version.inc.in
diff --git a/include/lld/Core/Atom.h b/include/lld/Core/Atom.h
index 156a5d4a736fe..149c3d5ee2c57 100644
--- a/include/lld/Core/Atom.h
+++ b/include/lld/Core/Atom.h
@@ -10,7 +10,7 @@
#ifndef LLD_CORE_ATOM_H
#define LLD_CORE_ATOM_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "llvm/ADT/StringRef.h"
namespace lld {
diff --git a/include/lld/Core/DefinedAtom.h b/include/lld/Core/DefinedAtom.h
index 7f623d2ea5e63..6229d67e25a5e 100644
--- a/include/lld/Core/DefinedAtom.h
+++ b/include/lld/Core/DefinedAtom.h
@@ -10,9 +10,9 @@
#ifndef LLD_CORE_DEFINED_ATOM_H
#define LLD_CORE_DEFINED_ATOM_H
+#include "lld/Common/LLVM.h"
#include "lld/Core/Atom.h"
#include "lld/Core/Reference.h"
-#include "lld/Core/LLVM.h"
#include "llvm/Support/ErrorHandling.h"
namespace lld {
diff --git a/include/lld/Core/Error.h b/include/lld/Core/Error.h
index b0bf73b1cb7b5..36a36724987a4 100644
--- a/include/lld/Core/Error.h
+++ b/include/lld/Core/Error.h
@@ -14,7 +14,7 @@
#ifndef LLD_CORE_ERROR_H
#define LLD_CORE_ERROR_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Error.h"
#include <system_error>
diff --git a/include/lld/Core/LinkingContext.h b/include/lld/Core/LinkingContext.h
index b3a999b00fbd2..eb9510cbd215c 100644
--- a/include/lld/Core/LinkingContext.h
+++ b/include/lld/Core/LinkingContext.h
@@ -62,7 +62,7 @@ public:
/// of DefinedAtoms that should be marked live (along with all Atoms they
/// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can
/// be kept live using this method.
- const std::vector<StringRef> &deadStripRoots() const {
+ ArrayRef<StringRef> deadStripRoots() const {
return _deadStripRoots;
}
@@ -106,7 +106,7 @@ public:
/// options which are used to configure LLVM's command line settings.
/// For instance the -debug-only XXX option can be used to dynamically
/// trace different parts of LLVM and lld.
- const std::vector<const char *> &llvmOptions() const { return _llvmOptions; }
+ ArrayRef<const char *> llvmOptions() const { return _llvmOptions; }
/// \name Methods used by Drivers to configure TargetInfo
/// @{
diff --git a/include/lld/Core/PassManager.h b/include/lld/Core/PassManager.h
index 09b417a2985d6..2ea65ae13aceb 100644
--- a/include/lld/Core/PassManager.h
+++ b/include/lld/Core/PassManager.h
@@ -10,7 +10,7 @@
#ifndef LLD_CORE_PASS_MANAGER_H
#define LLD_CORE_PASS_MANAGER_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "lld/Core/Pass.h"
#include "llvm/Support/Error.h"
#include <memory>
diff --git a/include/lld/Core/Reader.h b/include/lld/Core/Reader.h
index 32d04249f3784..c7baf86af61fb 100644
--- a/include/lld/Core/Reader.h
+++ b/include/lld/Core/Reader.h
@@ -10,7 +10,7 @@
#ifndef LLD_CORE_READER_H
#define LLD_CORE_READER_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "lld/Core/Reference.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Magic.h"
diff --git a/include/lld/Core/SymbolTable.h b/include/lld/Core/SymbolTable.h
index ba4951e5bd133..9c39a6ed507c3 100644
--- a/include/lld/Core/SymbolTable.h
+++ b/include/lld/Core/SymbolTable.h
@@ -10,7 +10,7 @@
#ifndef LLD_CORE_SYMBOL_TABLE_H
#define LLD_CORE_SYMBOL_TABLE_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringExtras.h"
#include <cstring>
diff --git a/include/lld/Core/Writer.h b/include/lld/Core/Writer.h
index 216f934916bc3..1f0ca4cda41f2 100644
--- a/include/lld/Core/Writer.h
+++ b/include/lld/Core/Writer.h
@@ -10,7 +10,7 @@
#ifndef LLD_CORE_WRITER_H
#define LLD_CORE_WRITER_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
diff --git a/include/lld/ReaderWriter/YamlContext.h b/include/lld/ReaderWriter/YamlContext.h
index b26161a154319..b97d21f68e55b 100644
--- a/include/lld/ReaderWriter/YamlContext.h
+++ b/include/lld/ReaderWriter/YamlContext.h
@@ -10,7 +10,7 @@
#ifndef LLD_READER_WRITER_YAML_CONTEXT_H
#define LLD_READER_WRITER_YAML_CONTEXT_H
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
#include <functional>
#include <memory>
#include <vector>
@@ -18,6 +18,7 @@
namespace lld {
class File;
class LinkingContext;
+class Registry;
namespace mach_o {
namespace normalized {
struct NormalizedFile;