mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 07:26:07 +00:00

Even after 13e2200fa426faffb62bdaf8b2f1f5699eee1511 (Solaris lacks `femode_t`, too), the Solaris `flang` build is still broken: ``` /vol/llvm/src/llvm-project/local/flang/runtime/exceptions.cpp:87:5: error: static assertion failed due to requirement 'sizeof(fenv_t) <= sizeof(int) * 8': increase ieee_status_type size 87 | sizeof(fenv_t) <= sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /vol/llvm/src/llvm-project/local/flang/runtime/exceptions.cpp:87:20: note: expression evaluates to '200 <= 32' 87 | sizeof(fenv_t) <= sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT, | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` This patch fixes this by removing the assertion. Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11`.
88 lines
3.2 KiB
C++
88 lines
3.2 KiB
C++
//===-- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Map Fortran ieee_arithmetic module exceptions to fenv.h exceptions.
|
|
|
|
#include "flang/Runtime/exceptions.h"
|
|
#include "terminator.h"
|
|
#include "flang/Runtime/magic-numbers.h"
|
|
#include <cfenv>
|
|
|
|
#ifndef __FE_DENORM
|
|
#define __FE_DENORM 0 // denorm is nonstandard
|
|
#endif
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
extern "C" {
|
|
|
|
std::int32_t RTNAME(MapException)(int32_t except) {
|
|
Terminator terminator{__FILE__, __LINE__};
|
|
|
|
static constexpr int32_t mask{_FORTRAN_RUNTIME_IEEE_INVALID |
|
|
_FORTRAN_RUNTIME_IEEE_DENORM | _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO |
|
|
_FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_UNDERFLOW |
|
|
_FORTRAN_RUNTIME_IEEE_INEXACT};
|
|
if (except == 0 || except != (except & mask)) {
|
|
terminator.Crash("Invalid exception value: %d", except);
|
|
}
|
|
|
|
// Fortran and fenv.h values are identical; return the value.
|
|
if constexpr (_FORTRAN_RUNTIME_IEEE_INVALID == FE_INVALID &&
|
|
_FORTRAN_RUNTIME_IEEE_DENORM == __FE_DENORM &&
|
|
_FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO == FE_DIVBYZERO &&
|
|
_FORTRAN_RUNTIME_IEEE_OVERFLOW == FE_OVERFLOW &&
|
|
_FORTRAN_RUNTIME_IEEE_UNDERFLOW == FE_UNDERFLOW &&
|
|
_FORTRAN_RUNTIME_IEEE_INEXACT == FE_INEXACT) {
|
|
return except;
|
|
}
|
|
|
|
// fenv.h calls that take exception arguments are able to process multiple
|
|
// exceptions in one call, such as FE_OVERFLOW | FE_DIVBYZERO | FE_INVALID.
|
|
// And intrinsic module procedures that manage exceptions are elemental
|
|
// procedures that may specify multiple exceptions, such as ieee_all.
|
|
// However, general elemental call processing places single scalar arguments
|
|
// in a loop. As a consequence, argument 'except' here will be a power of
|
|
// two, corresponding to a single exception. If code generation were
|
|
// modified to bypass normal elemental call processing for calls with
|
|
// ieee_usual, ieee_all, or user-specified array arguments, this switch
|
|
// could be extended to support that.
|
|
|
|
// Fortran and fenv.h values differ.
|
|
switch (except) {
|
|
case _FORTRAN_RUNTIME_IEEE_INVALID:
|
|
return FE_INVALID;
|
|
case _FORTRAN_RUNTIME_IEEE_DENORM:
|
|
if (__FE_DENORM) {
|
|
return __FE_DENORM;
|
|
}
|
|
break;
|
|
case _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO:
|
|
return FE_DIVBYZERO;
|
|
case _FORTRAN_RUNTIME_IEEE_OVERFLOW:
|
|
return FE_OVERFLOW;
|
|
case _FORTRAN_RUNTIME_IEEE_UNDERFLOW:
|
|
return FE_UNDERFLOW;
|
|
case _FORTRAN_RUNTIME_IEEE_INEXACT:
|
|
return FE_INEXACT;
|
|
}
|
|
|
|
terminator.Crash("Invalid exception set: %d", except);
|
|
}
|
|
|
|
// Verify that the size of ieee_modes_type and ieee_status_type objects from
|
|
// intrinsic module file __fortran_ieee_exceptions.f90 are large enough to
|
|
// hold fenv_t object.
|
|
// TODO: fenv_t can be way larger than
|
|
// sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT
|
|
// on some systems, e.g. Solaris, so omit object size comparison for now.
|
|
// TODO: consider femode_t object size comparison once its more mature.
|
|
|
|
} // extern "C"
|
|
} // namespace Fortran::runtime
|