On 24/02/21 17:00 +0000, Jonathan Wakely via Libstdc++ wrote:
libstdc++: Define std::to_chars overloads for __ieee128 [PR 98389]
This adds overloads of std::to_chars for powerpc64's __ieee128, so that
std::to_chars can be used for long double when -mabi=ieeelongdouble is
in used.
Eventually we'll want to extend these new overloads to work for
__float128 on all targets that support that type. For now, we're only
doing it for powerpc64 when the new long double type is supported in
parallel to the old long double type.
Additionally the existing std::to_chars overloads for long double
are given the right symbol version, resolving PR libstdc++/98389.
libstdc++-v3/ChangeLog:
PR libstdc++/98389
* config/abi/pre/gnu.ver (GLIBCXX_3.4.29): Do not match to_chars
symbols for long double arguments mangled as 'g'.
* config/os/gnu-linux/ldbl-extra.ver: Likewise.
* config/os/gnu-linux/ldbl-ieee128-extra.ver: Likewise.
* src/c++17/Makefile.am [GLIBCXX_LDBL_ALT128_COMPAT_TRUE]:
Use -mabi=ibmlongdouble for floating_to_chars.cc.
* src/c++17/Makefile.in: Regenerate.
* src/c++17/floating_to_chars.cc (floating_type_traits_binary128):
New type defining type traits of IEEE binary128 format.
(floating_type_traits<__float128>): Define specialization.
(floating_type_traits<long double>): Define in terms of
floating_type_traits_binary128 when appropriate.
(floating_to_shortest_scientific): Handle __float128.
(sprintf_ld): New function template for printing a long double
or __ieee128 value using sprintf.
(__floating_to_chars_shortest, __floating_to_chars_precision):
Use sprintf_ld.
(to_chars): Define overloads for __float128.
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver
b/libstdc++-v3/config/abi/pre/gnu.ver
index d0c8066ce83..a2c151d11ac 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2394,11 +2394,11 @@ GLIBCXX_3.4.29 {
_ZNSt9once_flag9_M_finishEb;
# std::to_chars(char*, char*, [float|double|long double])
- _ZSt8to_charsPcS_[defg];
+ _ZSt8to_charsPcS_[def];
# std::to_chars(char*, char*, [float|double|long double], chars_format)
- _ZSt8to_charsPcS_[defg]St12chars_format;
+ _ZSt8to_charsPcS_[def]St12chars_format;
# std::to_chars(char*, char*, [float|double|long double], chars_format, int)
- _ZSt8to_charsPcS_[defg]St12chars_formati;
+ _ZSt8to_charsPcS_[def]St12chars_formati;
N.B. when we add std::to_chars for __float128 (on other targets where
it's not __ieee128) and we restore the _ZSt8to_charsPcS_g* symbols
they'll have a new symbol version (probably GLIBCXX_3.4.30). When we
add those patterns into config/abi/pre/gnu.ver we'll need to do it
conditionally, so that for powerpc64le those symbols still get the
GLIBCXX_LDBL_3.4.29 version from config/os/gnu-linux/ldbl-extra.ver
e.g.
GLIBCXX_3.4.30 {
#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
_ZSt8to_charsPcS_g*;
#endif
} GLIBCXX_3.4.29;
This isn't *strictly* necessary, because GNU ld (unintentionally?)
allows a symbol to match more than one version and it seems to use the
later version. But we shouldn't rely on that. Solaris ld gives an
error in that case, but that's not a concern here because Solaris ld
isn't used for powerpc64le-linux (where those symbols want to use the
GLIBCXX_LDBL_3.4.29 version). But it would be better to make the
linker script clean and not rely on the GNU ld quirk.
I'm noting that here in case I get hit by a bus before that change is
needed.
} GLIBCXX_3.4.28;
diff --git a/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
b/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
index b4f3af0f9d9..8c7c783ba58 100644
--- a/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
+++ b/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
@@ -42,6 +42,7 @@ GLIBCXX_LDBL_3.4.21 {
GLIBCXX_LDBL_3.4.29 {
_ZSt10from_charsPKcS0_RgSt12chars_format;
+ _ZSt8to_charsPcS_g*;
} GLIBCXX_LDBL_3.4.21;