On 9/5/21 11:20 PM, Sandra Loosemore wrote:
Unless the aarch64 maintainers think it is a bug that __float128 is not supported, I think the right solution here is the one I was thinking of previously, to fix the Fortran front end to tie the C_FLOAT128 kind to _Float128 rather than __float128, and fix the runtime support and test cases accordingly. Then there should be no need to depend on quadmath.h at all. C_FLOAT128 is a GNU extension and _Float128 is supported on a superset of targets that __float128 is, so there should be no issue with backward compatibility.
Here's a new patch that does this. I've tested it on x86_64-linux-gnu, powerpc64le-linux-gnu, and aarch64-linux-gnu, and it does fix the previously reported failure compiling gfortran.dg/PR100914.c on aarch64. OK to commit?
-Sandra
commit cc7e47df550485654efa5f523c3be35007125340 Author: Sandra Loosemore <san...@codesourcery.com> Date: Tue Sep 14 19:07:36 2021 -0700 Fortran: Use _Float128 rather than __float128 for c_float128 kind. The GNU Fortran manual documents that the c_float128 kind corresponds to __float128, but in fact the implementation uses float128_type_node, which is _Float128. Both refer to the 128-bit IEEE/ISO encoding, but some targets including aarch64 only define _Float128 and not __float128, and do not provide quadmath.h. This caused errors in some test cases referring to __float128. This patch changes the documentation (including code comments) and test cases to use _Float128 to match the implementation. 2021-09-16 Sandra Loosemore <san...@codesourcery.com> gcc/fortran/ * intrinsic.texi (ISO_C_BINDING): Change C_FLOAT128 to correspond to _Float128 rather than __float128. * iso-c-binding.def (c_float128): Update comments. * trans-intrinsic.c (gfc_builtin_decl_for_float_kind): Likewise. (build_round_expr): Likewise. (gfc_build_intrinsic_lib_fndcecls): Likewise. * trans-types.h (gfc_real16_is_float128): Likewise. gcc/testsuite/ * gfortran.dg/PR100914.c: Do not include quadmath.h. Use _Float128 _Complex instead of __complex128. * gfortran.dg/PR100914.f90: Add -Wno-pedantic to suppress error about use of _Float128. * gfortran.dg/c-interop/typecodes-array-float128-c.c: Use _Float128 instead of __float128. * gfortran.dg/c-interop/typecodes-sanity-c.c: Likewise. * gfortran.dg/c-interop/typecodes-scalar-float128-c.c: Likewise. * lib/target-supports.exp (check_effective_target_fortran_real_c_float128): Update comments. libgfortran/ * ISO_Fortran_binding.h: Update comments. * runtime/ISO_Fortran_binding.c: Likewise. diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 1aacd33..1b9a89d 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -15193,8 +15193,8 @@ In addition to the integer named constants required by the Fortran 2003 standard and @code{C_PTRDIFF_T} of TS 29113, GNU Fortran provides as an extension named constants for the 128-bit integer types supported by the C compiler: @code{C_INT128_T, C_INT_LEAST128_T, C_INT_FAST128_T}. -Furthermore, if @code{__float128} is supported in C, the named constants -@code{C_FLOAT128, C_FLOAT128_COMPLEX} are defined. +Furthermore, if @code{_Float128} is supported in C, the named constants +@code{C_FLOAT128} and @code{C_FLOAT128_COMPLEX} are defined. @multitable @columnfractions .15 .35 .35 .35 @headitem Fortran Type @tab Named constant @tab C type @tab Extension @@ -15225,11 +15225,11 @@ Furthermore, if @code{__float128} is supported in C, the named constants @item @code{REAL} @tab @code{C_FLOAT} @tab @code{float} @item @code{REAL} @tab @code{C_DOUBLE} @tab @code{double} @item @code{REAL} @tab @code{C_LONG_DOUBLE} @tab @code{long double} -@item @code{REAL} @tab @code{C_FLOAT128} @tab @code{__float128} @tab Ext. +@item @code{REAL} @tab @code{C_FLOAT128} @tab @code{_Float128} @tab Ext. @item @code{COMPLEX}@tab @code{C_FLOAT_COMPLEX} @tab @code{float _Complex} @item @code{COMPLEX}@tab @code{C_DOUBLE_COMPLEX}@tab @code{double _Complex} @item @code{COMPLEX}@tab @code{C_LONG_DOUBLE_COMPLEX}@tab @code{long double _Complex} -@item @code{REAL} @tab @code{C_FLOAT128_COMPLEX} @tab @code{__float128 _Complex} @tab Ext. +@item @code{COMPLEX}@tab @code{C_FLOAT128_COMPLEX} @tab @code{_Float128 _Complex} @tab Ext. @item @code{LOGICAL}@tab @code{C_BOOL} @tab @code{_Bool} @item @code{CHARACTER}@tab @code{C_CHAR} @tab @code{char} @end multitable diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def index e65c750..50256fe 100644 --- a/gcc/fortran/iso-c-binding.def +++ b/gcc/fortran/iso-c-binding.def @@ -116,7 +116,7 @@ NAMED_REALCST (ISOCBINDING_LONG_DOUBLE, "c_long_double", \ get_real_kind_from_node (long_double_type_node), GFC_STD_F2003) /* GNU Extension. Note that the equivalence here is specifically to - the IEEE 128-bit type __float128; if that does not map onto a type + the IEEE 128-bit type _Float128; if that does not map onto a type otherwise supported by the Fortran front end, get_real_kind_from_node will reject it as unsupported. */ NAMED_REALCST (ISOCBINDING_FLOAT128, "c_float128", \ diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 46670ba..42a995b 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -175,7 +175,7 @@ gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in, if (gfc_real_kinds[i].c_float128) { - /* For __float128, the story is a bit different, because we return + /* For _Float128, the story is a bit different, because we return a decl to a library function rather than a built-in. */ gfc_intrinsic_map_t *m; for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++) @@ -387,7 +387,7 @@ build_round_expr (tree arg, tree restype) resprec = TYPE_PRECISION (restype); /* Depending on the type of the result, choose the int intrinsic (iround, - available only as a builtin, therefore cannot use it for __float128), long + available only as a builtin, therefore cannot use it for _Float128), long int intrinsic (lround family) or long long intrinsic (llround). If we don't have an appropriate function that converts directly to the integer type (such as kind == 16), just use ROUND, and then convert the result to @@ -689,7 +689,7 @@ gfc_build_intrinsic_lib_fndecls (void) if (gfc_real16_is_float128) { /* If we have soft-float types, we create the decls for their - C99-like library functions. For now, we only handle __float128 + C99-like library functions. For now, we only handle _Float128 q-suffixed functions. */ tree type, complex_type, func_1, func_2, func_cabs, func_frexp; diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h index 3b45ce2..6804bfe 100644 --- a/gcc/fortran/trans-types.h +++ b/gcc/fortran/trans-types.h @@ -55,7 +55,7 @@ extern GTY(()) tree gfc_charlen_type_node; /* The following flags give us information on the correspondence of real (and complex) kinds with C floating-point types long double - and __float128. */ + and _Float128. */ extern bool gfc_real16_is_float128; enum gfc_packed { diff --git a/gcc/testsuite/gfortran.dg/PR100914.c b/gcc/testsuite/gfortran.dg/PR100914.c index c6bd973..ea339e7 100644 --- a/gcc/testsuite/gfortran.dg/PR100914.c +++ b/gcc/testsuite/gfortran.dg/PR100914.c @@ -5,7 +5,6 @@ #include <stdbool.h> #include <stdio.h> #include <math.h> -#include <quadmath.h> #include <ISO_Fortran_binding.h> @@ -29,7 +28,7 @@ #define CMPLXL(x, y) ((long double complex)((long double)(x) + (long double complex)I * (long double)(y))) #undef CMPLX -#define CMPLX(x, y) ((__complex128 )((double)(x) + (double complex)I * (double)(y))) +#define CMPLX(x, y) ((_Float128 _Complex )((double)(x) + (double complex)I * (double)(y))) #define N 11 #define M 7 @@ -37,7 +36,7 @@ typedef float _Complex c_float_complex; typedef double _Complex c_double_complex; typedef long double _Complex c_long_double_complex; -typedef __complex128 c_float128_complex; +typedef _Float128 _Complex c_float128_complex; bool c_vrfy_c_float_complex (const CFI_cdesc_t *restrict); diff --git a/gcc/testsuite/gfortran.dg/PR100914.f90 b/gcc/testsuite/gfortran.dg/PR100914.f90 index 64b3335..d8057fd 100644 --- a/gcc/testsuite/gfortran.dg/PR100914.f90 +++ b/gcc/testsuite/gfortran.dg/PR100914.f90 @@ -2,6 +2,7 @@ ! { dg-do run { xfail { { x86_64*-*-* i?86*-*-* } && longdouble128 } } } ! { dg-additional-sources PR100914.c } ! { dg-require-effective-target fortran_real_c_float128 } +! { dg-additional-options "-Wno-pedantic" } ! ! Test the fix for PR100914 ! diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c index d081feb..4fcb6e2 100644 --- a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c +++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c @@ -32,7 +32,7 @@ void ctest (CFI_cdesc_t *arg_float128, CFI_cdesc_t *arg_complex128) { - check (arg_float128, sizeof (__float128), CFI_type_float128); - check (arg_complex128, sizeof (__float128) * 2, + check (arg_float128, sizeof (_Float128), CFI_type_float128); + check (arg_complex128, sizeof (_Float128) * 2, CFI_type_float128_Complex); } diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c index a1d044b..90f0b20 100644 --- a/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c +++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c @@ -23,8 +23,7 @@ static struct tc_info tc_table[] = { /* Extension types. Note there is no portable C equivalent type for CFI_type_ucs4_char type - (4-byte Unicode characters), and GCC rejects "__float128 _Complex", - so this is kind of hacky... */ + (4-byte Unicode characters), so this is kind of hacky... */ #if CFI_type_int128_t > 0 { CFI_type_int128_t, "CFI_type_int128_t", sizeof (__int128), 1 }, @@ -38,9 +37,9 @@ static struct tc_info tc_table[] = #endif #if CFI_type_float128 > 0 { CFI_type_float128, "CFI_type_float128", - sizeof (__float128), 1 }, + sizeof (_Float128), 1 }, { CFI_type_float128_Complex, "CFI_type_float128_Complex", - sizeof (__float128) * 2, 1 }, + sizeof (_Float128 _Complex), 1 }, #endif #if CFI_type_cfunptr > 0 { CFI_type_cfunptr, "CFI_type_cfunptr", diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c index f1833aa..7eafa93 100644 --- a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c +++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c @@ -31,8 +31,8 @@ void ctest (CFI_cdesc_t *arg_float128, CFI_cdesc_t *arg_complex128) { - check (arg_float128, sizeof (__float128), CFI_type_float128); - check (arg_complex128, sizeof (__float128) * 2, + check (arg_float128, sizeof (_Float128), CFI_type_float128); + check (arg_complex128, sizeof (_Float128) * 2, CFI_type_float128_Complex); } diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 8697ceb..f11c4e6 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -1578,8 +1578,8 @@ proc check_effective_target_fortran_real_10 { } { # Return 1 if the target supports Fortran real kind C_FLOAT128, # 0 otherwise. This differs from check_effective_target_fortran_real_16 -# because __float128 has the additional requirement that it be the -# 128-bit IEEE encoding; even if __float128 is available in C, it may not +# because _Float128 has the additional requirement that it be the +# 128-bit IEEE encoding; even if _Float128 is available in C, it may not # have a corresponding Fortran kind on targets (PowerPC) that use some # other encoding for long double/TFmode/real(16). proc check_effective_target_fortran_real_c_float128 { } { diff --git a/libgfortran/ISO_Fortran_binding.h b/libgfortran/ISO_Fortran_binding.h index a3c6f80..276d958 100644 --- a/libgfortran/ISO_Fortran_binding.h +++ b/libgfortran/ISO_Fortran_binding.h @@ -281,7 +281,7 @@ extern int CFI_setpointer (CFI_cdesc_t *, CFI_cdesc_t *, const CFI_index_t []); #define CFI_type_long_double (CFI_type_Real + (10 << CFI_type_kind_shift)) #define CFI_type_long_double_Complex (CFI_type_Complex + (10 << CFI_type_kind_shift)) -/* This is the IEEE 128-bit encoding, same as float128. */ +/* This is the IEEE 128-bit encoding, same as _Float128. */ #elif (__CFI_LDBL_MANT_DIG__ == 113 \ && __CFI_LDBL_MIN_EXP__ == -16381 \ && __CFI_LDBL_MAX_EXP__ == 16384) @@ -303,7 +303,7 @@ extern int CFI_setpointer (CFI_cdesc_t *, CFI_cdesc_t *, const CFI_index_t []); #error "Can't determine kind of long double" #endif -/* Similarly for __float128. This always refers to the IEEE encoding +/* Similarly for _Float128. This always refers to the IEEE encoding and not some other 128-bit representation, so if we already used kind 16 for a non-IEEE representation, this one must be unsupported in Fortran even if it's available in C. */ diff --git a/libgfortran/runtime/ISO_Fortran_binding.c b/libgfortran/runtime/ISO_Fortran_binding.c index 0e1a419..e01cc65 100644 --- a/libgfortran/runtime/ISO_Fortran_binding.c +++ b/libgfortran/runtime/ISO_Fortran_binding.c @@ -222,7 +222,7 @@ gfc_desc_to_cfi_desc (CFI_cdesc_t **d_ptr, const gfc_array_void *s) elem_len and not the kind, we get into trouble with long double kinds that do not correspond directly to the elem_len, specifically the kind 10 80-bit long double on x86 targets. On x86_64, this has size - 16 and cannot be differentiated from true __float128. Prefer the + 16 and cannot be differentiated from true _Float128. Prefer the standard long double type over the GNU extension in that case. */ if (d->type == CFI_type_Real && kind == sizeof (long double)) d->type = CFI_type_long_double;