
Mostly mechanical changes in preparation of extracting the Flang-RT "subproject" in #110217. This PR intends to only move pre-existing files to the new folder structure, with no behavioral change. Common files (headers, testing, cmake) shared by Flang-RT and Flang remain in `flang/`. Some cosmetic changes and files paths were necessary: * Relative paths to the new path for the source files and `add_subdirectory`. * Add the new location's include directory to `include_directories` * The unittest/Evaluate directory has unitests for flang-rt and Flang. A new `CMakeLists.txt` was introduced for the flang-rt tests. * Change the `#include` paths relative to the include directive * clang-format on the `#include` directives * Since the paths are part if the copyright header and include guards, a script was used to canonicalize those * `test/Runtime` and runtime tests in `test/Driver` are moved, but the lit.cfg.py mechanism to execute the will only be added in #110217.
125 lines
4.0 KiB
C++
125 lines
4.0 KiB
C++
//===-- include/flang-rt/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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Termination of the image
|
|
|
|
#ifndef FLANG_RT_RUNTIME_TERMINATOR_H_
|
|
#define FLANG_RT_RUNTIME_TERMINATOR_H_
|
|
|
|
#include "flang/Common/api-attrs.h"
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
// A mixin class for statement-specific image error termination
|
|
// for errors detected in the runtime library
|
|
class Terminator {
|
|
public:
|
|
RT_API_ATTRS Terminator() {}
|
|
Terminator(const Terminator &) = default;
|
|
explicit RT_API_ATTRS Terminator(
|
|
const char *sourceFileName, int sourceLine = 0)
|
|
: sourceFileName_{sourceFileName}, sourceLine_{sourceLine} {}
|
|
|
|
RT_API_ATTRS const char *sourceFileName() const { return sourceFileName_; }
|
|
RT_API_ATTRS int sourceLine() const { return sourceLine_; }
|
|
|
|
RT_API_ATTRS void SetLocation(
|
|
const char *sourceFileName = nullptr, int sourceLine = 0) {
|
|
sourceFileName_ = sourceFileName;
|
|
sourceLine_ = sourceLine;
|
|
}
|
|
|
|
// 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>
|
|
[[noreturn]] RT_DEVICE_NOINLINE RT_API_ATTRS const char *Crash(
|
|
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 {
|
|
#if defined(RT_DEVICE_COMPILATION)
|
|
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
|
|
[[noreturn]] RT_API_ATTRS void CheckFailed(
|
|
const char *predicate, const char *file, int line) const;
|
|
[[noreturn]] RT_API_ATTRS void CheckFailed(const char *predicate) const;
|
|
|
|
// For test harnessing - overrides CrashArgs().
|
|
static void RegisterCrashHandler(void (*)(const char *sourceFile,
|
|
int sourceLine, const char *message, va_list &ap));
|
|
|
|
private:
|
|
const char *sourceFileName_{nullptr};
|
|
int sourceLine_{0};
|
|
};
|
|
|
|
// RUNTIME_CHECK() guarantees evaluation of its predicate.
|
|
#define RUNTIME_CHECK(terminator, pred) \
|
|
if (pred) \
|
|
; \
|
|
else \
|
|
(terminator).CheckFailed(#pred, __FILE__, __LINE__)
|
|
|
|
#define INTERNAL_CHECK(pred) \
|
|
if (pred) \
|
|
; \
|
|
else \
|
|
Terminator{__FILE__, __LINE__}.CheckFailed(#pred)
|
|
|
|
RT_API_ATTRS void NotifyOtherImagesOfNormalEnd();
|
|
RT_API_ATTRS void NotifyOtherImagesOfFailImageStatement();
|
|
RT_API_ATTRS void NotifyOtherImagesOfErrorTermination();
|
|
} // namespace Fortran::runtime
|
|
|
|
namespace Fortran::runtime::io {
|
|
RT_API_ATTRS void FlushOutputOnCrash(const Terminator &);
|
|
}
|
|
|
|
#endif // FLANG_RT_RUNTIME_TERMINATOR_H_
|