1 //===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
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 // We designed lld's error handlers with the following goals in mind:
11 //
12 //  - Errors can occur at any place where we handle user input, but we don't
13 //    want them to affect the normal execution path too much. Ideally,
14 //    handling errors should be as simple as reporting them and exit (but
15 //    without actually doing exit).
16 //
17 //    In particular, the design to wrap all functions that could fail with
18 //    ErrorOr<T> is rejected because otherwise we would have to wrap a large
19 //    number of functions in lld with ErrorOr. With that approach, if some
20 //    function F can fail, not only F but all functions that transitively call
21 //    F have to be wrapped with ErrorOr. That seemed too much.
22 //
23 //  - Finding only one error at a time is not sufficient. We want to find as
24 //    many errors as possible with one execution of the linker. That means the
25 //    linker needs to keep running after a first error and give up at some
26 //    checkpoint (beyond which it would find cascading, false errors caused by
27 //    the previous errors).
28 //
29 //  - We want a simple interface to report errors. Unlike Clang, the data we
30 //    handle is compiled binary, so we don't need an error reporting mechanism
31 //    that's as sophisticated as the one that Clang has.
32 //
33 // The current lld's error handling mechanism is simple:
34 //
35 //  - When you find an error, report it using error() and continue as far as
36 //    you can. An internal error counter is incremented by one every time you
37 //    call error().
38 //
39 //    A common idiom to handle an error is calling error() and then returning
40 //    a reasonable default value. For example, if your function handles a
41 //    user-supplied alignment value, and if you find an invalid alignment
42 //    (e.g. 17 which is not 2^n), you may report it using error() and continue
43 //    as if it were alignment 1 (which is the simplest reasonable value).
44 //
45 //    Note that you should not continue with an invalid value; that breaks the
46 //    internal consistency. You need to maintain all variables have some sane
47 //    value even after an error occurred. So, when you have to continue with
48 //    some value, always use a dummy value.
49 //
50 //  - Find a reasonable checkpoint at where you want to stop the linker, and
51 //    add code to return from the function if errorCount() > 0. In most cases,
52 //    a checkpoint already exists, so you don't need to do anything for this.
53 //
54 // This interface satisfies all the goals that we mentioned above.
55 //
56 // You should never call fatal() except for reporting a corrupted input file.
57 // fatal() immediately terminates the linker, so the function is not desirable
58 // if you are using lld as a subroutine in other program, and with that you
59 // can find only one error at a time.
60 //
61 // warn() doesn't do anything but printing out a given message.
62 //
63 // It is not recommended to use llvm::outs() or llvm::errs() directly in lld
64 // because they are not thread-safe. The functions declared in this file are
65 // thread-safe.
66 //
67 //===----------------------------------------------------------------------===//
68 
69 #ifndef LLD_COMMON_ERRORHANDLER_H
70 #define LLD_COMMON_ERRORHANDLER_H
71 
72 #include "lld/Common/LLVM.h"
73 
74 #include "llvm/ADT/STLExtras.h"
75 #include "llvm/Support/Error.h"
76 #include "llvm/Support/FileOutputBuffer.h"
77 
78 namespace llvm {
79 class DiagnosticInfo;
80 }
81 
82 namespace lld {
83 
84 class ErrorHandler {
85 public:
86   uint64_t ErrorCount = 0;
87   uint64_t ErrorLimit = 20;
88   StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now";
89   StringRef LogName = "lld";
90   llvm::raw_ostream *ErrorOS = &llvm::errs();
91   bool ColorDiagnostics = llvm::errs().has_colors();
92   bool ExitEarly = true;
93   bool FatalWarnings = false;
94   bool Verbose = false;
95 
96   void error(const Twine &Msg);
97   LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
98   void log(const Twine &Msg);
99   void message(const Twine &Msg);
100   void warn(const Twine &Msg);
101 
102   std::unique_ptr<llvm::FileOutputBuffer> OutputBuffer;
103 
104 private:
105   void print(StringRef S, raw_ostream::Colors C);
106 };
107 
108 /// Returns the default error handler.
109 ErrorHandler &errorHandler();
110 
error(const Twine & Msg)111 inline void error(const Twine &Msg) { errorHandler().error(Msg); }
fatal(const Twine & Msg)112 inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) {
113   errorHandler().fatal(Msg);
114 }
log(const Twine & Msg)115 inline void log(const Twine &Msg) { errorHandler().log(Msg); }
message(const Twine & Msg)116 inline void message(const Twine &Msg) { errorHandler().message(Msg); }
warn(const Twine & Msg)117 inline void warn(const Twine &Msg) { errorHandler().warn(Msg); }
errorCount()118 inline uint64_t errorCount() { return errorHandler().ErrorCount; }
119 
120 LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
121 
122 void diagnosticHandler(const llvm::DiagnosticInfo &DI);
123 void checkError(Error E);
124 
125 // check functions are convenient functions to strip errors
126 // from error-or-value objects.
check(ErrorOr<T> E)127 template <class T> T check(ErrorOr<T> E) {
128   if (auto EC = E.getError())
129     fatal(EC.message());
130   return std::move(*E);
131 }
132 
check(Expected<T> E)133 template <class T> T check(Expected<T> E) {
134   if (!E)
135     fatal(llvm::toString(E.takeError()));
136   return std::move(*E);
137 }
138 
139 template <class T>
check2(ErrorOr<T> E,llvm::function_ref<std::string ()> Prefix)140 T check2(ErrorOr<T> E, llvm::function_ref<std::string()> Prefix) {
141   if (auto EC = E.getError())
142     fatal(Prefix() + ": " + EC.message());
143   return std::move(*E);
144 }
145 
146 template <class T>
check2(Expected<T> E,llvm::function_ref<std::string ()> Prefix)147 T check2(Expected<T> E, llvm::function_ref<std::string()> Prefix) {
148   if (!E)
149     fatal(Prefix() + ": " + toString(E.takeError()));
150   return std::move(*E);
151 }
152 
toString(const Twine & S)153 inline std::string toString(const Twine &S) { return S.str(); }
154 
155 // To evaluate the second argument lazily, we use C macro.
156 #define CHECK(E, S) check2((E), [&] { return toString(S); })
157 
158 } // namespace lld
159 
160 #endif
161