Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:41

0001 //===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // We designed lld's error handlers with the following goals in mind:
0010 //
0011 //  - Errors can occur at any place where we handle user input, but we don't
0012 //    want them to affect the normal execution path too much. Ideally,
0013 //    handling errors should be as simple as reporting them and exit (but
0014 //    without actually doing exit).
0015 //
0016 //    In particular, the design to wrap all functions that could fail with
0017 //    ErrorOr<T> is rejected because otherwise we would have to wrap a large
0018 //    number of functions in lld with ErrorOr. With that approach, if some
0019 //    function F can fail, not only F but all functions that transitively call
0020 //    F have to be wrapped with ErrorOr. That seemed too much.
0021 //
0022 //  - Finding only one error at a time is not sufficient. We want to find as
0023 //    many errors as possible with one execution of the linker. That means the
0024 //    linker needs to keep running after a first error and give up at some
0025 //    checkpoint (beyond which it would find cascading, false errors caused by
0026 //    the previous errors).
0027 //
0028 //  - We want a simple interface to report errors. Unlike Clang, the data we
0029 //    handle is compiled binary, so we don't need an error reporting mechanism
0030 //    that's as sophisticated as the one that Clang has.
0031 //
0032 // The current lld's error handling mechanism is simple:
0033 //
0034 //  - When you find an error, report it using error() and continue as far as
0035 //    you can. An internal error counter is incremented by one every time you
0036 //    call error().
0037 //
0038 //    A common idiom to handle an error is calling error() and then returning
0039 //    a reasonable default value. For example, if your function handles a
0040 //    user-supplied alignment value, and if you find an invalid alignment
0041 //    (e.g. 17 which is not 2^n), you may report it using error() and continue
0042 //    as if it were alignment 1 (which is the simplest reasonable value).
0043 //
0044 //    Note that you should not continue with an invalid value; that breaks the
0045 //    internal consistency. You need to maintain all variables have some sane
0046 //    value even after an error occurred. So, when you have to continue with
0047 //    some value, always use a dummy value.
0048 //
0049 //  - Find a reasonable checkpoint at where you want to stop the linker, and
0050 //    add code to return from the function if errorCount() > 0. In most cases,
0051 //    a checkpoint already exists, so you don't need to do anything for this.
0052 //
0053 // This interface satisfies all the goals that we mentioned above.
0054 //
0055 // You should never call fatal() except for reporting a corrupted input file.
0056 // fatal() immediately terminates the linker, so the function is not desirable
0057 // if you are using lld as a subroutine in other program, and with that you
0058 // can find only one error at a time.
0059 //
0060 // warn() doesn't do anything but printing out a given message.
0061 //
0062 // It is not recommended to use llvm::outs() or lld::errs() directly in lld
0063 // because they are not thread-safe. The functions declared in this file are
0064 // thread-safe.
0065 //
0066 //===----------------------------------------------------------------------===//
0067 
0068 #ifndef LLD_COMMON_ERRORHANDLER_H
0069 #define LLD_COMMON_ERRORHANDLER_H
0070 
0071 #include "lld/Common/LLVM.h"
0072 
0073 #include "llvm/ADT/STLExtras.h"
0074 #include "llvm/ADT/SmallString.h"
0075 #include "llvm/Support/Error.h"
0076 #include "llvm/Support/FileOutputBuffer.h"
0077 #include "llvm/Support/raw_ostream.h"
0078 #include <mutex>
0079 
0080 namespace llvm {
0081 class DiagnosticInfo;
0082 }
0083 
0084 namespace lld {
0085 
0086 llvm::raw_ostream &outs();
0087 
0088 enum class ErrorTag { LibNotFound, SymbolNotFound };
0089 
0090 class ErrorHandler {
0091 public:
0092   ~ErrorHandler();
0093 
0094   void initialize(llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS,
0095                   bool exitEarly, bool disableOutput);
0096 
0097   uint64_t errorCount = 0;
0098   uint64_t errorLimit = 20;
0099   StringRef errorLimitExceededMsg = "too many errors emitted, stopping now";
0100   StringRef errorHandlingScript;
0101   StringRef logName = "lld";
0102   bool exitEarly = true;
0103   bool fatalWarnings = false;
0104   bool suppressWarnings = false;
0105   bool verbose = false;
0106   bool vsDiagnostics = false;
0107   bool disableOutput = false;
0108   std::function<void()> cleanupCallback;
0109 
0110   void error(const Twine &msg);
0111   void error(const Twine &msg, ErrorTag tag, ArrayRef<StringRef> args);
0112   [[noreturn]] void fatal(const Twine &msg);
0113   void log(const Twine &msg);
0114   void message(const Twine &msg, llvm::raw_ostream &s);
0115   void warn(const Twine &msg);
0116 
0117   raw_ostream &outs();
0118   raw_ostream &errs();
0119   void flushStreams();
0120 
0121   std::unique_ptr<llvm::FileOutputBuffer> outputBuffer;
0122 
0123 private:
0124   using Colors = raw_ostream::Colors;
0125 
0126   std::string getLocation(const Twine &msg);
0127   void reportDiagnostic(StringRef location, Colors c, StringRef diagKind,
0128                         const Twine &msg);
0129 
0130   // We want to separate multi-line messages with a newline. `sep` is "\n"
0131   // if the last messages was multi-line. Otherwise "".
0132   llvm::StringRef sep;
0133 
0134   // We wrap stdout and stderr so that you can pass alternative stdout/stderr as
0135   // arguments to lld::*::link() functions. Since lld::outs() or lld::errs() can
0136   // be indirectly called from multiple threads, we protect them using a mutex.
0137   // In the future, we plan on supporting several concurrent linker contexts,
0138   // which explains why the mutex is not a global but part of this context.
0139   std::mutex mu;
0140   llvm::raw_ostream *stdoutOS{};
0141   llvm::raw_ostream *stderrOS{};
0142 };
0143 
0144 /// Returns the default error handler.
0145 ErrorHandler &errorHandler();
0146 
0147 void error(const Twine &msg);
0148 void error(const Twine &msg, ErrorTag tag, ArrayRef<StringRef> args);
0149 [[noreturn]] void fatal(const Twine &msg);
0150 void log(const Twine &msg);
0151 void message(const Twine &msg, llvm::raw_ostream &s = outs());
0152 void warn(const Twine &msg);
0153 uint64_t errorCount();
0154 
0155 enum class DiagLevel { None, Log, Msg, Warn, Err, Fatal };
0156 
0157 // A class that synchronizes thread writing to the same stream similar
0158 // std::osyncstream.
0159 class SyncStream {
0160   ErrorHandler &e;
0161   DiagLevel level;
0162   llvm::SmallString<0> buf;
0163 
0164 public:
0165   mutable llvm::raw_svector_ostream os{buf};
0166   SyncStream(ErrorHandler &e, DiagLevel level) : e(e), level(level) {}
0167   SyncStream(SyncStream &&o) : e(o.e), level(o.level), buf(std::move(o.buf)) {}
0168   ~SyncStream();
0169   StringRef str() { return os.str(); }
0170   uint64_t tell() { return os.tell(); }
0171 };
0172 
0173 [[noreturn]] void exitLld(int val);
0174 
0175 void diagnosticHandler(const llvm::DiagnosticInfo &di);
0176 void checkError(Error e);
0177 void checkError(ErrorHandler &eh, Error e);
0178 
0179 // check functions are convenient functions to strip errors
0180 // from error-or-value objects.
0181 template <class T> T check(ErrorOr<T> e) {
0182   if (auto ec = e.getError())
0183     fatal(ec.message());
0184   return std::move(*e);
0185 }
0186 
0187 template <class T> T check(Expected<T> e) {
0188   if (!e)
0189     fatal(llvm::toString(e.takeError()));
0190   return std::move(*e);
0191 }
0192 
0193 // Don't move from Expected wrappers around references.
0194 template <class T> T &check(Expected<T &> e) {
0195   if (!e)
0196     fatal(llvm::toString(e.takeError()));
0197   return *e;
0198 }
0199 
0200 template <class T>
0201 T check2(ErrorOr<T> e, llvm::function_ref<std::string()> prefix) {
0202   if (auto ec = e.getError())
0203     fatal(prefix() + ": " + ec.message());
0204   return std::move(*e);
0205 }
0206 
0207 template <class T>
0208 T check2(Expected<T> e, llvm::function_ref<std::string()> prefix) {
0209   if (!e)
0210     fatal(prefix() + ": " + toString(e.takeError()));
0211   return std::move(*e);
0212 }
0213 
0214 inline std::string toString(const Twine &s) { return s.str(); }
0215 
0216 // To evaluate the second argument lazily, we use C macro.
0217 #define CHECK(E, S) check2((E), [&] { return toString(S); })
0218 
0219 } // namespace lld
0220 
0221 #endif