From 375564339a2c07f952e755b08185d6d8272ff383 Mon Sep 17 00:00:00 2001 From: Torok Edwin Date: Tue, 7 Jul 2009 17:32:34 +0000 Subject: [PATCH] Introduce new error handling API. This will replace exit()/abort() style error handling with an API that allows clients to register custom error handling hooks. The default is to call exit(1) when no error handler is provided. llvm-svn: 74922 --- include/llvm/Support/Compiler.h | 6 +++ include/llvm/Support/ErrorHandling.h | 52 ++++++++++++++++++++++++ lib/ExecutionEngine/ExecutionEngine.cpp | 8 ++-- lib/ExecutionEngine/JIT/JIT.cpp | 6 +-- lib/Support/ErrorHandling.cpp | 53 +++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 include/llvm/Support/ErrorHandling.h create mode 100644 lib/Support/ErrorHandling.cpp diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 90292df3819..853324611bb 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -56,4 +56,10 @@ #define DISABLE_INLINE #endif +#ifdef __GNUC__ +#define NORETURN __attribute__((noreturn)) +#else +#define NORETURN +#endif + #endif diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h new file mode 100644 index 00000000000..445d3b6cf0f --- /dev/null +++ b/include/llvm/Support/ErrorHandling.h @@ -0,0 +1,52 @@ +//===- llvm/Support/ErrorHandling.h - Callbacks for errors ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API used to indicate error conditions. +// Callbacks can be registered for these errors through this API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRORHANDLING_H +#define LLVM_SUPPORT_ERRORHANDLING_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + // An error handler callback. + typedef void (*llvm_error_handler_t)(const std::string& reason); + + // Installs a new error handler: this function will be called whenever a + // serious error is encountered by LLVM. + // If you are using llvm_start_multithreaded, you should register the handler + // before doing that. + // + // If no error handler is installed the default is to print the error message + // to stderr, and call exit(1). + // If an error handler is installed then it is the handler's responsibility to + // log the message, it will no longer be printed to stderr. + // If the error handler returns, then exit(1) will be called. + void llvm_install_error_handler(llvm_error_handler_t handler); + + // Restores default error handling behaviour. + // This must not be called between llvm_start_multithreaded() and + // llvm_stop_multithreaded(). + void llvm_remove_error_handler(void); + + // Reports a serious error, calling any installed error handler. + // If no error handler is installed the default is to print the message to + void llvm_report_error(const std::string &reason) NORETURN; + + // This function calls abort(). + // Call this after assert(0), so that compiler knows the path is not + // reachable. + void llvm_unreachable(void) NORETURN; +} + +#endif + diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index a80513f3df9..69518b65849 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -22,6 +22,7 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MutexGuard.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/System/Host.h" @@ -640,7 +641,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { case Type::FP128TyID: { APFloat apfLHS = APFloat(LHS.IntVal); switch (CE->getOpcode()) { - default: assert(0 && "Invalid long double opcode"); abort(); + default: assert(0 && "Invalid long double opcode");llvm_unreachable(); case Instruction::FAdd: apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); @@ -953,9 +954,8 @@ void ExecutionEngine::emitGlobals() { sys::DynamicLibrary::SearchForAddressOfSymbol(I->getName().c_str())) addGlobalMapping(I, SymAddr); else { - cerr << "Could not resolve external global address: " - << I->getName() << "\n"; - abort(); + llvm_report_error("Could not resolve external global address: " + +I->getName()); } } } diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 1d8312f7629..785b5b9284f 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -27,6 +27,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetJITInfo.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MutexGuard.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/Config/config.h" @@ -671,9 +672,8 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { #endif Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName().c_str()); if (Ptr == 0 && !areDlsymStubsEnabled()) { - cerr << "Could not resolve external global address: " - << GV->getName() << "\n"; - abort(); + llvm_report_error("Could not resolve external global address: " + +GV->getName()); } addGlobalMapping(GV, Ptr); } else { diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp new file mode 100644 index 00000000000..2f8f7d4830c --- /dev/null +++ b/lib/Support/ErrorHandling.cpp @@ -0,0 +1,53 @@ +//===- lib/Support/ErrorHandling.cpp - Callbacks for errors -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API for error handling, it supersedes cerr+abort(), and +// cerr+exit() style error handling. +// Callbacks can be registered for these errors through this API. +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Threading.h" +#include +#include + +using namespace llvm; +using namespace std; + +static llvm_error_handler_t ErrorHandler = 0; +namespace llvm { +void llvm_install_error_handler(llvm_error_handler_t handler) { + assert(!llvm_is_multithreaded() && + "Cannot register error handlers after starting multithreaded mode!\n"); + assert(!ErrorHandler && "Error handler already registered!\n"); + ErrorHandler = handler; +} + +void llvm_remove_error_handler(void) { + ErrorHandler = 0; +} + +void llvm_report_error(const std::string &reason) +{ + if (!ErrorHandler) { + errs() << "LLVM ERROR: " << reason << "\n"; + } else { + ErrorHandler(reason); + } + exit(1); +} + +void llvm_unreachable(void) +{ + abort(); +} +} +