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