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/Support/Error.h"
16 #include "llvm/Support/ManagedStatic.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <mutex>
19 
20 #if !defined(_MSC_VER) && !defined(__MINGW32__)
21 #include <unistd.h>
22 #endif
23 
24 using namespace llvm;
25 using namespace lld;
26 
27 // The functions defined in this file can be called from multiple threads,
28 // but outs() or errs() are not thread-safe. We protect them using a mutex.
29 static std::mutex Mu;
30 
31 // Prints "\n" or does nothing, depending on Msg contents of
32 // the previous call of this function.
33 static void newline(raw_ostream *ErrorOS, const Twine &Msg) {
34   // True if the previous error message contained "\n".
35   // We want to separate multi-line error messages with a newline.
36   static bool Flag;
37 
38   if (Flag)
39     *ErrorOS << "\n";
40   Flag = StringRef(Msg.str()).contains('\n');
41 }
42 
43 ErrorHandler &lld::errorHandler() {
44   static ErrorHandler Handler;
45   return Handler;
46 }
47 
48 void lld::exitLld(int Val) {
49   // Delete the output buffer so that any tempory file is deleted.
50   errorHandler().OutputBuffer.reset();
51 
52   // Dealloc/destroy ManagedStatic variables before calling
53   // _exit(). In a non-LTO build, this is a nop. In an LTO
54   // build allows us to get the output of -time-passes.
55   llvm_shutdown();
56 
57   outs().flush();
58   errs().flush();
59   _exit(Val);
60 }
61 
62 void ErrorHandler::print(StringRef S, raw_ostream::Colors C) {
63   *ErrorOS << LogName << ": ";
64   if (ColorDiagnostics) {
65     ErrorOS->changeColor(C, true);
66     *ErrorOS << S;
67     ErrorOS->resetColor();
68   } else {
69     *ErrorOS << S;
70   }
71 }
72 
73 void ErrorHandler::log(const Twine &Msg) {
74   if (Verbose) {
75     std::lock_guard<std::mutex> Lock(Mu);
76     outs() << LogName << ": " << Msg << "\n";
77     outs().flush();
78   }
79 }
80 
81 void ErrorHandler::message(const Twine &Msg) {
82   std::lock_guard<std::mutex> Lock(Mu);
83   outs() << Msg << "\n";
84   outs().flush();
85 }
86 
87 void ErrorHandler::warn(const Twine &Msg) {
88   if (FatalWarnings) {
89     error(Msg);
90     return;
91   }
92 
93   std::lock_guard<std::mutex> Lock(Mu);
94   newline(ErrorOS, Msg);
95   print("warning: ", raw_ostream::MAGENTA);
96   *ErrorOS << Msg << "\n";
97 }
98 
99 void ErrorHandler::error(const Twine &Msg) {
100   std::lock_guard<std::mutex> Lock(Mu);
101   newline(ErrorOS, Msg);
102 
103   if (ErrorLimit == 0 || ErrorCount < ErrorLimit) {
104     print("error: ", raw_ostream::RED);
105     *ErrorOS << Msg << "\n";
106   } else if (ErrorCount == ErrorLimit) {
107     print("error: ", raw_ostream::RED);
108     *ErrorOS << ErrorLimitExceededMsg << "\n";
109     if (ExitEarly)
110       exitLld(1);
111   }
112 
113   ++ErrorCount;
114 }
115 
116 void ErrorHandler::fatal(const Twine &Msg) {
117   error(Msg);
118   exitLld(1);
119 }
120