[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
//===-- runtime/exceptions.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
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
[flang] IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP, NEAREST (#100782)
IEEE_ARITHMETIC intrinsic module procedures IEEE_NEXT_AFTER,
IEEE_NEXT_DOWN, and IEEE_NEXT_UP, and intrinsic NEAREST return larger or
smaller values adjacent to their primary REAL argument. The four
procedures vary in how the direction is chosen, in how special cases are
treated, and in what exceptions are generated. Implement the three
IEEE_ARITHMETIC procedures. Update the NEAREST implementation to support
all six REAL kinds 2,3,4,8,10,16, and fix several bugs.
IEEE_NEXT_AFTER(X,Y) returns a NaN when Y is a NaN as that seems to be
the universal choice of other compilers.
Change the front end compile time implementation of these procedures to
return normal (HUGE) values for infinities when applicable, rather than
always returning the input infinity.
2024-07-29 09:22:36 -04:00
|
|
|
// Runtime exception support.
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
|
|
|
|
|
#include "flang/Runtime/exceptions.h"
|
|
|
|
|
#include "terminator.h"
|
|
|
|
|
#include <cfenv>
|
2025-01-27 09:18:47 -05:00
|
|
|
#if __aarch64__
|
|
|
|
|
#include <fpu_control.h>
|
|
|
|
|
#elif __x86_64__
|
2024-12-04 16:21:11 -05:00
|
|
|
#include <xmmintrin.h>
|
|
|
|
|
#endif
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
|
2025-01-15 10:55:09 -05:00
|
|
|
// fenv.h may not define exception macros.
|
2024-08-21 07:42:18 +00:00
|
|
|
#ifndef FE_INVALID
|
|
|
|
|
#define FE_INVALID 0
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef FE_DIVBYZERO
|
|
|
|
|
#define FE_DIVBYZERO 0
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef FE_OVERFLOW
|
|
|
|
|
#define FE_OVERFLOW 0
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef FE_UNDERFLOW
|
|
|
|
|
#define FE_UNDERFLOW 0
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef FE_INEXACT
|
|
|
|
|
#define FE_INEXACT 0
|
|
|
|
|
#endif
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
|
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
[flang] IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP, NEAREST (#100782)
IEEE_ARITHMETIC intrinsic module procedures IEEE_NEXT_AFTER,
IEEE_NEXT_DOWN, and IEEE_NEXT_UP, and intrinsic NEAREST return larger or
smaller values adjacent to their primary REAL argument. The four
procedures vary in how the direction is chosen, in how special cases are
treated, and in what exceptions are generated. Implement the three
IEEE_ARITHMETIC procedures. Update the NEAREST implementation to support
all six REAL kinds 2,3,4,8,10,16, and fix several bugs.
IEEE_NEXT_AFTER(X,Y) returns a NaN when Y is a NaN as that seems to be
the universal choice of other compilers.
Change the front end compile time implementation of these procedures to
return normal (HUGE) values for infinities when applicable, rather than
always returning the input infinity.
2024-07-29 09:22:36 -04:00
|
|
|
// Map a set of Fortran ieee_arithmetic module exceptions to a libm fenv.h
|
|
|
|
|
// excepts value.
|
|
|
|
|
uint32_t RTNAME(MapException)(uint32_t excepts) {
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
Terminator terminator{__FILE__, __LINE__};
|
|
|
|
|
|
[flang] IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP, NEAREST (#100782)
IEEE_ARITHMETIC intrinsic module procedures IEEE_NEXT_AFTER,
IEEE_NEXT_DOWN, and IEEE_NEXT_UP, and intrinsic NEAREST return larger or
smaller values adjacent to their primary REAL argument. The four
procedures vary in how the direction is chosen, in how special cases are
treated, and in what exceptions are generated. Implement the three
IEEE_ARITHMETIC procedures. Update the NEAREST implementation to support
all six REAL kinds 2,3,4,8,10,16, and fix several bugs.
IEEE_NEXT_AFTER(X,Y) returns a NaN when Y is a NaN as that seems to be
the universal choice of other compilers.
Change the front end compile time implementation of these procedures to
return normal (HUGE) values for infinities when applicable, rather than
always returning the input infinity.
2024-07-29 09:22:36 -04:00
|
|
|
static constexpr uint32_t v{FE_INVALID};
|
2025-01-15 10:55:09 -05:00
|
|
|
#if __x86_64__
|
|
|
|
|
static constexpr uint32_t s{__FE_DENORM}; // nonstandard, not a #define
|
|
|
|
|
#else
|
|
|
|
|
static constexpr uint32_t s{0};
|
|
|
|
|
#endif
|
[flang] IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP, NEAREST (#100782)
IEEE_ARITHMETIC intrinsic module procedures IEEE_NEXT_AFTER,
IEEE_NEXT_DOWN, and IEEE_NEXT_UP, and intrinsic NEAREST return larger or
smaller values adjacent to their primary REAL argument. The four
procedures vary in how the direction is chosen, in how special cases are
treated, and in what exceptions are generated. Implement the three
IEEE_ARITHMETIC procedures. Update the NEAREST implementation to support
all six REAL kinds 2,3,4,8,10,16, and fix several bugs.
IEEE_NEXT_AFTER(X,Y) returns a NaN when Y is a NaN as that seems to be
the universal choice of other compilers.
Change the front end compile time implementation of these procedures to
return normal (HUGE) values for infinities when applicable, rather than
always returning the input infinity.
2024-07-29 09:22:36 -04:00
|
|
|
static constexpr uint32_t z{FE_DIVBYZERO};
|
|
|
|
|
static constexpr uint32_t o{FE_OVERFLOW};
|
|
|
|
|
static constexpr uint32_t u{FE_UNDERFLOW};
|
|
|
|
|
static constexpr uint32_t x{FE_INEXACT};
|
|
|
|
|
|
|
|
|
|
#define vm(p) p, p | v
|
|
|
|
|
#define sm(p) vm(p), vm(p | s)
|
|
|
|
|
#define zm(p) sm(p), sm(p | z)
|
|
|
|
|
#define om(p) zm(p), zm(p | o)
|
|
|
|
|
#define um(p) om(p), om(p | u)
|
|
|
|
|
#define xm um(0), um(x)
|
|
|
|
|
|
|
|
|
|
static constexpr uint32_t map[]{xm};
|
|
|
|
|
static constexpr uint32_t mapSize{sizeof(map) / sizeof(uint32_t)};
|
|
|
|
|
static_assert(mapSize == 64);
|
2025-01-15 10:55:09 -05:00
|
|
|
if (excepts >= mapSize) {
|
[flang] IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP, NEAREST (#100782)
IEEE_ARITHMETIC intrinsic module procedures IEEE_NEXT_AFTER,
IEEE_NEXT_DOWN, and IEEE_NEXT_UP, and intrinsic NEAREST return larger or
smaller values adjacent to their primary REAL argument. The four
procedures vary in how the direction is chosen, in how special cases are
treated, and in what exceptions are generated. Implement the three
IEEE_ARITHMETIC procedures. Update the NEAREST implementation to support
all six REAL kinds 2,3,4,8,10,16, and fix several bugs.
IEEE_NEXT_AFTER(X,Y) returns a NaN when Y is a NaN as that seems to be
the universal choice of other compilers.
Change the front end compile time implementation of these procedures to
return normal (HUGE) values for infinities when applicable, rather than
always returning the input infinity.
2024-07-29 09:22:36 -04:00
|
|
|
terminator.Crash("Invalid excepts value: %d", excepts);
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
}
|
2024-08-21 07:42:18 +00:00
|
|
|
uint32_t except_value = map[excepts];
|
|
|
|
|
return except_value;
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
}
|
|
|
|
|
|
2024-12-23 09:30:45 -05:00
|
|
|
// Check if the processor has the ability to control whether to halt or
|
|
|
|
|
// continue execution when a given exception is raised.
|
|
|
|
|
bool RTNAME(SupportHalting)([[maybe_unused]] uint32_t except) {
|
2024-12-24 03:19:29 -05:00
|
|
|
#ifdef __USE_GNU
|
2024-12-23 09:30:45 -05:00
|
|
|
except = RTNAME(MapException)(except);
|
|
|
|
|
int currentSet = fegetexcept(), flipSet, ok;
|
|
|
|
|
if (currentSet & except) {
|
|
|
|
|
ok = fedisableexcept(except);
|
|
|
|
|
flipSet = fegetexcept();
|
|
|
|
|
ok |= feenableexcept(except);
|
|
|
|
|
} else {
|
|
|
|
|
ok = feenableexcept(except);
|
|
|
|
|
flipSet = fegetexcept();
|
|
|
|
|
ok |= fedisableexcept(except);
|
|
|
|
|
}
|
|
|
|
|
return ok != -1 && currentSet != flipSet;
|
2024-12-23 11:07:20 -05:00
|
|
|
#else
|
|
|
|
|
return false;
|
2024-12-23 09:30:45 -05:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-27 09:18:47 -05:00
|
|
|
// A hardware FZ (flush to zero) bit is the negation of the
|
|
|
|
|
// ieee_[get|set]_underflow_mode GRADUAL argument.
|
|
|
|
|
#if defined(_MM_FLUSH_ZERO_MASK)
|
|
|
|
|
// The MXCSR FZ bit affects computations of real kinds 3, 4, and 8.
|
|
|
|
|
#elif defined(_FPU_GETCW)
|
|
|
|
|
// The FPCR FZ bit affects computations of real kinds 3, 4, and 8.
|
|
|
|
|
// bit 24: FZ -- single, double precision flush to zero bit
|
|
|
|
|
// bit 19: FZ16 -- half precision flush to zero bit [not currently relevant]
|
|
|
|
|
#define _FPU_FPCR_FZ_MASK_ 0x01080000
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-12-04 16:21:11 -05:00
|
|
|
bool RTNAME(GetUnderflowMode)(void) {
|
2025-01-27 09:18:47 -05:00
|
|
|
#if defined(_MM_FLUSH_ZERO_MASK)
|
2024-12-04 16:21:11 -05:00
|
|
|
return _MM_GET_FLUSH_ZERO_MODE() == _MM_FLUSH_ZERO_OFF;
|
2025-01-27 09:18:47 -05:00
|
|
|
#elif defined(_FPU_GETCW)
|
|
|
|
|
uint32_t fpcr;
|
2025-01-27 10:32:13 -05:00
|
|
|
__asm__ __volatile__("mrs %w0, fpcr" : "=r"(fpcr));
|
2025-01-27 09:18:47 -05:00
|
|
|
return (fpcr & _FPU_FPCR_FZ_MASK_) != _FPU_FPCR_FZ_MASK_;
|
2024-12-04 16:21:11 -05:00
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
void RTNAME(SetUnderflowMode)(bool flag) {
|
2025-01-27 09:18:47 -05:00
|
|
|
#if defined(_MM_FLUSH_ZERO_MASK)
|
2024-12-04 16:21:11 -05:00
|
|
|
_MM_SET_FLUSH_ZERO_MODE(flag ? _MM_FLUSH_ZERO_OFF : _MM_FLUSH_ZERO_ON);
|
2025-01-27 09:18:47 -05:00
|
|
|
#elif defined(_FPU_GETCW)
|
|
|
|
|
uint32_t fpcr;
|
2025-01-27 10:32:13 -05:00
|
|
|
__asm__ __volatile__("mrs %w0, fpcr" : "=r"(fpcr));
|
2025-01-27 09:18:47 -05:00
|
|
|
if (flag) {
|
|
|
|
|
fpcr &= ~_FPU_FPCR_FZ_MASK_;
|
|
|
|
|
} else {
|
|
|
|
|
fpcr |= _FPU_FPCR_FZ_MASK_;
|
|
|
|
|
}
|
2025-01-27 10:32:13 -05:00
|
|
|
__asm__ __volatile__("msr fpcr, %w0" : : "r"(fpcr));
|
2024-12-04 16:21:11 -05:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-15 10:55:09 -05:00
|
|
|
size_t RTNAME(GetModesTypeSize)(void) {
|
|
|
|
|
#ifdef __GLIBC_USE_IEC_60559_BFP_EXT
|
|
|
|
|
return sizeof(femode_t); // byte size of ieee_modes_type data
|
|
|
|
|
#else
|
|
|
|
|
return 8; // femode_t is not defined
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
size_t RTNAME(GetStatusTypeSize)(void) {
|
|
|
|
|
return sizeof(fenv_t); // byte size of ieee_status_type data
|
|
|
|
|
}
|
|
|
|
|
|
[flang] IEEE_ARITHMETIC and IEEE_EXCEPTIONS intrinsic module procedures (#74138)
Implement a selection of intrinsic module procedures that involve
exceptions.
- IEEE_GET_FLAG
- IEEE_GET_HALTING_MODE
- IEEE_GET_MODES
- IEEE_GET_STATUS
- IEEE_LOGB
- [f23] IEEE_MAX, IEEE_MAX_MAG, IEEE_MAX_NUM, IEEE_MAX_NUM_MAG
- [f23] IEEE_MIN, IEEE_MIN_MAG, IEEE_MIN_NUM, IEEE_MIN_NUM_MAG
- IEEE_QUIET_EQ, IEEE_QUIET_GE, IEEE_QUIET_GT,
- IEEE_QUIET_LE, IEEE_QUIET_LT, IEEE_QUIET_NE
- IEEE_SET_FLAG
- IEEE_SET_HALTING_MODE
- IEEE_SET_MODES
- IEEE_SET_STATUS
- IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
- IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
- IEEE_SUPPORT_FLAG
- IEEE_SUPPORT_HALTING
2023-12-04 09:55:54 -08:00
|
|
|
} // extern "C"
|
|
|
|
|
} // namespace Fortran::runtime
|