[libc++][Android] Allow testing libc++ with clang-r536225 (#116149)
[llvm-project.git] / flang / runtime / exceptions.cpp
blob8239c556bcea97fe93a940aa44f6109caeca822c
1 //===-- runtime/exceptions.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 // Runtime exception support.
11 #include "flang/Runtime/exceptions.h"
12 #include "terminator.h"
13 #include <cfenv>
15 // When not supported, these macro are undefined in cfenv.h,
16 // set them to zero in that case.
17 #ifndef FE_INVALID
18 #define FE_INVALID 0
19 #endif
20 #ifndef __FE_DENORM
21 #define __FE_DENORM 0 // denorm is nonstandard
22 #endif
23 #ifndef FE_DIVBYZERO
24 #define FE_DIVBYZERO 0
25 #endif
26 #ifndef FE_OVERFLOW
27 #define FE_OVERFLOW 0
28 #endif
29 #ifndef FE_UNDERFLOW
30 #define FE_UNDERFLOW 0
31 #endif
32 #ifndef FE_INEXACT
33 #define FE_INEXACT 0
34 #endif
36 namespace Fortran::runtime {
38 extern "C" {
40 // Map a set of Fortran ieee_arithmetic module exceptions to a libm fenv.h
41 // excepts value.
42 uint32_t RTNAME(MapException)(uint32_t excepts) {
43 Terminator terminator{__FILE__, __LINE__};
45 static constexpr uint32_t v{FE_INVALID};
46 static constexpr uint32_t s{__FE_DENORM}; // subnormal
47 static constexpr uint32_t z{FE_DIVBYZERO};
48 static constexpr uint32_t o{FE_OVERFLOW};
49 static constexpr uint32_t u{FE_UNDERFLOW};
50 static constexpr uint32_t x{FE_INEXACT};
52 #define vm(p) p, p | v
53 #define sm(p) vm(p), vm(p | s)
54 #define zm(p) sm(p), sm(p | z)
55 #define om(p) zm(p), zm(p | o)
56 #define um(p) om(p), om(p | u)
57 #define xm um(0), um(x)
59 static constexpr uint32_t map[]{xm};
60 static constexpr uint32_t mapSize{sizeof(map) / sizeof(uint32_t)};
61 static_assert(mapSize == 64);
62 if (excepts == 0 || excepts >= mapSize) {
63 terminator.Crash("Invalid excepts value: %d", excepts);
65 uint32_t except_value = map[excepts];
66 if (except_value == 0) {
67 terminator.Crash(
68 "Excepts value %d not supported by flang runtime", excepts);
70 return except_value;
73 // Verify that the size of ieee_modes_type and ieee_status_type objects from
74 // intrinsic module file __fortran_ieee_exceptions.f90 are large enough to
75 // hold fenv_t object.
76 // TODO: fenv_t can be way larger than
77 // sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT
78 // on some systems, e.g. Solaris, so omit object size comparison for now.
79 // TODO: consider femode_t object size comparison once its more mature.
81 } // extern "C"
82 } // namespace Fortran::runtime