about summary refs log tree commit diff
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.gz
glibc-7d67a196b6548562070ac11fc673c0d3d263d846.tar.xz
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 */