1326947Sdim//===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
2326947Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326947Sdim//
7326947Sdim//===----------------------------------------------------------------------===//
8326947Sdim//
9341825Sdim// We designed lld's error handlers with the following goals in mind:
10326947Sdim//
11341825Sdim//  - Errors can occur at any place where we handle user input, but we don't
12341825Sdim//    want them to affect the normal execution path too much. Ideally,
13341825Sdim//    handling errors should be as simple as reporting them and exit (but
14341825Sdim//    without actually doing exit).
15326947Sdim//
16341825Sdim//    In particular, the design to wrap all functions that could fail with
17341825Sdim//    ErrorOr<T> is rejected because otherwise we would have to wrap a large
18341825Sdim//    number of functions in lld with ErrorOr. With that approach, if some
19341825Sdim//    function F can fail, not only F but all functions that transitively call
20341825Sdim//    F have to be wrapped with ErrorOr. That seemed too much.
21326947Sdim//
22341825Sdim//  - Finding only one error at a time is not sufficient. We want to find as
23341825Sdim//    many errors as possible with one execution of the linker. That means the
24341825Sdim//    linker needs to keep running after a first error and give up at some
25341825Sdim//    checkpoint (beyond which it would find cascading, false errors caused by
26341825Sdim//    the previous errors).
27326947Sdim//
28341825Sdim//  - We want a simple interface to report errors. Unlike Clang, the data we
29341825Sdim//    handle is compiled binary, so we don't need an error reporting mechanism
30341825Sdim//    that's as sophisticated as the one that Clang has.
31326947Sdim//
32341825Sdim// The current lld's error handling mechanism is simple:
33341825Sdim//
34341825Sdim//  - When you find an error, report it using error() and continue as far as
35341825Sdim//    you can. An internal error counter is incremented by one every time you
36341825Sdim//    call error().
37341825Sdim//
38341825Sdim//    A common idiom to handle an error is calling error() and then returning
39341825Sdim//    a reasonable default value. For example, if your function handles a
40341825Sdim//    user-supplied alignment value, and if you find an invalid alignment
41341825Sdim//    (e.g. 17 which is not 2^n), you may report it using error() and continue
42341825Sdim//    as if it were alignment 1 (which is the simplest reasonable value).
43341825Sdim//
44341825Sdim//    Note that you should not continue with an invalid value; that breaks the
45341825Sdim//    internal consistency. You need to maintain all variables have some sane
46341825Sdim//    value even after an error occurred. So, when you have to continue with
47341825Sdim//    some value, always use a dummy value.
48341825Sdim//
49341825Sdim//  - Find a reasonable checkpoint at where you want to stop the linker, and
50341825Sdim//    add code to return from the function if errorCount() > 0. In most cases,
51341825Sdim//    a checkpoint already exists, so you don't need to do anything for this.
52341825Sdim//
53341825Sdim// This interface satisfies all the goals that we mentioned above.
54341825Sdim//
55341825Sdim// You should never call fatal() except for reporting a corrupted input file.
56341825Sdim// fatal() immediately terminates the linker, so the function is not desirable
57341825Sdim// if you are using lld as a subroutine in other program, and with that you
58341825Sdim// can find only one error at a time.
59341825Sdim//
60341825Sdim// warn() doesn't do anything but printing out a given message.
61341825Sdim//
62360784Sdim// It is not recommended to use llvm::outs() or lld::errs() directly in lld
63341825Sdim// because they are not thread-safe. The functions declared in this file are
64341825Sdim// thread-safe.
65341825Sdim//
66326947Sdim//===----------------------------------------------------------------------===//
67326947Sdim
68326947Sdim#ifndef LLD_COMMON_ERRORHANDLER_H
69326947Sdim#define LLD_COMMON_ERRORHANDLER_H
70326947Sdim
71326947Sdim#include "lld/Common/LLVM.h"
72326947Sdim
73326947Sdim#include "llvm/ADT/STLExtras.h"
74326947Sdim#include "llvm/Support/Error.h"
75326947Sdim#include "llvm/Support/FileOutputBuffer.h"
76326947Sdim
77341825Sdimnamespace llvm {
78341825Sdimclass DiagnosticInfo;
79360784Sdimclass raw_ostream;
80341825Sdim}
81341825Sdim
82326947Sdimnamespace lld {
83326947Sdim
84360784Sdim// We wrap stdout and stderr so that you can pass alternative stdout/stderr as
85360784Sdim// arguments to lld::*::link() functions.
86360784Sdimextern llvm::raw_ostream *stdoutOS;
87360784Sdimextern llvm::raw_ostream *stderrOS;
88360784Sdim
89360784Sdimllvm::raw_ostream &outs();
90360784Sdimllvm::raw_ostream &errs();
91360784Sdim
92326947Sdimclass ErrorHandler {
93326947Sdimpublic:
94353358Sdim  uint64_t errorCount = 0;
95353358Sdim  uint64_t errorLimit = 20;
96353358Sdim  StringRef errorLimitExceededMsg = "too many errors emitted, stopping now";
97353358Sdim  StringRef logName = "lld";
98353358Sdim  bool exitEarly = true;
99353358Sdim  bool fatalWarnings = false;
100353358Sdim  bool verbose = false;
101353358Sdim  bool vsDiagnostics = false;
102326947Sdim
103353358Sdim  void error(const Twine &msg);
104353358Sdim  LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg);
105353358Sdim  void log(const Twine &msg);
106353358Sdim  void message(const Twine &msg);
107353358Sdim  void warn(const Twine &msg);
108326947Sdim
109353358Sdim  std::unique_ptr<llvm::FileOutputBuffer> outputBuffer;
110326947Sdim
111326947Sdimprivate:
112360784Sdim  using Colors = raw_ostream::Colors;
113360784Sdim
114360784Sdim  std::string getLocation(const Twine &msg);
115326947Sdim};
116326947Sdim
117326947Sdim/// Returns the default error handler.
118326947SdimErrorHandler &errorHandler();
119326947Sdim
120353358Sdiminline void error(const Twine &msg) { errorHandler().error(msg); }
121353358Sdiminline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg) {
122353358Sdim  errorHandler().fatal(msg);
123326947Sdim}
124353358Sdiminline void log(const Twine &msg) { errorHandler().log(msg); }
125353358Sdiminline void message(const Twine &msg) { errorHandler().message(msg); }
126353358Sdiminline void warn(const Twine &msg) { errorHandler().warn(msg); }
127353358Sdiminline uint64_t errorCount() { return errorHandler().errorCount; }
128326947Sdim
129353358SdimLLVM_ATTRIBUTE_NORETURN void exitLld(int val);
130326947Sdim
131353358Sdimvoid diagnosticHandler(const llvm::DiagnosticInfo &di);
132353358Sdimvoid checkError(Error e);
133341825Sdim
134326947Sdim// check functions are convenient functions to strip errors
135326947Sdim// from error-or-value objects.
136353358Sdimtemplate <class T> T check(ErrorOr<T> e) {
137353358Sdim  if (auto ec = e.getError())
138353358Sdim    fatal(ec.message());
139353358Sdim  return std::move(*e);
140326947Sdim}
141326947Sdim
142353358Sdimtemplate <class T> T check(Expected<T> e) {
143353358Sdim  if (!e)
144353358Sdim    fatal(llvm::toString(e.takeError()));
145353358Sdim  return std::move(*e);
146326947Sdim}
147326947Sdim
148326947Sdimtemplate <class T>
149353358SdimT check2(ErrorOr<T> e, llvm::function_ref<std::string()> prefix) {
150353358Sdim  if (auto ec = e.getError())
151353358Sdim    fatal(prefix() + ": " + ec.message());
152353358Sdim  return std::move(*e);
153326947Sdim}
154326947Sdim
155326947Sdimtemplate <class T>
156353358SdimT check2(Expected<T> e, llvm::function_ref<std::string()> prefix) {
157353358Sdim  if (!e)
158353358Sdim    fatal(prefix() + ": " + toString(e.takeError()));
159353358Sdim  return std::move(*e);
160326947Sdim}
161326947Sdim
162353358Sdiminline std::string toString(const Twine &s) { return s.str(); }
163326947Sdim
164326947Sdim// To evaluate the second argument lazily, we use C macro.
165344779Sdim#define CHECK(E, S) check2((E), [&] { return toString(S); })
166326947Sdim
167326947Sdim} // namespace lld
168326947Sdim
169326947Sdim#endif
170