]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Use STRFMON_LDBL_IS_DBL instead of __ldbl_is_dbl.
authorZack Weinberg <zackw@panix.com>
Wed, 7 Mar 2018 19:31:57 +0000 (14:31 -0500)
committerGabriel F. T. Gomes <gabriel@inconstante.eti.br>
Fri, 16 Nov 2018 11:21:14 +0000 (09:21 -0200)
On platforms where long double used to have the same format as double,
but later switched to a different format (alpha, s390, sparc, and
powerpc), accessing the older behavior is possible and it happens via
__nldbl_* functions (not on the API, but accessible from header
redirection and from compat symbols).  These functions write to the
global flag __ldbl_is_dbl, which tells other functions that long double
variables should be handled as double.  This patch takes the first step
towards removing this global flag and creates __vstrfmon_l_internal,
which takes an explicit flags parameter.

This change arguably makes the generated code slightly worse on
architectures where __ldbl_is_dbl is never true; right now, on those
architectures, it's a compile-time constant; after this change, the
compiler could theoretically prove that __vstrfmon_l_internal was
never called with a nonzero flags argument, but it would probably need
LTO to do it.  This is not performance critical code and I tend to
think that the maintainability benefits of removing action at a
distance are worth it.  However, we _could_ wrap the runtime flag
check with a macro that was defined to ignore its argument and always
return false on architectures where __ldbl_is_dbl is never true, if
people think the codegen benefits are important.

Tested for powerpc and powerpc64le.

ChangeLog
include/monetary.h
manual/locale.texi
stdlib/strfmon.c
stdlib/strfmon_l.c
sysdeps/ieee754/ldbl-opt/nldbl-compat.c
sysdeps/ieee754/ldbl-opt/nldbl-compat.h

index 8dcdcc8b07024b7a134d59b2ea584eb8da4b28a2..c71209b039cb861d6b504fdd91b4496019583d61 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2018-11-16  Zack Weinberg  <zackw@panix.com>
+           Gabriel F. T. Gomes  <gabriel@inconstante.eti.br>
+
+       * include/monetary.h (STRFMON_LDBL_IS_DBL): New constant.
+       (__vstrfmon_l): Rename to __vstrfmon_l_internal and add flags
+       argument.
+       * stdlib/strfmon_l.c (__vstrfmon_l): Rename to __vstrfmon_l_internal
+       and add flags argument.  Check flags instead of __ldbl_is_dbl when
+       deciding whether to set is_long_double.
+       (__strfmon_l): Call __vstrfmon_l_internal instead of __vstrfmon_l,
+       passing zero for flags argument.
+       * stdlib/strfmon.c (strfmon): Same change as made to __strfmon_l.
+
+       * sysdeps/ieee754/ldbl-opt/nldbl-compat.c
+       (__nldbl___vstrfmon, __nldbl___vstrfmon_l)
+       (__nldbl_strfmon, __nldbl___strfmon_l): Call __vstrfmon_l_internal
+       directly, passing STRFMON_LDBL_IS_DBL for flags argument.  Normalize
+       variable names.  Remove libc_hidden_def/libc_hidden_proto from
+       __nldbl___vstrfmon and __nldbl___vstrfmon_l, because they are no
+       longer called from within the library.
+       * sysdeps/ieee754/ldbl-opt/nldbl-compat.h: Don't use NLDBL_DECL
+       for __nldbl___vstrfmon_l, declare it explicitly.
+
+       * manual/locale.texi: Update a reference to vstrfmon_l in comments.
+
 2018-11-15  Samuel Thibault  <samuel.thibault@ens-lyon.org>
 
        * sysdeps/mach/hurd/bits/fcntl.h (F_GETLK64, F_SETLK64, F_SETLKW64): New
index c130ed56a3e43a206ee3dcb45dac2b8fdfffeabc..f59bdf9150b5f882038831d83bc500d1067466df 100644 (file)
@@ -2,7 +2,18 @@
 #ifndef _ISOMAC
 #include <stdarg.h>
 
-extern ssize_t __vstrfmon_l (char *s, size_t maxsize, locale_t loc,
-                            const char *format, va_list ap)
-     attribute_hidden;
+extern ssize_t
+__vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
+                      const char *format, va_list ap,
+                      unsigned int flags)
+  attribute_hidden;
+
+/* Flags for __vstrfmon_l_internal.
+
+   STRFMON_LDBL_IS_DBL is a one-bit mask for the flags parameter that
+   indicates whether long double values are to be handled as having the
+   same format as double, in which case the flag should be set to one,
+   or as another format, otherwise.  */
+#define STRFMON_LDBL_IS_DBL 0x0001
+
 #endif
index dabb959f9eec5471d10df2d1b93d0795b1c2269b..720e0ca952a665bd12a8e5bc3821187ceec59bbd 100644 (file)
@@ -1209,10 +1209,11 @@ numbers according to these rules.
 
 @deftypefun ssize_t strfmon (char *@var{s}, size_t @var{maxsize}, const char *@var{format}, @dots{})
 @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
-@c It (and strfmon_l) both call vstrfmon_l, which, besides accessing the
-@c locale object passed to it, accesses the active locale through
-@c isdigit (but to_digit assumes ASCII digits only).  It may call
-@c __printf_fp (@mtslocale @ascuheap @acsmem) and guess_grouping (safe).
+@c It (and strfmon_l) both call __vstrfmon_l_internal, which, besides
+@c accessing the locale object passed to it, accesses the active
+@c locale through isdigit (but to_digit assumes ASCII digits only).
+@c It may call __printf_fp (@mtslocale @ascuheap @acsmem) and
+@c guess_grouping (safe).
 The @code{strfmon} function is similar to the @code{strftime} function
 in that it takes a buffer, its size, a format string,
 and values to write into the buffer as text in a form specified
index 01980d3e15d78a118ec1d1b1cbb2442a374ea94c..3058b3eed1aa0e4d28bbdee6c9b09f3c6a4b7f0b 100644 (file)
@@ -30,7 +30,8 @@ __strfmon (char *s, size_t maxsize, const char *format, ...)
 
   va_start (ap, format);
 
-  ssize_t res = __vstrfmon_l (s, maxsize, _NL_CURRENT_LOCALE, format, ap);
+  ssize_t res = __vstrfmon_l_internal (s, maxsize, _NL_CURRENT_LOCALE,
+                                      format, ap, 0);
 
   va_end (ap);
 
index cd3796ced9805dbe57d26713f16555d5bc77058d..5293104400751585db569945ddaf1acec55eb1ef 100644 (file)
@@ -76,8 +76,8 @@
    too.  Some of the information contradicts the information which can
    be specified in format string.  */
 ssize_t
-__vstrfmon_l (char *s, size_t maxsize, locale_t loc, const char *format,
-             va_list ap)
+__vstrfmon_l_internal (char *s, size_t maxsize, locale_t loc,
+                      const char *format, va_list ap, unsigned int flags)
 {
   struct __locale_data *current = loc->__locales[LC_MONETARY];
   _IO_strfile f;
@@ -268,7 +268,7 @@ __vstrfmon_l (char *s, size_t maxsize, locale_t loc, const char *format,
       if (*fmt == 'L')
        {
          ++fmt;
-         if (!__ldbl_is_dbl)
+         if (__glibc_likely ((flags & STRFMON_LDBL_IS_DBL) == 0))
            is_long_double = 1;
        }
 
@@ -608,7 +608,7 @@ ___strfmon_l (char *s, size_t maxsize, locale_t loc, const char *format, ...)
 
   va_start (ap, format);
 
-  ssize_t res = __vstrfmon_l (s, maxsize, loc, format, ap);
+  ssize_t res = __vstrfmon_l_internal (s, maxsize, loc, format, ap, 0);
 
   va_end (ap);
 
index ffb5fabebe7f5a2c31f176ef99fba1e700348ae8..7a1e89c1a30587208695bdd251413fb6e2bf600a 100644 (file)
@@ -51,8 +51,6 @@ libc_hidden_proto (__nldbl___vswprintf_chk)
 libc_hidden_proto (__nldbl___vasprintf_chk)
 libc_hidden_proto (__nldbl___vdprintf_chk)
 libc_hidden_proto (__nldbl___obstack_vprintf_chk)
-libc_hidden_proto (__nldbl___vstrfmon)
-libc_hidden_proto (__nldbl___vstrfmon_l)
 libc_hidden_proto (__nldbl___isoc99_vsscanf)
 libc_hidden_proto (__nldbl___isoc99_vfscanf)
 libc_hidden_proto (__nldbl___isoc99_vswscanf)
@@ -780,12 +778,13 @@ attribute_compat_text_section
 __nldbl_strfmon (char *s, size_t maxsize, const char *format, ...)
 {
   va_list ap;
-  ssize_t res;
+  ssize_t ret;
 
   va_start (ap, format);
-  res = __nldbl___vstrfmon (s, maxsize, format, ap);
+  ret = __vstrfmon_l_internal (s, maxsize, _NL_CURRENT_LOCALE, format, ap,
+                              STRFMON_LDBL_IS_DBL);
   va_end (ap);
-  return res;
+  return ret;
 }
 
 ssize_t
@@ -794,12 +793,13 @@ __nldbl___strfmon_l (char *s, size_t maxsize, locale_t loc,
                     const char *format, ...)
 {
   va_list ap;
-  ssize_t res;
+  ssize_t ret;
 
   va_start (ap, format);
-  res = __nldbl___vstrfmon_l (s, maxsize, loc, format, ap);
+  ret = __vstrfmon_l_internal (s, maxsize, loc, format, ap,
+                              STRFMON_LDBL_IS_DBL);
   va_end (ap);
-  return res;
+  return ret;
 }
 weak_alias (__nldbl___strfmon_l, __nldbl_strfmon_l)
 
@@ -807,28 +807,18 @@ ssize_t
 attribute_compat_text_section
 __nldbl___vstrfmon (char *s, size_t maxsize, const char *format, va_list ap)
 {
-  ssize_t res;
-  __no_long_double = 1;
-  res = __vstrfmon_l (s, maxsize, _NL_CURRENT_LOCALE, format, ap);
-  __no_long_double = 0;
-  va_end (ap);
-  return res;
+  return __vstrfmon_l_internal (s, maxsize, _NL_CURRENT_LOCALE, format, ap,
+                               STRFMON_LDBL_IS_DBL);
 }
-libc_hidden_def (__nldbl___vstrfmon)
 
 ssize_t
 attribute_compat_text_section
 __nldbl___vstrfmon_l (char *s, size_t maxsize, locale_t loc,
                      const char *format, va_list ap)
 {
-  ssize_t res;
-  __no_long_double = 1;
-  res = __vstrfmon_l (s, maxsize, loc, format, ap);
-  __no_long_double = 0;
-  va_end (ap);
-  return res;
+  return __vstrfmon_l_internal (s, maxsize, loc, format, ap,
+                               STRFMON_LDBL_IS_DBL);
 }
-libc_hidden_def (__nldbl___vstrfmon_l)
 
 void
 attribute_compat_text_section
index b7e938f7854d1c425a57f1cc62ce653cb6266d18..b7606c3c2dc6acdeac945c5d6f054ee17431d78a 100644 (file)
@@ -64,7 +64,6 @@ NLDBL_DECL (vsyslog);
 NLDBL_DECL (qecvt);
 NLDBL_DECL (qfcvt);
 NLDBL_DECL (qgcvt);
-NLDBL_DECL (__vstrfmon_l);
 NLDBL_DECL (__isoc99_scanf);
 NLDBL_DECL (__isoc99_fscanf);
 NLDBL_DECL (__isoc99_sscanf);
@@ -78,10 +77,13 @@ NLDBL_DECL (__isoc99_vwscanf);
 NLDBL_DECL (__isoc99_vfwscanf);
 NLDBL_DECL (__isoc99_vswscanf);
 
-/* This one does not exist in the normal interface, only
-   __nldbl___vstrfmon really exists.  */
+/* These do not exist in the normal interface, but must exist in the
+   __nldbl interface so that they can be called from libnldbl.  */
 extern ssize_t __nldbl___vstrfmon (char *, size_t, const char *, va_list)
   __THROW;
+extern ssize_t __nldbl___vstrfmon_l (char *, size_t, locale_t, const char *,
+                                    va_list)
+  __THROW;
 
 /* These don't use __typeof because they were not declared by the headers,
    since we don't compile with _FORTIFY_SOURCE.  */