xref: /llvm-project/flang/runtime/terminator.cpp (revision 4bdec5830bc398cecf6e775cc54d9dd511e6e237)
1651f58bfSDiana Picus //===-- runtime/terminate.cpp ---------------------------------------------===//
2352d347aSAlexis Perry //
3352d347aSAlexis Perry // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4352d347aSAlexis Perry // See https://llvm.org/LICENSE.txt for license information.
5352d347aSAlexis Perry // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6352d347aSAlexis Perry //
7352d347aSAlexis Perry //===----------------------------------------------------------------------===//
8352d347aSAlexis Perry 
9352d347aSAlexis Perry #include "terminator.h"
10352d347aSAlexis Perry #include <cstdio>
11352d347aSAlexis Perry #include <cstdlib>
12352d347aSAlexis Perry 
13352d347aSAlexis Perry namespace Fortran::runtime {
14352d347aSAlexis Perry 
15*4bdec583SSlava Zakharin #if !defined(RT_DEVICE_COMPILATION)
16*4bdec583SSlava Zakharin [[maybe_unused]] static void (*crashHandler)(
17*4bdec583SSlava Zakharin     const char *, int, const char *, va_list &){nullptr};
183b635714Speter klausler 
RegisterCrashHandler(void (* handler)(const char *,int,const char *,va_list &))193b635714Speter klausler void Terminator::RegisterCrashHandler(
20a39e9cf6Speter klausler     void (*handler)(const char *, int, const char *, va_list &)) {
213b635714Speter klausler   crashHandler = handler;
223b635714Speter klausler }
233b635714Speter klausler 
InvokeCrashHandler(const char * message,...) const24*4bdec583SSlava Zakharin void Terminator::InvokeCrashHandler(const char *message, ...) const {
25*4bdec583SSlava Zakharin   if (crashHandler) {
26*4bdec583SSlava Zakharin     va_list ap;
27*4bdec583SSlava Zakharin     va_start(ap, message);
28*4bdec583SSlava Zakharin     crashHandler(sourceFileName_, sourceLine_, message, ap);
29*4bdec583SSlava Zakharin     va_end(ap);
30*4bdec583SSlava Zakharin   }
31*4bdec583SSlava Zakharin }
32*4bdec583SSlava Zakharin 
CrashArgs(const char * message,va_list & ap) const3395696d56Speter klausler [[noreturn]] void Terminator::CrashArgs(
3495696d56Speter klausler     const char *message, va_list &ap) const {
35*4bdec583SSlava Zakharin   CrashHeader();
36*4bdec583SSlava Zakharin   std::vfprintf(stderr, message, ap);
37*4bdec583SSlava Zakharin   va_end(ap);
38*4bdec583SSlava Zakharin   CrashFooter();
393b635714Speter klausler }
40*4bdec583SSlava Zakharin #endif
41*4bdec583SSlava Zakharin 
42*4bdec583SSlava Zakharin RT_OFFLOAD_API_GROUP_BEGIN
43*4bdec583SSlava Zakharin 
CrashHeader() const44*4bdec583SSlava Zakharin RT_API_ATTRS void Terminator::CrashHeader() const {
45*4bdec583SSlava Zakharin #if defined(RT_DEVICE_COMPILATION)
46*4bdec583SSlava Zakharin   std::printf("\nfatal Fortran runtime error");
47*4bdec583SSlava Zakharin   if (sourceFileName_) {
48*4bdec583SSlava Zakharin     std::printf("(%s", sourceFileName_);
49*4bdec583SSlava Zakharin     if (sourceLine_) {
50*4bdec583SSlava Zakharin       std::printf(":%d", sourceLine_);
51*4bdec583SSlava Zakharin     }
52*4bdec583SSlava Zakharin     std::printf(")");
53*4bdec583SSlava Zakharin   }
54*4bdec583SSlava Zakharin   std::printf(": ");
55*4bdec583SSlava Zakharin #else
56352d347aSAlexis Perry   std::fputs("\nfatal Fortran runtime error", stderr);
57352d347aSAlexis Perry   if (sourceFileName_) {
58352d347aSAlexis Perry     std::fprintf(stderr, "(%s", sourceFileName_);
59352d347aSAlexis Perry     if (sourceLine_) {
60352d347aSAlexis Perry       std::fprintf(stderr, ":%d", sourceLine_);
61352d347aSAlexis Perry     }
62352d347aSAlexis Perry     fputc(')', stderr);
63352d347aSAlexis Perry   }
64352d347aSAlexis Perry   std::fputs(": ", stderr);
65*4bdec583SSlava Zakharin #endif
66352d347aSAlexis Perry }
67352d347aSAlexis Perry 
CrashFooter() const68*4bdec583SSlava Zakharin [[noreturn]] RT_API_ATTRS void Terminator::CrashFooter() const {
69*4bdec583SSlava Zakharin #if defined(RT_DEVICE_COMPILATION)
70*4bdec583SSlava Zakharin   std::printf("\n");
71*4bdec583SSlava Zakharin #else
72*4bdec583SSlava Zakharin   fputc('\n', stderr);
73*4bdec583SSlava Zakharin   // FIXME: re-enable the flush along with the IO enabling.
74*4bdec583SSlava Zakharin   io::FlushOutputOnCrash(*this);
75*4bdec583SSlava Zakharin #endif
76*4bdec583SSlava Zakharin   NotifyOtherImagesOfErrorTermination();
77*4bdec583SSlava Zakharin #if defined(RT_DEVICE_COMPILATION)
78*4bdec583SSlava Zakharin #if defined(__CUDACC__)
79*4bdec583SSlava Zakharin   // NVCC supports __trap().
80*4bdec583SSlava Zakharin   __trap();
81*4bdec583SSlava Zakharin #elif defined(__clang__)
82*4bdec583SSlava Zakharin   // Clang supports __builtin_trap().
83*4bdec583SSlava Zakharin   __builtin_trap();
84*4bdec583SSlava Zakharin #else
85*4bdec583SSlava Zakharin #error "unsupported compiler"
86*4bdec583SSlava Zakharin #endif
87*4bdec583SSlava Zakharin #else
88*4bdec583SSlava Zakharin   std::abort();
89*4bdec583SSlava Zakharin #endif
90*4bdec583SSlava Zakharin }
91*4bdec583SSlava Zakharin 
CheckFailed(const char * predicate,const char * file,int line) const92*4bdec583SSlava Zakharin [[noreturn]] RT_API_ATTRS void Terminator::CheckFailed(
9395696d56Speter klausler     const char *predicate, const char *file, int line) const {
94352d347aSAlexis Perry   Crash("Internal error: RUNTIME_CHECK(%s) failed at %s(%d)", predicate, file,
95352d347aSAlexis Perry       line);
96352d347aSAlexis Perry }
97352d347aSAlexis Perry 
CheckFailed(const char * predicate) const98*4bdec583SSlava Zakharin [[noreturn]] RT_API_ATTRS void Terminator::CheckFailed(
99*4bdec583SSlava Zakharin     const char *predicate) const {
1008df28f0aSpeter klausler   Crash("Internal error: RUNTIME_CHECK(%s) failed at %s(%d)", predicate,
1018df28f0aSpeter klausler       sourceFileName_, sourceLine_);
1028df28f0aSpeter klausler }
1038df28f0aSpeter klausler 
10495696d56Speter klausler // TODO: These will be defined in the coarray runtime library
NotifyOtherImagesOfNormalEnd()105*4bdec583SSlava Zakharin RT_API_ATTRS void NotifyOtherImagesOfNormalEnd() {}
NotifyOtherImagesOfFailImageStatement()106*4bdec583SSlava Zakharin RT_API_ATTRS void NotifyOtherImagesOfFailImageStatement() {}
NotifyOtherImagesOfErrorTermination()107*4bdec583SSlava Zakharin RT_API_ATTRS void NotifyOtherImagesOfErrorTermination() {}
108*4bdec583SSlava Zakharin 
109*4bdec583SSlava Zakharin RT_OFFLOAD_API_GROUP_END
110*4bdec583SSlava Zakharin 
1111f879005STim Keith } // namespace Fortran::runtime
112