1 //===- ErrorHandler.cpp ---------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lld/Common/ErrorHandler.h" 10 11 #include "lld/Common/Threads.h" 12 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/IR/DiagnosticInfo.h" 15 #include "llvm/IR/DiagnosticPrinter.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 any temporary file, while keeping the memory mapping open. 50 if (errorHandler().outputBuffer) 51 errorHandler().outputBuffer->discard(); 52 53 // Dealloc/destroy ManagedStatic variables before calling 54 // _exit(). In a non-LTO build, this is a nop. In an LTO 55 // build allows us to get the output of -time-passes. 56 llvm_shutdown(); 57 58 outs().flush(); 59 errs().flush(); 60 _exit(val); 61 } 62 63 void lld::diagnosticHandler(const DiagnosticInfo &di) { 64 SmallString<128> s; 65 raw_svector_ostream os(s); 66 DiagnosticPrinterRawOStream dp(os); 67 di.print(dp); 68 switch (di.getSeverity()) { 69 case DS_Error: 70 error(s); 71 break; 72 case DS_Warning: 73 warn(s); 74 break; 75 case DS_Remark: 76 case DS_Note: 77 message(s); 78 break; 79 } 80 } 81 82 void lld::checkError(Error e) { 83 handleAllErrors(std::move(e), 84 [&](ErrorInfoBase &eib) { error(eib.message()); }); 85 } 86 87 void ErrorHandler::print(StringRef s, raw_ostream::Colors c) { 88 *errorOS << logName << ": "; 89 if (colorDiagnostics) { 90 errorOS->changeColor(c, true); 91 *errorOS << s; 92 errorOS->resetColor(); 93 } else { 94 *errorOS << s; 95 } 96 } 97 98 void ErrorHandler::log(const Twine &msg) { 99 if (verbose) { 100 std::lock_guard<std::mutex> lock(mu); 101 *errorOS << logName << ": " << msg << "\n"; 102 } 103 } 104 105 void ErrorHandler::message(const Twine &msg) { 106 std::lock_guard<std::mutex> lock(mu); 107 outs() << msg << "\n"; 108 outs().flush(); 109 } 110 111 void ErrorHandler::warn(const Twine &msg) { 112 if (fatalWarnings) { 113 error(msg); 114 return; 115 } 116 117 std::lock_guard<std::mutex> lock(mu); 118 newline(errorOS, msg); 119 print("warning: ", raw_ostream::MAGENTA); 120 *errorOS << msg << "\n"; 121 } 122 123 void ErrorHandler::error(const Twine &msg) { 124 std::lock_guard<std::mutex> lock(mu); 125 newline(errorOS, msg); 126 127 if (errorLimit == 0 || errorCount < errorLimit) { 128 print("error: ", raw_ostream::RED); 129 *errorOS << msg << "\n"; 130 } else if (errorCount == errorLimit) { 131 print("error: ", raw_ostream::RED); 132 *errorOS << errorLimitExceededMsg << "\n"; 133 if (exitEarly) 134 exitLld(1); 135 } 136 137 ++errorCount; 138 } 139 140 void ErrorHandler::fatal(const Twine &msg) { 141 error(msg); 142 exitLld(1); 143 } 144