From 7d67a196b6548562070ac11fc673c0d3d263d846 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 12 Mar 2015 18:43:21 +0000 Subject: soft-fp: Define and use _FP_STATIC_ASSERT. This patch makes soft-fp use static assertions in place of conditional calls to abort, in places where there are checks for conditions (on the types for which a macro is used) that the code is not prepared to handle. The fallback definition of _FP_STATIC_ASSERT (for kernel use only, as only relevant to compilers not supported for building glibc) is as in misc/sys/cdefs.h. This means that soft-fp only ever calls abort for _FP_UNREACHABLE calls in builds with GCC versions before 4.5. Thus, there is no need for an abort declaration or include, since the kernel code handles defining abort as a macro itself - and so this avoids any need for an __KERNEL__ condition on the abort declaration to avoid it breaking with the kernel's macro definition. That is, this patch is intended to make glibc's soft-fp code suitable for kernel use with no kernel-local changes to the soft-fp code needed at all. Tested for powerpc-nofpu that installed stripped shared libraries are unchanged by the patch. One explicit include had to be added to a file that was relying on the include from soft-fp.h. * soft-fp/soft-fp.h (_FP_STATIC_ASSERT): New macro. [_LIBC]: Do not include . [!_LIBC] (abort): Remove declaration. * soft-fp/op-2.h (_FP_MUL_MEAT_2_120_240_double): Use _FP_STATIC_ASSERT instead of conditionally calling abort. * soft-fp/op-common.h (_FP_FROM_INT): Likewise. (_FP_EXTEND_CNAN): Likewise. (FP_TRUNC): Likewise. (__FP_CLZ): Likewise. * sysdeps/powerpc/nofpu/flt-rounds.c: Include . --- soft-fp/op-2.h | 4 ++-- soft-fp/op-common.h | 62 ++++++++++++++++++++++++++++++++--------------------- soft-fp/soft-fp.h | 17 +++++++++------ 3 files changed, 51 insertions(+), 32 deletions(-) (limited to 'soft-fp') diff --git a/soft-fp/op-2.h b/soft-fp/op-2.h index c27b890c98..a51eb6b35d 100644 --- a/soft-fp/op-2.h +++ b/soft-fp/op-2.h @@ -458,8 +458,8 @@ _p240, _q240, _r240, _s240; \ UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \ \ - if ((wfracbits) < 106 || (wfracbits) > 120) \ - abort (); \ + _FP_STATIC_ASSERT ((wfracbits) >= 106 && (wfracbits) <= 120, \ + "wfracbits out of range"); \ \ setfetz; \ \ diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index 83c2156954..9c1c5e35f2 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -1800,6 +1800,8 @@ (r) = -(rtype) (r); \ \ _FP_FROM_INT_ur = (rtype) (r); \ + _FP_STATIC_ASSERT ((rsize) <= 2 * _FP_W_TYPE_SIZE, \ + "rsize too large"); \ (void) (((rsize) <= _FP_W_TYPE_SIZE) \ ? ({ \ int _FP_FROM_INT_lz; \ @@ -1808,17 +1810,15 @@ X##_e = (_FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 \ - _FP_FROM_INT_lz); \ }) \ - : (((rsize) <= 2 * _FP_W_TYPE_SIZE) \ - ? ({ \ - int _FP_FROM_INT_lz; \ - __FP_CLZ_2 (_FP_FROM_INT_lz, \ - (_FP_W_TYPE) (_FP_FROM_INT_ur \ - >> _FP_W_TYPE_SIZE), \ - (_FP_W_TYPE) _FP_FROM_INT_ur); \ - X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ - - _FP_FROM_INT_lz); \ - }) \ - : ({ abort (); 0; }))); \ + : ({ \ + int _FP_FROM_INT_lz; \ + __FP_CLZ_2 (_FP_FROM_INT_lz, \ + (_FP_W_TYPE) (_FP_FROM_INT_ur \ + >> _FP_W_TYPE_SIZE), \ + (_FP_W_TYPE) _FP_FROM_INT_ur); \ + X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ + - _FP_FROM_INT_lz); \ + })); \ \ if ((rsize) - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \ && X##_e >= _FP_EXPMAX_##fs) \ @@ -1876,12 +1876,18 @@ #define _FP_EXTEND_CNAN(dfs, sfs, dwc, swc, D, S, check_nan) \ do \ { \ - if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \ - || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ - < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \ - || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \ - && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \ - abort (); \ + _FP_STATIC_ASSERT (_FP_FRACBITS_##dfs >= _FP_FRACBITS_##sfs, \ + "destination mantissa narrower than source"); \ + _FP_STATIC_ASSERT ((_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ + >= _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs), \ + "destination max exponent smaller" \ + " than source"); \ + _FP_STATIC_ASSERT (((_FP_EXPBIAS_##dfs \ + >= (_FP_EXPBIAS_##sfs \ + + _FP_FRACBITS_##sfs - 1)) \ + || (_FP_EXPBIAS_##dfs == _FP_EXPBIAS_##sfs)), \ + "source subnormals do not all become normal," \ + " but bias not the same"); \ D##_s = S##_s; \ _FP_FRAC_COPY_##dwc##_##swc (D, S); \ if (_FP_EXP_NORMAL (sfs, swc, S)) \ @@ -1944,10 +1950,14 @@ #define FP_TRUNC(dfs, sfs, dwc, swc, D, S) \ do \ { \ - if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \ - || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \ - && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \ - abort (); \ + _FP_STATIC_ASSERT (_FP_FRACBITS_##sfs >= _FP_FRACBITS_##dfs, \ + "destination mantissa wider than source"); \ + _FP_STATIC_ASSERT (((_FP_EXPBIAS_##sfs \ + >= (_FP_EXPBIAS_##dfs \ + + _FP_FRACBITS_##dfs - 1)) \ + || _FP_EXPBIAS_##sfs == _FP_EXPBIAS_##dfs), \ + "source subnormals do not all become same," \ + " but bias not the same"); \ D##_s = S##_s; \ if (_FP_EXP_NORMAL (sfs, swc, S)) \ { \ @@ -2036,14 +2046,18 @@ # define __FP_CLZ(r, x) \ do \ { \ + _FP_STATIC_ASSERT ((sizeof (_FP_W_TYPE) == sizeof (unsigned int) \ + || (sizeof (_FP_W_TYPE) \ + == sizeof (unsigned long)) \ + || (sizeof (_FP_W_TYPE) \ + == sizeof (unsigned long long))), \ + "_FP_W_TYPE size unsupported for clz"); \ if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \ (r) = __builtin_clz (x); \ else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \ (r) = __builtin_clzl (x); \ - else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \ + else /* sizeof (_FP_W_TYPE) == sizeof (unsigned long long). */ \ (r) = __builtin_clzll (x); \ - else \ - abort (); \ } \ while (0) #endif /* ndef __FP_CLZ */ diff --git a/soft-fp/soft-fp.h b/soft-fp/soft-fp.h index b247125a39..3b39336b38 100644 --- a/soft-fp/soft-fp.h +++ b/soft-fp/soft-fp.h @@ -60,6 +60,17 @@ # define _FP_UNREACHABLE abort () #endif +#if ((defined __GNUC__ \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)) +# define _FP_STATIC_ASSERT(expr, msg) \ + _Static_assert ((expr), msg) +#else +# define _FP_STATIC_ASSERT(expr, msg) \ + extern int (*__Static_assert_function (void)) \ + [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] +#endif + /* In the Linux kernel, some architectures have a single function that uses different kinds of unpacking and packing depending on the instruction being emulated, meaning it is not readily visible to @@ -340,10 +351,4 @@ typedef USItype UHWtype; # endif #endif -#ifdef _LIBC -# include -#else -extern void abort (void); -#endif - #endif /* !SOFT_FP_H */ -- cgit v1.2.3