diff options
Diffstat (limited to 'include/lld/Common')
| -rw-r--r-- | include/lld/Common/Args.h | 35 | ||||
| -rw-r--r-- | include/lld/Common/Driver.h | 43 | ||||
| -rw-r--r-- | include/lld/Common/ErrorHandler.h | 112 | ||||
| -rw-r--r-- | include/lld/Common/LLVM.h | 83 | ||||
| -rw-r--r-- | include/lld/Common/Memory.h | 60 | ||||
| -rw-r--r-- | include/lld/Common/Reproduce.h | 39 | ||||
| -rw-r--r-- | include/lld/Common/Strings.h | 23 | ||||
| -rw-r--r-- | include/lld/Common/TargetOptionsCommandFlags.h | 21 | ||||
| -rw-r--r-- | include/lld/Common/Threads.h | 86 | ||||
| -rw-r--r-- | include/lld/Common/Version.h | 25 | ||||
| -rw-r--r-- | include/lld/Common/Version.inc.in | 6 |
11 files changed, 533 insertions, 0 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/Common/Driver.h b/include/lld/Common/Driver.h new file mode 100644 index 0000000000000..15ec3cd44cb55 --- /dev/null +++ b/include/lld/Common/Driver.h @@ -0,0 +1,43 @@ +//===- lld/Common/Driver.h - Linker Driver Emulator -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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()); +} + +namespace elf { +bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, + llvm::raw_ostream &Diag = llvm::errs()); +} + +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/Common/LLVM.h b/include/lld/Common/LLVM.h new file mode 100644 index 0000000000000..b5d0e2bffb038 --- /dev/null +++ b/include/lld/Common/LLVM.h @@ -0,0 +1,83 @@ +//===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forward declares and imports various common LLVM datatypes that +// lld wants to use unqualified. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_COMMON_LLVM_H +#define LLD_COMMON_LLVM_H + +// This should be the only #include, force #includes of all the others on +// clients. +#include "llvm/ADT/Hashing.h" +#include "llvm/Support/Casting.h" +#include <utility> + +namespace llvm { + // ADT's. + class Error; + class StringRef; + class Twine; + class MemoryBuffer; + class MemoryBufferRef; + template<typename T> class ArrayRef; + template<unsigned InternalLen> class SmallString; + template<typename T, unsigned N> class SmallVector; + template<typename T> class SmallVectorImpl; + + template<typename T> + struct SaveAndRestore; + + template<typename T> + class ErrorOr; + + template<typename T> + class Expected; + + class raw_ostream; + // TODO: DenseMap, ... +} + +namespace lld { + // Casting operators. + using llvm::isa; + using llvm::cast; + using llvm::dyn_cast; + using llvm::dyn_cast_or_null; + using llvm::cast_or_null; + + // ADT's. + using llvm::Error; + using llvm::StringRef; + using llvm::Twine; + using llvm::MemoryBuffer; + using llvm::MemoryBufferRef; + using llvm::ArrayRef; + using llvm::SmallString; + using llvm::SmallVector; + using llvm::SmallVectorImpl; + using llvm::SaveAndRestore; + using llvm::ErrorOr; + using llvm::Expected; + + using llvm::raw_ostream; +} // end namespace lld. + +namespace std { +template <> struct hash<llvm::StringRef> { +public: + size_t operator()(const llvm::StringRef &s) const { + return llvm::hash_value(s); + } +}; +} + +#endif 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/Common/Reproduce.h b/include/lld/Common/Reproduce.h new file mode 100644 index 0000000000000..0f425de269c7f --- /dev/null +++ b/include/lld/Common/Reproduce.h @@ -0,0 +1,39 @@ +//===- Reproduce.h - Utilities for creating reproducers ---------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_COMMON_REPRODUCE_H +#define LLD_COMMON_REPRODUCE_H + +#include "lld/Common/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace opt { class Arg; } +} + +namespace lld { + +// Makes a given pathname an absolute path first, and then remove +// beginning /. For example, "../foo.o" is converted to "home/john/foo.o", +// assuming that the current directory is "/home/john/bar". +std::string relativeToRoot(StringRef Path); + +// Quote a given string if it contains a space character. +std::string quote(StringRef S); + +// Rewrite the given path if a file exists with that pathname, otherwise +// returns the original path. +std::string rewritePath(StringRef S); + +// Returns the string form of the given argument. +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/Common/TargetOptionsCommandFlags.h b/include/lld/Common/TargetOptionsCommandFlags.h new file mode 100644 index 0000000000000..9c4ff7cea3fb8 --- /dev/null +++ b/include/lld/Common/TargetOptionsCommandFlags.h @@ -0,0 +1,21 @@ +//===-- TargetOptionsCommandFlags.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Helper to create TargetOptions from command line flags. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Target/TargetOptions.h" + +namespace lld { +llvm::TargetOptions InitTargetOptionsFromCodeGenFlags(); +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/Common/Version.h b/include/lld/Common/Version.h new file mode 100644 index 0000000000000..93de77df5804e --- /dev/null +++ b/include/lld/Common/Version.h @@ -0,0 +1,25 @@ +//===- lld/Common/Version.h - LLD Version Number ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a version-related utility function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_VERSION_H +#define LLD_VERSION_H + +#include "lld/Common/Version.inc" +#include "llvm/ADT/StringRef.h" + +namespace lld { +/// \brief Retrieves a string representing the complete lld version. +std::string getLLDVersion(); +} + +#endif // LLD_VERSION_H diff --git a/include/lld/Common/Version.inc.in b/include/lld/Common/Version.inc.in new file mode 100644 index 0000000000000..2789a5c460892 --- /dev/null +++ b/include/lld/Common/Version.inc.in @@ -0,0 +1,6 @@ +#define LLD_VERSION @LLD_VERSION@ +#define LLD_VERSION_STRING "@LLD_VERSION@" +#define LLD_VERSION_MAJOR @LLD_VERSION_MAJOR@ +#define LLD_VERSION_MINOR @LLD_VERSION_MINOR@ +#define LLD_REVISION_STRING "@LLD_REVISION@" +#define LLD_REPOSITORY_STRING "@LLD_REPOSITORY@" |
