soft-fp: Define and use _FP_STATIC_ASSERT.
authorJoseph Myers <joseph@codesourcery.com>
Thu, 12 Mar 2015 18:43:21 +0000 (18:43 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 12 Mar 2015 18:43:21 +0000 (18:43 +0000)
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 <stdlib.h> 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 <stdlib.h> 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 <stdlib.h>.
[!_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 <stdlib.h>.

ChangeLog
soft-fp/op-2.h
soft-fp/op-common.h
soft-fp/soft-fp.h
sysdeps/powerpc/nofpu/flt-rounds.c

index a176009..d6526e9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2015-03-12  Joseph Myers  <joseph@codesourcery.com>
+
+       * soft-fp/soft-fp.h (_FP_STATIC_ASSERT): New macro.
+       [_LIBC]: Do not include <stdlib.h>.
+       [!_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 <stdlib.h>.
+
 2015-03-12  Yaakov Selkowitz  <yselkowi@redhat.com>
 
        * manual/string.texi (XPG basename): Fix prototype.
index c27b890..a51eb6b 100644 (file)
                                       _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;                                                         \
                                                                        \
index 83c2156..9c1c5e3 100644 (file)
            (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;                              \
                      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)                              \
 #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))                                        \
 #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))                                        \
        {                                                               \
 # 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 */
index b247125..3b39336 100644 (file)
 # 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 <stdlib.h>
-#else
-extern void abort (void);
-#endif
-
 #endif /* !SOFT_FP_H */
index e581873..3792856 100644 (file)
@@ -16,6 +16,8 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <stdlib.h>
+
 #include "soft-fp.h"
 #include "soft-supp.h"