summaryrefslogtreecommitdiff
path: root/Common
diff options
context:
space:
mode:
Diffstat (limited to 'Common')
-rw-r--r--Common/Args.cpp62
-rw-r--r--Common/CMakeLists.txt32
-rw-r--r--Common/ErrorHandler.cpp118
-rw-r--r--Common/Memory.cpp23
-rw-r--r--Common/Reproduce.cpp66
-rw-r--r--Common/Strings.cpp32
-rw-r--r--Common/TargetOptionsCommandFlags.cpp32
-rw-r--r--Common/Threads.cpp12
-rw-r--r--Common/Version.cpp43
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();
+}