diff options
Diffstat (limited to 'Common')
-rw-r--r-- | Common/Args.cpp | 62 | ||||
-rw-r--r-- | Common/CMakeLists.txt | 32 | ||||
-rw-r--r-- | Common/ErrorHandler.cpp | 118 | ||||
-rw-r--r-- | Common/Memory.cpp | 23 | ||||
-rw-r--r-- | Common/Reproduce.cpp | 66 | ||||
-rw-r--r-- | Common/Strings.cpp | 32 | ||||
-rw-r--r-- | Common/TargetOptionsCommandFlags.cpp | 32 | ||||
-rw-r--r-- | Common/Threads.cpp | 12 | ||||
-rw-r--r-- | Common/Version.cpp | 43 |
9 files changed, 420 insertions, 0 deletions
diff --git a/Common/Args.cpp b/Common/Args.cpp new file mode 100644 index 000000000000..680cf5bd0a6e --- /dev/null +++ b/Common/Args.cpp @@ -0,0 +1,62 @@ +//===- Args.cpp -----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Args.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/ArgList.h" + +using namespace llvm; +using namespace lld; + +int lld::args::getInteger(opt::InputArgList &Args, unsigned Key, int Default) { + int V = Default; + if (auto *Arg = Args.getLastArg(Key)) { + StringRef S = Arg->getValue(); + if (!to_integer(S, V, 10)) + error(Arg->getSpelling() + ": number expected, but got '" + S + "'"); + } + return V; +} + +std::vector<StringRef> lld::args::getStrings(opt::InputArgList &Args, int Id) { + std::vector<StringRef> V; + for (auto *Arg : Args.filtered(Id)) + V.push_back(Arg->getValue()); + return V; +} + +uint64_t lld::args::getZOptionValue(opt::InputArgList &Args, int Id, + StringRef Key, uint64_t Default) { + for (auto *Arg : Args.filtered(Id)) { + std::pair<StringRef, StringRef> KV = StringRef(Arg->getValue()).split('='); + if (KV.first == Key) { + uint64_t Result = Default; + if (!to_integer(KV.second, Result)) + error("invalid " + Key + ": " + KV.second); + return Result; + } + } + return Default; +} + +std::vector<StringRef> lld::args::getLines(MemoryBufferRef MB) { + SmallVector<StringRef, 0> Arr; + MB.getBuffer().split(Arr, '\n'); + + std::vector<StringRef> Ret; + for (StringRef S : Arr) { + S = S.trim(); + if (!S.empty() && S[0] != '#') + Ret.push_back(S); + } + return Ret; +} diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt new file mode 100644 index 000000000000..b376893f35a4 --- /dev/null +++ b/Common/CMakeLists.txt @@ -0,0 +1,32 @@ +if(NOT LLD_BUILT_STANDALONE) + set(tablegen_deps intrinsics_gen) +endif() + +add_lld_library(lldCommon + Args.cpp + ErrorHandler.cpp + Memory.cpp + Reproduce.cpp + Strings.cpp + TargetOptionsCommandFlags.cpp + Threads.cpp + Version.cpp + + ADDITIONAL_HEADER_DIRS + ${LLD_INCLUDE_DIR}/lld/Common + + LINK_COMPONENTS + Codegen + Core + Demangle + MC + Option + Support + Target + + LINK_LIBS + ${LLVM_PTHREAD_LIB} + + DEPENDS + ${tablegen_deps} + ) diff --git a/Common/ErrorHandler.cpp b/Common/ErrorHandler.cpp new file mode 100644 index 000000000000..18affce4d5a6 --- /dev/null +++ b/Common/ErrorHandler.cpp @@ -0,0 +1,118 @@ +//===- ErrorHandler.cpp ---------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/ErrorHandler.h" + +#include "lld/Common/Threads.h" + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include <mutex> + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#endif + +using namespace llvm; +using namespace lld; + +// The functions defined in this file can be called from multiple threads, +// but outs() or errs() are not thread-safe. We protect them using a mutex. +static std::mutex Mu; + +// Prints "\n" or does nothing, depending on Msg contents of +// the previous call of this function. +static void newline(raw_ostream *ErrorOS, const Twine &Msg) { + // True if the previous error message contained "\n". + // We want to separate multi-line error messages with a newline. + static bool Flag; + + if (Flag) + *ErrorOS << "\n"; + Flag = StringRef(Msg.str()).contains('\n'); +} + +ErrorHandler &lld::errorHandler() { + static ErrorHandler Handler; + return Handler; +} + +void lld::exitLld(int Val) { + // Delete the output buffer so that any tempory file is deleted. + errorHandler().OutputBuffer.reset(); + + // Dealloc/destroy ManagedStatic variables before calling + // _exit(). In a non-LTO build, this is a nop. In an LTO + // build allows us to get the output of -time-passes. + llvm_shutdown(); + + outs().flush(); + errs().flush(); + _exit(Val); +} + +void ErrorHandler::print(StringRef S, raw_ostream::Colors C) { + *ErrorOS << LogName << ": "; + if (ColorDiagnostics) { + ErrorOS->changeColor(C, true); + *ErrorOS << S; + ErrorOS->resetColor(); + } else { + *ErrorOS << S; + } +} + +void ErrorHandler::log(const Twine &Msg) { + if (Verbose) { + std::lock_guard<std::mutex> Lock(Mu); + *ErrorOS << LogName << ": " << Msg << "\n"; + } +} + +void ErrorHandler::message(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + outs() << Msg << "\n"; + outs().flush(); +} + +void ErrorHandler::warn(const Twine &Msg) { + if (FatalWarnings) { + error(Msg); + return; + } + + std::lock_guard<std::mutex> Lock(Mu); + newline(ErrorOS, Msg); + print("warning: ", raw_ostream::MAGENTA); + *ErrorOS << Msg << "\n"; +} + +void ErrorHandler::error(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + newline(ErrorOS, Msg); + + if (ErrorLimit == 0 || ErrorCount < ErrorLimit) { + print("error: ", raw_ostream::RED); + *ErrorOS << Msg << "\n"; + } else if (ErrorCount == ErrorLimit) { + print("error: ", raw_ostream::RED); + *ErrorOS << ErrorLimitExceededMsg << "\n"; + if (ExitEarly) + exitLld(1); + } + + ++ErrorCount; +} + +void ErrorHandler::fatal(const Twine &Msg) { + error(Msg); + exitLld(1); +} diff --git a/Common/Memory.cpp b/Common/Memory.cpp new file mode 100644 index 000000000000..efc5bcc2218b --- /dev/null +++ b/Common/Memory.cpp @@ -0,0 +1,23 @@ +//===- Memory.cpp ---------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Memory.h" + +using namespace llvm; +using namespace lld; + +BumpPtrAllocator lld::BAlloc; +StringSaver lld::Saver{BAlloc}; +std::vector<SpecificAllocBase *> lld::SpecificAllocBase::Instances; + +void lld::freeArena() { + for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) + Alloc->reset(); + BAlloc.Reset(); +} diff --git a/Common/Reproduce.cpp b/Common/Reproduce.cpp new file mode 100644 index 000000000000..7be4ea6bb98b --- /dev/null +++ b/Common/Reproduce.cpp @@ -0,0 +1,66 @@ +//===- Reproduce.cpp - Utilities for creating reproducers -----------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Reproduce.h" +#include "llvm/Option/Arg.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace lld; +using namespace llvm; +using namespace llvm::sys; + +// 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". +// Returned string is a forward slash separated path even on Windows to avoid +// a mess with backslash-as-escape and backslash-as-path-separator. +std::string lld::relativeToRoot(StringRef Path) { + SmallString<128> Abs = Path; + if (fs::make_absolute(Abs)) + return Path; + path::remove_dots(Abs, /*remove_dot_dot=*/true); + + // This is Windows specific. root_name() returns a drive letter + // (e.g. "c:") or a UNC name (//net). We want to keep it as part + // of the result. + SmallString<128> Res; + StringRef Root = path::root_name(Abs); + if (Root.endswith(":")) + Res = Root.drop_back(); + else if (Root.startswith("//")) + Res = Root.substr(2); + + path::append(Res, path::relative_path(Abs)); + return path::convert_to_slash(Res); +} + +// Quote a given string if it contains a space character. +std::string lld::quote(StringRef S) { + if (S.contains(' ')) + return ("\"" + S + "\"").str(); + return S; +} + +std::string lld::rewritePath(StringRef S) { + if (fs::exists(S)) + return relativeToRoot(S); + return S; +} + +std::string lld::toString(const opt::Arg &Arg) { + std::string K = Arg.getSpelling(); + if (Arg.getNumValues() == 0) + return K; + std::string V = quote(Arg.getValue()); + if (Arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) + return K + V; + return K + " " + V; +} diff --git a/Common/Strings.cpp b/Common/Strings.cpp new file mode 100644 index 000000000000..6cd4ad8d600a --- /dev/null +++ b/Common/Strings.cpp @@ -0,0 +1,32 @@ +//===- Strings.cpp -------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Strings.h" +#include "llvm/Demangle/Demangle.h" + +using namespace llvm; +using namespace lld; + +// Returns the demangled C++ symbol name for Name. +Optional<std::string> lld::demangleItanium(StringRef Name) { + // itaniumDemangle can be used to demangle strings other than symbol + // names which do not necessarily start with "_Z". Name can be + // either a C or C++ symbol. Don't call itaniumDemangle if the name + // does not look like a C++ symbol name to avoid getting unexpected + // result for a C symbol that happens to match a mangled type name. + if (!Name.startswith("_Z")) + return None; + + char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); + if (!Buf) + return None; + std::string S(Buf); + free(Buf); + return S; +} diff --git a/Common/TargetOptionsCommandFlags.cpp b/Common/TargetOptionsCommandFlags.cpp new file mode 100644 index 000000000000..e8e582f4c256 --- /dev/null +++ b/Common/TargetOptionsCommandFlags.cpp @@ -0,0 +1,32 @@ +//===-- TargetOptionsCommandFlags.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exists as a place for global variables defined in LLVM's +// CodeGen/CommandFlags.def. By putting the resulting object file in +// an archive and linking with it, the definitions will automatically be +// included when needed and skipped when already present. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/TargetOptionsCommandFlags.h" + +#include "llvm/CodeGen/CommandFlags.def" +#include "llvm/Target/TargetOptions.h" + +// Define an externally visible version of +// InitTargetOptionsFromCodeGenFlags, so that its functionality can be +// used without having to include llvm/CodeGen/CommandFlags.def, which +// would lead to multiple definitions of the command line flags. +llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() { + return ::InitTargetOptionsFromCodeGenFlags(); +} + +llvm::Optional<llvm::CodeModel::Model> lld::GetCodeModelFromCMModel() { + return getCodeModel(); +} diff --git a/Common/Threads.cpp b/Common/Threads.cpp new file mode 100644 index 000000000000..c64b8c38b909 --- /dev/null +++ b/Common/Threads.cpp @@ -0,0 +1,12 @@ +//===- Threads.cpp --------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Threads.h" + +bool lld::ThreadsEnabled = true; diff --git a/Common/Version.cpp b/Common/Version.cpp new file mode 100644 index 000000000000..6226c9a2fac6 --- /dev/null +++ b/Common/Version.cpp @@ -0,0 +1,43 @@ +//===- lib/Common/Version.cpp - 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. +// +//===----------------------------------------------------------------------===// +// +// This file defines several version-related utility functions for LLD. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Version.h" + +using namespace llvm; + +// Returns an SVN repository path, which is usually "trunk". +static std::string getRepositoryPath() { + StringRef S = LLD_REPOSITORY_STRING; + size_t Pos = S.find("lld/"); + if (Pos != StringRef::npos) + return S.substr(Pos + 4); + return S; +} + +// Returns an SVN repository name, e.g., " (trunk 284614)" +// or an empty string if no repository info is available. +static std::string getRepository() { + std::string Repo = getRepositoryPath(); + std::string Rev = LLD_REVISION_STRING; + + if (Repo.empty() && Rev.empty()) + return ""; + if (!Repo.empty() && !Rev.empty()) + return " (" + Repo + " " + Rev + ")"; + return " (" + Repo + Rev + ")"; +} + +// Returns a version string, e.g., "LLD 4.0 (lld/trunk 284614)". +std::string lld::getLLDVersion() { + return "LLD " + std::string(LLD_VERSION_STRING) + getRepository(); +} |