Index: lld/COFF/Driver.cpp =================================================================== --- lld/COFF/Driver.cpp +++ lld/COFF/Driver.cpp @@ -19,6 +19,7 @@ #include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Exit.h" #include "lld/Common/Memory.h" #include "lld/Common/Timer.h" #include "lld/Common/Version.h" Index: lld/Common/CMakeLists.txt =================================================================== --- lld/Common/CMakeLists.txt +++ lld/Common/CMakeLists.txt @@ -5,6 +5,7 @@ add_lld_library(lldCommon Args.cpp ErrorHandler.cpp + Exit.cpp Memory.cpp Reproduce.cpp Strings.cpp Index: lld/Common/ErrorHandler.cpp =================================================================== --- lld/Common/ErrorHandler.cpp +++ lld/Common/ErrorHandler.cpp @@ -9,19 +9,15 @@ #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Exit.h" #include "lld/Common/Threads.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include -#if !defined(_MSC_VER) && !defined(__MINGW32__) -#include -#endif - using namespace llvm; using namespace lld; @@ -46,20 +42,6 @@ return Handler; } -void lld::exitLld(int Val) { - // Delete the output buffer so that any tempory file is deleted. - errorHandler().OutputBuffer.reset(); - - // Dealloc/destroy ManagedStatic variables before calling - // _exit(). In a non-LTO build, this is a nop. In an LTO - // build allows us to get the output of -time-passes. - llvm_shutdown(); - - outs().flush(); - errs().flush(); - _exit(Val); -} - void lld::diagnosticHandler(const DiagnosticInfo &DI) { SmallString<128> S; raw_svector_ostream OS(S); Index: lld/Common/Exit.cpp =================================================================== --- /dev/null +++ lld/Common/Exit.cpp @@ -0,0 +1,51 @@ +//===- Exit.cpp - Exiting LLD -----------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Exit.h" + +#include "lld/Common/ErrorHandler.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" + +#include + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include +#endif + +using namespace llvm; + +namespace { +SmallVector, 4> ExitHandlers; +} // anonymous namespace + +namespace lld { +void addLldExitHandler(std::function &&Handler) { + ExitHandlers.push_back(Handler); +} + +void exitLld(int Val) { + for (auto I = ExitHandlers.rbegin(); I != ExitHandlers.rend(); ++I) + (*I)(); + + // Delete the output buffer so that any tempory file is deleted. + errorHandler().OutputBuffer.reset(); + + // Dealloc/destroy ManagedStatic variables before calling + // _exit(). In a non-LTO build, this is a nop. In an LTO + // build allows us to get the output of -time-passes. + llvm_shutdown(); + + outs().flush(); + errs().flush(); + _exit(Val); +} +} // namespace lld Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -41,6 +41,7 @@ #include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Exit.h" #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" #include "lld/Common/TargetOptionsCommandFlags.h" Index: lld/include/lld/Common/ErrorHandler.h =================================================================== --- lld/include/lld/Common/ErrorHandler.h +++ lld/include/lld/Common/ErrorHandler.h @@ -117,8 +117,6 @@ inline void warn(const Twine &Msg) { errorHandler().warn(Msg); } inline uint64_t errorCount() { return errorHandler().ErrorCount; } -LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); - void diagnosticHandler(const llvm::DiagnosticInfo &DI); void checkError(Error E); Index: lld/include/lld/Common/Exit.h =================================================================== --- /dev/null +++ lld/include/lld/Common/Exit.h @@ -0,0 +1,35 @@ +//===- Exit.h - Exiting LLD -------------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// In LLD, we use the exitLld() function instead of exit(). This saves time +// by not running most destructors. +// +// Because in rare cases we do want some code to run on exit, we also define +// an interface for registering such code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_COMMON_EXIT_H +#define LLD_COMMON_EXIT_H + +#include "llvm/Support/Compiler.h" + +#include + +namespace lld { + +/// Registers a function to be called when LLD exits. +/// Functions are called in reverse order of registration. +void addLldExitHandler(std::function &&Handler); + +LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); + +} // namespace lld + +#endif Index: lld/lib/Driver/DarwinLdDriver.cpp =================================================================== --- lld/lib/Driver/DarwinLdDriver.cpp +++ lld/lib/Driver/DarwinLdDriver.cpp @@ -15,6 +15,7 @@ #include "lld/Common/Args.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Exit.h" #include "lld/Common/LLVM.h" #include "lld/Core/ArchiveLibraryFile.h" #include "lld/Core/Error.h" Index: lld/wasm/Driver.cpp =================================================================== --- lld/wasm/Driver.cpp +++ lld/wasm/Driver.cpp @@ -16,6 +16,7 @@ #include "Writer.h" #include "lld/Common/Args.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Exit.h" #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" #include "lld/Common/Threads.h"