| //===-- 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 <cstdio> |
| #include <cstdlib> |
| |
| 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 |