aboutsummaryrefslogtreecommitdiff
path: root/soft-fp
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2015-03-12 18:43:21 +0000
committerJoseph Myers <joseph@codesourcery.com>2015-03-12 18:43:21 +0000
commit7d67a196b6548562070ac11fc673c0d3d263d846 (patch)
tree34b3481a8038d6756a4a652951847cb04a2b78dd /soft-fp
parentaf85ebcdf7a754d3d3d3d26ba8250ab58310f535 (diff)
downloadglibc-7d67a196b6548562070ac11fc673c0d3d263d846.tar
glibc-7d67a196b6548562070ac11fc673c0d3d263d846.tar.gz
glibc-7d67a196b6548562070ac11fc673c0d3d263d846.tar.bz2
glibc-7d67a196b6548562070ac11fc673c0d3d263d846.zip
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 <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>.
Diffstat (limited to 'soft-fp')
-rw-r--r--soft-fp/op-2.h4
-rw-r--r--soft-fp/op-common.h62
-rw-r--r--soft-fp/soft-fp.h17
3 files changed, 51 insertions, 32 deletions
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 <stdlib.h>
-#else
-extern void abort (void);
-#endif
-
#endif /* !SOFT_FP_H */