diff options
Diffstat (limited to 'contrib/llvm/tools/lld/Common')
-rw-r--r-- | contrib/llvm/tools/lld/Common/Args.cpp | 18 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/Common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/Common/ErrorHandler.cpp | 27 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/Common/Strings.cpp | 77 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp | 8 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/Common/Timer.cpp | 80 |
6 files changed, 200 insertions, 11 deletions
diff --git a/contrib/llvm/tools/lld/Common/Args.cpp b/contrib/llvm/tools/lld/Common/Args.cpp index 680cf5bd0a6e..ff77bfcc3b76 100644 --- a/contrib/llvm/tools/lld/Common/Args.cpp +++ b/contrib/llvm/tools/lld/Common/Args.cpp @@ -18,13 +18,17 @@ 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; + auto *A = Args.getLastArg(Key); + if (!A) + return Default; + + int V; + if (to_integer(A->getValue(), V, 10)) + return V; + + StringRef Spelling = Args.getArgString(A->getIndex()); + error(Spelling + ": number expected, but got '" + A->getValue() + "'"); + return 0; } std::vector<StringRef> lld::args::getStrings(opt::InputArgList &Args, int Id) { diff --git a/contrib/llvm/tools/lld/Common/CMakeLists.txt b/contrib/llvm/tools/lld/Common/CMakeLists.txt index b376893f35a4..a45fe209f06f 100644 --- a/contrib/llvm/tools/lld/Common/CMakeLists.txt +++ b/contrib/llvm/tools/lld/Common/CMakeLists.txt @@ -10,6 +10,7 @@ add_lld_library(lldCommon Strings.cpp TargetOptionsCommandFlags.cpp Threads.cpp + Timer.cpp Version.cpp ADDITIONAL_HEADER_DIRS diff --git a/contrib/llvm/tools/lld/Common/ErrorHandler.cpp b/contrib/llvm/tools/lld/Common/ErrorHandler.cpp index 18affce4d5a6..d1cb3dbbe03c 100644 --- a/contrib/llvm/tools/lld/Common/ErrorHandler.cpp +++ b/contrib/llvm/tools/lld/Common/ErrorHandler.cpp @@ -12,7 +12,8 @@ #include "lld/Common/Threads.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/Error.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include <mutex> @@ -59,6 +60,30 @@ void lld::exitLld(int Val) { _exit(Val); } +void lld::diagnosticHandler(const DiagnosticInfo &DI) { + SmallString<128> S; + raw_svector_ostream OS(S); + DiagnosticPrinterRawOStream DP(OS); + DI.print(DP); + switch (DI.getSeverity()) { + case DS_Error: + error(S); + break; + case DS_Warning: + warn(S); + break; + case DS_Remark: + case DS_Note: + message(S); + break; + } +} + +void lld::checkError(Error E) { + handleAllErrors(std::move(E), + [&](ErrorInfoBase &EIB) { error(EIB.message()); }); +} + void ErrorHandler::print(StringRef S, raw_ostream::Colors C) { *ErrorOS << LogName << ": "; if (ColorDiagnostics) { diff --git a/contrib/llvm/tools/lld/Common/Strings.cpp b/contrib/llvm/tools/lld/Common/Strings.cpp index 6cd4ad8d600a..36f4f77d8476 100644 --- a/contrib/llvm/tools/lld/Common/Strings.cpp +++ b/contrib/llvm/tools/lld/Common/Strings.cpp @@ -8,7 +8,21 @@ //===----------------------------------------------------------------------===// #include "lld/Common/Strings.h" +#include "lld/Common/ErrorHandler.h" +#include "lld/Common/LLVM.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/Support/GlobPattern.h" +#include <algorithm> +#include <mutex> +#include <vector> + +#if defined(_MSC_VER) +#include <Windows.h> + +// DbgHelp.h must be included after Windows.h. +#include <DbgHelp.h> +#pragma comment(lib, "dbghelp.lib") +#endif using namespace llvm; using namespace lld; @@ -30,3 +44,66 @@ Optional<std::string> lld::demangleItanium(StringRef Name) { free(Buf); return S; } + +Optional<std::string> lld::demangleMSVC(StringRef S) { +#if defined(_MSC_VER) + // UnDecorateSymbolName is not thread-safe, so we need a mutex. + static std::mutex Mu; + std::lock_guard<std::mutex> Lock(Mu); + + char Buf[4096]; + if (S.startswith("?")) + if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0)) + return std::string(Buf, Len); +#endif + return None; +} + +StringMatcher::StringMatcher(ArrayRef<StringRef> Pat) { + for (StringRef S : Pat) { + Expected<GlobPattern> Pat = GlobPattern::create(S); + if (!Pat) + error(toString(Pat.takeError())); + else + Patterns.push_back(*Pat); + } +} + +bool StringMatcher::match(StringRef S) const { + for (const GlobPattern &Pat : Patterns) + if (Pat.match(S)) + return true; + return false; +} + +// Converts a hex string (e.g. "deadbeef") to a vector. +std::vector<uint8_t> lld::parseHex(StringRef S) { + std::vector<uint8_t> Hex; + while (!S.empty()) { + StringRef B = S.substr(0, 2); + S = S.substr(2); + uint8_t H; + if (!to_integer(B, H, 16)) { + error("not a hexadecimal value: " + B); + return {}; + } + Hex.push_back(H); + } + return Hex; +} + +// Returns true if S is valid as a C language identifier. +bool lld::isValidCIdentifier(StringRef S) { + return !S.empty() && (isAlpha(S[0]) || S[0] == '_') && + std::all_of(S.begin() + 1, S.end(), + [](char C) { return C == '_' || isAlnum(C); }); +} + +// Write the contents of the a buffer to a file +void lld::saveBuffer(StringRef Buffer, const Twine &Path) { + std::error_code EC; + raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); + if (EC) + error("cannot create " + Path + ": " + EC.message()); + OS << Buffer; +} diff --git a/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp b/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp index e8e582f4c256..b46df363c361 100644 --- a/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp +++ b/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file exists as a place for global variables defined in LLVM's -// CodeGen/CommandFlags.def. By putting the resulting object file in +// CodeGen/CommandFlags.inc. 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. // @@ -16,12 +16,12 @@ #include "lld/Common/TargetOptionsCommandFlags.h" -#include "llvm/CodeGen/CommandFlags.def" +#include "llvm/CodeGen/CommandFlags.inc" #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 +// used without having to include llvm/CodeGen/CommandFlags.inc, which // would lead to multiple definitions of the command line flags. llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() { return ::InitTargetOptionsFromCodeGenFlags(); @@ -30,3 +30,5 @@ llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() { llvm::Optional<llvm::CodeModel::Model> lld::GetCodeModelFromCMModel() { return getCodeModel(); } + +std::string lld::GetCPUStr() { return ::getCPUStr(); } diff --git a/contrib/llvm/tools/lld/Common/Timer.cpp b/contrib/llvm/tools/lld/Common/Timer.cpp new file mode 100644 index 000000000000..89f9829b47cf --- /dev/null +++ b/contrib/llvm/tools/lld/Common/Timer.cpp @@ -0,0 +1,80 @@ +//===- Timer.cpp ----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Timer.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/Support/Format.h" + +using namespace lld; +using namespace llvm; + +ScopedTimer::ScopedTimer(Timer &T) : T(&T) { T.start(); } + +void ScopedTimer::stop() { + if (!T) + return; + T->stop(); + T = nullptr; +} + +ScopedTimer::~ScopedTimer() { stop(); } + +Timer::Timer(llvm::StringRef Name) : Name(Name), Parent(nullptr) {} +Timer::Timer(llvm::StringRef Name, Timer &Parent) + : Name(Name), Parent(&Parent) {} + +void Timer::start() { + if (Parent && Total.count() == 0) + Parent->Children.push_back(this); + StartTime = std::chrono::high_resolution_clock::now(); +} + +void Timer::stop() { + Total += (std::chrono::high_resolution_clock::now() - StartTime); +} + +Timer &Timer::root() { + static Timer RootTimer("Total Link Time"); + return RootTimer; +} + +void Timer::print() { + double TotalDuration = static_cast<double>(root().millis()); + + // We want to print the grand total under all the intermediate phases, so we + // print all children first, then print the total under that. + for (const auto &Child : Children) + Child->print(1, TotalDuration); + + message(std::string(49, '-')); + + root().print(0, root().millis(), false); +} + +double Timer::millis() const { + return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>( + Total) + .count(); +} + +void Timer::print(int Depth, double TotalDuration, bool Recurse) const { + double P = 100.0 * millis() / TotalDuration; + + SmallString<32> Str; + llvm::raw_svector_ostream Stream(Str); + std::string S = std::string(Depth * 2, ' ') + Name + std::string(":"); + Stream << format("%-30s%5d ms (%5.1f%%)", S.c_str(), (int)millis(), P); + + message(Str); + + if (Recurse) { + for (const auto &Child : Children) + Child->print(Depth + 1, TotalDuration); + } +} |