mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
Use STRFMON_LDBL_IS_DBL instead of __ldbl_is_dbl.
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.
This commit is contained in:
parent
346ef23f19
commit
c75772e3f0
25
ChangeLog
25
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user