This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH 5/8] float128: Add public _Float128 declarations to libm.
On Wed, 9 Nov 2016, Gabriel F. T. Gomes wrote:
> This introduces the machine-dependent bits/floatn.h to control
> the inclusion of _Float128 ABI.
>
> This leverages the _Generic feature of C11 as __USE_FLOAT128
> must imply a test for __STDC_WANT_IEC_60559_TYPES_EXT__
> which requires C11 to prevent increasingly complex math
> macros for the sake of old (and unsupported?) GCC toolchains.
Older tools are supported for compiling code using glibc. 4.7 and later
are supported for building glibc (I'd hope we can add float128 support on
x86-64 / x86 without needing to increase the minimum GCC version for
building glibc there).
> +/* Defined if the compiler supports the _Float128 (and __float128) type. */
> +#define __USE_FLOAT128 0
Support for _Float128 and __float128 are distinct things. GCC 7 supports
_Float128 on lots of platforms where long double has that format, but not
__float128.
> +/* Defined if the runtime supports _Float128. */
> +#define __HAVE_FLOAT128 0
You appear to be using __USE_FLOAT128 conditionals on things assuming
library facilities to be present.
You need to be very careful in designing exactly what macros are needed to
specify the available types and their properties, and in writing the
comments documenting the design.
> +#if __GNUC_PREREQ (7, 0)
> +# define HUGE_VAL_F128 (__builtin_huge_valf128 ())
> +#elif __GNUC_PREREQ (6,2)
Missing space after comma.
> +# define HUGE_VAL_F128 (__builtin_huge_valq ())
My inclination would be to localize the workarounds for old compilers to
one place, that defines __builtin_huge_valf128 as a macro. And the choice
of 6.2 as version here is questionable. A generic header here should not
have architecture-specific version conditionals. For x86, GCC supports
__builtin_huge_valq long before 6.2 - but even 6.2 doesn't support it in
static initializers for x86. So the definition casting HUGE_VAL is safer
for old compilers. That is, a bits/floatn-compat.h header could do
#if !__GNUC_PREREQ (7, 0)
# define __builtin_huge_valf128() ((_Float128) __builtin_huge_val ())
#endif
and similarly for defining _Float128 to __float128 and defining other
__builtin_* macros as needed. Of course that header would only be needed
for certain architectures.
> @@ -55,6 +59,10 @@ __BEGIN_DECLS
> # define CMPLXL(x, y) __builtin_complex ((long double) (x), (long double) (y))
> #endif
>
> +#if __USE_FLOAT128
> +# define CMPLXF128(x, y) __builtin_complex ((__float128) (x), (__float128) (y))
> +#endif
CMPLXF128 is only reserved when TS 18661-3 names are defined. That is,
all function or macro definitions for the new types need to be conditional
on an __GLIBC_USE conditional for TS 18661-3 *and* on the particular type
in question being supported. Whereas type-generic macros in <math.h>, as
opposed to those in <tgmath.h>, should support the new types even if the
__GLIBC_USE conditional for TS 18661-3 is false (meaning you might need to
split <bits/mathcalls.h> so you can declare e.g. __signbitf128 when not
declaring sinf128).
> +#if __USE_FLOAT128
> +# ifndef _Mfloat128_
> +# define _Mfloat128_ _Float128
> +# endif
> +/* GCC < 7 requires extra convincing to expose a complex float128 type. */
> +# ifdef __CFLOAT128
> +# undef _Mdouble_complex_
> +# define _Mdouble_complex_ __CFLOAT128
> +# endif
> +# define _Mdouble_ _Mfloat128_
> +# define __MATH_PRECNAME(name) name##f128
> +# include <bits/cmathcalls.h>
Likewise.
> +#if __USE_FLOAT128
> +# include <bits/huge_val_flt128.h>
> +#endif
Likewise.
> +/* Include the file of declarations again, this time using `_Float128'
> + instead of `double' and appending f128 to each function name. */
> +
> +#if __USE_FLOAT128
> +#ifndef _Mfloat128_
> +# define _Mfloat128_ _Float128
> +#endif
> +#define __FLOATN_TYPE 1
> +#define _Mdouble_ _Mfloat128_
> +#define __MATH_PRECNAME(name,r) name##f128##r
> +#define __MATH_DECLARING_DOUBLE 0
> +#define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99
> +#define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99
> +#include <bits/mathcalls.h>
Likewise.
> /* Return nonzero value if sign of X is negative. */
> -# if __GNUC_PREREQ (4,0)
> +# if __GNUC_PREREQ (6,2)
> +# define signbit(x) __builtin_signbit (x)
6.2 isn't the right version. __builtin_signbit is type-generic in GCC
from before GCC 6 branched, so use 6.0.
> @@ -299,8 +363,20 @@ enum
> # endif
>
> /* Return nonzero value if X is positive or negative infinity. */
> -# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
> +# if __USE_FLOAT128 && !defined __SUPPORT_SNAN__ && defined __GNUC__
> +/* __builtin_isinf_sign is broken for float128. */
Only broken before GCC 7.
> +#if __USE_FLOAT128
__USE_GNU conditional needed as well.
--
Joseph S. Myers
joseph@codesourcery.com