]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/ELF/Error.cpp
Merge lld trunk r300422 and resolve conflicts.
[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   }
64 }
65
66 void elf::message(const Twine &Msg) {
67   std::lock_guard<std::mutex> Lock(Mu);
68   outs() << Msg << "\n";
69   outs().flush();
70 }
71
72 void elf::warn(const Twine &Msg) {
73   if (Config->FatalWarnings) {
74     error(Msg);
75     return;
76   }
77
78   std::lock_guard<std::mutex> Lock(Mu);
79   newline(Msg);
80   print("warning: ", raw_ostream::MAGENTA);
81   *ErrorOS << Msg << "\n";
82 }
83
84 void elf::error(const Twine &Msg) {
85   std::lock_guard<std::mutex> Lock(Mu);
86   newline(Msg);
87
88   if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
89     print("error: ", raw_ostream::RED);
90     *ErrorOS << Msg << "\n";
91   } else if (ErrorCount == Config->ErrorLimit) {
92     print("error: ", raw_ostream::RED);
93     *ErrorOS << "too many errors emitted, stopping now"
94              << " (use -error-limit=0 to see all errors)\n";
95     if (Config->ExitEarly)
96       exitLld(1);
97   }
98
99   ++ErrorCount;
100 }
101
102 void elf::exitLld(int Val) {
103   // Dealloc/destroy ManagedStatic variables before calling
104   // _exit(). In a non-LTO build, this is a nop. In an LTO
105   // build allows us to get the output of -time-passes.
106   llvm_shutdown();
107
108   outs().flush();
109   errs().flush();
110   _exit(Val);
111 }
112
113 void elf::fatal(const Twine &Msg) {
114   error(Msg);
115   exitLld(1);
116 }