2020-01-08 13:27:32 -08:00
|
|
|
//===-- runtime/terminator.h ------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
2020-01-10 12:12:03 -08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2020-01-08 13:27:32 -08:00
|
|
|
|
|
|
|
// Termination of the image
|
|
|
|
|
|
|
|
#ifndef FORTRAN_RUNTIME_TERMINATOR_H_
|
|
|
|
#define FORTRAN_RUNTIME_TERMINATOR_H_
|
|
|
|
|
2024-03-25 16:01:25 -07:00
|
|
|
#include "flang/Common/api-attrs.h"
|
2020-01-08 13:27:32 -08:00
|
|
|
#include <cstdarg>
|
2023-09-27 08:20:17 -07:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
2020-01-08 13:27:32 -08:00
|
|
|
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
|
|
|
|
// A mixin class for statement-specific image error termination
|
|
|
|
// for errors detected in the runtime library
|
|
|
|
class Terminator {
|
|
|
|
public:
|
2023-09-27 08:20:17 -07:00
|
|
|
RT_API_ATTRS Terminator() {}
|
2020-02-04 16:55:45 -08:00
|
|
|
Terminator(const Terminator &) = default;
|
2023-05-22 14:05:18 -07:00
|
|
|
explicit RT_API_ATTRS Terminator(
|
|
|
|
const char *sourceFileName, int sourceLine = 0)
|
2020-03-28 21:00:16 -07:00
|
|
|
: sourceFileName_{sourceFileName}, sourceLine_{sourceLine} {}
|
2021-04-20 09:19:21 -07:00
|
|
|
|
2023-09-27 08:20:17 -07:00
|
|
|
RT_API_ATTRS const char *sourceFileName() const { return sourceFileName_; }
|
|
|
|
RT_API_ATTRS int sourceLine() const { return sourceLine_; }
|
2021-04-20 09:19:21 -07:00
|
|
|
|
2023-09-27 08:20:17 -07:00
|
|
|
RT_API_ATTRS void SetLocation(
|
|
|
|
const char *sourceFileName = nullptr, int sourceLine = 0) {
|
2020-01-08 13:27:32 -08:00
|
|
|
sourceFileName_ = sourceFileName;
|
|
|
|
sourceLine_ = sourceLine;
|
|
|
|
}
|
2023-05-22 14:05:18 -07:00
|
|
|
|
2023-09-27 08:20:17 -07:00
|
|
|
// Silence compiler warnings about the format string being
|
|
|
|
// non-literal. A more precise control would be
|
|
|
|
// __attribute__((format_arg(2))), but it requires the function
|
|
|
|
// to return 'char *', which does not work well with noreturn.
|
|
|
|
#if defined(__clang__)
|
|
|
|
#pragma clang diagnostic push
|
|
|
|
#pragma clang diagnostic ignored "-Wformat-security"
|
|
|
|
#elif defined(__GNUC__)
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wformat-security"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Device offload compilers do not normally support varargs and va_list,
|
|
|
|
// so use C++ variadic templates to forward the crash arguments
|
|
|
|
// to regular printf for the device compilation.
|
|
|
|
// Try to keep the inline implementations as small as possible.
|
|
|
|
template <typename... Args>
|
2024-05-23 13:15:53 -07:00
|
|
|
[[noreturn]] RT_DEVICE_NOINLINE RT_API_ATTRS const char *Crash(
|
2023-09-27 08:20:17 -07:00
|
|
|
const char *message, Args... args) const {
|
|
|
|
#if !defined(RT_DEVICE_COMPILATION)
|
|
|
|
// Invoke handler set up by the test harness.
|
|
|
|
InvokeCrashHandler(message, args...);
|
|
|
|
#endif
|
|
|
|
CrashHeader();
|
|
|
|
PrintCrashArgs(message, args...);
|
|
|
|
CrashFooter();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
RT_API_ATTRS void PrintCrashArgs(const char *message, Args... args) const {
|
2024-03-25 16:01:25 -07:00
|
|
|
#if defined(RT_DEVICE_COMPILATION)
|
2023-09-27 08:20:17 -07:00
|
|
|
std::printf(message, args...);
|
|
|
|
#else
|
|
|
|
std::fprintf(stderr, message, args...);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__clang__)
|
|
|
|
#pragma clang diagnostic pop
|
|
|
|
#elif defined(__GNUC__)
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RT_API_ATTRS void CrashHeader() const;
|
|
|
|
[[noreturn]] RT_API_ATTRS void CrashFooter() const;
|
|
|
|
#if !defined(RT_DEVICE_COMPILATION)
|
|
|
|
void InvokeCrashHandler(const char *message, ...) const;
|
|
|
|
[[noreturn]] void CrashArgs(const char *message, va_list &) const;
|
|
|
|
#endif
|
2023-05-22 14:05:18 -07:00
|
|
|
[[noreturn]] RT_API_ATTRS void CheckFailed(
|
2020-02-04 16:55:45 -08:00
|
|
|
const char *predicate, const char *file, int line) const;
|
2023-05-22 14:05:18 -07:00
|
|
|
[[noreturn]] RT_API_ATTRS void CheckFailed(const char *predicate) const;
|
2020-01-08 13:27:32 -08:00
|
|
|
|
2020-02-13 14:41:56 -08:00
|
|
|
// For test harnessing - overrides CrashArgs().
|
2020-07-04 14:24:32 -07:00
|
|
|
static void RegisterCrashHandler(void (*)(const char *sourceFile,
|
|
|
|
int sourceLine, const char *message, va_list &ap));
|
2020-02-13 14:41:56 -08:00
|
|
|
|
2020-01-08 13:27:32 -08:00
|
|
|
private:
|
|
|
|
const char *sourceFileName_{nullptr};
|
|
|
|
int sourceLine_{0};
|
|
|
|
};
|
|
|
|
|
2020-02-13 14:41:56 -08:00
|
|
|
// RUNTIME_CHECK() guarantees evaluation of its predicate.
|
2020-01-16 13:51:25 -08:00
|
|
|
#define RUNTIME_CHECK(terminator, pred) \
|
|
|
|
if (pred) \
|
|
|
|
; \
|
|
|
|
else \
|
|
|
|
(terminator).CheckFailed(#pred, __FILE__, __LINE__)
|
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
#define INTERNAL_CHECK(pred) \
|
|
|
|
if (pred) \
|
|
|
|
; \
|
|
|
|
else \
|
|
|
|
Terminator{__FILE__, __LINE__}.CheckFailed(#pred)
|
|
|
|
|
2023-09-27 08:20:17 -07:00
|
|
|
RT_API_ATTRS void NotifyOtherImagesOfNormalEnd();
|
|
|
|
RT_API_ATTRS void NotifyOtherImagesOfFailImageStatement();
|
|
|
|
RT_API_ATTRS void NotifyOtherImagesOfErrorTermination();
|
2020-03-28 21:00:16 -07:00
|
|
|
} // namespace Fortran::runtime
|
2020-02-04 16:55:45 -08:00
|
|
|
|
|
|
|
namespace Fortran::runtime::io {
|
2023-09-27 08:20:17 -07:00
|
|
|
RT_API_ATTRS void FlushOutputOnCrash(const Terminator &);
|
2020-02-04 16:55:45 -08:00
|
|
|
}
|
|
|
|
|
2020-03-28 21:00:16 -07:00
|
|
|
#endif // FORTRAN_RUNTIME_TERMINATOR_H_
|