Split __kernel_standard* functions (fixes bug 17724) [committed].

Message ID alpine.DEB.2.10.1412221846120.5278@digraph.polyomino.org.uk
State Committed
Headers

Commit Message

Joseph Myers Dec. 22, 2014, 6:46 p.m. UTC
  Bug 17724 reports references to fesetround being brought in by
ldbl-128ibm rintl via references to __rintl from __kernel_standard_l.
Because all three __kernel_standard* functions are in the same file,
this gets brought in even though only the long double version
__kernel_standard_l needs __rintl, and the C90 functions use only
__kernel_standard.

This patch fixes this by splitting the three versions into separate
files; it's fine for long double functions to refer to fe* functions
directly, unless they get called by C90 double functions.

Tested for x86_64 (testsuite; the reordering of code means disassembly
of shared libraries can't usefully be compared).  Tested for powerpc
that the relevant issue disappears from the linknamespace test
output.  Committed.

2014-12-22  Joseph Myers  <joseph@codesourcery.com>

	[BZ #17724]
	* sysdeps/ieee754/k_standard.c: Don't include <float.h>.
	(__kernel_standard_f): Remove.  Moved to k_standardf.c.
	(__kernel_standard_l): Remove.  Moved to k_standardl.c with
	(char *) casts added.
	* sysdeps/ieee754/k_standardf.c: New file.
	* sysdeps/ieee754/k_standardl.c: Likewise.
	* math/Makefile (libm-support): Remove k_standard.
	(libm-calls): Add k_standard.
  

Patch

diff --git a/math/Makefile b/math/Makefile
index 866bc0f..276a207 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -36,7 +36,7 @@  aux		:= setfpucw fpu_control
 extra-libs	:= libm
 extra-libs-others = $(extra-libs)
 
-libm-support = k_standard s_lib_version s_matherr s_signgam		\
+libm-support = s_lib_version s_matherr s_signgam			\
 	       fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg		\
 	       ftestexcept fegetround fesetround fegetenv feholdexcpt	\
 	       fesetenv feupdateenv t_exp fedisblxcpt feenablxcpt	\
@@ -61,7 +61,7 @@  libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod	\
 	     s_casinh s_cacosh s_catanh s_csqrt s_cpow s_cproj s_clog10 \
 	     s_fma s_lrint s_llrint s_lround s_llround e_exp10 w_log2	\
 	     s_isinf_ns s_issignaling $(calls:s_%=m_%) x2y2m1 k_casinh	\
-	     gamma_product
+	     gamma_product k_standard
 
 dbl-only-routines := branred doasin dosincos halfulp mpa mpatan2	\
 		     mpatan mpexp mplog mpsqrt mptan sincos32 slowexp	\
diff --git a/sysdeps/ieee754/k_standard.c b/sysdeps/ieee754/k_standard.c
index 5399c66..7b82cd1 100644
--- a/sysdeps/ieee754/k_standard.c
+++ b/sysdeps/ieee754/k_standard.c
@@ -16,7 +16,6 @@  static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $
 
 #include <math.h>
 #include <math_private.h>
-#include <float.h>
 #include <errno.h>
 
 #include <assert.h>
@@ -997,92 +996,3 @@  __kernel_standard(double x, double y, int type)
 	}
 	return exc.retval;
 }
-
-
-float
-__kernel_standard_f(float x, float y, int type)
-{
-	return __kernel_standard(x, y, type);
-}
-
-#ifndef __NO_LONG_DOUBLE_MATH
-long double
-__kernel_standard_l (long double x, long double y, int type)
-{
-  double dx, dy;
-  struct exception exc;
-
-  if (isfinite (x))
-    {
-      long double ax = fabsl (x);
-      if (ax > DBL_MAX)
-	dx = __copysignl (DBL_MAX, x);
-      else if (ax > 0 && ax < DBL_MIN)
-	dx = __copysignl (DBL_MIN, x);
-      else
-	dx = x;
-    }
-  else
-    dx = x;
-  if (isfinite (y))
-    {
-      long double ay = fabsl (y);
-      if (ay > DBL_MAX)
-	dy = __copysignl (DBL_MAX, y);
-      else if (ay > 0 && ay < DBL_MIN)
-	dy = __copysignl (DBL_MIN, y);
-      else
-	dy = y;
-    }
-  else
-    dy = y;
-
-  switch (type)
-    {
-    case 221:
-      /* powl (x, y) overflow.  */
-      exc.arg1 = dx;
-      exc.arg2 = dy;
-      exc.type = OVERFLOW;
-      exc.name = "powl";
-      if (_LIB_VERSION == _SVID_)
-	{
-	  exc.retval = HUGE;
-	  y *= 0.5;
-	  if (x < zero && __rintl (y) != y)
-	    exc.retval = -HUGE;
-	}
-      else
-	{
-	  exc.retval = HUGE_VAL;
-	  y *= 0.5;
-	  if (x < zero && __rintl (y) != y)
-	    exc.retval = -HUGE_VAL;
-	}
-      if (_LIB_VERSION == _POSIX_)
-	__set_errno (ERANGE);
-      else if (!matherr (&exc))
-	__set_errno (ERANGE);
-      return exc.retval;
-
-    case 222:
-      /* powl (x, y) underflow.  */
-      exc.arg1 = dx;
-      exc.arg2 = dy;
-      exc.type = UNDERFLOW;
-      exc.name = "powl";
-      exc.retval = zero;
-      y *= 0.5;
-      if (x < zero && __rintl (y) != y)
-	exc.retval = -zero;
-      if (_LIB_VERSION == _POSIX_)
-	__set_errno (ERANGE);
-      else if (!matherr (&exc))
-	__set_errno (ERANGE);
-      return exc.retval;
-
-    default:
-      return __kernel_standard (dx, dy, type);
-    }
-}
-#endif
diff --git a/sysdeps/ieee754/k_standardf.c b/sysdeps/ieee754/k_standardf.c
new file mode 100644
index 0000000..b4aeadf
--- /dev/null
+++ b/sysdeps/ieee754/k_standardf.c
@@ -0,0 +1,31 @@ 
+/* Implement __kernel_standard_f.
+   Copyright (C) 2011-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+
+/* Handle errors for a libm function as specified by TYPE (see
+   comments in k_standard.c for details), with arguments X and Y,
+   returning the appropriate return value for that function.  */
+
+float
+__kernel_standard_f (float x, float y, int type)
+{
+  return __kernel_standard (x, y, type);
+}
diff --git a/sysdeps/ieee754/k_standardl.c b/sysdeps/ieee754/k_standardl.c
new file mode 100644
index 0000000..3c0a447
--- /dev/null
+++ b/sysdeps/ieee754/k_standardl.c
@@ -0,0 +1,123 @@ 
+/* Implement __kernel_standard_l.
+   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.
+
+   Parts based on k_standard.c from fdlibm: */
+
+/* @(#)k_standard.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+#include <errno.h>
+
+
+static double zero = 0.0;
+
+/* Handle errors for a libm function as specified by TYPE (see
+   comments in k_standard.c for details), with arguments X and Y,
+   returning the appropriate return value for that function.  */
+
+long double
+__kernel_standard_l (long double x, long double y, int type)
+{
+  double dx, dy;
+  struct exception exc;
+
+  if (isfinite (x))
+    {
+      long double ax = fabsl (x);
+      if (ax > DBL_MAX)
+	dx = __copysignl (DBL_MAX, x);
+      else if (ax > 0 && ax < DBL_MIN)
+	dx = __copysignl (DBL_MIN, x);
+      else
+	dx = x;
+    }
+  else
+    dx = x;
+  if (isfinite (y))
+    {
+      long double ay = fabsl (y);
+      if (ay > DBL_MAX)
+	dy = __copysignl (DBL_MAX, y);
+      else if (ay > 0 && ay < DBL_MIN)
+	dy = __copysignl (DBL_MIN, y);
+      else
+	dy = y;
+    }
+  else
+    dy = y;
+
+  switch (type)
+    {
+    case 221:
+      /* powl (x, y) overflow.  */
+      exc.arg1 = dx;
+      exc.arg2 = dy;
+      exc.type = OVERFLOW;
+      exc.name = (char *) "powl";
+      if (_LIB_VERSION == _SVID_)
+	{
+	  exc.retval = HUGE;
+	  y *= 0.5;
+	  if (x < zero && __rintl (y) != y)
+	    exc.retval = -HUGE;
+	}
+      else
+	{
+	  exc.retval = HUGE_VAL;
+	  y *= 0.5;
+	  if (x < zero && __rintl (y) != y)
+	    exc.retval = -HUGE_VAL;
+	}
+      if (_LIB_VERSION == _POSIX_)
+	__set_errno (ERANGE);
+      else if (!matherr (&exc))
+	__set_errno (ERANGE);
+      return exc.retval;
+
+    case 222:
+      /* powl (x, y) underflow.  */
+      exc.arg1 = dx;
+      exc.arg2 = dy;
+      exc.type = UNDERFLOW;
+      exc.name = (char *) "powl";
+      exc.retval = zero;
+      y *= 0.5;
+      if (x < zero && __rintl (y) != y)
+	exc.retval = -zero;
+      if (_LIB_VERSION == _POSIX_)
+	__set_errno (ERANGE);
+      else if (!matherr (&exc))
+	__set_errno (ERANGE);
+      return exc.retval;
+
+    default:
+      return __kernel_standard (dx, dy, type);
+    }
+}