summaryrefslogtreecommitdiff
path: root/ELF/Error.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/Error.cpp')
-rw-r--r--ELF/Error.cpp91
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