diff options
Diffstat (limited to 'ELF/Error.cpp')
-rw-r--r-- | ELF/Error.cpp | 91 |
1 files changed, 66 insertions, 25 deletions
diff --git a/ELF/Error.cpp b/ELF/Error.cpp index 59a49c17b97c..6e30f08143ed 100644 --- a/ELF/Error.cpp +++ b/ELF/Error.cpp @@ -12,54 +12,95 @@ #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 lld::elf; using namespace llvm; namespace lld { -namespace elf { -bool HasError; -raw_ostream *ErrorOS; +uint64_t elf::ErrorCount; +raw_ostream *elf::ErrorOS; +StringRef elf::Argv0; + +// 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; + +static void print(StringRef S, raw_ostream::Colors C) { + *ErrorOS << Argv0 + ": "; + if (Config->ColorDiagnostics) { + ErrorOS->changeColor(C, true); + *ErrorOS << S; + ErrorOS->resetColor(); + } else { + *ErrorOS << S; + } +} -void log(const Twine &Msg) { +void elf::log(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); if (Config->Verbose) - outs() << Msg << "\n"; + outs() << Argv0 << ": " << Msg << "\n"; } -void warning(const Twine &Msg) { - if (Config->FatalWarnings) +void elf::warn(const Twine &Msg) { + if (Config->FatalWarnings) { error(Msg); - else - *ErrorOS << Msg << "\n"; + return; + } + std::lock_guard<std::mutex> Lock(Mu); + print("warning: ", raw_ostream::MAGENTA); + *ErrorOS << Msg << "\n"; } -void error(const Twine &Msg) { - *ErrorOS << Msg << "\n"; - HasError = true; +void elf::error(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + + if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) { + print("error: ", raw_ostream::RED); + *ErrorOS << Msg << "\n"; + } else if (ErrorCount == Config->ErrorLimit) { + print("error: ", raw_ostream::RED); + *ErrorOS << "too many errors emitted, stopping now" + << " (use -error-limit=0 to see all errors)\n"; + if (Config->ExitEarly) + exitLld(1); + } + + ++ErrorCount; } -void error(std::error_code EC, const Twine &Prefix) { +void elf::error(std::error_code EC, const Twine &Prefix) { error(Prefix + ": " + EC.message()); } -void fatal(const Twine &Msg) { - *ErrorOS << Msg << "\n"; - exit(1); -} +void elf::exitLld(int Val) { + // 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(); -void fatal(const Twine &Msg, const Twine &Prefix) { - fatal(Prefix + ": " + Msg); + outs().flush(); + errs().flush(); + _exit(Val); } -void check(std::error_code EC) { - if (EC) - fatal(EC.message()); +void elf::fatal(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + print("error: ", raw_ostream::RED); + *ErrorOS << Msg << "\n"; + exitLld(1); } -void check(Error Err) { - check(errorToErrorCode(std::move(Err))); +void elf::fatal(std::error_code EC, const Twine &Prefix) { + fatal(Prefix + ": " + EC.message()); } -} // namespace elf } // namespace lld |