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