diff options
author | Zack Weinberg <zackw@panix.com> | 2018-03-07 14:31:57 -0500 |
---|---|---|
committer | Gabriel F. T. Gomes <gabriel@inconstante.eti.br> | 2018-11-16 09:21:14 -0200 |
commit | c75772e3f079b9265738e2f54644ee47f932d99a (patch) | |
tree | f779b4f7b6e2de6eb5dbcf367824c71419d046fb /stdlib | |
parent | 346ef23f197a0c8ba807c344bd39101b711050ee (diff) | |
download | glibc-c75772e3f079b9265738e2f54644ee47f932d99a.zip glibc-c75772e3f079b9265738e2f54644ee47f932d99a.tar.gz glibc-c75772e3f079b9265738e2f54644ee47f932d99a.tar.bz2 |
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.
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/strfmon.c | 3 | ||||
-rw-r--r-- | stdlib/strfmon_l.c | 8 |
2 files changed, 6 insertions, 5 deletions
diff --git a/stdlib/strfmon.c b/stdlib/strfmon.c index 01980d3..3058b3e 100644 --- a/stdlib/strfmon.c +++ b/stdlib/strfmon.c @@ -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); diff --git a/stdlib/strfmon_l.c b/stdlib/strfmon_l.c index cd3796c..5293104 100644 --- a/stdlib/strfmon_l.c +++ b/stdlib/strfmon_l.c @@ -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); |