1 //===- ErrorHandler.cpp ---------------------------------------------------===//
2 //
3 // The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lld/Common/ErrorHandler.h"
11
12 #include "lld/Common/Threads.h"
13
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/IR/DiagnosticInfo.h"
16 #include "llvm/IR/DiagnosticPrinter.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include <mutex>
20
21 #if !defined(_MSC_VER) && !defined(__MINGW32__)
22 #include <unistd.h>
23 #endif
24
25 using namespace llvm;
26 using namespace lld;
27
28 // The functions defined in this file can be called from multiple threads,
29 // but outs() or errs() are not thread-safe. We protect them using a mutex.
30 static std::mutex Mu;
31
32 // Prints "\n" or does nothing, depending on Msg contents of
33 // the previous call of this function.
newline(raw_ostream * ErrorOS,const Twine & Msg)34 static void newline(raw_ostream *ErrorOS, const Twine &Msg) {
35 // True if the previous error message contained "\n".
36 // We want to separate multi-line error messages with a newline.
37 static bool Flag;
38
39 if (Flag)
40 *ErrorOS << "\n";
41 Flag = StringRef(Msg.str()).contains('\n');
42 }
43
errorHandler()44 ErrorHandler &lld::errorHandler() {
45 static ErrorHandler Handler;
46 return Handler;
47 }
48
exitLld(int Val)49 void lld::exitLld(int Val) {
50 // Delete any temporary file, while keeping the memory mapping open.
51 if (errorHandler().OutputBuffer)
52 errorHandler().OutputBuffer->discard();
53
54 // Dealloc/destroy ManagedStatic variables before calling
55 // _exit(). In a non-LTO build, this is a nop. In an LTO
56 // build allows us to get the output of -time-passes.
57 llvm_shutdown();
58
59 outs().flush();
60 errs().flush();
61 _exit(Val);
62 }
63
diagnosticHandler(const DiagnosticInfo & DI)64 void lld::diagnosticHandler(const DiagnosticInfo &DI) {
65 SmallString<128> S;
66 raw_svector_ostream OS(S);
67 DiagnosticPrinterRawOStream DP(OS);
68 DI.print(DP);
69 switch (DI.getSeverity()) {
70 case DS_Error:
71 error(S);
72 break;
73 case DS_Warning:
74 warn(S);
75 break;
76 case DS_Remark:
77 case DS_Note:
78 message(S);
79 break;
80 }
81 }
82
checkError(Error E)83 void lld::checkError(Error E) {
84 handleAllErrors(std::move(E),
85 [&](ErrorInfoBase &EIB) { error(EIB.message()); });
86 }
87
print(StringRef S,raw_ostream::Colors C)88 void ErrorHandler::print(StringRef S, raw_ostream::Colors C) {
89 *ErrorOS << LogName << ": ";
90 if (ColorDiagnostics) {
91 ErrorOS->changeColor(C, true);
92 *ErrorOS << S;
93 ErrorOS->resetColor();
94 } else {
95 *ErrorOS << S;
96 }
97 }
98
log(const Twine & Msg)99 void ErrorHandler::log(const Twine &Msg) {
100 if (Verbose) {
101 std::lock_guard<std::mutex> Lock(Mu);
102 *ErrorOS << LogName << ": " << Msg << "\n";
103 }
104 }
105
message(const Twine & Msg)106 void ErrorHandler::message(const Twine &Msg) {
107 std::lock_guard<std::mutex> Lock(Mu);
108 outs() << Msg << "\n";
109 outs().flush();
110 }
111
warn(const Twine & Msg)112 void ErrorHandler::warn(const Twine &Msg) {
113 if (FatalWarnings) {
114 error(Msg);
115 return;
116 }
117
118 std::lock_guard<std::mutex> Lock(Mu);
119 newline(ErrorOS, Msg);
120 print("warning: ", raw_ostream::MAGENTA);
121 *ErrorOS << Msg << "\n";
122 }
123
error(const Twine & Msg)124 void ErrorHandler::error(const Twine &Msg) {
125 std::lock_guard<std::mutex> Lock(Mu);
126 newline(ErrorOS, Msg);
127
128 if (ErrorLimit == 0 || ErrorCount < ErrorLimit) {
129 print("error: ", raw_ostream::RED);
130 *ErrorOS << Msg << "\n";
131 } else if (ErrorCount == ErrorLimit) {
132 print("error: ", raw_ostream::RED);
133 *ErrorOS << ErrorLimitExceededMsg << "\n";
134 if (ExitEarly)
135 exitLld(1);
136 }
137
138 ++ErrorCount;
139 }
140
fatal(const Twine & Msg)141 void ErrorHandler::fatal(const Twine &Msg) {
142 error(Msg);
143 exitLld(1);
144 }
145