xref: /llvm-project/flang/include/flang/Common/float128.h (revision fc51c7f0cc1abf1679100d71d103fe5d943f580b)
1 /*===-- flang/Common/float128.h ----------------------------------*- C -*-===
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  *===----------------------------------------------------------------------===*/
8 
9 /* This header is usable in both C and C++ code.
10  * Isolates build compiler checks to determine the presence of an IEEE-754
11  * quad-precision type named __float128 type that isn't __ibm128
12  * (double/double). We don't care whether the type has underlying hardware
13  * support or is emulated.
14  *
15  * 128-bit arithmetic may be available via "long double"; this can
16  * be determined by LDBL_MANT_DIG == 113.  A machine may have both 128-bit
17  * long double and __float128; prefer long double by testing for it first.
18  */
19 
20 #ifndef FORTRAN_COMMON_FLOAT128_H_
21 #define FORTRAN_COMMON_FLOAT128_H_
22 
23 #include "api-attrs.h"
24 #include <float.h>
25 
26 #ifdef __cplusplus
27 /*
28  * libc++ does not fully support __float128 right now, e.g.
29  * std::complex<__float128> multiplication ends up calling
30  * copysign() that is not defined for __float128.
31  * In order to check for libc++'s _LIBCPP_VERSION macro
32  * we need to include at least one libc++ header file.
33  */
34 #include <cstddef>
35 #endif
36 
37 #undef HAS_FLOAT128
38 #if (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) && \
39     !defined(_LIBCPP_VERSION) && !defined(__CUDA_ARCH__)
40 /*
41  * It may still be worth checking for compiler versions,
42  * since earlier versions may define the macros above, but
43  * still do not support __float128 fully.
44  */
45 #if __x86_64__
46 #if __GNUC__ >= 7 || __clang_major__ >= 7
47 #define HAS_FLOAT128 1
48 #endif
49 #elif defined __PPC__ && __GNUC__ >= 8
50 #define HAS_FLOAT128 1
51 #endif
52 #endif /* (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) && \
53           !defined(_LIBCPP_VERSION)  && !defined(__CUDA_ARCH__) */
54 
55 #if LDBL_MANT_DIG == 113
56 #define HAS_LDBL128 1
57 #endif
58 
59 #if defined(RT_DEVICE_COMPILATION) && defined(__CUDACC__)
60 /*
61  * Most offload targets do not support 128-bit 'long double'.
62  * Disable HAS_LDBL128 for __CUDACC__ for the time being.
63  */
64 #undef HAS_LDBL128
65 #endif
66 
67 /* Define pure C CFloat128Type and CFloat128ComplexType. */
68 #if HAS_LDBL128
69 typedef long double CFloat128Type;
70 #ifndef __cplusplus
71 typedef long double _Complex CFloat128ComplexType;
72 #endif
73 #elif HAS_FLOAT128
74 typedef __float128 CFloat128Type;
75 
76 #ifndef __cplusplus
77 /*
78  * Use mode() attribute supported by GCC and Clang.
79  * Adjust it for other compilers as needed.
80  */
81 #if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__)
82 typedef _Complex float __attribute__((mode(TC))) CFloat128ComplexType;
83 #else
84 typedef _Complex float __attribute__((mode(KC))) CFloat128ComplexType;
85 #endif
86 #endif // __cplusplus
87 #endif
88 #endif /* FORTRAN_COMMON_FLOAT128_H_ */
89