//===-- runtime/terminate.cpp ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "terminator.h" #include #include namespace Fortran::runtime { #if !defined(RT_DEVICE_COMPILATION) [[maybe_unused]] static void (*crashHandler)( const char *, int, const char *, va_list &){nullptr}; void Terminator::RegisterCrashHandler( void (*handler)(const char *, int, const char *, va_list &)) { crashHandler = handler; } void Terminator::InvokeCrashHandler(const char *message, ...) const { if (crashHandler) { va_list ap; va_start(ap, message); crashHandler(sourceFileName_, sourceLine_, message, ap); va_end(ap); } } [[noreturn]] void Terminator::CrashArgs( const char *message, va_list &ap) const { CrashHeader(); std::vfprintf(stderr, message, ap); va_end(ap); CrashFooter(); } #endif RT_OFFLOAD_API_GROUP_BEGIN RT_API_ATTRS void Terminator::CrashHeader() const { #if defined(RT_DEVICE_COMPILATION) std::printf("\nfatal Fortran runtime error"); if (sourceFileName_) { std::printf("(%s", sourceFileName_); if (sourceLine_) { std::printf(":%d", sourceLine_); } std::printf(")"); } std::printf(": "); #else std::fputs("\nfatal Fortran runtime error", stderr); if (sourceFileName_) { std::fprintf(stderr, "(%s", sourceFileName_); if (sourceLine_) { std::fprintf(stderr, ":%d", sourceLine_); } fputc(')', stderr); } std::fputs(": ", stderr); #endif } [[noreturn]] RT_API_ATTRS void Terminator::CrashFooter() const { #if defined(RT_DEVICE_COMPILATION) std::printf("\n"); #else fputc('\n', stderr); // FIXME: re-enable the flush along with the IO enabling. io::FlushOutputOnCrash(*this); #endif NotifyOtherImagesOfErrorTermination(); #if defined(RT_DEVICE_COMPILATION) #if defined(__CUDACC__) // NVCC supports __trap(). __trap(); #elif defined(__clang__) // Clang supports __builtin_trap(). __builtin_trap(); #else #error "unsupported compiler" #endif #else std::abort(); #endif } [[noreturn]] RT_API_ATTRS void Terminator::CheckFailed( const char *predicate, const char *file, int line) const { Crash("Internal error: RUNTIME_CHECK(%s) failed at %s(%d)", predicate, file, line); } [[noreturn]] RT_API_ATTRS void Terminator::CheckFailed( const char *predicate) const { Crash("Internal error: RUNTIME_CHECK(%s) failed at %s(%d)", predicate, sourceFileName_, sourceLine_); } // TODO: These will be defined in the coarray runtime library RT_API_ATTRS void NotifyOtherImagesOfNormalEnd() {} RT_API_ATTRS void NotifyOtherImagesOfFailImageStatement() {} RT_API_ATTRS void NotifyOtherImagesOfErrorTermination() {} RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime