public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
@ 2020-11-11 21:50 Jonathan Wakely
  2020-11-30 21:30 ` Michael Meissner
  2020-11-30 23:29 ` Segher Boessenkool
  0 siblings, 2 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-11-11 21:50 UTC (permalink / raw)
  To: libstdc++, gcc-patches
  Cc: Peter Bergner, Michael Meissner, Segher Boessenkool,
	David Edelsohn, Bill Schmidt

[-- Attachment #1: Type: text/plain, Size: 2162 bytes --]

This adds support for the new __ieee128 long double format on
powerpc64le targets.

Most of the complexity comes from wanting a single libstdc++.so library
that contains the symbols needed by code compiled with both
-mabi=ibmlongdouble and -mabi=ieeelongdouble (and not forgetting
-mlong-double-64 as well!)

In a few places this just requires an extra overload, for example
std::from_chars has to be overloaded for both forms of long double.
That can be done in a single translation unit that defines overloads
for 'long double' and also '__ieee128', so that user code including
<charconv> will be able to link to a definition for either type of long
double. Those are the easy cases.

The difficult parts are (as for the std::string ABI transition) the I/O
and locale facets. In order to be able to write either form of long
double to an ostream such as std::cout we need the locale to contain a
std::num_put facet that can handle both forms. The same approach is
taken as was already done for supporting 64-bit long double and 128-bit
long double: adding extra overloads of do_put to the facet class. On
targets where the new long double code is enabled, the facets that are
registered in the locale at program startup have additional overloads so
that they can work with any long double type. Where this fails to work
is if user code installs its own facet, which will probably not have the
additional overloads and so will only be able to output one or the other
type. In practice the number of users expecting to be able to use their
own locale facets in code using a mix of -mabi=ibmlongdouble and
-mabi=ieeelongdouble is probably close to zero.



Not yet pushed to master.

Tested x86_64-linux, powerpc64pe-linux (glibc 2.31 and 2.32, i.e.
with and without libc support for ieee128 long double).

There are still some test failures when using -mabi=ieeelongdouble
(whether adding that to the dejagnu test flags or by configuring GCC
with --with-long-double-format=ieee). Some of them are testing the
problem case mentioned above (custom facets that don't handle both
types of long double) but others are less clear, and I'm still hoping
to fix them.




[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 94846 bytes --]

commit c2ac6fe2105cac1e83dffc303082e337fd97fcc5
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Nov 12 10:47:41 2018

    libstdc++: Add C++ runtime support for new 128-bit long double format
    
    This adds support for the new __ieee128 long double format on
    powerpc64le targets.
    
    Most of the complexity comes from wanting a single libstdc++.so library
    that contains the symbols needed by code compiled with both
    -mabi=ibmlongdouble and -mabi=ieeelongdouble (and not forgetting
    -mlong-double-64 as well!)
    
    In a few places this just requires an extra overload, for example
    std::from_chars has to be overloaded for both forms of long double.
    That can be done in a single translation unit that defines overloads
    for 'long double' and also '__ieee128', so that user code including
    <charconv> will be able to link to a definition for either type of long
    double. Those are the easy cases.
    
    The difficult parts are (as for the std::string ABI transition) the I/O
    and locale facets. In order to be able to write either form of long
    double to an ostream such as std::cout we need the locale to contain a
    std::num_put facet that can handle both forms. The same approach is
    taken as was already done for supporting 64-bit long double and 128-bit
    long double: adding extra overloads of do_put to the facet class. On
    targets where the new long double code is enabled, the facets that are
    registered in the locale at program startup have additional overloads so
    that they can work with any long double type. Where this fails to work
    is if user code installs its own facet, which will probably not have the
    additional overloads and so will only be able to output one or the other
    type. In practice the number of users expecting to be able to use their
    own locale facets in code using a mix of -mabi=ibmlongdouble and
    -mabi=ieeelongdouble is probably close to zero.
    
    libstdc++-v3/ChangeLog:
    
            * Makefile.in: Regenerate.
            * config.h.in: Regenerate.
            * config/abi/pre/gnu.ver: Make patterns less greedy.
            * config/os/gnu-linux/ldbl-ieee128-extra.ver: New file with patterns
            for IEEE128 long double symbols.
            * configure: Regenerate.
            * configure.ac: Enable alternative 128-bit long double format on
            powerpc64*-*-linux*.
            * doc/Makefile.in: Regenerate.
            * fragment.am: Regenerate.
            * include/Makefile.am: Set _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT.
            * include/Makefile.in: Regenerate.
            * include/bits/c++config: Define inline namespace for new long
            double symbols. Don't define _GLIBCXX_USE_FLOAT128 when it's the
            same type as long double.
            * include/bits/locale_classes.h [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT]
            (locale::_Impl::_M_init_extra_ldbl128): Declare new member function.
            * include/bits/locale_facets.h (_GLIBCXX_NUM_FACETS): Simplify by
            only counting narrow character facets.
            (_GLIBCXX_NUM_CXX11_FACETS): Likewise.
            (_GLIBCXX_NUM_LBDL_ALT128_FACETS): New.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT] (num_get::__do_get): Define
            vtable placeholder for __ibm128 long double type.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (num_get::__do_get): Declare vtable placeholder for __ibm128 long
            double type.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (num_put::__do_put): Likewise.
            * include/bits/locale_facets.tcc
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (num_get::__do_get, num_put::__do_put): Define.
            * include/bits/locale_facets_nonio.h
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (money_get::__do_get): Declare vtable placeholder for __ibm128 long
            double type.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (money_put::__do_put): Likewise.
            * include/bits/locale_facets_nonio.tcc
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (money_get::__do_get, money_put::__do_put): Define.
            * libsupc++/Makefile.in: Regenerate.
            * po/Makefile.in: Regenerate.
            * python/Makefile.in: Regenerate.
            * src/Makefile.am: Add compatibility-ldbl-alt128.cc and
            compatibility-ldbl-alt128-cxx11.cc sources and recipes for objects.
            * src/Makefile.in: Regenerate.
            * src/c++11/Makefile.in: Regenerate.
            * src/c++11/compatibility-ldbl-alt128-cxx11.cc: New file defining
            symbols using the old 128-bit long double format, for the cxx11 ABI.
            * src/c++11/compatibility-ldbl-alt128.cc: Likewise, for the
            gcc4-compatible ABI.
            * src/c++11/compatibility-ldbl-facets-aliases.h: New header for long
            double compat aliases.
            * src/c++11/cow-locale_init.cc: Add comment.
            * src/c++11/cxx11-locale-inst.cc: Define C and C_is_char
            unconditionally.
            * src/c++11/cxx11-wlocale-inst.cc: Add sanity check. Include
            locale-inst.cc directly, not via cxx11-locale-inst.cc.
            * src/c++11/locale-inst-monetary.h: New header for monetary
            category instantiations.
            * src/c++11/locale-inst-numeric.h: New header for numeric category
            instantiations.
            * src/c++11/locale-inst.cc: Include new headers for monetary,
            numeric, and long double definitions.
            * src/c++11/wlocale-inst.cc: Remove long double compat aliases that
            are defined in new header now.
            * src/c++17/Makefile.am: Use -mabi=ibmlongdouble for
            floating_from_chars.cc.
            * src/c++17/Makefile.in: Regenerate.
            * src/c++17/floating_from_chars.cc (from_chars_impl): Add
            if-constexpr branch for __ieee128.
            (from_chars): Overload for __ieee128.
            * src/c++20/Makefile.in: Regenerate.
            * src/c++98/Makefile.in: Regenerate.
            * src/c++98/locale_init.cc (num_facets): Adjust calculation.
            (locale::_Impl::_Impl(size_t)): Call _M_init_extra_ldbl128.
            * src/c++98/localename.cc (num_facets): Adjust calculation.
            (locale::_Impl::_Impl(const char*, size_t)): Call
            _M_init_extra_ldbl128.
            * src/filesystem/Makefile.in: Regenerate.
            * testsuite/Makefile.in: Regenerate.
            * testsuite/util/testsuite_abi.cc: Add new symbol versions.
            Allow new symbols to be added to GLIBCXX_IEEE128_3.4.29 and
            CXXABI_IEEE128_1.3.13 too.
            * testsuite/27_numerics/complex/abi_tag.cc: Add u9___ieee128 to
            regex matching expected symbols.
    
    libstdc++-v3/ChangeLog:
    
            * Makefile.in:
            * config.h.in:
            * config/abi/pre/gnu.ver:
            * configure:
            * configure.ac:
            * doc/Makefile.in:
            * fragment.am:
            * include/Makefile.am:
            * include/Makefile.in:
            * include/bits/c++config:
            * include/bits/locale_classes.h:
            * include/bits/locale_facets.h (_GLIBCXX_NUM_FACETS):
            (_GLIBCXX_NUM_CXX11_FACETS):
            (_GLIBCXX_NUM_LBDL_ALT128_FACETS):
            * include/bits/locale_facets.tcc:
            * include/bits/locale_facets_nonio.h:
            * include/bits/locale_facets_nonio.tcc:
            * libsupc++/Makefile.in:
            * po/Makefile.in:
            * python/Makefile.in:
            * src/Makefile.am:
            * src/Makefile.in:
            * src/c++11/Makefile.in:
            * src/c++11/cow-locale_init.cc:
            * src/c++11/cxx11-locale-inst.cc (C):
            (C_is_char):
            * src/c++11/cxx11-wlocale-inst.cc (C):
            * src/c++11/locale-inst.cc (_GLIBCXX_LDBL_COMPAT):
            * src/c++11/wlocale-inst.cc (_GLIBCXX_LDBL_COMPAT):
            * src/c++17/Makefile.am:
            * src/c++17/Makefile.in:
            * src/c++17/floating_from_chars.cc (__strtoieee128):
            (from_chars):
            * src/c++20/Makefile.in:
            * src/c++98/Makefile.in:
            * src/c++98/locale_init.cc:
            * src/c++98/localename.cc:
            * src/filesystem/Makefile.in:
            * testsuite/26_numerics/complex/abi_tag.cc:
            * testsuite/Makefile.in:
            * testsuite/util/testsuite_abi.cc:
            * config/os/gnu-linux/ldbl-ieee128-extra.ver: New file.
            * src/c++11/compatibility-ldbl-alt128-cxx11.cc: New file.
            * src/c++11/compatibility-ldbl-alt128.cc: New file.
            * src/c++11/compatibility-ldbl-facets-aliases.h: New file.
            * src/c++11/locale-inst-monetary.h: New file.
            * src/c++11/locale-inst-numeric.h: New file.

diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 46769db15303..4b4bd8ab6da0 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -682,7 +682,7 @@ GLIBCXX_3.4 {
     _ZNSt12__basic_fileIcED*;
 
     # std::__convert_to_v
-    _ZSt14__convert_to_vI[^g]*;
+    _ZSt14__convert_to_vI[^gU]*;
 
     # __gnu_cxx::stdio_sync_filebuf
     _ZTVN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EEE;
@@ -931,7 +931,7 @@ GLIBCXX_3.4 {
     _ZGVNSt8time_putI[cw]*;
     _ZGVNSt9money_getI[cw]*;
     _ZGVNSt9money_putI[cw]*;
-    _ZGVNSt1[^07]*;
+    _ZGVNSt1[^079]*;
     _ZGVNSt10moneypunctI[cw]Lb[01]*;
 
     # exception constructors taking std::string
diff --git a/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
new file mode 100644
index 000000000000..3c3395e4d4e2
--- /dev/null
+++ b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
@@ -0,0 +1,53 @@
+# Appended to version file.
+
+GLIBCXX_IEEE128_3.4.29 {
+
+  *__gnu_cxx_ieee128*;
+
+  _ZNSt14numeric_limitsIu9__ieee128E*;
+  _ZNSirsERu9__ieee128;
+  _ZNSolsEu9__ieee128;
+  _ZNSt13basic_istreamIwSt11char_traitsIwEErsERu9__ieee128;
+  _ZNSt13basic_ostreamIwSt11char_traitsIwEElsEu9__ieee128;
+  _ZSt14__convert_to_vIu9__ieee128EvPKcRT_RSt12_Ios_IostateRKP*;
+  _ZStlsIu9__ieee128[cw]St11char_traitsI[cw]EERSt13basic_ostreamIT0_T1_ES6_RKSt7complexIT_E;
+  _ZStrsIu9__ieee128[cw]St11char_traitsI[cw]EERSt13basic_istreamIT0_T1_ES6_RSt7complexIT_E;
+
+  _ZNSi10_M_extractIu9__ieee128EERSiRT_;
+  _ZNSt13basic_istreamIwSt11char_traitsIwEE10_M_extractIu9__ieee128EERS2_RT_;
+  _ZNSo9_M_insertIu9__ieee128EERSoT_;
+  _ZNSt13basic_ostreamIwSt11char_traitsIwEE9_M_insertIu9__ieee128EERS2_T_;
+
+  _ZNKSt3tr14hashIu9__ieee128EclEu9__ieee128;
+  _ZNKSt4hashIu9__ieee128EclEu9__ieee128;
+
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRNSt7__cxx1112basic_stringIcS3_SaIcEEE;
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRu9__ieee128;
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE8__do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRd;
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE8__do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRg;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES4_bRSt8ios_basecRKNSt7__cxx1112basic_stringIcS3_SaIcEEE;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES4_bRSt8ios_basecu9__ieee128;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE8__do_putES4_bRSt8ios_basecd;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE8__do_putES4_bRSt8ios_basecg;
+  _ZSt9has_facetINSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEEbRKSt6locale;
+  _ZSt9has_facetINSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEEbRKSt6locale;
+  _ZSt9use_facetINSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEERKT_RKSt6locale;
+  _ZSt9use_facetINSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEERKT_RKSt6locale;
+  _ZTINSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+  _ZTVNSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+  _ZTINSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+  _ZTVNSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+
+  _ZNKSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE3putES4_bRSt8ios_base[cw]u9__ieee128;
+
+  _ZSt10from_charsPKcS0_Ru9__ieee128St12chars_format;
+
+} GLIBCXX_3.4.29;
+
+CXXABI_IEEE128_1.3.13 {
+
+  _ZT[IS]u9__ieee128;
+  _ZT[IS]Pu9__ieee128;
+  _ZT[IS]PKu9__ieee128;
+
+} CXXABI_1.3.13;
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index cbfdf4c6bad1..d25842fef35d 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -404,7 +404,11 @@ GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI([yes])
 GLIBCXX_DEFAULT_ABI
 
 ac_ldbl_compat=no
+ac_ldbl_alt128_compat=no
+ac_ldbl_ieee128_default=no
 LONG_DOUBLE_COMPAT_FLAGS="-mlong-double-64"
+LONG_DOUBLE_128_FLAGS=
+LONG_DOUBLE_ALT128_COMPAT_FLAGS=
 case "$target" in
   powerpc*-*-linux* | \
   sparc*-*-linux* | \
@@ -421,12 +425,43 @@ case "$target" in
     port_specific_symbol_files="\$(top_srcdir)/config/os/gnu-linux/ldbl-extra.ver"
     case "$target" in
       powerpc*-*-linux*)
-	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute" ;;
+	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute"
+        # Check for IEEE128 support in libm:
+        AC_CHECK_LIB(m, frexpf128,
+                     [ac_ldbl_ieee128_in_libc=yes],
+                     [ac_ldbl_ieee128_in_libc=no])
+        if test $ac_ldbl_ieee128_in_libc = yes; then
+          # Determine which long double format is the compiler's default:
+          AC_TRY_COMPILE(, [
+            #ifndef __LONG_DOUBLE_IEEE128__
+            #error compiler defaults to ibm128
+            #endif
+          ], [ac_ldbl_ieee128_default=yes], [ac_ldbl_ieee128_default=no])
+          # Library objects should use default long double format.
+          if test "$ac_ldbl_ieee128_default" = yes; then
+            LONG_DOUBLE_128_FLAGS="-mno-gnu-attribute"
+            # Except for the ones that explicitly use these flags:
+            LONG_DOUBLE_ALT128_COMPAT_FLAGS="-mabi=ibmlongdouble -mno-gnu-attribute -Wno-psabi"
+          else
+            LONG_DOUBLE_128_FLAGS="-mno-gnu-attribute"
+            LONG_DOUBLE_ALT128_COMPAT_FLAGS="-mabi=ieeelongdouble -mno-gnu-attribute -Wno-psabi"
+          fi
+          AC_DEFINE([_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT],1,
+                [Define if compatibility should be provided for alternative 128-bit long double formats.])
+          port_specific_symbol_files="$port_specific_symbol_files \$(top_srcdir)/config/os/gnu-linux/ldbl-ieee128-extra.ver"
+          ac_ldbl_alt128_compat=yes
+        else
+          ac_ldbl_alt128_compat=no
+        fi
+	;;
     esac
   fi
 esac
 AC_SUBST(LONG_DOUBLE_COMPAT_FLAGS)
+AC_SUBST(LONG_DOUBLE_128_FLAGS)
+AC_SUBST(LONG_DOUBLE_ALT128_COMPAT_FLAGS)
 GLIBCXX_CONDITIONAL(GLIBCXX_LDBL_COMPAT, test $ac_ldbl_compat = yes)
+GLIBCXX_CONDITIONAL(GLIBCXX_LDBL_ALT128_COMPAT, test $ac_ldbl_alt128_compat = yes)
 
 # Check if assembler supports disabling hardware capability support.
 GCC_CHECK_ASSEMBLER_HWCAP
diff --git a/libstdc++-v3/fragment.am b/libstdc++-v3/fragment.am
index 216c572fc60e..54645739e5cd 100644
--- a/libstdc++-v3/fragment.am
+++ b/libstdc++-v3/fragment.am
@@ -25,10 +25,16 @@ else
 XTEMPLATE_FLAGS =
 endif
 
+if GLIBCXX_LDBL_ALT128_COMPAT
+LDBL_128_FLAGS = $(LONG_DOUBLE_128_FLAGS)
+else
+LDBL_128_FLAGS =
+endif
+
 # These bits are all figured out from configure.  Look in acinclude.m4
 # or configure.ac to see how they are set.  See GLIBCXX_EXPORT_FLAGS.
 CONFIG_CXXFLAGS = \
-	$(SECTION_FLAGS) $(HWCAP_CFLAGS) -frandom-seed=$@
+	$(SECTION_FLAGS) $(HWCAP_CFLAGS) -frandom-seed=$@ $(LDBL_128_FLAGS)
 
 WARN_CXXFLAGS = \
 	$(WARN_FLAGS) $(WERROR_FLAG) -fdiagnostics-show-location=once 
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 292d89da8ba7..9670c7c0de6c 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1287,6 +1287,10 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	grep "^[	 ]*#[	 ]*define[	 ][	 ]*_GLIBCXX_LONG_DOUBLE_COMPAT[	 ][	 ]*1[	 ]*$$" \
 	${CONFIG_HEADER} > /dev/null 2>&1 \
 	&& ldbl_compat='s,^#undef _GLIBCXX_LONG_DOUBLE_COMPAT$$,#define _GLIBCXX_LONG_DOUBLE_COMPAT 1,' ;\
+	ldbl_alt128_compat='s,g,g,' ;\
+	grep "^[	 ]*#[	 ]*define[	 ][	 ]*_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT[	 ][	 ]*1[	 ]*$$" \
+	${CONFIG_HEADER} > /dev/null 2>&1 \
+	&& ldbl_alt128_compat='s,^#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT$$,#define _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT 1,' ;\
 	sed -e "s,define __GLIBCXX__,define __GLIBCXX__ $$date," \
 	-e "s,define _GLIBCXX_RELEASE,define _GLIBCXX_RELEASE $$release," \
 	-e "s,define _GLIBCXX_INLINE_VERSION, define _GLIBCXX_INLINE_VERSION $$ns_version," \
@@ -1297,6 +1301,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	-e "s,define _GLIBCXX_USE_ALLOCATOR_NEW, define _GLIBCXX_USE_ALLOCATOR_NEW $$allocatornew," \
 	-e "s,define _GLIBCXX_USE_FLOAT128,$$float128," \
 	-e "$$ldbl_compat" \
+	-e "$$ldbl_alt128_compat" \
 	    < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
 	sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
 	    -e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
@@ -1307,6 +1312,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	    -e 's/_LARGE_FILES/_GLIBCXX_LARGE_FILES/g' \
 	    -e 's/ICONV_CONST/_GLIBCXX_ICONV_CONST/g' \
 	    -e '/[	 ]_GLIBCXX_LONG_DOUBLE_COMPAT[	 ]/d' \
+	    -e '/[	 ]_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT[	 ]/d' \
 	    < ${CONFIG_HEADER} >> $@ ;\
 	echo "" >> $@ ;\
 	echo "#endif // _GLIBCXX_CXX_CONFIG_H" >> $@
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 2e6c880ad95a..6af203d03ec3 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -425,8 +425,28 @@ _GLIBCXX_END_NAMESPACE_VERSION
 // GLIBCXX_ABI Deprecated
 // Define if compatibility should be provided for -mlong-double-64.
 #undef _GLIBCXX_LONG_DOUBLE_COMPAT
+// Define if compatibility should be provided for alternative 128-bit long
+// double formats.
+#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+// Inline namespaces for long double 128 modes.
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+  && defined __LONG_DOUBLE_IEEE128__
+namespace std
+{
+  // Namespaces for 128-bit IEEE long double format on 64-bit POWER LE.
+  inline namespace __gnu_cxx_ieee128 { }
+  inline namespace __gnu_cxx11_ieee128 { }
+}
+# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ieee128::
+# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ieee128 {
+# define _GLIBCXX_END_NAMESPACE_LDBL }
+# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 __gnu_cxx11_ieee128::
+# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 namespace __gnu_cxx11_ieee128 {
+# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 }
+
+#else // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && IEEE128
 
-// Inline namespace for long double 128 mode.
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
 namespace std
 {
@@ -440,6 +460,7 @@ namespace std
 # define _GLIBCXX_BEGIN_NAMESPACE_LDBL
 # define _GLIBCXX_END_NAMESPACE_LDBL
 #endif
+
 #if _GLIBCXX_USE_CXX11_ABI
 # define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_CXX11
 # define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_CXX11
@@ -450,6 +471,8 @@ namespace std
 # define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL
 #endif
 
+#endif // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && IEEE128
+
 // Debug Mode implies checking assertions.
 #if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS)
 # define _GLIBCXX_ASSERTIONS 1
@@ -648,9 +671,12 @@ namespace std
 # define __cpp_lib_char8_t 201907L
 #endif
 
-/* Define if __float128 is supported on this host. */
+/* Define if __float128 is supported on this host.  */
 #if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
-#define _GLIBCXX_USE_FLOAT128
+/* For powerpc64 don't use __float128 when it's the same type as long double. */
+# if !(defined(_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT) && defined(__LONG_DOUBLE_IEEE128__))
+#  define _GLIBCXX_USE_FLOAT128
+# endif
 #endif
 
 #if __GNUC__ >= 7
diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h
index ab90682cde23..ed7764e06e78 100644
--- a/libstdc++-v3/include/bits/locale_classes.h
+++ b/libstdc++-v3/include/bits/locale_classes.h
@@ -625,6 +625,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     void _M_init_extra(facet**);
     void _M_init_extra(void*, void*, const char*, const char*);
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    void _M_init_extra_ldbl128(bool);
+#endif
   };
 
 
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 3e0ae8776c9a..07be38fc92fa 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -51,20 +51,23 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  // NB: Don't instantiate required wchar_t facets if no wchar_t support.
-#ifdef _GLIBCXX_USE_WCHAR_T
-# define  _GLIBCXX_NUM_FACETS 28
-# define  _GLIBCXX_NUM_CXX11_FACETS 16
-#else
-# define  _GLIBCXX_NUM_FACETS 14
-# define  _GLIBCXX_NUM_CXX11_FACETS 8
-#endif
+// Number of standard facets (for narrow characters only)
+#define  _GLIBCXX_NUM_FACETS 14
+
+// Number of duplicated facets for cxx11 ABI
+#define  _GLIBCXX_NUM_CXX11_FACETS (_GLIBCXX_USE_DUAL_ABI ? 8 : 0)
+
+// codecvt<char16_t> and codecvt<char32_t>
 #ifdef _GLIBCXX_USE_CHAR8_T
 # define _GLIBCXX_NUM_UNICODE_FACETS 4
 #else
 # define _GLIBCXX_NUM_UNICODE_FACETS 2
 #endif
 
+// Facets duplicated for alt128 long double format
+// num_get, num_put, money_get, money_put (+ cxx11 money_get, money_put)
+#define _GLIBCXX_NUM_LBDL_ALT128_FACETS (4 + (_GLIBCXX_USE_DUAL_ABI ? 2 : 0))
+
   // Convert string to numeric value of type _Tp and store results.
   // NB: This is specialized for all required types, there is no
   // generic definition.
@@ -2252,6 +2255,10 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
 
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      // For __gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get
+      // this entry in the vtable is for a 64-bit "long double" with the
+      // same format as double. This keeps the vtable layout consistent
+      // with std::num_get (visible when -mlong-double-64 is used).
       virtual iter_type
       __do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
 	       double&) const;
@@ -2264,8 +2271,21 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       virtual iter_type
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, void*&) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      // For __gnu_cxx_ieee128::num_get this entry in the vtable is for
+      // the non-IEEE 128-bit "long double" (aka "double double"). This
+      // is consistent with __gnu_cxx_ldbl128::num_get (-mabi=ibmlongdouble)
+      virtual iter_type
+      __do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
+	       __ibm128&) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      // For __gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get
+      // this entry in the vtable is for the 128-bit "long double" type.
       virtual iter_type
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
 	     long double&) const;
@@ -2545,6 +2565,13 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       virtual iter_type
       do_put(iter_type, ios_base&, char_type, const void*) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_put(iter_type, ios_base&, char_type, __ibm128) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
       virtual iter_type
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index ebc993339a6d..4fdca180a877 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -772,6 +772,24 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       return __beg;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    num_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, ios_base& __io,
+	     ios_base::iostate& __err, __ibm128& __v) const
+    {
+      string __xtrc;
+      __xtrc.reserve(32);
+      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
+      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+    }
+#endif
+
   // For use by integer and floating-point types after they have been
   // converted into a char_type string.
   template<typename _CharT, typename _OutIter>
@@ -1194,6 +1212,15 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       return __s;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    num_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, ios_base& __io, char_type __fill,
+	     __ibm128 __v) const
+    { return _M_insert_float(__s, __io, __fill, 'L', __v); }
+#endif
 _GLIBCXX_END_NAMESPACE_LDBL
 
   // Construct correctly padded string, as per 22.2.2.2.2
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.h b/libstdc++-v3/include/bits/locale_facets_nonio.h
index b76eac435bd3..6af68d3fa903 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.h
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.h
@@ -1566,7 +1566,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
        */
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       __do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
 	       ios_base::iostate& __err, double& __units) const;
@@ -1587,9 +1587,17 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
 	     ios_base::iostate& __err, string_type& __digits) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	       ios_base::iostate& __err, __ibm128& __units) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
 	     ios_base::iostate& __err, long double& __units) const;
@@ -1711,7 +1719,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
        */
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 	       double __units) const;
@@ -1744,9 +1752,17 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 	     const string_type& __digits) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	       __ibm128 __units) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 	     long double __units) const;
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index a8639f6ba28a..9e2b65779698 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -350,7 +350,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       }
 
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
   template<typename _CharT, typename _InIter>
     _InIter
     money_get<_CharT, _InIter>::
@@ -401,6 +401,22 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       return __beg;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    money_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+	     ios_base::iostate& __err, __ibm128& __units) const
+    {
+      string __str;
+      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
+	             : _M_extract<false>(__beg, __end, __io, __err, __str);
+      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
+      return __beg;
+    }
+#endif
+
   template<typename _CharT, typename _OutIter>
     template<bool _Intl>
       _OutIter
@@ -562,7 +578,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       }
 
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
   template<typename _CharT, typename _OutIter>
     _OutIter
     money_put<_CharT, _OutIter>::
@@ -617,6 +633,47 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
 	            : _M_insert<false>(__s, __io, __fill, __digits); }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    money_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	     __ibm128 __units) const
+    {
+      const locale __loc = __io.getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+#if _GLIBCXX_USE_C99_STDIO
+      // First try a buffer perhaps big enough.
+      int __cs_size = 64;
+      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 328. Bad sprintf format modifier in money_put<>::do_put()
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					"%.*Lf", 0, __units);
+      // If the buffer was not large enough, try again with the correct size.
+      if (__len >= __cs_size)
+	{
+	  __cs_size = __len + 1;
+	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					"%.*Lf", 0, __units);
+	}
+#else
+      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
+      const int __cs_size =
+	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
+      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
+					0, __units);
+#endif
+      string_type __digits(__len, char_type());
+      __ctype.widen(__cs, __cs + __len, &__digits[0]);
+      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
+	            : _M_insert<false>(__s, __io, __fill, __digits);
+    }
+#endif
+
 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 
   // NB: Not especially useful. Without an ios_base object or some
diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am
index 1eda70edb379..bc51238af4bd 100644
--- a/libstdc++-v3/src/Makefile.am
+++ b/libstdc++-v3/src/Makefile.am
@@ -71,6 +71,20 @@ else
 ldbl_compat_sources =
 endif
 
+if GLIBCXX_LDBL_ALT128_COMPAT
+if ENABLE_DUAL_ABI
+ldbl_alt128_compat_cxx11_sources = \
+	compatibility-ldbl-alt128-cxx11.cc
+else
+ldbl_alt128_compat_cxx11_sources =
+endif
+ldbl_alt128_compat_sources = \
+	compatibility-ldbl-alt128.cc \
+	${ldbl_alt128_compat_cxx11_sources}
+else
+ldbl_alt128_compat_sources =
+endif
+
 
 parallel_compat_sources = \
 	compatibility-parallel_list.cc  compatibility-parallel_list-2.cc
@@ -87,7 +101,8 @@ cxx11_sources = \
 	compatibility-atomic-c++0x.cc \
 	compatibility-thread-c++0x.cc \
 	compatibility-chrono.cc \
-	compatibility-condvar.cc
+	compatibility-condvar.cc \
+	${ldbl_alt128_compat_sources}
 
 libstdc___la_SOURCES = $(cxx98_sources) $(cxx11_sources)
 
@@ -113,12 +128,36 @@ libstdc___la_LDFLAGS = \
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS) $(lt_host_flags)
 
 # Use special rules for compatibility-ldbl.cc compilation, as we need to
-# pass -mlong-double-64.
+# pass -mlong-double-64, and not use -mabi={ieee,ibm}longdouble.
 if GLIBCXX_LDBL_COMPAT
+if GLIBCXX_LDBL_ALT128_COMPAT
+LTCXXCOMPILE64 = \
+  $(filter-out -mabi=ieeelongdouble -mabi=ibmlongdouble,$(LTCXXCOMPILE))
+CXXCOMPILE64 = \
+  $(filter-out -mabi=ieeelongdouble -mabi=ibmlongdouble,$(CXXCOMPILE))
+else
+LTCXXCOMPILE64 = $(LTCXXCOMPILE)
+CXXCOMPILE64 = $(CXXCOMPILE)
+endif
 compatibility-ldbl.lo: compatibility-ldbl.cc
-	$(LTCXXCOMPILE) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
+	$(LTCXXCOMPILE64) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
 compatibility-ldbl.o: compatibility-ldbl.cc
-	$(CXXCOMPILE) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
+	$(CXXCOMPILE64) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
+endif
+
+# Use special rules for compatibility-ldbl-alt128.cc compilation, as we need to
+# ensure it is compiled with the correct flag.
+if GLIBCXX_LDBL_ALT128_COMPAT
+compatibility-ldbl-alt128.lo: compatibility-ldbl-alt128.cc
+	$(LTCXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+compatibility-ldbl-alt128.o: compatibility-ldbl-alt128.cc
+	$(CXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+if ENABLE_DUAL_ABI
+compatibility-ldbl-alt128-cxx11.lo: compatibility-ldbl-alt128-cxx11.cc
+	$(LTCXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+compatibility-ldbl-alt128-cxx11.o: compatibility-ldbl-alt128-cxx11.cc
+	$(CXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+endif
 endif
 
 # Use special rules for C++11 files/objects.
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-alt128-cxx11.cc b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128-cxx11.cc
new file mode 100644
index 000000000000..7c03606bce4d
--- /dev/null
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128-cxx11.cc
@@ -0,0 +1,102 @@
+// Compatibility symbols for alternate 128-bit long-double format -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_USE_CXX11_ABI 1
+#include <locale>
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+#if !defined(_GLIBCXX_USE_DUAL_ABI)
+#error "compatibility-ldbl-alt128-cxx11.cc must only be compiled when dual ABI is enabled"
+#endif
+
+#if ! defined __LONG_DOUBLE_IBM128__ && ! defined __LONG_DOUBLE_IEEE128__
+#error "compatibility-ldbl-alt128.cc must only be compiled for 128-bit long double"
+#endif
+
+#define C char
+#define C_is_char
+#include "locale-inst-monetary.h"
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+# undef C
+# undef C_is_char
+# define C wchar_t
+# include "locale-inst-monetary.h"
+#endif
+
+#include <functional>
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  namespace
+  {
+    alignas(money_get<char>) char money_get_c[sizeof(money_get<char>)];
+    alignas(money_put<char>) char money_put_c[sizeof(money_put<char>)];
+#ifdef _GLIBCXX_USE_WCHAR_T
+    alignas(money_get<wchar_t>) char money_get_w[sizeof(money_get<wchar_t>)];
+    alignas(money_put<wchar_t>) char money_put_w[sizeof(money_put<wchar_t>)];
+#endif
+
+  template<typename Facet>
+    void
+    init_facet(function<void(const locale::id*, const locale::facet*)>& func,
+	       Facet* facet)
+    {
+      func(&Facet::id, facet);
+    }
+
+  } // namespace
+
+  template class function<void(const locale::id*, const locale::facet*)>;
+
+  void
+  __locale_Impl_init_extra_ldbl128(
+      function<void(const locale::id*, const locale::facet*)> f,
+      bool classic)
+  {
+    if (classic)
+      {
+	init_facet(f, new (&money_get_c) money_get<char>(1));
+	init_facet(f, new (&money_put_c) money_put<char>(1));
+#ifdef _GLIBCXX_USE_WCHAR_T
+	init_facet(f, new (&money_get_w) money_get<wchar_t>(1));
+	init_facet(f, new (&money_put_w) money_put<wchar_t>(1));
+#endif
+      }
+    else
+      {
+	init_facet(f, new money_get<char>);
+	init_facet(f, new money_put<char>);
+#ifdef _GLIBCXX_USE_WCHAR_T
+	init_facet(f, new money_get<wchar_t>);
+	init_facet(f, new money_put<wchar_t>);
+#endif
+      }
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-alt128.cc b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128.cc
new file mode 100644
index 000000000000..7fb66917db13
--- /dev/null
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128.cc
@@ -0,0 +1,244 @@
+// Compatibility symbols for alternate 128-bit long-double format -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_USE_CXX11_ABI 0
+#include <locale>
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+#if ! defined __LONG_DOUBLE_IBM128__ && ! defined __LONG_DOUBLE_IEEE128__
+#error "compatibility-ldbl-alt128.cc must only be compiled for 128-bit long double"
+#endif
+
+#define C char
+#define C_is_char
+#include "locale-inst-numeric.h"
+#include "locale-inst-monetary.h"
+#include "compatibility-ldbl-facets-aliases.h"
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+# undef C
+# undef C_is_char
+# define C wchar_t
+# include "locale-inst-numeric.h"
+# include "locale-inst-monetary.h"
+# include "compatibility-ldbl-facets-aliases.h"
+# undef C
+#endif
+
+#include <limits>
+#include <functional>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // long double
+  const bool numeric_limits<long double>::is_specialized;
+  const int  numeric_limits<long double>::digits;
+  const int  numeric_limits<long double>::digits10;
+  const int  numeric_limits<long double>::max_digits10;
+  const bool numeric_limits<long double>::is_signed;
+  const bool numeric_limits<long double>::is_integer;
+  const bool numeric_limits<long double>::is_exact;
+  const int  numeric_limits<long double>::radix;
+  const int  numeric_limits<long double>::min_exponent;
+  const int  numeric_limits<long double>::min_exponent10;
+  const int  numeric_limits<long double>::max_exponent;
+  const int  numeric_limits<long double>::max_exponent10;
+  const bool numeric_limits<long double>::has_infinity;
+  const bool numeric_limits<long double>::has_quiet_NaN;
+  const bool numeric_limits<long double>::has_signaling_NaN;
+  const float_denorm_style numeric_limits<long double>::has_denorm;
+  const bool numeric_limits<long double>::has_denorm_loss;
+  const bool numeric_limits<long double>::is_iec559;
+  const bool numeric_limits<long double>::is_bounded;
+  const bool numeric_limits<long double>::is_modulo;
+  const bool numeric_limits<long double>::traps;
+  const bool numeric_limits<long double>::tinyness_before;
+  const float_round_style numeric_limits<long double>::round_style;
+
+  template<>
+    void
+    __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
+		   const __c_locale& __cloc) throw()
+    {
+      char* __sanity;
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+      // Prefer strtold_l, as __strtold_l isn't prototyped in more recent
+      // glibc versions.
+      __v = strtold_l(__s, &__sanity, __cloc);
+#else
+      __v = __strtold_l(__s, &__sanity, __cloc);
+#endif
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 23. Num_get overflow result.
+      if (__sanity == __s || *__sanity != '\0')
+	{
+	  __v = 0.0l;
+	  __err = ios_base::failbit;
+	}
+      else if (__v == numeric_limits<long double>::infinity())
+	{
+	  __v = numeric_limits<long double>::max();
+	  __err = ios_base::failbit;
+	}
+      else if (__v == -numeric_limits<long double>::infinity())
+	{
+	  __v = -numeric_limits<long double>::max();
+	  __err = ios_base::failbit;
+	}
+    }
+
+  namespace
+  {
+    alignas(money_get<char>) char money_get_c[sizeof(money_get<char>)];
+    alignas(money_put<char>) char money_put_c[sizeof(money_put<char>)];
+    alignas(num_get<char>) char num_get_c[sizeof(num_get<char>)];
+    alignas(num_put<char>) char num_put_c[sizeof(num_put<char>)];
+#ifdef _GLIBCXX_USE_WCHAR_T
+    alignas(money_get<wchar_t>) char money_get_w[sizeof(money_get<wchar_t>)];
+    alignas(money_put<wchar_t>) char money_put_w[sizeof(money_put<wchar_t>)];
+    alignas(num_get<wchar_t>) char num_get_w[sizeof(num_get<wchar_t>)];
+    alignas(num_put<wchar_t>) char num_put_w[sizeof(num_put<wchar_t>)];
+#endif
+  }
+
+  extern void
+  __locale_Impl_init_extra_ldbl128(
+      function<void(const locale::id*, const locale::facet*)>,
+      bool);
+
+  void
+  locale::_Impl::_M_init_extra_ldbl128(bool classic)
+  {
+    if (classic)
+      {
+	_M_init_facet(new (&money_get_c) money_get<char>(1));
+	_M_init_facet(new (&money_put_c) money_put<char>(1));
+	_M_init_facet(new (&num_get_c) num_get<char>(1));
+	_M_init_facet(new (&num_put_c) num_put<char>(1));
+#ifdef _GLIBCXX_USE_WCHAR_T
+	_M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
+	_M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
+	_M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
+	_M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
+#endif
+      }
+    else
+      {
+	_M_init_facet(new money_get<char>);
+	_M_init_facet(new money_put<char>);
+	_M_init_facet(new num_get<char>);
+	_M_init_facet(new num_put<char>);
+#ifdef _GLIBCXX_USE_WCHAR_T
+	_M_init_facet(new money_get<wchar_t>);
+	_M_init_facet(new money_put<wchar_t>);
+	_M_init_facet(new num_get<wchar_t>);
+	_M_init_facet(new num_put<wchar_t>);
+#endif
+      }
+
+#if _GLIBCXX_USE_DUAL_ABI
+    __locale_Impl_init_extra_ldbl128(
+	[this](const locale::id* i, const facet* f) {
+	    _M_install_facet(i, f);
+	},
+	classic);
+#endif
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#include <istream>
+#include <ostream>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template istream& istream::operator>>(long double&);
+  template istream& istream::_M_extract(long double&);
+  template ostream& ostream::operator<<(long double);
+  template ostream& ostream::_M_insert(long double);
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template wistream& wistream::operator>>(long double&);
+  template wistream& wistream::_M_extract(long double&);
+  template wostream& wostream::operator<<(long double);
+  template wostream& wostream::_M_insert(long double);
+#endif
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#include <complex>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template
+    basic_istream<char, char_traits<char> >&
+    operator>>(basic_istream<char, char_traits<char> >&,
+	       complex<long double>&);
+  template
+    basic_ostream<char, char_traits<char> >&
+    operator<<(basic_ostream<char, char_traits<char> >&,
+               const complex<long double>&);
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template
+    basic_istream<wchar_t, char_traits<wchar_t> >&
+    operator>>(basic_istream<wchar_t, char_traits<wchar_t> >&,
+               complex<long double>&);
+  template
+    basic_ostream<wchar_t, char_traits<wchar_t> >&
+    operator<<(basic_ostream<wchar_t, char_traits<wchar_t> >&,
+               const complex<long double>&);
+#endif
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#include <cmath>
+#include <tr1/functional>
+
+// For std::tr1::hash<long double>::operator()
+#include "../c++98/hash-long-double-tr1-aux.cc"
+
+// std::tr1::hash<long double>::operator()
+// and std::hash<long double>::operator()
+// are the same, no need to duplicate them.
+#ifdef __LONG_DOUBLE_IBM128__
+extern "C" size_t
+_ZNKSt4hashIgEclEg (void)
+  __attribute__((pure))
+  __attribute__((alias ("_ZNKSt3tr14hashIgEclEg")));
+#elif __LONG_DOUBLE_IEEE128__
+extern "C" size_t
+_ZNKSt4hashIu9__ieee128EclEu9__ieee128 (void)
+  __attribute__((pure))
+  __attribute__((alias ("_ZNKSt3tr14hashIu9__ieee128EclEu9__ieee128")));
+#else
+# error "Configuration error"
+#endif
+
+#endif
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h b/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
new file mode 100644
index 000000000000..7bdf9810d0ec
--- /dev/null
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
@@ -0,0 +1,128 @@
+// Compatibility aliases for long double support in locales -*- C++ -*-
+
+// Copyright (C) 1999-2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef C
+#define "This file should not be compiled directly, only included"
+#endif
+
+#ifndef _GLIBCXX_LONG_DOUBLE_COMPAT
+#define "This file should only be used for _GLIBCXX_LONG_DOUBLE_COMPAT builds"
+#endif
+
+// XXX GLIBCXX_ABI Deprecated
+#if defined __LONG_DOUBLE_128__ && ! defined __LONG_DOUBLE_IEEE128__
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattribute-alias"
+
+#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
+  extern "C" void ldbl (void) __attribute__ ((alias (#dbl), weak))
+
+// Define members of std::num_get and std::num_put as aliases for
+// members of __gnu_cxx_ldbl128::num_get and __gnu_cxx_ldbl128::num_put
+#ifdef C_is_char
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES4_S4_RSt8ios_baseccT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIeEES3_S3_RSt8ios_baseccT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES4_S4_RSt8ios_basecRKSs,
+		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES3_S3_RSt8ios_basecRKSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES4_S4_RSt8ios_basecRKSs,
+		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES3_S3_RSt8ios_basecRKSs);
+#else // ! C_is_char
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES4_S4_RSt8ios_basewcT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIeEES3_S3_RSt8ios_basewcT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
+		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
+		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
+#endif // C_is_char
+
+
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+// Define __gnu_cxx_ieee128::num_put<>::_M_insert_float(..., __ibm128) as
+// alias of __gnu_cxx_ldbl128::num_put<>::_M_insert_float(..., __ibm128)
+# ifdef C_is_char
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIgEES4_S4_RSt8ios_baseccT_,
+		     _ZNKSt17__gnu_cxx_ieee1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIgEES4_S4_RSt8ios_baseccT_);
+# else
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIgEES4_S4_RSt8ios_basewcT_,
+		     _ZNKSt17__gnu_cxx_ieee1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIgEES4_S4_RSt8ios_basewcT_);
+# endif
+#endif // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+#undef _GLIBCXX_LDBL_COMPAT
+#pragma GCC diagnostic pop
+
+#endif  // __LONG_DOUBLE_128__ && ! __LONG_DOUBLE_IEEE128__
diff --git a/libstdc++-v3/src/c++11/cow-locale_init.cc b/libstdc++-v3/src/c++11/cow-locale_init.cc
index 98a2ef41f563..bf270712e47a 100644
--- a/libstdc++-v3/src/c++11/cow-locale_init.cc
+++ b/libstdc++-v3/src/c++11/cow-locale_init.cc
@@ -125,6 +125,7 @@ namespace
     _M_init_facet_unchecked(new (&messages_w) std::messages<wchar_t>(1));
 #endif
 
+    // The caches must be populated last, after creating all facets.
     _M_caches[numpunct<char>::id._M_id()] = __npc;
     _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf;
     _M_caches[moneypunct<char, true>::id._M_id()] = __mpct;
diff --git a/libstdc++-v3/src/c++11/cxx11-locale-inst.cc b/libstdc++-v3/src/c++11/cxx11-locale-inst.cc
index 7b132a748bf3..9378550124f1 100644
--- a/libstdc++-v3/src/c++11/cxx11-locale-inst.cc
+++ b/libstdc++-v3/src/c++11/cxx11-locale-inst.cc
@@ -32,8 +32,6 @@
 # error This file should not be compiled for this configuration.
 #endif
 
-#ifndef C
-# define C char
-# define C_is_char
-#endif
+#define C char
+#define C_is_char
 # include "locale-inst.cc"
diff --git a/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc b/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc
index cf3d6dc7e348..07eb60083616 100644
--- a/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc
+++ b/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc
@@ -24,9 +24,15 @@
 // ISO C++ 14882: 22.1  Locales
 //
 
+// Facet wchar_t instantiations using new ABI strings.
+
 #define _GLIBCXX_USE_CXX11_ABI 1
 #include <bits/c++config.h>
+#if ! _GLIBCXX_USE_DUAL_ABI
+# error This file should not be compiled for this configuration.
+#endif
+
 #ifdef _GLIBCXX_USE_WCHAR_T
 #define C wchar_t
-#include "cxx11-locale-inst.cc"
+#include "locale-inst.cc"
 #endif
diff --git a/libstdc++-v3/src/c++11/locale-inst-monetary.h b/libstdc++-v3/src/c++11/locale-inst-monetary.h
new file mode 100644
index 000000000000..e9b3e7c4e0cc
--- /dev/null
+++ b/libstdc++-v3/src/c++11/locale-inst-monetary.h
@@ -0,0 +1,69 @@
+// Explicit instantantiations for monetary facets -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef C
+#define "This file should not be compiled directly, only included"
+#endif
+
+// This header is included multiple times, to instantiate these symbols
+// for char/wchar_t and for both std::string ABIs,
+// and (depending on the target) for two long double formats.
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+  template const money_put<C>& use_facet<money_put<C> >(const locale&);
+  template const money_get<C>& use_facet<money_get<C> >(const locale&);
+
+  template bool has_facet<money_put<C> >(const locale&);
+  template bool has_facet<money_get<C> >(const locale&);
+
+_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
+  template class money_get<C, istreambuf_iterator<C> >;
+  template class money_put<C, ostreambuf_iterator<C> >;
+
+  template
+    istreambuf_iterator<C>
+    money_get<C, istreambuf_iterator<C> >::
+    _M_extract<true>(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		     ios_base&, ios_base::iostate&, string&) const;
+
+  template
+    istreambuf_iterator<C>
+    money_get<C, istreambuf_iterator<C> >::
+    _M_extract<false>(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		      ios_base&, ios_base::iostate&, string&) const;
+
+  template
+    ostreambuf_iterator<C>
+    money_put<C, ostreambuf_iterator<C> >::
+    _M_insert<true>(ostreambuf_iterator<C>, ios_base&, C,
+		    const string_type&) const;
+
+  template
+    ostreambuf_iterator<C>
+    money_put<C, ostreambuf_iterator<C> >::
+    _M_insert<false>(ostreambuf_iterator<C>, ios_base&, C,
+		     const string_type&) const;
+_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
+} // namespace std
diff --git a/libstdc++-v3/src/c++11/locale-inst-numeric.h b/libstdc++-v3/src/c++11/locale-inst-numeric.h
new file mode 100644
index 000000000000..0ec93e27937f
--- /dev/null
+++ b/libstdc++-v3/src/c++11/locale-inst-numeric.h
@@ -0,0 +1,133 @@
+// Explicit instantantiations for numeric facets -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef C
+#define "This file should not be compiled directly, only included"
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+#if ! _GLIBCXX_USE_CXX11_ABI
+  template const num_get<C>& use_facet<num_get<C> >(const locale&);
+  template const num_put<C>& use_facet<num_put<C> >(const locale&);
+
+  template bool has_facet<num_get<C> >(const locale&);
+  template bool has_facet<num_put<C> >(const locale&);
+#endif
+
+_GLIBCXX_BEGIN_NAMESPACE_LDBL
+
+#if ! _GLIBCXX_USE_CXX11_ABI
+  template class num_get<C, istreambuf_iterator<C> >;
+  template class num_put<C, ostreambuf_iterator<C> >;
+#endif
+
+  // num_get member function templates
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   long&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned short&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned int&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned long&) const;
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   long long&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned long long&) const;
+#endif
+
+#if ! _GLIBCXX_USE_CXX11_ABI
+  // num_put member function templates
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  long) const;
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  unsigned long) const;
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  long long) const;
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  unsigned long long) const;
+#endif
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
+		    double) const;
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
+		    long double) const;
+#endif
+
+_GLIBCXX_END_NAMESPACE_LDBL
+} // namespace std
diff --git a/libstdc++-v3/src/c++11/locale-inst.cc b/libstdc++-v3/src/c++11/locale-inst.cc
index 4dc7f5c07805..cd99648e8f68 100644
--- a/libstdc++-v3/src/c++11/locale-inst.cc
+++ b/libstdc++-v3/src/c++11/locale-inst.cc
@@ -43,6 +43,9 @@
 # define C_is_char
 #endif
 
+#include "locale-inst-numeric.h"
+#include "locale-inst-monetary.h"
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -58,33 +61,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   template class moneypunct_byname<C, false>;
   template class moneypunct_byname<C, true>;
 _GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
-  template class money_get<C, istreambuf_iterator<C> >;
-  template class money_put<C, ostreambuf_iterator<C> >;
-  template
-    istreambuf_iterator<C>
-    money_get<C, istreambuf_iterator<C> >::
-    _M_extract<true>(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		     ios_base&, ios_base::iostate&, string&) const;
-
-  template
-    istreambuf_iterator<C>
-    money_get<C, istreambuf_iterator<C> >::
-    _M_extract<false>(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		      ios_base&, ios_base::iostate&, string&) const;
-
-  template
-    ostreambuf_iterator<C>
-    money_put<C, ostreambuf_iterator<C> >::
-    _M_insert<true>(ostreambuf_iterator<C>, ios_base&, C,
-		    const string_type&) const;
-
-  template
-    ostreambuf_iterator<C>
-    money_put<C, ostreambuf_iterator<C> >::
-    _M_insert<false>(ostreambuf_iterator<C>, ios_base&, C,
-		     const string_type&) const;
-_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 
   // numpunct, numpunct_byname, num_get, and num_put
 #if ! _GLIBCXX_USE_CXX11_ABI
@@ -94,97 +70,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   template class numpunct<C>;
   template class numpunct_byname<C>;
 _GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_BEGIN_NAMESPACE_LDBL
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template class num_get<C, istreambuf_iterator<C> >;
-#endif
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   long&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned short&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned int&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned long&) const;
-
-#ifdef _GLIBCXX_USE_LONG_LONG
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   long long&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned long long&) const;
-#endif
-
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template class num_put<C, ostreambuf_iterator<C> >;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  long) const;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  unsigned long) const;
-
-#ifdef _GLIBCXX_USE_LONG_LONG
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  long long) const;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  unsigned long long) const;
-#endif
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
-		    double) const;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
-		    long double) const;
-#endif
-_GLIBCXX_END_NAMESPACE_LDBL
 
   // time_get and time_put
 #if ! _GLIBCXX_USE_CXX11_ABI
@@ -250,16 +135,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
     const numpunct<C>&
     use_facet<numpunct<C> >(const locale&);
 
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    const num_put<C>&
-    use_facet<num_put<C> >(const locale&);
-
-  template
-    const num_get<C>&
-    use_facet<num_get<C> >(const locale&);
-#endif
-
   template
     const moneypunct<C, true>&
     use_facet<moneypunct<C, true> >(const locale&);
@@ -268,14 +143,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
     const moneypunct<C, false>&
     use_facet<moneypunct<C, false> >(const locale&);
 
-  template
-    const money_put<C>&
-    use_facet<money_put<C> >(const locale&);
-
-  template
-    const money_get<C>&
-    use_facet<money_get<C> >(const locale&);
-
 #if ! _GLIBCXX_USE_CXX11_ABI
   template
     const __timepunct<C>&
@@ -313,28 +180,10 @@ _GLIBCXX_END_NAMESPACE_CXX11
     bool
     has_facet<numpunct<C> >(const locale&);
 
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    bool
-    has_facet<num_put<C> >(const locale&);
-
-  template
-    bool
-    has_facet<num_get<C> >(const locale&);
-#endif
-
   template
     bool
     has_facet<moneypunct<C> >(const locale&);
 
-  template
-    bool
-    has_facet<money_put<C> >(const locale&);
-
-  template
-    bool
-    has_facet<money_get<C> >(const locale&);
-
 #if ! _GLIBCXX_USE_CXX11_ABI
   template
     bool
@@ -380,45 +229,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 // XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined C_is_char \
-      && _GLIBCXX_USE_CXX11_ABI == 0
-
-#pragma GCC diagnostic ignored "-Wattribute-alias"
-
-#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
-  extern "C" void ldbl (void) __attribute__ ((alias (#dbl), weak))
-
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES4_S4_RSt8ios_baseccT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIeEES3_S3_RSt8ios_baseccT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES4_S4_RSt8ios_basecRKSs,
-		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES3_S3_RSt8ios_basecRKSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES4_S4_RSt8ios_basecRKSs,
-		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES3_S3_RSt8ios_basecRKSs);
-
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && ! _GLIBCXX_USE_CXX11_ABI
+#include "compatibility-ldbl-facets-aliases.h"
 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT
diff --git a/libstdc++-v3/src/c++11/wlocale-inst.cc b/libstdc++-v3/src/c++11/wlocale-inst.cc
index 3a54fb51aab4..a9a246f8f97f 100644
--- a/libstdc++-v3/src/c++11/wlocale-inst.cc
+++ b/libstdc++-v3/src/c++11/wlocale-inst.cc
@@ -33,47 +33,4 @@
 #ifdef _GLIBCXX_USE_WCHAR_T
 #define C wchar_t
 #include "locale-inst.cc"
-
-// XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT
-
-#pragma GCC diagnostic ignored "-Wattribute-alias"
-
-#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
-  extern "C" void ldbl (void) __attribute__ ((alias (#dbl), weak))
-
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES4_S4_RSt8ios_basewcT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIeEES3_S3_RSt8ios_basewcT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
-		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
-		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
-
-#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
-#endif
+#endif // _GLIBCXX_USE_WCHAR_T
diff --git a/libstdc++-v3/src/c++17/Makefile.am b/libstdc++-v3/src/c++17/Makefile.am
index 642efb976acc..37cdb53c0766 100644
--- a/libstdc++-v3/src/c++17/Makefile.am
+++ b/libstdc++-v3/src/c++17/Makefile.am
@@ -61,6 +61,13 @@ vpath % $(top_srcdir)/src/c++17
 
 libc__17convenience_la_SOURCES = $(sources)  $(inst_sources)
 
+if GLIBCXX_LDBL_ALT128_COMPAT
+floating_from_chars.lo: floating_from_chars.cc
+	$(LTCXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
+floating_from_chars.o: floating_from_chars.cc
+	$(CXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
+endif
+
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
 # modified in a per-library or per-sub-library way.  Need to manually
 # set this option because CONFIG_CXXFLAGS has to be after
diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc
index c279809cf35d..a19433514937 100644
--- a/libstdc++-v3/src/c++17/floating_from_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_from_chars.cc
@@ -44,6 +44,14 @@
 # include <xlocale.h>
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+#ifndef __LONG_DOUBLE_IBM128__
+#error "floating_from_chars.cc must be compiled with -mabi=ibmlongdouble"
+#endif
+// strtold for __ieee128
+extern "C" __ieee128 __strtoieee128(const char*, char**);
+#endif
+
 #if _GLIBCXX_HAVE_USELOCALE
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -316,6 +324,10 @@ namespace
 	  tmpval = std::strtod(str, &endptr);
 	else if constexpr (is_same_v<T, long double>)
 	  tmpval = std::strtold(str, &endptr);
+# ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+	else if constexpr (is_same_v<T, __ieee128>)
+	  tmpval = __strtoieee128(str, &endptr);
+# endif
 #else
 	tmpval = std::strtod(str, &endptr);
 #endif
@@ -332,7 +344,7 @@ namespace
 	const ptrdiff_t n = endptr - str;
 	if (conv_errno == ERANGE) [[unlikely]]
 	  {
-	    if (isinf(tmpval)) // overflow
+	    if (__builtin_isinf(tmpval)) // overflow
 	      ec = errc::result_out_of_range;
 	    else // underflow (LWG 3081 wants to set value = tmpval here)
 	      ec = errc::result_out_of_range;
@@ -469,6 +481,8 @@ from_chars(const char* first, const char* last, long double& value,
 }
 
 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
+// Make std::from_chars for 64-bit long double an alias for the overload
+// for double.
 extern "C" from_chars_result
 _ZSt10from_charsPKcS0_ReSt12chars_format(const char* first, const char* last,
 					 long double& value,
@@ -476,6 +490,28 @@ _ZSt10from_charsPKcS0_ReSt12chars_format(const char* first, const char* last,
 __attribute__((alias ("_ZSt10from_charsPKcS0_RdSt12chars_format")));
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+from_chars_result
+from_chars(const char* first, const char* last, __ieee128& value,
+	   chars_format fmt) noexcept
+{
+  buffer_resource mr;
+  pmr::string buf(&mr);
+  size_t len = 0;
+  errc ec = errc::invalid_argument;
+  __try
+    {
+      if (const char* pat = pattern(first, last, fmt, buf)) [[likely]]
+	len = from_chars_impl(pat, value, ec);
+    }
+  __catch (const std::bad_alloc&)
+    {
+      fmt = chars_format{};
+    }
+  return make_result(first, len, fmt, ec);
+}
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // _GLIBCXX_HAVE_USELOCALE
diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
index c3841ccbd3c9..77c6eecc1a3a 100644
--- a/libstdc++-v3/src/c++98/locale_init.cc
+++ b/libstdc++-v3/src/c++98/locale_init.cc
@@ -57,8 +57,16 @@ _GLIBCXX_LOC_ID(_ZNSt8messagesIwE2idE);
 
 namespace
 {
-  const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
-    + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0);
+  const int num_facets = (
+      _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_CXX11_FACETS
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+      + _GLIBCXX_NUM_LBDL_ALT128_FACETS
+#endif
+      )
+#ifdef _GLIBCXX_USE_WCHAR_T
+    * 2
+#endif
+    + _GLIBCXX_NUM_UNICODE_FACETS;
 
   __gnu_cxx::__mutex&
   get_locale_mutex()
@@ -559,6 +567,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    _M_init_extra_ldbl128(true);
+#endif
+
 #if _GLIBCXX_USE_DUAL_ABI
     facet* extra[] = { __npc, __mpcf, __mpct
 # ifdef  _GLIBCXX_USE_WCHAR_T
@@ -566,6 +578,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # endif
     };
 
+    // This call must be after creating all facets, as it sets caches.
     _M_init_extra(extra);
 #endif
 
diff --git a/libstdc++-v3/src/c++98/localename.cc b/libstdc++-v3/src/c++98/localename.cc
index 243acce164c5..29f439ffa9ab 100644
--- a/libstdc++-v3/src/c++98/localename.cc
+++ b/libstdc++-v3/src/c++98/localename.cc
@@ -171,8 +171,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
   }
 
-const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
-  + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0);
+const int num_facets = (
+    _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_CXX11_FACETS
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    + _GLIBCXX_NUM_LBDL_ALT128_FACETS
+#endif
+    )
+#ifdef _GLIBCXX_USE_WCHAR_T
+  * 2
+#endif
+  + _GLIBCXX_NUM_UNICODE_FACETS;
 
   // Construct named _Impl.
   locale::_Impl::
@@ -284,6 +292,10 @@ const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
         _M_init_extra(&__cloc, &__clocm, __s, __smon);
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+	_M_init_extra_ldbl128(false);
+#endif
+
 	locale::facet::_S_destroy_c_locale(__cloc);
 	if (__clocm != __cloc)
 	  locale::facet::_S_destroy_c_locale(__clocm);
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc b/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
index 2f8569eb8b9d..bf2441320c6d 100644
--- a/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
+++ b/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
@@ -8,7 +8,7 @@
 float (std::complex<float>::*p1)() const = &std::complex<float>::real;
 // { dg-final { scan-assembler "_ZNKSt7complexIdE4realB5cxx11Ev" } }
 double (std::complex<double>::*p2)() const = &std::complex<double>::real;
-// { dg-final { scan-assembler "_ZNKSt7complexI\[eg\]E4realB5cxx11Ev" } }
+// { dg-final { scan-assembler "_ZNKSt7complexI\(e\|g\|u9__ieee128\)E4realB5cxx11Ev" } }
 long double (std::complex<long double>::*p3)() const
   = &std::complex<long double>::real;
 // { dg-final { scan-assembler "_ZNKSt7complexIiE4realB5cxx11Ev" } }
@@ -18,7 +18,7 @@ int (std::complex<int>::*p4)() const = &std::complex<int>::real;
 float (std::complex<float>::*p5)() const = &std::complex<float>::imag;
 // { dg-final { scan-assembler "_ZNKSt7complexIdE4imagB5cxx11Ev" } }
 double (std::complex<double>::*p6)() const = &std::complex<double>::imag;
-// { dg-final { scan-assembler "_ZNKSt7complexI\[eg\]E4imagB5cxx11Ev" } }
+// { dg-final { scan-assembler "_ZNKSt7complexI\(e\|g\|u9__ieee128\)E4imagB5cxx11Ev" } }
 long double (std::complex<long double>::*p7)() const
   = &std::complex<long double>::imag;
 // { dg-final { scan-assembler "_ZNKSt7complexIiE4imagB5cxx11Ev" } }
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 33b9ec159355..75029549c0d6 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -211,6 +211,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("GLIBCXX_3.4.28");
       known_versions.push_back("GLIBCXX_3.4.29");
       known_versions.push_back("GLIBCXX_LDBL_3.4.29");
+      known_versions.push_back("GLIBCXX_IEEE128_3.4.29");
       known_versions.push_back("CXXABI_1.3");
       known_versions.push_back("CXXABI_LDBL_1.3");
       known_versions.push_back("CXXABI_1.3.1");
@@ -226,6 +227,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("CXXABI_1.3.11");
       known_versions.push_back("CXXABI_1.3.12");
       known_versions.push_back("CXXABI_1.3.13");
+      known_versions.push_back("CXXABI_IEEE128_1.3.13");
       known_versions.push_back("CXXABI_TM_1");
       known_versions.push_back("CXXABI_FLOAT128");
     }
@@ -244,9 +246,11 @@ check_version(symbol& test, bool added)
 
       // Check that added symbols are added in the latest pre-release version.
       bool latestp = (test.version_name == "GLIBCXX_3.4.29"
-	  // XXX remove next line when GLIBCXX_3.4.30 is added and baselines
-	  // have been regenerated to include GLIBCXX_LDBL_3.4.29 symbols:
+	  // XXX remove next 3 lines when baselines have been regenerated
+	  // to include {IEEE128,LDBL} symbols:
 		     || test.version_name == "GLIBCXX_LDBL_3.4.29"
+		     || test.version_name == "GLIBCXX_IEEE128_3.4.29"
+		     || test.version_name == "CXXABI_IEEE128_1.3.13"
 		     || test.version_name == "CXXABI_1.3.13"
 		     || test.version_name == "CXXABI_FLOAT128"
 		     || test.version_name == "CXXABI_TM_1");
@@ -260,7 +264,17 @@ check_version(symbol& test, bool added)
 	  && test.demangled_name.find("std::__cxx11::") != 0)
 	{
 	  if (test.version_name.find("_LDBL_") == std::string::npos
-	      && test.version_name.find("_FLOAT128") == std::string::npos)
+	      && test.version_name.find("_FLOAT128") == std::string::npos
+	      && test.version_name.find("_IEEE128") == std::string::npos)
+	    test.version_status = symbol::incompatible;
+	}
+
+      // Check that IEEE128 long double compatibility symbols demangled as
+      // __ieee128 are put into some _LDBL_IEEE version name.
+      // XXX is this right? might not want *everything* for __ieee128 in here.
+      if (added && test.demangled_name.find("__ieee128") != std::string::npos)
+	{
+	  if (test.version_name.find("_IEEE128") == std::string::npos)
 	    test.version_status = symbol::incompatible;
 	}
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-11-11 21:50 [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format Jonathan Wakely
@ 2020-11-30 21:30 ` Michael Meissner
  2020-12-01 15:10   ` Jonathan Wakely
  2020-11-30 23:29 ` Segher Boessenkool
  1 sibling, 1 reply; 19+ messages in thread
From: Michael Meissner @ 2020-11-30 21:30 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: libstdc++,
	gcc-patches, Michael Meissner, Bill Schmidt, David Edelsohn,
	Segher Boessenkool, Peter Berner

Jonathan, could you send a fresh set of patches (or at least replacements)?  I
tried installing the patches on a master branch I checked out this morning, and
I got two rejects:

--- libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -207,6 +207,7 @@
       known_versions.push_back("GLIBCXX_3.4.24");
       known_versions.push_back("GLIBCXX_3.4.25");
       known_versions.push_back("GLIBCXX_3.4.26");
+      known_versions.push_back("GLIBCXX_IEEE128_3.4.26");
       known_versions.push_back("CXXABI_1.3");
       known_versions.push_back("CXXABI_LDBL_1.3");
       known_versions.push_back("CXXABI_1.3.1");
@@ -220,6 +221,8 @@
       known_versions.push_back("CXXABI_1.3.9");
       known_versions.push_back("CXXABI_1.3.10");
       known_versions.push_back("CXXABI_1.3.11");
+      known_versions.push_back("CXXABI_1.3.12");
+      known_versions.push_back("CXXABI_IEEE128_1.3.12");
       known_versions.push_back("CXXABI_TM_1");
       known_versions.push_back("CXXABI_FLOAT128");
     }
@@ -238,7 +241,7 @@
 
       // Check that added symbols are added in the latest pre-release version.
       bool latestp = (test.version_name == "GLIBCXX_3.4.26"
-		     || test.version_name == "CXXABI_1.3.11"
+		     || test.version_name == "CXXABI_1.3.12"
 		     || test.version_name == "CXXABI_FLOAT128"
 		     || test.version_name == "CXXABI_TM_1");
       if (added && !latestp)
--- libstdc++-v3/include/bits/locale_facets.h
+++ libstdc++-v3/include/bits/locale_facets.h
@@ -51,16 +51,19 @@
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  // NB: Don't instantiate required wchar_t facets if no wchar_t support.
-#ifdef _GLIBCXX_USE_WCHAR_T
-# define  _GLIBCXX_NUM_FACETS 28
-# define  _GLIBCXX_NUM_CXX11_FACETS 16
-#else
-# define  _GLIBCXX_NUM_FACETS 14
-# define  _GLIBCXX_NUM_CXX11_FACETS 8
-#endif
+// Number of standard facets (for narrow characters only)
+#define  _GLIBCXX_NUM_FACETS 14
+
+// Number of duplicated facets for cxx11 ABI
+#define  _GLIBCXX_NUM_CXX11_FACETS (_GLIBCXX_USE_DUAL_ABI ? 8 : 0)
+
+// codecvt<char16_t> and codecvt<char32_t>
 #define _GLIBCXX_NUM_UNICODE_FACETS 2
 
+// Facets duplicated for alt128 long double format
+// num_get, num_put, money_get, money_put (+ cxx11 money_get, money_put)
+#define _GLIBCXX_NUM_LBDL_ALT128_FACETS (4 + (_GLIBCXX_USE_DUAL_ABI ? 2 : 0))
+
   // Convert string to numeric value of type _Tp and store results.
   // NB: This is specialized for all required types, there is no
   // generic definition.


I tried to fix it with the following patches, but I get the error when I build
libstdc++:

	.../bin/ld: duplicate version tag `CXXABI_1.3.12'

diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 33b9ec15935..bbe397ae8a4 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -207,6 +207,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("GLIBCXX_3.4.24");
       known_versions.push_back("GLIBCXX_3.4.25");
       known_versions.push_back("GLIBCXX_3.4.26");
+      known_versions.push_back("GLIBCXX_IEEE128_3.4.26");
       known_versions.push_back("GLIBCXX_3.4.27");
       known_versions.push_back("GLIBCXX_3.4.28");
       known_versions.push_back("GLIBCXX_3.4.29");
@@ -225,6 +226,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("CXXABI_1.3.10");
       known_versions.push_back("CXXABI_1.3.11");
       known_versions.push_back("CXXABI_1.3.12");
+      known_versions.push_back("CXXABI_IEEE128_1.3.12");
       known_versions.push_back("CXXABI_1.3.13");
       known_versions.push_back("CXXABI_TM_1");
       known_versions.push_back("CXXABI_FLOAT128");
@@ -260,7 +262,17 @@ check_version(symbol& test, bool added)
 	  && test.demangled_name.find("std::__cxx11::") != 0)
 	{
 	  if (test.version_name.find("_LDBL_") == std::string::npos
-	      && test.version_name.find("_FLOAT128") == std::string::npos)
+	      && test.version_name.find("_FLOAT128") == std::string::npos
+	      && test.version_name.find("_IEEE128") == std::string::npos)
+	    test.version_status = symbol::incompatible;
+	}
+
+      // Check that IEEE128 long double compatibility symbols demangled as
+      // __ieee128 are put into some _LDBL_IEEE version name.
+      // XXX is this right? might not want *everything* for __ieee128 in here.
+      if (added && test.demangled_name.find("__ieee128") != std::string::npos)
+	{
+	  if (test.version_name.find("_IEEE128") == std::string::npos)
 	    test.version_status = symbol::incompatible;
 	}
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 3e0ae8776c9..9b262c2d228 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -65,6 +65,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # define _GLIBCXX_NUM_UNICODE_FACETS 2
 #endif
 
+// Facets duplicated for alt128 long double format
+// num_get, num_put, money_get, money_put (+ cxx11 money_get, money_put)
+#define _GLIBCXX_NUM_LBDL_ALT128_FACETS (4 + (_GLIBCXX_USE_DUAL_ABI ? 2 : 0))
+
   // Convert string to numeric value of type _Tp and store results.
   // NB: This is specialized for all required types, there is no
   // generic definition.
@@ -2252,6 +2256,10 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
 
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      // For __gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get
+      // this entry in the vtable is for a 64-bit "long double" with the
+      // same format as double. This keeps the vtable layout consistent
+      // with std::num_get (visible when -mlong-double-64 is used).
       virtual iter_type
       __do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
 	       double&) const;
@@ -2264,8 +2272,21 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       virtual iter_type
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, void*&) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      // For __gnu_cxx_ieee128::num_get this entry in the vtable is for
+      // the non-IEEE 128-bit "long double" (aka "double double"). This
+      // is consistent with __gnu_cxx_ldbl128::num_get (-mabi=ibmlongdouble)
+      virtual iter_type
+      __do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
+	       __ibm128&) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      // For __gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get
+      // this entry in the vtable is for the 128-bit "long double" type.
       virtual iter_type
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
 	     long double&) const;
@@ -2545,6 +2566,13 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       virtual iter_type
       do_put(iter_type, ios_base&, char_type, const void*) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_put(iter_type, ios_base&, char_type, __ibm128) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
       virtual iter_type


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-11-11 21:50 [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format Jonathan Wakely
  2020-11-30 21:30 ` Michael Meissner
@ 2020-11-30 23:29 ` Segher Boessenkool
  2020-12-01 15:04   ` Jonathan Wakely
  1 sibling, 1 reply; 19+ messages in thread
From: Segher Boessenkool @ 2020-11-30 23:29 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: libstdc++,
	gcc-patches, Peter Bergner, Michael Meissner, David Edelsohn,
	Bill Schmidt

Hi!

Thank you for all this.

On Wed, Nov 11, 2020 at 09:50:01PM +0000, Jonathan Wakely wrote:
> This adds support for the new __ieee128 long double format on
> powerpc64le targets.

>             * testsuite/27_numerics/complex/abi_tag.cc: Add u9___ieee128 to
>             regex matching expected symbols.

One less underscore.

>     libstdc++-v3/ChangeLog:
>     
>             * Makefile.in:
>             * config.h.in:

(etc.)  Something missing here?

All the actual patch looks fine to me, but that doesn't say much :-)


Segher

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-11-30 23:29 ` Segher Boessenkool
@ 2020-12-01 15:04   ` Jonathan Wakely
  0 siblings, 0 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-01 15:04 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Michael Meissner, Peter Bergner, libstdc++,
	Bill Schmidt, gcc-patches, David Edelsohn

On 30/11/20 17:29 -0600, Segher Boessenkool wrote:
>Hi!
>
>Thank you for all this.
>
>On Wed, Nov 11, 2020 at 09:50:01PM +0000, Jonathan Wakely wrote:
>> This adds support for the new __ieee128 long double format on
>> powerpc64le targets.
>
>>             * testsuite/27_numerics/complex/abi_tag.cc: Add u9___ieee128 to
>>             regex matching expected symbols.
>
>One less underscore.

Thanks. There was also a misnamed test in the changelog which I've
also fixed.

>>     libstdc++-v3/ChangeLog:
>>
>>             * Makefile.in:
>>             * config.h.in:
>
>(etc.)  Something missing here?

It's just an empty changelog template added by my prepare-commit-msg.
The complete changelog was present above it already. I've removed the
duplication, thanks.

Updated patch coming shortly ...



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-11-30 21:30 ` Michael Meissner
@ 2020-12-01 15:10   ` Jonathan Wakely
  2020-12-01 16:04     ` Jonathan Wakely
  0 siblings, 1 reply; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-01 15:10 UTC (permalink / raw)
  To: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
>tried installing the patches on a master branch I checked out this morning, and
>I got two rejects:

I don't understand why those chunks failed, but I'll rebase and send a
new patch ASAP.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 15:10   ` Jonathan Wakely
@ 2020-12-01 16:04     ` Jonathan Wakely
  2020-12-01 19:10       ` Michael Meissner
  2020-12-03 23:07       ` Tulio Magno Quites Machado Filho
  0 siblings, 2 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-01 16:04 UTC (permalink / raw)
  To: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

[-- Attachment #1: Type: text/plain, Size: 654 bytes --]

On 01/12/20 15:10 +0000, Jonathan Wakely wrote:
>On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
>>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
>>tried installing the patches on a master branch I checked out this morning, and
>>I got two rejects:
>
>I don't understand why those chunks failed, but I'll rebase and send a
>new patch ASAP.

Here's the rebased patch, with regenerated autoconf files and a fix
for the <ext/numeric_limits.h> header. I'd changed it since sending
the previous patch, and broke the "there's more than one long double"
case (i.e. the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case).




[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 94271 bytes --]

commit 8739b6c0223fa38592b93e706c6e532fe027e3da
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Nov 12 10:47:41 2018

    libstdc++: Add C++ runtime support for new 128-bit long double format
    
    This adds support for the new __ieee128 long double format on
    powerpc64le targets.
    
    Most of the complexity comes from wanting a single libstdc++.so library
    that contains the symbols needed by code compiled with both
    -mabi=ibmlongdouble and -mabi=ieeelongdouble (and not forgetting
    -mlong-double-64 as well!)
    
    In a few places this just requires an extra overload, for example
    std::from_chars has to be overloaded for both forms of long double.
    That can be done in a single translation unit that defines overloads
    for 'long double' and also '__ieee128', so that user code including
    <charconv> will be able to link to a definition for either type of long
    double. Those are the easy cases.
    
    The difficult parts are (as for the std::string ABI transition) the I/O
    and locale facets. In order to be able to write either form of long
    double to an ostream such as std::cout we need the locale to contain a
    std::num_put facet that can handle both forms. The same approach is
    taken as was already done for supporting 64-bit long double and 128-bit
    long double: adding extra overloads of do_put to the facet class. On
    targets where the new long double code is enabled, the facets that are
    registered in the locale at program startup have additional overloads so
    that they can work with any long double type. Where this fails to work
    is if user code installs its own facet, which will probably not have the
    additional overloads and so will only be able to output one or the other
    type. In practice the number of users expecting to be able to use their
    own locale facets in code using a mix of -mabi=ibmlongdouble and
    -mabi=ieeelongdouble is probably close to zero.
    
    libstdc++-v3/ChangeLog:
    
            * Makefile.in: Regenerate.
            * config.h.in: Regenerate.
            * config/abi/pre/gnu.ver: Make patterns less greedy.
            * config/os/gnu-linux/ldbl-ieee128-extra.ver: New file with patterns
            for IEEE128 long double symbols.
            * configure: Regenerate.
            * configure.ac: Enable alternative 128-bit long double format on
            powerpc64*-*-linux*.
            * doc/Makefile.in: Regenerate.
            * fragment.am: Regenerate.
            * include/Makefile.am: Set _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT.
            * include/Makefile.in: Regenerate.
            * include/bits/c++config: Define inline namespace for new long
            double symbols. Don't define _GLIBCXX_USE_FLOAT128 when it's the
            same type as long double.
            * include/bits/locale_classes.h [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT]
            (locale::_Impl::_M_init_extra_ldbl128): Declare new member function.
            * include/bits/locale_facets.h (_GLIBCXX_NUM_FACETS): Simplify by
            only counting narrow character facets.
            (_GLIBCXX_NUM_CXX11_FACETS): Likewise.
            (_GLIBCXX_NUM_LBDL_ALT128_FACETS): New.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT] (num_get::__do_get): Define
            vtable placeholder for __ibm128 long double type.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (num_get::__do_get): Declare vtable placeholder for __ibm128 long
            double type.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (num_put::__do_put): Likewise.
            * include/bits/locale_facets.tcc
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (num_get::__do_get, num_put::__do_put): Define.
            * include/bits/locale_facets_nonio.h
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (money_get::__do_get): Declare vtable placeholder for __ibm128 long
            double type.
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (money_put::__do_put): Likewise.
            * include/bits/locale_facets_nonio.tcc
            [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __LONG_DOUBLE_IEEE128__]
            (money_get::__do_get, money_put::__do_put): Define.
            * include/ext/numeric_traits.h [_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT]
            (__numeric_traits<__ibm128>, __numeric_traits<__ieee128>): Define.
            * libsupc++/Makefile.in: Regenerate.
            * po/Makefile.in: Regenerate.
            * python/Makefile.in: Regenerate.
            * src/Makefile.am: Add compatibility-ldbl-alt128.cc and
            compatibility-ldbl-alt128-cxx11.cc sources and recipes for objects.
            * src/Makefile.in: Regenerate.
            * src/c++11/Makefile.in: Regenerate.
            * src/c++11/compatibility-ldbl-alt128-cxx11.cc: New file defining
            symbols using the old 128-bit long double format, for the cxx11 ABI.
            * src/c++11/compatibility-ldbl-alt128.cc: Likewise, for the
            gcc4-compatible ABI.
            * src/c++11/compatibility-ldbl-facets-aliases.h: New header for long
            double compat aliases.
            * src/c++11/cow-locale_init.cc: Add comment.
            * src/c++11/cxx11-locale-inst.cc: Define C and C_is_char
            unconditionally.
            * src/c++11/cxx11-wlocale-inst.cc: Add sanity check. Include
            locale-inst.cc directly, not via cxx11-locale-inst.cc.
            * src/c++11/locale-inst-monetary.h: New header for monetary
            category instantiations.
            * src/c++11/locale-inst-numeric.h: New header for numeric category
            instantiations.
            * src/c++11/locale-inst.cc: Include new headers for monetary,
            numeric, and long double definitions.
            * src/c++11/wlocale-inst.cc: Remove long double compat aliases that
            are defined in new header now.
            * src/c++17/Makefile.am: Use -mabi=ibmlongdouble for
            floating_from_chars.cc.
            * src/c++17/Makefile.in: Regenerate.
            * src/c++17/floating_from_chars.cc (from_chars_impl): Add
            if-constexpr branch for __ieee128.
            (from_chars): Overload for __ieee128.
            * src/c++20/Makefile.in: Regenerate.
            * src/c++98/Makefile.in: Regenerate.
            * src/c++98/locale_init.cc (num_facets): Adjust calculation.
            (locale::_Impl::_Impl(size_t)): Call _M_init_extra_ldbl128.
            * src/c++98/localename.cc (num_facets): Adjust calculation.
            (locale::_Impl::_Impl(const char*, size_t)): Call
            _M_init_extra_ldbl128.
            * src/filesystem/Makefile.in: Regenerate.
            * testsuite/Makefile.in: Regenerate.
            * testsuite/util/testsuite_abi.cc: Add new symbol versions.
            Allow new symbols to be added to GLIBCXX_IEEE128_3.4.29 and
            CXXABI_IEEE128_1.3.13 too.
            * testsuite/26_numerics/complex/abi_tag.cc: Add u9__ieee128 to
            regex matching expected symbols.

diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 46769db1530..4b4bd8ab6da 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -682,7 +682,7 @@ GLIBCXX_3.4 {
     _ZNSt12__basic_fileIcED*;
 
     # std::__convert_to_v
-    _ZSt14__convert_to_vI[^g]*;
+    _ZSt14__convert_to_vI[^gU]*;
 
     # __gnu_cxx::stdio_sync_filebuf
     _ZTVN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EEE;
@@ -931,7 +931,7 @@ GLIBCXX_3.4 {
     _ZGVNSt8time_putI[cw]*;
     _ZGVNSt9money_getI[cw]*;
     _ZGVNSt9money_putI[cw]*;
-    _ZGVNSt1[^07]*;
+    _ZGVNSt1[^079]*;
     _ZGVNSt10moneypunctI[cw]Lb[01]*;
 
     # exception constructors taking std::string
diff --git a/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
new file mode 100644
index 00000000000..3c3395e4d4e
--- /dev/null
+++ b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
@@ -0,0 +1,53 @@
+# Appended to version file.
+
+GLIBCXX_IEEE128_3.4.29 {
+
+  *__gnu_cxx_ieee128*;
+
+  _ZNSt14numeric_limitsIu9__ieee128E*;
+  _ZNSirsERu9__ieee128;
+  _ZNSolsEu9__ieee128;
+  _ZNSt13basic_istreamIwSt11char_traitsIwEErsERu9__ieee128;
+  _ZNSt13basic_ostreamIwSt11char_traitsIwEElsEu9__ieee128;
+  _ZSt14__convert_to_vIu9__ieee128EvPKcRT_RSt12_Ios_IostateRKP*;
+  _ZStlsIu9__ieee128[cw]St11char_traitsI[cw]EERSt13basic_ostreamIT0_T1_ES6_RKSt7complexIT_E;
+  _ZStrsIu9__ieee128[cw]St11char_traitsI[cw]EERSt13basic_istreamIT0_T1_ES6_RSt7complexIT_E;
+
+  _ZNSi10_M_extractIu9__ieee128EERSiRT_;
+  _ZNSt13basic_istreamIwSt11char_traitsIwEE10_M_extractIu9__ieee128EERS2_RT_;
+  _ZNSo9_M_insertIu9__ieee128EERSoT_;
+  _ZNSt13basic_ostreamIwSt11char_traitsIwEE9_M_insertIu9__ieee128EERS2_T_;
+
+  _ZNKSt3tr14hashIu9__ieee128EclEu9__ieee128;
+  _ZNKSt4hashIu9__ieee128EclEu9__ieee128;
+
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRNSt7__cxx1112basic_stringIcS3_SaIcEEE;
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRu9__ieee128;
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE8__do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRd;
+  _ZNKSt19__gnu_cxx11_ieee1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE8__do_getES4_S4_bRSt8ios_baseRSt12_Ios_IostateRg;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES4_bRSt8ios_basecRKNSt7__cxx1112basic_stringIcS3_SaIcEEE;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES4_bRSt8ios_basecu9__ieee128;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE8__do_putES4_bRSt8ios_basecd;
+  _ZNKSt19__gnu_cxx11_ieee1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE8__do_putES4_bRSt8ios_basecg;
+  _ZSt9has_facetINSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEEbRKSt6locale;
+  _ZSt9has_facetINSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEEbRKSt6locale;
+  _ZSt9use_facetINSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEERKT_RKSt6locale;
+  _ZSt9use_facetINSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEEERKT_RKSt6locale;
+  _ZTINSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+  _ZTVNSt19__gnu_cxx11_ieee1289money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+  _ZTINSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+  _ZTVNSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEEE;
+
+  _ZNKSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE3putES4_bRSt8ios_base[cw]u9__ieee128;
+
+  _ZSt10from_charsPKcS0_Ru9__ieee128St12chars_format;
+
+} GLIBCXX_3.4.29;
+
+CXXABI_IEEE128_1.3.13 {
+
+  _ZT[IS]u9__ieee128;
+  _ZT[IS]Pu9__ieee128;
+  _ZT[IS]PKu9__ieee128;
+
+} CXXABI_1.3.13;
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index cbfdf4c6bad..d25842fef35 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -404,7 +404,11 @@ GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI([yes])
 GLIBCXX_DEFAULT_ABI
 
 ac_ldbl_compat=no
+ac_ldbl_alt128_compat=no
+ac_ldbl_ieee128_default=no
 LONG_DOUBLE_COMPAT_FLAGS="-mlong-double-64"
+LONG_DOUBLE_128_FLAGS=
+LONG_DOUBLE_ALT128_COMPAT_FLAGS=
 case "$target" in
   powerpc*-*-linux* | \
   sparc*-*-linux* | \
@@ -421,12 +425,43 @@ case "$target" in
     port_specific_symbol_files="\$(top_srcdir)/config/os/gnu-linux/ldbl-extra.ver"
     case "$target" in
       powerpc*-*-linux*)
-	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute" ;;
+	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute"
+        # Check for IEEE128 support in libm:
+        AC_CHECK_LIB(m, frexpf128,
+                     [ac_ldbl_ieee128_in_libc=yes],
+                     [ac_ldbl_ieee128_in_libc=no])
+        if test $ac_ldbl_ieee128_in_libc = yes; then
+          # Determine which long double format is the compiler's default:
+          AC_TRY_COMPILE(, [
+            #ifndef __LONG_DOUBLE_IEEE128__
+            #error compiler defaults to ibm128
+            #endif
+          ], [ac_ldbl_ieee128_default=yes], [ac_ldbl_ieee128_default=no])
+          # Library objects should use default long double format.
+          if test "$ac_ldbl_ieee128_default" = yes; then
+            LONG_DOUBLE_128_FLAGS="-mno-gnu-attribute"
+            # Except for the ones that explicitly use these flags:
+            LONG_DOUBLE_ALT128_COMPAT_FLAGS="-mabi=ibmlongdouble -mno-gnu-attribute -Wno-psabi"
+          else
+            LONG_DOUBLE_128_FLAGS="-mno-gnu-attribute"
+            LONG_DOUBLE_ALT128_COMPAT_FLAGS="-mabi=ieeelongdouble -mno-gnu-attribute -Wno-psabi"
+          fi
+          AC_DEFINE([_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT],1,
+                [Define if compatibility should be provided for alternative 128-bit long double formats.])
+          port_specific_symbol_files="$port_specific_symbol_files \$(top_srcdir)/config/os/gnu-linux/ldbl-ieee128-extra.ver"
+          ac_ldbl_alt128_compat=yes
+        else
+          ac_ldbl_alt128_compat=no
+        fi
+	;;
     esac
   fi
 esac
 AC_SUBST(LONG_DOUBLE_COMPAT_FLAGS)
+AC_SUBST(LONG_DOUBLE_128_FLAGS)
+AC_SUBST(LONG_DOUBLE_ALT128_COMPAT_FLAGS)
 GLIBCXX_CONDITIONAL(GLIBCXX_LDBL_COMPAT, test $ac_ldbl_compat = yes)
+GLIBCXX_CONDITIONAL(GLIBCXX_LDBL_ALT128_COMPAT, test $ac_ldbl_alt128_compat = yes)
 
 # Check if assembler supports disabling hardware capability support.
 GCC_CHECK_ASSEMBLER_HWCAP
diff --git a/libstdc++-v3/fragment.am b/libstdc++-v3/fragment.am
index 216c572fc60..54645739e5c 100644
--- a/libstdc++-v3/fragment.am
+++ b/libstdc++-v3/fragment.am
@@ -25,10 +25,16 @@ else
 XTEMPLATE_FLAGS =
 endif
 
+if GLIBCXX_LDBL_ALT128_COMPAT
+LDBL_128_FLAGS = $(LONG_DOUBLE_128_FLAGS)
+else
+LDBL_128_FLAGS =
+endif
+
 # These bits are all figured out from configure.  Look in acinclude.m4
 # or configure.ac to see how they are set.  See GLIBCXX_EXPORT_FLAGS.
 CONFIG_CXXFLAGS = \
-	$(SECTION_FLAGS) $(HWCAP_CFLAGS) -frandom-seed=$@
+	$(SECTION_FLAGS) $(HWCAP_CFLAGS) -frandom-seed=$@ $(LDBL_128_FLAGS)
 
 WARN_CXXFLAGS = \
 	$(WARN_FLAGS) $(WERROR_FLAG) -fdiagnostics-show-location=once 
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index ca413b8fdfe..5bd61bea6e3 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1293,6 +1293,10 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	grep "^[	 ]*#[	 ]*define[	 ][	 ]*_GLIBCXX_LONG_DOUBLE_COMPAT[	 ][	 ]*1[	 ]*$$" \
 	${CONFIG_HEADER} > /dev/null 2>&1 \
 	&& ldbl_compat='s,^#undef _GLIBCXX_LONG_DOUBLE_COMPAT$$,#define _GLIBCXX_LONG_DOUBLE_COMPAT 1,' ;\
+	ldbl_alt128_compat='s,g,g,' ;\
+	grep "^[	 ]*#[	 ]*define[	 ][	 ]*_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT[	 ][	 ]*1[	 ]*$$" \
+	${CONFIG_HEADER} > /dev/null 2>&1 \
+	&& ldbl_alt128_compat='s,^#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT$$,#define _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT 1,' ;\
 	sed -e "s,define __GLIBCXX__,define __GLIBCXX__ $$date," \
 	-e "s,define _GLIBCXX_RELEASE,define _GLIBCXX_RELEASE $$release," \
 	-e "s,define _GLIBCXX_INLINE_VERSION, define _GLIBCXX_INLINE_VERSION $$ns_version," \
@@ -1303,6 +1307,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	-e "s,define _GLIBCXX_USE_ALLOCATOR_NEW, define _GLIBCXX_USE_ALLOCATOR_NEW $$allocatornew," \
 	-e "s,define _GLIBCXX_USE_FLOAT128,$$float128," \
 	-e "$$ldbl_compat" \
+	-e "$$ldbl_alt128_compat" \
 	    < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
 	sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
 	    -e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
@@ -1313,6 +1318,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	    -e 's/_LARGE_FILES/_GLIBCXX_LARGE_FILES/g' \
 	    -e 's/ICONV_CONST/_GLIBCXX_ICONV_CONST/g' \
 	    -e '/[	 ]_GLIBCXX_LONG_DOUBLE_COMPAT[	 ]/d' \
+	    -e '/[	 ]_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT[	 ]/d' \
 	    < ${CONFIG_HEADER} >> $@ ;\
 	echo "" >> $@ ;\
 	echo "#endif // _GLIBCXX_CXX_CONFIG_H" >> $@
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 27302ed392e..1a23b56fa13 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -425,8 +425,28 @@ _GLIBCXX_END_NAMESPACE_VERSION
 // GLIBCXX_ABI Deprecated
 // Define if compatibility should be provided for -mlong-double-64.
 #undef _GLIBCXX_LONG_DOUBLE_COMPAT
+// Define if compatibility should be provided for alternative 128-bit long
+// double formats.
+#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+// Inline namespaces for long double 128 modes.
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+  && defined __LONG_DOUBLE_IEEE128__
+namespace std
+{
+  // Namespaces for 128-bit IEEE long double format on 64-bit POWER LE.
+  inline namespace __gnu_cxx_ieee128 { }
+  inline namespace __gnu_cxx11_ieee128 { }
+}
+# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ieee128::
+# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ieee128 {
+# define _GLIBCXX_END_NAMESPACE_LDBL }
+# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 __gnu_cxx11_ieee128::
+# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 namespace __gnu_cxx11_ieee128 {
+# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 }
+
+#else // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && IEEE128
 
-// Inline namespace for long double 128 mode.
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
 namespace std
 {
@@ -440,6 +460,7 @@ namespace std
 # define _GLIBCXX_BEGIN_NAMESPACE_LDBL
 # define _GLIBCXX_END_NAMESPACE_LDBL
 #endif
+
 #if _GLIBCXX_USE_CXX11_ABI
 # define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_CXX11
 # define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_CXX11
@@ -450,6 +471,8 @@ namespace std
 # define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL
 #endif
 
+#endif // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && IEEE128
+
 // Debug Mode implies checking assertions.
 #if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS)
 # define _GLIBCXX_ASSERTIONS 1
@@ -648,9 +671,12 @@ namespace std
 # define __cpp_lib_char8_t 201907L
 #endif
 
-/* Define if __float128 is supported on this host. */
+/* Define if __float128 is supported on this host.  */
 #if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
-#define _GLIBCXX_USE_FLOAT128
+/* For powerpc64 don't use __float128 when it's the same type as long double. */
+# if !(defined(_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT) && defined(__LONG_DOUBLE_IEEE128__))
+#  define _GLIBCXX_USE_FLOAT128
+# endif
 #endif
 
 #ifdef __has_builtin
diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h
index ab90682cde2..ed7764e06e7 100644
--- a/libstdc++-v3/include/bits/locale_classes.h
+++ b/libstdc++-v3/include/bits/locale_classes.h
@@ -625,6 +625,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     void _M_init_extra(facet**);
     void _M_init_extra(void*, void*, const char*, const char*);
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    void _M_init_extra_ldbl128(bool);
+#endif
   };
 
 
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 3e0ae8776c9..07be38fc92f 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -51,20 +51,23 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  // NB: Don't instantiate required wchar_t facets if no wchar_t support.
-#ifdef _GLIBCXX_USE_WCHAR_T
-# define  _GLIBCXX_NUM_FACETS 28
-# define  _GLIBCXX_NUM_CXX11_FACETS 16
-#else
-# define  _GLIBCXX_NUM_FACETS 14
-# define  _GLIBCXX_NUM_CXX11_FACETS 8
-#endif
+// Number of standard facets (for narrow characters only)
+#define  _GLIBCXX_NUM_FACETS 14
+
+// Number of duplicated facets for cxx11 ABI
+#define  _GLIBCXX_NUM_CXX11_FACETS (_GLIBCXX_USE_DUAL_ABI ? 8 : 0)
+
+// codecvt<char16_t> and codecvt<char32_t>
 #ifdef _GLIBCXX_USE_CHAR8_T
 # define _GLIBCXX_NUM_UNICODE_FACETS 4
 #else
 # define _GLIBCXX_NUM_UNICODE_FACETS 2
 #endif
 
+// Facets duplicated for alt128 long double format
+// num_get, num_put, money_get, money_put (+ cxx11 money_get, money_put)
+#define _GLIBCXX_NUM_LBDL_ALT128_FACETS (4 + (_GLIBCXX_USE_DUAL_ABI ? 2 : 0))
+
   // Convert string to numeric value of type _Tp and store results.
   // NB: This is specialized for all required types, there is no
   // generic definition.
@@ -2252,6 +2255,10 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
 
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      // For __gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get
+      // this entry in the vtable is for a 64-bit "long double" with the
+      // same format as double. This keeps the vtable layout consistent
+      // with std::num_get (visible when -mlong-double-64 is used).
       virtual iter_type
       __do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
 	       double&) const;
@@ -2264,8 +2271,21 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       virtual iter_type
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, void*&) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      // For __gnu_cxx_ieee128::num_get this entry in the vtable is for
+      // the non-IEEE 128-bit "long double" (aka "double double"). This
+      // is consistent with __gnu_cxx_ldbl128::num_get (-mabi=ibmlongdouble)
+      virtual iter_type
+      __do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
+	       __ibm128&) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      // For __gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get
+      // this entry in the vtable is for the 128-bit "long double" type.
       virtual iter_type
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
 	     long double&) const;
@@ -2545,6 +2565,13 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       virtual iter_type
       do_put(iter_type, ios_base&, char_type, const void*) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_put(iter_type, ios_base&, char_type, __ibm128) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
       virtual iter_type
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index ebc993339a6..4fdca180a87 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -772,6 +772,24 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       return __beg;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    num_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, ios_base& __io,
+	     ios_base::iostate& __err, __ibm128& __v) const
+    {
+      string __xtrc;
+      __xtrc.reserve(32);
+      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
+      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+    }
+#endif
+
   // For use by integer and floating-point types after they have been
   // converted into a char_type string.
   template<typename _CharT, typename _OutIter>
@@ -1194,6 +1212,15 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
       return __s;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    num_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, ios_base& __io, char_type __fill,
+	     __ibm128 __v) const
+    { return _M_insert_float(__s, __io, __fill, 'L', __v); }
+#endif
 _GLIBCXX_END_NAMESPACE_LDBL
 
   // Construct correctly padded string, as per 22.2.2.2.2
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.h b/libstdc++-v3/include/bits/locale_facets_nonio.h
index b76eac435bd..6af68d3fa90 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.h
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.h
@@ -1566,7 +1566,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
        */
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       __do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
 	       ios_base::iostate& __err, double& __units) const;
@@ -1587,9 +1587,17 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
 	     ios_base::iostate& __err, string_type& __digits) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	       ios_base::iostate& __err, __ibm128& __units) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
 	     ios_base::iostate& __err, long double& __units) const;
@@ -1711,7 +1719,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
        */
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 	       double __units) const;
@@ -1744,9 +1752,17 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 	     const string_type& __digits) const;
 
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+      virtual iter_type
+      __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	       __ibm128 __units) const;
+#endif
+
       // XXX GLIBCXX_ABI Deprecated
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
       virtual iter_type
       do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 	     long double __units) const;
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index a8639f6ba28..9e2b6577969 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -350,7 +350,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       }
 
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
   template<typename _CharT, typename _InIter>
     _InIter
     money_get<_CharT, _InIter>::
@@ -401,6 +401,22 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       return __beg;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    money_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+	     ios_base::iostate& __err, __ibm128& __units) const
+    {
+      string __str;
+      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
+	             : _M_extract<false>(__beg, __end, __io, __err, __str);
+      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
+      return __beg;
+    }
+#endif
+
   template<typename _CharT, typename _OutIter>
     template<bool _Intl>
       _OutIter
@@ -562,7 +578,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
       }
 
 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
-      && _GLIBCXX_USE_CXX11_ABI == 0
+      && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
   template<typename _CharT, typename _OutIter>
     _OutIter
     money_put<_CharT, _OutIter>::
@@ -617,6 +633,47 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
 	            : _M_insert<false>(__s, __io, __fill, __digits); }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+      && defined __LONG_DOUBLE_IEEE128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    money_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	     __ibm128 __units) const
+    {
+      const locale __loc = __io.getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+#if _GLIBCXX_USE_C99_STDIO
+      // First try a buffer perhaps big enough.
+      int __cs_size = 64;
+      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 328. Bad sprintf format modifier in money_put<>::do_put()
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					"%.*Lf", 0, __units);
+      // If the buffer was not large enough, try again with the correct size.
+      if (__len >= __cs_size)
+	{
+	  __cs_size = __len + 1;
+	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					"%.*Lf", 0, __units);
+	}
+#else
+      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
+      const int __cs_size =
+	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
+      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
+					0, __units);
+#endif
+      string_type __digits(__len, char_type());
+      __ctype.widen(__cs, __cs + __len, &__digits[0]);
+      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
+	            : _M_insert<false>(__s, __io, __fill, __digits);
+    }
+#endif
+
 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 
   // NB: Not especially useful. Without an ios_base object or some
diff --git a/libstdc++-v3/include/ext/numeric_traits.h b/libstdc++-v3/include/ext/numeric_traits.h
index 2cac7f1d1ed..78a03e3f00d 100644
--- a/libstdc++-v3/include/ext/numeric_traits.h
+++ b/libstdc++-v3/include/ext/numeric_traits.h
@@ -201,6 +201,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __numeric_traits_floating<long double>
     { };
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+# if defined __LONG_DOUBLE_IEEE128__
+  // long double is __ieee128, define traits for __ibm128
+  template<>
+    struct __numeric_traits_floating<__ibm128>
+    {
+      static const int __max_digits10 = 33;
+      static const bool __is_signed = true;
+      static const int __digits10 = 31;
+      static const int __max_exponent10 = 308;
+    };
+  template<>
+    struct __numeric_traits<__ibm128>
+    : public __numeric_traits_floating<__ibm128>
+    { };
+# elif defined __LONG_DOUBLE_IBM128__
+  // long double is __ibm128, define traits for __ieee128
+  template<>
+    struct __numeric_traits_floating<__ieee128>
+    {
+      static const int __max_digits10 = 36;
+      static const bool __is_signed = true;
+      static const int __digits10 = 33;
+      static const int __max_exponent10 = 4932;
+    };
+  template<>
+    struct __numeric_traits<__ieee128>
+    : public __numeric_traits_floating<__ieee128>
+    { };
+# endif
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am
index 21b6db7fb1c..c32c88954f3 100644
--- a/libstdc++-v3/src/Makefile.am
+++ b/libstdc++-v3/src/Makefile.am
@@ -71,6 +71,20 @@ else
 ldbl_compat_sources =
 endif
 
+if GLIBCXX_LDBL_ALT128_COMPAT
+if ENABLE_DUAL_ABI
+ldbl_alt128_compat_cxx11_sources = \
+	compatibility-ldbl-alt128-cxx11.cc
+else
+ldbl_alt128_compat_cxx11_sources =
+endif
+ldbl_alt128_compat_sources = \
+	compatibility-ldbl-alt128.cc \
+	${ldbl_alt128_compat_cxx11_sources}
+else
+ldbl_alt128_compat_sources =
+endif
+
 
 parallel_compat_sources = \
 	compatibility-parallel_list.cc  compatibility-parallel_list-2.cc
@@ -87,7 +101,8 @@ cxx11_sources = \
 	compatibility-atomic-c++0x.cc \
 	compatibility-thread-c++0x.cc \
 	compatibility-chrono.cc \
-	compatibility-condvar.cc
+	compatibility-condvar.cc \
+	${ldbl_alt128_compat_sources}
 
 libstdc___la_SOURCES = $(cxx98_sources) $(cxx11_sources)
 
@@ -113,12 +128,36 @@ libstdc___la_LDFLAGS = \
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS) $(lt_host_flags)
 
 # Use special rules for compatibility-ldbl.cc compilation, as we need to
-# pass -mlong-double-64.
+# pass -mlong-double-64, and not use -mabi={ieee,ibm}longdouble.
 if GLIBCXX_LDBL_COMPAT
+if GLIBCXX_LDBL_ALT128_COMPAT
+LTCXXCOMPILE64 = \
+  $(filter-out -mabi=ieeelongdouble -mabi=ibmlongdouble,$(LTCXXCOMPILE))
+CXXCOMPILE64 = \
+  $(filter-out -mabi=ieeelongdouble -mabi=ibmlongdouble,$(CXXCOMPILE))
+else
+LTCXXCOMPILE64 = $(LTCXXCOMPILE)
+CXXCOMPILE64 = $(CXXCOMPILE)
+endif
 compatibility-ldbl.lo: compatibility-ldbl.cc
-	$(LTCXXCOMPILE) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
+	$(LTCXXCOMPILE64) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
 compatibility-ldbl.o: compatibility-ldbl.cc
-	$(CXXCOMPILE) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
+	$(CXXCOMPILE64) $(LONG_DOUBLE_COMPAT_FLAGS) -c $<
+endif
+
+# Use special rules for compatibility-ldbl-alt128.cc compilation, as we need to
+# ensure it is compiled with the correct flag.
+if GLIBCXX_LDBL_ALT128_COMPAT
+compatibility-ldbl-alt128.lo: compatibility-ldbl-alt128.cc
+	$(LTCXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+compatibility-ldbl-alt128.o: compatibility-ldbl-alt128.cc
+	$(CXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+if ENABLE_DUAL_ABI
+compatibility-ldbl-alt128-cxx11.lo: compatibility-ldbl-alt128-cxx11.cc
+	$(LTCXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+compatibility-ldbl-alt128-cxx11.o: compatibility-ldbl-alt128-cxx11.cc
+	$(CXXCOMPILE) $(LONG_DOUBLE_ALT128_COMPAT_FLAGS) -std=gnu++11 -c $<
+endif
 endif
 
 # Use special rules for C++11 files/objects.
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-alt128-cxx11.cc b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128-cxx11.cc
new file mode 100644
index 00000000000..7c03606bce4
--- /dev/null
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128-cxx11.cc
@@ -0,0 +1,102 @@
+// Compatibility symbols for alternate 128-bit long-double format -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_USE_CXX11_ABI 1
+#include <locale>
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+#if !defined(_GLIBCXX_USE_DUAL_ABI)
+#error "compatibility-ldbl-alt128-cxx11.cc must only be compiled when dual ABI is enabled"
+#endif
+
+#if ! defined __LONG_DOUBLE_IBM128__ && ! defined __LONG_DOUBLE_IEEE128__
+#error "compatibility-ldbl-alt128.cc must only be compiled for 128-bit long double"
+#endif
+
+#define C char
+#define C_is_char
+#include "locale-inst-monetary.h"
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+# undef C
+# undef C_is_char
+# define C wchar_t
+# include "locale-inst-monetary.h"
+#endif
+
+#include <functional>
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  namespace
+  {
+    alignas(money_get<char>) char money_get_c[sizeof(money_get<char>)];
+    alignas(money_put<char>) char money_put_c[sizeof(money_put<char>)];
+#ifdef _GLIBCXX_USE_WCHAR_T
+    alignas(money_get<wchar_t>) char money_get_w[sizeof(money_get<wchar_t>)];
+    alignas(money_put<wchar_t>) char money_put_w[sizeof(money_put<wchar_t>)];
+#endif
+
+  template<typename Facet>
+    void
+    init_facet(function<void(const locale::id*, const locale::facet*)>& func,
+	       Facet* facet)
+    {
+      func(&Facet::id, facet);
+    }
+
+  } // namespace
+
+  template class function<void(const locale::id*, const locale::facet*)>;
+
+  void
+  __locale_Impl_init_extra_ldbl128(
+      function<void(const locale::id*, const locale::facet*)> f,
+      bool classic)
+  {
+    if (classic)
+      {
+	init_facet(f, new (&money_get_c) money_get<char>(1));
+	init_facet(f, new (&money_put_c) money_put<char>(1));
+#ifdef _GLIBCXX_USE_WCHAR_T
+	init_facet(f, new (&money_get_w) money_get<wchar_t>(1));
+	init_facet(f, new (&money_put_w) money_put<wchar_t>(1));
+#endif
+      }
+    else
+      {
+	init_facet(f, new money_get<char>);
+	init_facet(f, new money_put<char>);
+#ifdef _GLIBCXX_USE_WCHAR_T
+	init_facet(f, new money_get<wchar_t>);
+	init_facet(f, new money_put<wchar_t>);
+#endif
+      }
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-alt128.cc b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128.cc
new file mode 100644
index 00000000000..7fb66917db1
--- /dev/null
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-alt128.cc
@@ -0,0 +1,244 @@
+// Compatibility symbols for alternate 128-bit long-double format -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_USE_CXX11_ABI 0
+#include <locale>
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+#if ! defined __LONG_DOUBLE_IBM128__ && ! defined __LONG_DOUBLE_IEEE128__
+#error "compatibility-ldbl-alt128.cc must only be compiled for 128-bit long double"
+#endif
+
+#define C char
+#define C_is_char
+#include "locale-inst-numeric.h"
+#include "locale-inst-monetary.h"
+#include "compatibility-ldbl-facets-aliases.h"
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+# undef C
+# undef C_is_char
+# define C wchar_t
+# include "locale-inst-numeric.h"
+# include "locale-inst-monetary.h"
+# include "compatibility-ldbl-facets-aliases.h"
+# undef C
+#endif
+
+#include <limits>
+#include <functional>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // long double
+  const bool numeric_limits<long double>::is_specialized;
+  const int  numeric_limits<long double>::digits;
+  const int  numeric_limits<long double>::digits10;
+  const int  numeric_limits<long double>::max_digits10;
+  const bool numeric_limits<long double>::is_signed;
+  const bool numeric_limits<long double>::is_integer;
+  const bool numeric_limits<long double>::is_exact;
+  const int  numeric_limits<long double>::radix;
+  const int  numeric_limits<long double>::min_exponent;
+  const int  numeric_limits<long double>::min_exponent10;
+  const int  numeric_limits<long double>::max_exponent;
+  const int  numeric_limits<long double>::max_exponent10;
+  const bool numeric_limits<long double>::has_infinity;
+  const bool numeric_limits<long double>::has_quiet_NaN;
+  const bool numeric_limits<long double>::has_signaling_NaN;
+  const float_denorm_style numeric_limits<long double>::has_denorm;
+  const bool numeric_limits<long double>::has_denorm_loss;
+  const bool numeric_limits<long double>::is_iec559;
+  const bool numeric_limits<long double>::is_bounded;
+  const bool numeric_limits<long double>::is_modulo;
+  const bool numeric_limits<long double>::traps;
+  const bool numeric_limits<long double>::tinyness_before;
+  const float_round_style numeric_limits<long double>::round_style;
+
+  template<>
+    void
+    __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
+		   const __c_locale& __cloc) throw()
+    {
+      char* __sanity;
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+      // Prefer strtold_l, as __strtold_l isn't prototyped in more recent
+      // glibc versions.
+      __v = strtold_l(__s, &__sanity, __cloc);
+#else
+      __v = __strtold_l(__s, &__sanity, __cloc);
+#endif
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 23. Num_get overflow result.
+      if (__sanity == __s || *__sanity != '\0')
+	{
+	  __v = 0.0l;
+	  __err = ios_base::failbit;
+	}
+      else if (__v == numeric_limits<long double>::infinity())
+	{
+	  __v = numeric_limits<long double>::max();
+	  __err = ios_base::failbit;
+	}
+      else if (__v == -numeric_limits<long double>::infinity())
+	{
+	  __v = -numeric_limits<long double>::max();
+	  __err = ios_base::failbit;
+	}
+    }
+
+  namespace
+  {
+    alignas(money_get<char>) char money_get_c[sizeof(money_get<char>)];
+    alignas(money_put<char>) char money_put_c[sizeof(money_put<char>)];
+    alignas(num_get<char>) char num_get_c[sizeof(num_get<char>)];
+    alignas(num_put<char>) char num_put_c[sizeof(num_put<char>)];
+#ifdef _GLIBCXX_USE_WCHAR_T
+    alignas(money_get<wchar_t>) char money_get_w[sizeof(money_get<wchar_t>)];
+    alignas(money_put<wchar_t>) char money_put_w[sizeof(money_put<wchar_t>)];
+    alignas(num_get<wchar_t>) char num_get_w[sizeof(num_get<wchar_t>)];
+    alignas(num_put<wchar_t>) char num_put_w[sizeof(num_put<wchar_t>)];
+#endif
+  }
+
+  extern void
+  __locale_Impl_init_extra_ldbl128(
+      function<void(const locale::id*, const locale::facet*)>,
+      bool);
+
+  void
+  locale::_Impl::_M_init_extra_ldbl128(bool classic)
+  {
+    if (classic)
+      {
+	_M_init_facet(new (&money_get_c) money_get<char>(1));
+	_M_init_facet(new (&money_put_c) money_put<char>(1));
+	_M_init_facet(new (&num_get_c) num_get<char>(1));
+	_M_init_facet(new (&num_put_c) num_put<char>(1));
+#ifdef _GLIBCXX_USE_WCHAR_T
+	_M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
+	_M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
+	_M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
+	_M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
+#endif
+      }
+    else
+      {
+	_M_init_facet(new money_get<char>);
+	_M_init_facet(new money_put<char>);
+	_M_init_facet(new num_get<char>);
+	_M_init_facet(new num_put<char>);
+#ifdef _GLIBCXX_USE_WCHAR_T
+	_M_init_facet(new money_get<wchar_t>);
+	_M_init_facet(new money_put<wchar_t>);
+	_M_init_facet(new num_get<wchar_t>);
+	_M_init_facet(new num_put<wchar_t>);
+#endif
+      }
+
+#if _GLIBCXX_USE_DUAL_ABI
+    __locale_Impl_init_extra_ldbl128(
+	[this](const locale::id* i, const facet* f) {
+	    _M_install_facet(i, f);
+	},
+	classic);
+#endif
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#include <istream>
+#include <ostream>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template istream& istream::operator>>(long double&);
+  template istream& istream::_M_extract(long double&);
+  template ostream& ostream::operator<<(long double);
+  template ostream& ostream::_M_insert(long double);
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template wistream& wistream::operator>>(long double&);
+  template wistream& wistream::_M_extract(long double&);
+  template wostream& wostream::operator<<(long double);
+  template wostream& wostream::_M_insert(long double);
+#endif
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#include <complex>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template
+    basic_istream<char, char_traits<char> >&
+    operator>>(basic_istream<char, char_traits<char> >&,
+	       complex<long double>&);
+  template
+    basic_ostream<char, char_traits<char> >&
+    operator<<(basic_ostream<char, char_traits<char> >&,
+               const complex<long double>&);
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template
+    basic_istream<wchar_t, char_traits<wchar_t> >&
+    operator>>(basic_istream<wchar_t, char_traits<wchar_t> >&,
+               complex<long double>&);
+  template
+    basic_ostream<wchar_t, char_traits<wchar_t> >&
+    operator<<(basic_ostream<wchar_t, char_traits<wchar_t> >&,
+               const complex<long double>&);
+#endif
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#include <cmath>
+#include <tr1/functional>
+
+// For std::tr1::hash<long double>::operator()
+#include "../c++98/hash-long-double-tr1-aux.cc"
+
+// std::tr1::hash<long double>::operator()
+// and std::hash<long double>::operator()
+// are the same, no need to duplicate them.
+#ifdef __LONG_DOUBLE_IBM128__
+extern "C" size_t
+_ZNKSt4hashIgEclEg (void)
+  __attribute__((pure))
+  __attribute__((alias ("_ZNKSt3tr14hashIgEclEg")));
+#elif __LONG_DOUBLE_IEEE128__
+extern "C" size_t
+_ZNKSt4hashIu9__ieee128EclEu9__ieee128 (void)
+  __attribute__((pure))
+  __attribute__((alias ("_ZNKSt3tr14hashIu9__ieee128EclEu9__ieee128")));
+#else
+# error "Configuration error"
+#endif
+
+#endif
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h b/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
new file mode 100644
index 00000000000..7bdf9810d0e
--- /dev/null
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
@@ -0,0 +1,128 @@
+// Compatibility aliases for long double support in locales -*- C++ -*-
+
+// Copyright (C) 1999-2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef C
+#define "This file should not be compiled directly, only included"
+#endif
+
+#ifndef _GLIBCXX_LONG_DOUBLE_COMPAT
+#define "This file should only be used for _GLIBCXX_LONG_DOUBLE_COMPAT builds"
+#endif
+
+// XXX GLIBCXX_ABI Deprecated
+#if defined __LONG_DOUBLE_128__ && ! defined __LONG_DOUBLE_IEEE128__
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattribute-alias"
+
+#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
+  extern "C" void ldbl (void) __attribute__ ((alias (#dbl), weak))
+
+// Define members of std::num_get and std::num_put as aliases for
+// members of __gnu_cxx_ldbl128::num_get and __gnu_cxx_ldbl128::num_put
+#ifdef C_is_char
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES4_S4_RSt8ios_basecT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES3_S3_RSt8ios_basecT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES4_S4_RSt8ios_baseccT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_,
+		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIeEES3_S3_RSt8ios_baseccT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES4_S4_RSt8ios_basecRKSs,
+		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES3_S3_RSt8ios_basecRKSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES4_S4_RSt8ios_basecRKSs,
+		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES3_S3_RSt8ios_basecRKSs);
+#else // ! C_is_char
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
+		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES4_S4_RSt8ios_basewT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES3_S3_RSt8ios_basewT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES4_S4_RSt8ios_basewcT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_,
+		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIeEES3_S3_RSt8ios_basewcT_);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
+		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
+		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
+		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
+#endif // C_is_char
+
+
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+// Define __gnu_cxx_ieee128::num_put<>::_M_insert_float(..., __ibm128) as
+// alias of __gnu_cxx_ldbl128::num_put<>::_M_insert_float(..., __ibm128)
+# ifdef C_is_char
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIgEES4_S4_RSt8ios_baseccT_,
+		     _ZNKSt17__gnu_cxx_ieee1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIgEES4_S4_RSt8ios_baseccT_);
+# else
+_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIgEES4_S4_RSt8ios_basewcT_,
+		     _ZNKSt17__gnu_cxx_ieee1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIgEES4_S4_RSt8ios_basewcT_);
+# endif
+#endif // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+
+#undef _GLIBCXX_LDBL_COMPAT
+#pragma GCC diagnostic pop
+
+#endif  // __LONG_DOUBLE_128__ && ! __LONG_DOUBLE_IEEE128__
diff --git a/libstdc++-v3/src/c++11/cow-locale_init.cc b/libstdc++-v3/src/c++11/cow-locale_init.cc
index 98a2ef41f56..bf270712e47 100644
--- a/libstdc++-v3/src/c++11/cow-locale_init.cc
+++ b/libstdc++-v3/src/c++11/cow-locale_init.cc
@@ -125,6 +125,7 @@ namespace
     _M_init_facet_unchecked(new (&messages_w) std::messages<wchar_t>(1));
 #endif
 
+    // The caches must be populated last, after creating all facets.
     _M_caches[numpunct<char>::id._M_id()] = __npc;
     _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf;
     _M_caches[moneypunct<char, true>::id._M_id()] = __mpct;
diff --git a/libstdc++-v3/src/c++11/cxx11-locale-inst.cc b/libstdc++-v3/src/c++11/cxx11-locale-inst.cc
index 7b132a748bf..9378550124f 100644
--- a/libstdc++-v3/src/c++11/cxx11-locale-inst.cc
+++ b/libstdc++-v3/src/c++11/cxx11-locale-inst.cc
@@ -32,8 +32,6 @@
 # error This file should not be compiled for this configuration.
 #endif
 
-#ifndef C
-# define C char
-# define C_is_char
-#endif
+#define C char
+#define C_is_char
 # include "locale-inst.cc"
diff --git a/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc b/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc
index cf3d6dc7e34..07eb6008361 100644
--- a/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc
+++ b/libstdc++-v3/src/c++11/cxx11-wlocale-inst.cc
@@ -24,9 +24,15 @@
 // ISO C++ 14882: 22.1  Locales
 //
 
+// Facet wchar_t instantiations using new ABI strings.
+
 #define _GLIBCXX_USE_CXX11_ABI 1
 #include <bits/c++config.h>
+#if ! _GLIBCXX_USE_DUAL_ABI
+# error This file should not be compiled for this configuration.
+#endif
+
 #ifdef _GLIBCXX_USE_WCHAR_T
 #define C wchar_t
-#include "cxx11-locale-inst.cc"
+#include "locale-inst.cc"
 #endif
diff --git a/libstdc++-v3/src/c++11/locale-inst-monetary.h b/libstdc++-v3/src/c++11/locale-inst-monetary.h
new file mode 100644
index 00000000000..e9b3e7c4e0c
--- /dev/null
+++ b/libstdc++-v3/src/c++11/locale-inst-monetary.h
@@ -0,0 +1,69 @@
+// Explicit instantantiations for monetary facets -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef C
+#define "This file should not be compiled directly, only included"
+#endif
+
+// This header is included multiple times, to instantiate these symbols
+// for char/wchar_t and for both std::string ABIs,
+// and (depending on the target) for two long double formats.
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+  template const money_put<C>& use_facet<money_put<C> >(const locale&);
+  template const money_get<C>& use_facet<money_get<C> >(const locale&);
+
+  template bool has_facet<money_put<C> >(const locale&);
+  template bool has_facet<money_get<C> >(const locale&);
+
+_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
+  template class money_get<C, istreambuf_iterator<C> >;
+  template class money_put<C, ostreambuf_iterator<C> >;
+
+  template
+    istreambuf_iterator<C>
+    money_get<C, istreambuf_iterator<C> >::
+    _M_extract<true>(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		     ios_base&, ios_base::iostate&, string&) const;
+
+  template
+    istreambuf_iterator<C>
+    money_get<C, istreambuf_iterator<C> >::
+    _M_extract<false>(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		      ios_base&, ios_base::iostate&, string&) const;
+
+  template
+    ostreambuf_iterator<C>
+    money_put<C, ostreambuf_iterator<C> >::
+    _M_insert<true>(ostreambuf_iterator<C>, ios_base&, C,
+		    const string_type&) const;
+
+  template
+    ostreambuf_iterator<C>
+    money_put<C, ostreambuf_iterator<C> >::
+    _M_insert<false>(ostreambuf_iterator<C>, ios_base&, C,
+		     const string_type&) const;
+_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
+} // namespace std
diff --git a/libstdc++-v3/src/c++11/locale-inst-numeric.h b/libstdc++-v3/src/c++11/locale-inst-numeric.h
new file mode 100644
index 00000000000..0ec93e27937
--- /dev/null
+++ b/libstdc++-v3/src/c++11/locale-inst-numeric.h
@@ -0,0 +1,133 @@
+// Explicit instantantiations for numeric facets -*- C++ -*-
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef C
+#define "This file should not be compiled directly, only included"
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+#if ! _GLIBCXX_USE_CXX11_ABI
+  template const num_get<C>& use_facet<num_get<C> >(const locale&);
+  template const num_put<C>& use_facet<num_put<C> >(const locale&);
+
+  template bool has_facet<num_get<C> >(const locale&);
+  template bool has_facet<num_put<C> >(const locale&);
+#endif
+
+_GLIBCXX_BEGIN_NAMESPACE_LDBL
+
+#if ! _GLIBCXX_USE_CXX11_ABI
+  template class num_get<C, istreambuf_iterator<C> >;
+  template class num_put<C, ostreambuf_iterator<C> >;
+#endif
+
+  // num_get member function templates
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   long&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned short&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned int&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned long&) const;
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   long long&) const;
+
+  template
+    istreambuf_iterator<C>
+    num_get<C, istreambuf_iterator<C> >::
+    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
+		   ios_base&, ios_base::iostate&,
+		   unsigned long long&) const;
+#endif
+
+#if ! _GLIBCXX_USE_CXX11_ABI
+  // num_put member function templates
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  long) const;
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  unsigned long) const;
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  long long) const;
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
+		  unsigned long long) const;
+#endif
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
+		    double) const;
+
+  template
+    ostreambuf_iterator<C>
+    num_put<C, ostreambuf_iterator<C> >::
+    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
+		    long double) const;
+#endif
+
+_GLIBCXX_END_NAMESPACE_LDBL
+} // namespace std
diff --git a/libstdc++-v3/src/c++11/locale-inst.cc b/libstdc++-v3/src/c++11/locale-inst.cc
index 4dc7f5c0780..cd99648e8f6 100644
--- a/libstdc++-v3/src/c++11/locale-inst.cc
+++ b/libstdc++-v3/src/c++11/locale-inst.cc
@@ -43,6 +43,9 @@
 # define C_is_char
 #endif
 
+#include "locale-inst-numeric.h"
+#include "locale-inst-monetary.h"
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -58,33 +61,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   template class moneypunct_byname<C, false>;
   template class moneypunct_byname<C, true>;
 _GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
-  template class money_get<C, istreambuf_iterator<C> >;
-  template class money_put<C, ostreambuf_iterator<C> >;
-  template
-    istreambuf_iterator<C>
-    money_get<C, istreambuf_iterator<C> >::
-    _M_extract<true>(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		     ios_base&, ios_base::iostate&, string&) const;
-
-  template
-    istreambuf_iterator<C>
-    money_get<C, istreambuf_iterator<C> >::
-    _M_extract<false>(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		      ios_base&, ios_base::iostate&, string&) const;
-
-  template
-    ostreambuf_iterator<C>
-    money_put<C, ostreambuf_iterator<C> >::
-    _M_insert<true>(ostreambuf_iterator<C>, ios_base&, C,
-		    const string_type&) const;
-
-  template
-    ostreambuf_iterator<C>
-    money_put<C, ostreambuf_iterator<C> >::
-    _M_insert<false>(ostreambuf_iterator<C>, ios_base&, C,
-		     const string_type&) const;
-_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 
   // numpunct, numpunct_byname, num_get, and num_put
 #if ! _GLIBCXX_USE_CXX11_ABI
@@ -94,97 +70,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   template class numpunct<C>;
   template class numpunct_byname<C>;
 _GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_BEGIN_NAMESPACE_LDBL
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template class num_get<C, istreambuf_iterator<C> >;
-#endif
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   long&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned short&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned int&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned long&) const;
-
-#ifdef _GLIBCXX_USE_LONG_LONG
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   long long&) const;
-
-  template
-    istreambuf_iterator<C>
-    num_get<C, istreambuf_iterator<C> >::
-    _M_extract_int(istreambuf_iterator<C>, istreambuf_iterator<C>,
-		   ios_base&, ios_base::iostate&,
-		   unsigned long long&) const;
-#endif
-
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template class num_put<C, ostreambuf_iterator<C> >;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  long) const;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  unsigned long) const;
-
-#ifdef _GLIBCXX_USE_LONG_LONG
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  long long) const;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_int(ostreambuf_iterator<C>, ios_base&, C,
-		  unsigned long long) const;
-#endif
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
-		    double) const;
-
-  template
-    ostreambuf_iterator<C>
-    num_put<C, ostreambuf_iterator<C> >::
-    _M_insert_float(ostreambuf_iterator<C>, ios_base&, C, char,
-		    long double) const;
-#endif
-_GLIBCXX_END_NAMESPACE_LDBL
 
   // time_get and time_put
 #if ! _GLIBCXX_USE_CXX11_ABI
@@ -250,16 +135,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
     const numpunct<C>&
     use_facet<numpunct<C> >(const locale&);
 
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    const num_put<C>&
-    use_facet<num_put<C> >(const locale&);
-
-  template
-    const num_get<C>&
-    use_facet<num_get<C> >(const locale&);
-#endif
-
   template
     const moneypunct<C, true>&
     use_facet<moneypunct<C, true> >(const locale&);
@@ -268,14 +143,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
     const moneypunct<C, false>&
     use_facet<moneypunct<C, false> >(const locale&);
 
-  template
-    const money_put<C>&
-    use_facet<money_put<C> >(const locale&);
-
-  template
-    const money_get<C>&
-    use_facet<money_get<C> >(const locale&);
-
 #if ! _GLIBCXX_USE_CXX11_ABI
   template
     const __timepunct<C>&
@@ -313,28 +180,10 @@ _GLIBCXX_END_NAMESPACE_CXX11
     bool
     has_facet<numpunct<C> >(const locale&);
 
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    bool
-    has_facet<num_put<C> >(const locale&);
-
-  template
-    bool
-    has_facet<num_get<C> >(const locale&);
-#endif
-
   template
     bool
     has_facet<moneypunct<C> >(const locale&);
 
-  template
-    bool
-    has_facet<money_put<C> >(const locale&);
-
-  template
-    bool
-    has_facet<money_get<C> >(const locale&);
-
 #if ! _GLIBCXX_USE_CXX11_ABI
   template
     bool
@@ -380,45 +229,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 // XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined C_is_char \
-      && _GLIBCXX_USE_CXX11_ABI == 0
-
-#pragma GCC diagnostic ignored "-Wattribute-alias"
-
-#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
-  extern "C" void ldbl (void) __attribute__ ((alias (#dbl), weak))
-
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIxEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES4_S4_RSt8ios_basecT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIyEES3_S3_RSt8ios_basecT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES4_S4_RSt8ios_baseccT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_,
-		     _ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIeEES3_S3_RSt8ios_baseccT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES4_S4_RSt8ios_basecRKSs,
-		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb0EEES3_S3_RSt8ios_basecRKSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES4_S4_RSt8ios_basecRKSs,
-		     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb1EEES3_S3_RSt8ios_basecRKSs);
-
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && ! _GLIBCXX_USE_CXX11_ABI
+#include "compatibility-ldbl-facets-aliases.h"
 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT
diff --git a/libstdc++-v3/src/c++11/wlocale-inst.cc b/libstdc++-v3/src/c++11/wlocale-inst.cc
index 3a54fb51aab..a9a246f8f97 100644
--- a/libstdc++-v3/src/c++11/wlocale-inst.cc
+++ b/libstdc++-v3/src/c++11/wlocale-inst.cc
@@ -33,47 +33,4 @@
 #ifdef _GLIBCXX_USE_WCHAR_T
 #define C wchar_t
 #include "locale-inst.cc"
-
-// XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT
-
-#pragma GCC diagnostic ignored "-Wattribute-alias"
-
-#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
-  extern "C" void ldbl (void) __attribute__ ((alias (#dbl), weak))
-
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIjEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIlEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intImEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intItEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIxEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRT_,
-		     _ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE14_M_extract_intIyEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intImEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIxEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES4_S4_RSt8ios_basewT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIyEES3_S3_RSt8ios_basewT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1287num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES4_S4_RSt8ios_basewcT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIdEES3_S3_RSt8ios_basewcT_,
-		     _ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE15_M_insert_floatIeEES3_S3_RSt8ios_basewcT_);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb0EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES4_S4_S4_RSt8ios_baseRSt12_Ios_IostateRSs,
-		     _ZNKSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE10_M_extractILb1EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
-		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb0EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
-_GLIBCXX_LDBL_COMPAT(_ZNKSt17__gnu_cxx_ldbl1289money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES4_S4_RSt8ios_basewRKSbIwS3_SaIwEE,
-		     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE);
-
-#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
-#endif
+#endif // _GLIBCXX_USE_WCHAR_T
diff --git a/libstdc++-v3/src/c++17/Makefile.am b/libstdc++-v3/src/c++17/Makefile.am
index 642efb976ac..37cdb53c076 100644
--- a/libstdc++-v3/src/c++17/Makefile.am
+++ b/libstdc++-v3/src/c++17/Makefile.am
@@ -61,6 +61,13 @@ vpath % $(top_srcdir)/src/c++17
 
 libc__17convenience_la_SOURCES = $(sources)  $(inst_sources)
 
+if GLIBCXX_LDBL_ALT128_COMPAT
+floating_from_chars.lo: floating_from_chars.cc
+	$(LTCXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
+floating_from_chars.o: floating_from_chars.cc
+	$(CXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
+endif
+
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
 # modified in a per-library or per-sub-library way.  Need to manually
 # set this option because CONFIG_CXXFLAGS has to be after
diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc
index c279809cf35..a1943351493 100644
--- a/libstdc++-v3/src/c++17/floating_from_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_from_chars.cc
@@ -44,6 +44,14 @@
 # include <xlocale.h>
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+#ifndef __LONG_DOUBLE_IBM128__
+#error "floating_from_chars.cc must be compiled with -mabi=ibmlongdouble"
+#endif
+// strtold for __ieee128
+extern "C" __ieee128 __strtoieee128(const char*, char**);
+#endif
+
 #if _GLIBCXX_HAVE_USELOCALE
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -316,6 +324,10 @@ namespace
 	  tmpval = std::strtod(str, &endptr);
 	else if constexpr (is_same_v<T, long double>)
 	  tmpval = std::strtold(str, &endptr);
+# ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+	else if constexpr (is_same_v<T, __ieee128>)
+	  tmpval = __strtoieee128(str, &endptr);
+# endif
 #else
 	tmpval = std::strtod(str, &endptr);
 #endif
@@ -332,7 +344,7 @@ namespace
 	const ptrdiff_t n = endptr - str;
 	if (conv_errno == ERANGE) [[unlikely]]
 	  {
-	    if (isinf(tmpval)) // overflow
+	    if (__builtin_isinf(tmpval)) // overflow
 	      ec = errc::result_out_of_range;
 	    else // underflow (LWG 3081 wants to set value = tmpval here)
 	      ec = errc::result_out_of_range;
@@ -469,6 +481,8 @@ from_chars(const char* first, const char* last, long double& value,
 }
 
 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
+// Make std::from_chars for 64-bit long double an alias for the overload
+// for double.
 extern "C" from_chars_result
 _ZSt10from_charsPKcS0_ReSt12chars_format(const char* first, const char* last,
 					 long double& value,
@@ -476,6 +490,28 @@ _ZSt10from_charsPKcS0_ReSt12chars_format(const char* first, const char* last,
 __attribute__((alias ("_ZSt10from_charsPKcS0_RdSt12chars_format")));
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+from_chars_result
+from_chars(const char* first, const char* last, __ieee128& value,
+	   chars_format fmt) noexcept
+{
+  buffer_resource mr;
+  pmr::string buf(&mr);
+  size_t len = 0;
+  errc ec = errc::invalid_argument;
+  __try
+    {
+      if (const char* pat = pattern(first, last, fmt, buf)) [[likely]]
+	len = from_chars_impl(pat, value, ec);
+    }
+  __catch (const std::bad_alloc&)
+    {
+      fmt = chars_format{};
+    }
+  return make_result(first, len, fmt, ec);
+}
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // _GLIBCXX_HAVE_USELOCALE
diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
index c3841ccbd3c..77c6eecc1a3 100644
--- a/libstdc++-v3/src/c++98/locale_init.cc
+++ b/libstdc++-v3/src/c++98/locale_init.cc
@@ -57,8 +57,16 @@ _GLIBCXX_LOC_ID(_ZNSt8messagesIwE2idE);
 
 namespace
 {
-  const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
-    + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0);
+  const int num_facets = (
+      _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_CXX11_FACETS
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+      + _GLIBCXX_NUM_LBDL_ALT128_FACETS
+#endif
+      )
+#ifdef _GLIBCXX_USE_WCHAR_T
+    * 2
+#endif
+    + _GLIBCXX_NUM_UNICODE_FACETS;
 
   __gnu_cxx::__mutex&
   get_locale_mutex()
@@ -559,6 +567,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    _M_init_extra_ldbl128(true);
+#endif
+
 #if _GLIBCXX_USE_DUAL_ABI
     facet* extra[] = { __npc, __mpcf, __mpct
 # ifdef  _GLIBCXX_USE_WCHAR_T
@@ -566,6 +578,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # endif
     };
 
+    // This call must be after creating all facets, as it sets caches.
     _M_init_extra(extra);
 #endif
 
diff --git a/libstdc++-v3/src/c++98/localename.cc b/libstdc++-v3/src/c++98/localename.cc
index 243acce164c..29f439ffa9a 100644
--- a/libstdc++-v3/src/c++98/localename.cc
+++ b/libstdc++-v3/src/c++98/localename.cc
@@ -171,8 +171,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
   }
 
-const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
-  + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0);
+const int num_facets = (
+    _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_CXX11_FACETS
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    + _GLIBCXX_NUM_LBDL_ALT128_FACETS
+#endif
+    )
+#ifdef _GLIBCXX_USE_WCHAR_T
+  * 2
+#endif
+  + _GLIBCXX_NUM_UNICODE_FACETS;
 
   // Construct named _Impl.
   locale::_Impl::
@@ -284,6 +292,10 @@ const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
         _M_init_extra(&__cloc, &__clocm, __s, __smon);
 #endif
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+	_M_init_extra_ldbl128(false);
+#endif
+
 	locale::facet::_S_destroy_c_locale(__cloc);
 	if (__clocm != __cloc)
 	  locale::facet::_S_destroy_c_locale(__clocm);
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc b/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
index 2f8569eb8b9..bf2441320c6 100644
--- a/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
+++ b/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
@@ -8,7 +8,7 @@
 float (std::complex<float>::*p1)() const = &std::complex<float>::real;
 // { dg-final { scan-assembler "_ZNKSt7complexIdE4realB5cxx11Ev" } }
 double (std::complex<double>::*p2)() const = &std::complex<double>::real;
-// { dg-final { scan-assembler "_ZNKSt7complexI\[eg\]E4realB5cxx11Ev" } }
+// { dg-final { scan-assembler "_ZNKSt7complexI\(e\|g\|u9__ieee128\)E4realB5cxx11Ev" } }
 long double (std::complex<long double>::*p3)() const
   = &std::complex<long double>::real;
 // { dg-final { scan-assembler "_ZNKSt7complexIiE4realB5cxx11Ev" } }
@@ -18,7 +18,7 @@ int (std::complex<int>::*p4)() const = &std::complex<int>::real;
 float (std::complex<float>::*p5)() const = &std::complex<float>::imag;
 // { dg-final { scan-assembler "_ZNKSt7complexIdE4imagB5cxx11Ev" } }
 double (std::complex<double>::*p6)() const = &std::complex<double>::imag;
-// { dg-final { scan-assembler "_ZNKSt7complexI\[eg\]E4imagB5cxx11Ev" } }
+// { dg-final { scan-assembler "_ZNKSt7complexI\(e\|g\|u9__ieee128\)E4imagB5cxx11Ev" } }
 long double (std::complex<long double>::*p7)() const
   = &std::complex<long double>::imag;
 // { dg-final { scan-assembler "_ZNKSt7complexIiE4imagB5cxx11Ev" } }
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 33b9ec15935..75029549c0d 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -211,6 +211,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("GLIBCXX_3.4.28");
       known_versions.push_back("GLIBCXX_3.4.29");
       known_versions.push_back("GLIBCXX_LDBL_3.4.29");
+      known_versions.push_back("GLIBCXX_IEEE128_3.4.29");
       known_versions.push_back("CXXABI_1.3");
       known_versions.push_back("CXXABI_LDBL_1.3");
       known_versions.push_back("CXXABI_1.3.1");
@@ -226,6 +227,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("CXXABI_1.3.11");
       known_versions.push_back("CXXABI_1.3.12");
       known_versions.push_back("CXXABI_1.3.13");
+      known_versions.push_back("CXXABI_IEEE128_1.3.13");
       known_versions.push_back("CXXABI_TM_1");
       known_versions.push_back("CXXABI_FLOAT128");
     }
@@ -244,9 +246,11 @@ check_version(symbol& test, bool added)
 
       // Check that added symbols are added in the latest pre-release version.
       bool latestp = (test.version_name == "GLIBCXX_3.4.29"
-	  // XXX remove next line when GLIBCXX_3.4.30 is added and baselines
-	  // have been regenerated to include GLIBCXX_LDBL_3.4.29 symbols:
+	  // XXX remove next 3 lines when baselines have been regenerated
+	  // to include {IEEE128,LDBL} symbols:
 		     || test.version_name == "GLIBCXX_LDBL_3.4.29"
+		     || test.version_name == "GLIBCXX_IEEE128_3.4.29"
+		     || test.version_name == "CXXABI_IEEE128_1.3.13"
 		     || test.version_name == "CXXABI_1.3.13"
 		     || test.version_name == "CXXABI_FLOAT128"
 		     || test.version_name == "CXXABI_TM_1");
@@ -260,7 +264,17 @@ check_version(symbol& test, bool added)
 	  && test.demangled_name.find("std::__cxx11::") != 0)
 	{
 	  if (test.version_name.find("_LDBL_") == std::string::npos
-	      && test.version_name.find("_FLOAT128") == std::string::npos)
+	      && test.version_name.find("_FLOAT128") == std::string::npos
+	      && test.version_name.find("_IEEE128") == std::string::npos)
+	    test.version_status = symbol::incompatible;
+	}
+
+      // Check that IEEE128 long double compatibility symbols demangled as
+      // __ieee128 are put into some _LDBL_IEEE version name.
+      // XXX is this right? might not want *everything* for __ieee128 in here.
+      if (added && test.demangled_name.find("__ieee128") != std::string::npos)
+	{
+	  if (test.version_name.find("_IEEE128") == std::string::npos)
 	    test.version_status = symbol::incompatible;
 	}
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 16:04     ` Jonathan Wakely
@ 2020-12-01 19:10       ` Michael Meissner
  2020-12-01 21:10         ` Jonathan Wakely
  2020-12-03 23:07       ` Tulio Magno Quites Machado Filho
  1 sibling, 1 reply; 19+ messages in thread
From: Michael Meissner @ 2020-12-01 19:10 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On Tue, Dec 01, 2020 at 04:04:30PM +0000, Jonathan Wakely wrote:
> On 01/12/20 15:10 +0000, Jonathan Wakely wrote:
> >On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
> >>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
> >>tried installing the patches on a master branch I checked out this morning, and
> >>I got two rejects:
> >
> >I don't understand why those chunks failed, but I'll rebase and send a
> >new patch ASAP.
> 
> Here's the rebased patch, with regenerated autoconf files and a fix
> for the <ext/numeric_limits.h> header. I'd changed it since sending
> the previous patch, and broke the "there's more than one long double"
> case (i.e. the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case).

Unfortunately this patch DOES NOT work at all.

If I build a compiler with the configure option:
	--with-long-double-format=ieee

And I compile this simple program:

	#include <iostream>

	int main(int argc, char *argv[], char *envp[])
	{
	  std::cout << "Hello World!\n";
	  return 0;
	}

I get all of these errors:

/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::money_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract<false>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, std::string&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::money_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert<true>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, std::string const&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract_int<unsigned long long>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, unsigned long long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract_int<long long>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, long long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::money_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract<true>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, std::string&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract_int<unsigned int>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, unsigned int&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract_int<unsigned long>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, unsigned long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<unsigned int>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, unsigned int&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::money_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract<false>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, std::string&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert_float<long double>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, char, long double) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<unsigned long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<long>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<long long>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, long long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert_float<double>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, char, double) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<unsigned short>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, unsigned short&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::money_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert<true>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert_int<unsigned long>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, unsigned long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract_int<unsigned short>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, unsigned short&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::money_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract<true>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, std::string&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_extract_int<long>(std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, std::_Ios_Iostate&, long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_float<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert_int<unsigned long long>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, unsigned long long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::money_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert<false>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, std::string const&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::money_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert<false>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_float<long double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, long double) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<unsigned long long>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, unsigned long long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<unsigned long>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, unsigned long&) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<unsigned long long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert_int<long>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, long) const'
/home3/meissner/fsf-install-ppc64le/binutils-gdb/bin/ld: /home/meissner/fsf-install-ppc64le/work029-kf/lib/../lib64/libstdc++.so: undefined reference to `std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::_M_insert_int<long long>(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, long long) const'
collect2: error: ld returned 1 exit status

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 19:10       ` Michael Meissner
@ 2020-12-01 21:10         ` Jonathan Wakely
  2020-12-01 21:41           ` Jonathan Wakely
                             ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-01 21:10 UTC (permalink / raw)
  To: Michael Meissner, Jonathan Wakely, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On Tue, 1 Dec 2020 at 19:13, Michael Meissner via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> On Tue, Dec 01, 2020 at 04:04:30PM +0000, Jonathan Wakely wrote:
> > On 01/12/20 15:10 +0000, Jonathan Wakely wrote:
> > >On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
> > >>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
> > >>tried installing the patches on a master branch I checked out this morning, and
> > >>I got two rejects:
> > >
> > >I don't understand why those chunks failed, but I'll rebase and send a
> > >new patch ASAP.
> >
> > Here's the rebased patch, with regenerated autoconf files and a fix
> > for the <ext/numeric_limits.h> header. I'd changed it since sending
> > the previous patch, and broke the "there's more than one long double"
> > case (i.e. the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case).
>
> Unfortunately this patch DOES NOT work at all.
>
> If I build a compiler with the configure option:
>         --with-long-double-format=ieee
>
> And I compile this simple program:
>
>         #include <iostream>
>
>         int main(int argc, char *argv[], char *envp[])
>         {
>           std::cout << "Hello World!\n";
>           return 0;
>         }
>
> I get all of these errors:

It works fine for me (see below). I think your symptoms are due to
using a glibc that doesn't support the new long double, and so
libstdc++ support for it is also disabled. You need at least glibc
2.32 for the libstdc++ changes to be enabled.

[test@ibm-p9b-30 build-ieee128]$ rpm -q glibc
glibc-2.32-2.fc33.ppc64le
[test@ibm-p9b-30 tmp]$ cat hello.C
#include <iostream>

int main(int argc, char *argv[], char *envp[])
{
  std::cout << "Hello World!\n";
  return 0;
}

[test@ibm-p9b-30 tmp]$ ~/gcc/ieee128/bin/g++ hello.C
-Wl,-rpath,$HOME/gcc/ieee128/lib64  -v
Using built-in specs.
COLLECT_GCC=/home/test/gcc/ieee128/bin/g++
COLLECT_LTO_WRAPPER=/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/lto-wrapper
Target: powerpc64le-unknown-linux-gnu
Configured with: ../gcc/configure --prefix=/home/test/gcc/ieee128/
--enable-libstdcxx-debug --disable-bootstrap --disable-multilib
--disable-libvtv --with-system-zlib --without-isl
--with-long-double-format=ieee --enable-languages=c,c++ :
(reconfigured) ../gcc/configure --prefix=/home/test/gcc/ieee128/
--enable-libstdcxx-debug --disable-bootstrap --disable-multilib
--disable-libvtv --with-system-zlib --without-isl
--with-long-double-format=ieee --enable-languages=c,c++ :
(reconfigured) ../gcc/configure --prefix=/home/test/gcc/ieee128/
--enable-libstdcxx-debug --disable-bootstrap --disable-multilib
--disable-libvtv --with-system-zlib --without-isl
--with-long-double-format=ieee --enable-languages=c,c++,lto
--no-create --no-recursion
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.0.0 20201201 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-dumpdir' 'a-'
/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/cc1plus
-quiet -v -D_GNU_SOURCE hello.C -quiet -dumpdir a- -dumpbase hello.C
-dumpbase-ext .C -version -o /tmp/cc1OWZTT.s
GNU C++17 (GCC) version 11.0.0 20201201 (experimental)
(powerpc64le-unknown-linux-gnu)
       compiled by GNU C version 10.2.1 20201016 (Red Hat 10.2.1-6),
GMP version 6.2.0, MPFR version 4.1.0, MPC version 1.1.0, isl version
none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
ignoring nonexistent directory
"/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../../powerpc64le-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../../include/c++/11.0.0
/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../../include/c++/11.0.0/powerpc64le-unknown-linux-gnu
/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../../include/c++/11.0.0/backward
/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/include
/usr/local/include
/home/test/gcc/ieee128/include
/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/include-fixed
/usr/include
End of search list.
GNU C++17 (GCC) version 11.0.0 20201201 (experimental)
(powerpc64le-unknown-linux-gnu)
       compiled by GNU C version 10.2.1 20201016 (Red Hat 10.2.1-6),
GMP version 6.2.0, MPFR version 4.1.0, MPC version 1.1.0, isl version
none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: 868967e3eb6523a59f0ddd7cc415f672
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-dumpdir' 'a-'
as -v -a64 -mpower8 -mlittle -o /tmp/ccpF549Q.o /tmp/cc1OWZTT.s
GNU assembler version 2.35 (ppc64le-redhat-linux) using BFD version
version 2.35-14.fc33
COMPILER_PATH=/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/:/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/:/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/:/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/:/home/test/gcc/ieee128
/lib/gcc/powerpc64le-unknown-linux-gnu/
LIBRARY_PATH=/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/:/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-dumpdir' 'a.'
/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/collect2
-plugin /home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/liblto_plugin.so
-plugin-opt=/home/test/gcc/ieee128/libexec/gcc/powerpc64le-unknown-linux-gnu/11.0.0/lto-wrapper
-plugin-opt=-fresolution=/tmp/cc69gZwR.res
-plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc
-plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s
-plugin-opt=-pass-through=-lgcc --eh-frame-hdr -V -m elf64lppc
-dynamic-linker /lib64/ld64.so.2 /lib/../lib64/crt1.o
/lib/../lib64/crti.o /home/test/gcc/ieee128/lib/gcc/powerpc64le-unkno
wn-linux-gnu/11.0.0/crtbegin.o
-L/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0
-L/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../../../lib64
-L/lib/../lib64 -L/usr/lib/../lib64
-L/home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/../../..
/tmp/ccpF549Q
.o -rpath /home/test/gcc/ieee128/lib64 -lstdc++ -lm -lgcc_s -lgcc -lc
-lgcc_s -lgcc /home/test/gcc/ieee128/lib/gcc/powerpc64le-unknown-linux-gnu/11.0.0/crtend.o
/lib/../lib64/crtn.o
GNU ld version 2.35-14.fc33
 Supported emulations:
  elf64lppc
  elf32lppc
  elf32lppclinux
  elf32lppcsim
  elf64ppc
  elf32ppc
  elf32ppclinux
  elf32ppcsim
  elf64bpf
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-dumpdir' 'a.'
[test@ibm-p9b-30 tmp]$ ldd a.out
       linux-vdso64.so.1 (0x00007fff8c890000)
       libstdc++.so.6 => /home/test/gcc/ieee128/lib64/libstdc++.so.6
(0x00007fff8c5b0000)
       libm.so.6 => /lib64/libm.so.6 (0x00007fff8c470000)
       libgcc_s.so.1 => /home/test/gcc/ieee128/lib64/libgcc_s.so.1
(0x00007fff8c430000)
       libc.so.6 => /lib64/libc.so.6 (0x00007fff8c210000)
       /lib64/ld64.so.2 (0x00007fff8c8b0000)
[test@ibm-p9b-30 tmp]$ ./a.out
Hello World!

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 21:10         ` Jonathan Wakely
@ 2020-12-01 21:41           ` Jonathan Wakely
       [not found]           ` <20201201222501.GA18971@ibm-toto.the-meissners.org>
  2020-12-01 23:32           ` Michael Meissner
  2 siblings, 0 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-01 21:41 UTC (permalink / raw)
  To: Michael Meissner, Jonathan Wakely, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On Tue, 1 Dec 2020 at 21:10, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>
> On Tue, 1 Dec 2020 at 19:13, Michael Meissner via Libstdc++
> <libstdc++@gcc.gnu.org> wrote:
> >
> > On Tue, Dec 01, 2020 at 04:04:30PM +0000, Jonathan Wakely wrote:
> > > On 01/12/20 15:10 +0000, Jonathan Wakely wrote:
> > > >On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
> > > >>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
> > > >>tried installing the patches on a master branch I checked out this morning, and
> > > >>I got two rejects:
> > > >
> > > >I don't understand why those chunks failed, but I'll rebase and send a
> > > >new patch ASAP.
> > >
> > > Here's the rebased patch, with regenerated autoconf files and a fix
> > > for the <ext/numeric_limits.h> header. I'd changed it since sending
> > > the previous patch, and broke the "there's more than one long double"
> > > case (i.e. the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case).
> >
> > Unfortunately this patch DOES NOT work at all.
> >
> > If I build a compiler with the configure option:
> >         --with-long-double-format=ieee
> >
> > And I compile this simple program:
> >
> >         #include <iostream>
> >
> >         int main(int argc, char *argv[], char *envp[])
> >         {
> >           std::cout << "Hello World!\n";
> >           return 0;
> >         }
> >
> > I get all of these errors:
>
> It works fine for me (see below). I think your symptoms are due to
> using a glibc that doesn't support the new long double, and so
> libstdc++ support for it is also disabled. You need at least glibc
> 2.32 for the libstdc++ changes to be enabled.

I should improve the failure mode (maybe refuse to compile anything
using the C++ library headers if __LONG_DOUBLE_IEEE128__ is defined
and __ieee128 support was disabled due to the missing glibc
dependency) but that hasn't been a priority. Making the C++ library
support __ieee128 on a machine that doesn't even have libc support for
it isn't possible, so I didn't spend time on that use case. It doesn't
work, and it's not going to work.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
       [not found]           ` <20201201222501.GA18971@ibm-toto.the-meissners.org>
@ 2020-12-01 22:36             ` Jonathan Wakely
  2020-12-01 23:24               ` Michael Meissner
  2020-12-02 15:14               ` Michael Meissner
  0 siblings, 2 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-01 22:36 UTC (permalink / raw)
  To: Michael Meissner, Jonathan Wakely, Jonathan Wakely, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

[-- Attachment #1: Type: text/plain, Size: 2694 bytes --]

On Tue, 1 Dec 2020 at 22:25, Michael Meissner <meissner@linux.ibm.com> wrote:
>
> On Tue, Dec 01, 2020 at 09:10:30PM +0000, Jonathan Wakely wrote:
> > On Tue, 1 Dec 2020 at 19:13, Michael Meissner via Libstdc++
> > <libstdc++@gcc.gnu.org> wrote:
> > >
> > > On Tue, Dec 01, 2020 at 04:04:30PM +0000, Jonathan Wakely wrote:
> > > > On 01/12/20 15:10 +0000, Jonathan Wakely wrote:
> > > > >On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
> > > > >>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
> > > > >>tried installing the patches on a master branch I checked out this morning, and
> > > > >>I got two rejects:
> > > > >
> > > > >I don't understand why those chunks failed, but I'll rebase and send a
> > > > >new patch ASAP.
> > > >
> > > > Here's the rebased patch, with regenerated autoconf files and a fix
> > > > for the <ext/numeric_limits.h> header. I'd changed it since sending
> > > > the previous patch, and broke the "there's more than one long double"
> > > > case (i.e. the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case).
> > >
> > > Unfortunately this patch DOES NOT work at all.
> > >
> > > If I build a compiler with the configure option:
> > >         --with-long-double-format=ieee
> > >
> > > And I compile this simple program:
> > >
> > >         #include <iostream>
> > >
> > >         int main(int argc, char *argv[], char *envp[])
> > >         {
> > >           std::cout << "Hello World!\n";
> > >           return 0;
> > >         }
> > >
> > > I get all of these errors:
> >
> > It works fine for me (see below). I think your symptoms are due to
> > using a glibc that doesn't support the new long double, and so
> > libstdc++ support for it is also disabled. You need at least glibc
> > 2.32 for the libstdc++ changes to be enabled.
>
> I am using the Advance Toolchain which includes GLIBC 2.32, which has the
> necessary support.  I will include the config.log as an attachment.

I see the problem. The patch I sent doesn't include the regenerated
files, as is normal for patches posted to the mailing lists.

You need to run autoconf-2.69's autoreconf in the libstdc++-v3 source
tree to regenerate configure, Makefile.in etc. Without doing that
you're just running the same configure script as is on current trunk,
and that doesn't even try looking for IEEE128 support in glibc, and so
the new code in libstdc++ doesn't get enabled.

I've attached a complete patch including those generated files, and
I've also pushed the branch to refs/users/redi/heads/ieee128-squash in
the gcc.gnu.org Git repo. That branch includes your patch for PR
libgcc/97543 which is required for some of the libstdc++ changes to
work properly.

[-- Attachment #2: patch.txt.bz2 --]
[-- Type: application/x-bzip, Size: 18137 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 22:36             ` Jonathan Wakely
@ 2020-12-01 23:24               ` Michael Meissner
  2020-12-02 15:14               ` Michael Meissner
  1 sibling, 0 replies; 19+ messages in thread
From: Michael Meissner @ 2020-12-01 23:24 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Michael Meissner, Jonathan Wakely, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On Tue, Dec 01, 2020 at 10:36:10PM +0000, Jonathan Wakely wrote:
> You need to run autoconf-2.69's autoreconf in the libstdc++-v3 source
> tree to regenerate configure, Makefile.in etc. Without doing that
> you're just running the same configure script as is on current trunk,
> and that doesn't even try looking for IEEE128 support in glibc, and so
> the new code in libstdc++ doesn't get enabled.
> 
> I've attached a complete patch including those generated files, and
> I've also pushed the branch to refs/users/redi/heads/ieee128-squash in
> the gcc.gnu.org Git repo. That branch includes your patch for PR
> libgcc/97543 which is required for some of the libstdc++ changes to
> work properly.

Sorry, I should have realized about needing to do autoconf.  Any way the new
patch builds the iostream version of hello world.  And it is going through the
rest of the build:

   1) Build 3 compilers with different long double formats;
   2) Build non-bootstrap compilers with the compilers in step 1;
   3) Build bootstrap compilers with the compilers in step 2;
   4) Build spec for the 2 128-bit long double types.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 21:10         ` Jonathan Wakely
  2020-12-01 21:41           ` Jonathan Wakely
       [not found]           ` <20201201222501.GA18971@ibm-toto.the-meissners.org>
@ 2020-12-01 23:32           ` Michael Meissner
  2 siblings, 0 replies; 19+ messages in thread
From: Michael Meissner @ 2020-12-01 23:32 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Michael Meissner, Jonathan Wakely, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

[-- Attachment #1: Type: text/plain, Size: 3117 bytes --]

Note this is just to keep the gcc-patches archive up to date.  I originally
posted this reply but the attached config.log file was too big.  It was also
sent directly to Jonathan, and he replied.  So I canceled the gcc-patches post,
and I'm sending out this one with a bzip2's config.log:

On Tue, Dec 01, 2020 at 09:10:30PM +0000, Jonathan Wakely wrote:
> On Tue, 1 Dec 2020 at 19:13, Michael Meissner via Libstdc++
> <libstdc++@gcc.gnu.org> wrote:
> >
> > On Tue, Dec 01, 2020 at 04:04:30PM +0000, Jonathan Wakely wrote:
> > > On 01/12/20 15:10 +0000, Jonathan Wakely wrote:
> > > >On 30/11/20 16:30 -0500, Michael Meissner via Libstdc++ wrote:
> > > >>Jonathan, could you send a fresh set of patches (or at least replacements)?  I
> > > >>tried installing the patches on a master branch I checked out this morning, and
> > > >>I got two rejects:
> > > >
> > > >I don't understand why those chunks failed, but I'll rebase and send a
> > > >new patch ASAP.
> > >
> > > Here's the rebased patch, with regenerated autoconf files and a fix
> > > for the <ext/numeric_limits.h> header. I'd changed it since sending
> > > the previous patch, and broke the "there's more than one long double"
> > > case (i.e. the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case).
> >
> > Unfortunately this patch DOES NOT work at all.
> >
> > If I build a compiler with the configure option:
> >         --with-long-double-format=ieee
> >
> > And I compile this simple program:
> >
> >         #include <iostream>
> >
> >         int main(int argc, char *argv[], char *envp[])
> >         {
> >           std::cout << "Hello World!\n";
> >           return 0;
> >         }
> >
> > I get all of these errors:
> 
> It works fine for me (see below). I think your symptoms are due to
> using a glibc that doesn't support the new long double, and so
> libstdc++ support for it is also disabled. You need at least glibc
> 2.32 for the libstdc++ changes to be enabled.

I am using the Advance Toolchain which includes GLIBC 2.32, which has the
necessary support.  I will include the config.log as an attachment.

Note, I am also using the patches I submitted around November 19th.

In particular, there is the patch that maps long double built-in names if long
double is IEEE 128-bit:
https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559659.html

I used the patch that tries to fix some problems with gnu attributes:
https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559657.html

I used the patch that fixes up the gnu attributes use in libgcc:
https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559660.html

I used the patch that adds float128 <-> Decimal conversions:
https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559661.html

I used the patch that allows -mabi={ieee,ibm}longdouble to override the default
configuration for long double == 64 bits, without having to use the
-mlong-double-64 option as well:
https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559660.html

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: libstdc++-v3-config.log.bz2 --]
[-- Type: application/x-bzip2, Size: 24642 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 22:36             ` Jonathan Wakely
  2020-12-01 23:24               ` Michael Meissner
@ 2020-12-02 15:14               ` Michael Meissner
  1 sibling, 0 replies; 19+ messages in thread
From: Michael Meissner @ 2020-12-02 15:14 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Michael Meissner, Jonathan Wakely, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On Tue, Dec 01, 2020 at 10:36:10PM +0000, Jonathan Wakely wrote:
> I've attached a complete patch including those generated files, and
> I've also pushed the branch to refs/users/redi/heads/ieee128-squash in
> the gcc.gnu.org Git repo. That branch includes your patch for PR
> libgcc/97543 which is required for some of the libstdc++ changes to
> work properly.

This patch along with my posted patches allows me to build the Spec 2017
parest_r benchmark with a PowerPC compiler configured for IEEE 128-bit long
doubles (that previously failed).  Thanks for the hard work!

In addition, I built a compiler where long double defaulted to 64-bit, and I
could build all of the Spec 2017 rate benchmarks.

I ran the two benchmarks that generate IEEE 128-bit instructions when long
double is IEEE 128-bit (perlbench_r and parest_r) on a little endian power9
running Linux with all different long double formats.  There was no difference
in runtime between the benchmark compiled for the different long double
formats.  I have to imagine that while the code is built using long double, the
actual benchmark does not use those functions in a significant way.

I did bootstrap builds for three different compilers configured to use each of
the long double formats.  There were no differences in the C++ tests between
the three compilers.

In the C tests, the two tests that test the nanq and nansq built-in functions
fail with IEEE 128-bit long double because I did not incorprate the patch for
that in this run.  There are 9 tests that fail with long double configured for
64-bits that I will look at adjusting in the future.

In the Fortran tests, there were three benchmarks that fail with IBM 128-bit
long double that now pass with IEEE 128-bit long double.  There is one test
that fails when long double is 64-bits.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-01 16:04     ` Jonathan Wakely
  2020-12-01 19:10       ` Michael Meissner
@ 2020-12-03 23:07       ` Tulio Magno Quites Machado Filho
  2020-12-04  0:35         ` Jonathan Wakely
  1 sibling, 1 reply; 19+ messages in thread
From: Tulio Magno Quites Machado Filho @ 2020-12-03 23:07 UTC (permalink / raw)
  To: Jonathan Wakely, Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org> writes:

> diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
> index cbfdf4c6bad..d25842fef35 100644
> --- a/libstdc++-v3/configure.ac
> +++ b/libstdc++-v3/configure.ac
> @@ -421,12 +425,43 @@ case "$target" in
>      port_specific_symbol_files="\$(top_srcdir)/config/os/gnu-linux/ldbl-extra.ver"
>      case "$target" in
>        powerpc*-*-linux*)
> -	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute" ;;
> +	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute"
> +        # Check for IEEE128 support in libm:
> +        AC_CHECK_LIB(m, frexpf128,

I suggest to replace frexpf128 with __frexpieee128.

The former is available on a glibc that support _Float128 (since glibc 2.26).
The later is available on a glibc that supports binary128 long double (since
glibc 2.32)

Without this modification, the build fails on glibc between 2.26 and 2.31.

I'm also running a couple of tests here.
I believe this is showing a couple of glitches in glibc which I'm already
investigating.

Thanks!

-- 
Tulio Magno

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-03 23:07       ` Tulio Magno Quites Machado Filho
@ 2020-12-04  0:35         ` Jonathan Wakely
  2020-12-10 16:14           ` Jonathan Wakely
  0 siblings, 1 reply; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-04  0:35 UTC (permalink / raw)
  To: Tulio Magno Quites Machado Filho
  Cc: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Berner

On 03/12/20 20:07 -0300, Tulio Magno Quites Machado Filho via Libstdc++ wrote:
>Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org> writes:
>
>> diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
>> index cbfdf4c6bad..d25842fef35 100644
>> --- a/libstdc++-v3/configure.ac
>> +++ b/libstdc++-v3/configure.ac
>> @@ -421,12 +425,43 @@ case "$target" in
>>      port_specific_symbol_files="\$(top_srcdir)/config/os/gnu-linux/ldbl-extra.ver"
>>      case "$target" in
>>        powerpc*-*-linux*)
>> -	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute" ;;
>> +	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute"
>> +        # Check for IEEE128 support in libm:
>> +        AC_CHECK_LIB(m, frexpf128,
>
>I suggest to replace frexpf128 with __frexpieee128.
>
>The former is available on a glibc that support _Float128 (since glibc 2.26).
>The later is available on a glibc that supports binary128 long double (since
>glibc 2.32)

Hmm, yes, you pointed me to __frexpieee128 a few months ago, but for
some reason I either didn't switch to using it, or lost a patch when
squashing and rebasing branches. Hopefully I just forgot to change it,
but I'll double check to make sure I haven't left any work on an old
branch. Thanks for suggesting it (again!)

>Without this modification, the build fails on glibc between 2.26 and 2.31.
>
>I'm also running a couple of tests here.
>I believe this is showing a couple of glitches in glibc which I'm already
>investigating.
>
>Thanks!
>
>-- 
>Tulio Magno
>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-04  0:35         ` Jonathan Wakely
@ 2020-12-10 16:14           ` Jonathan Wakely
  2020-12-10 17:14             ` Peter Bergner
  2020-12-15  0:57             ` Tulio Magno Quites Machado Filho
  0 siblings, 2 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-10 16:14 UTC (permalink / raw)
  To: Tulio Magno Quites Machado Filho
  Cc: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Bergner

On 04/12/20 00:35 +0000, Jonathan Wakely wrote:
>On 03/12/20 20:07 -0300, Tulio Magno Quites Machado Filho via Libstdc++ wrote:
>>Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org> writes:
>>
>>>diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
>>>index cbfdf4c6bad..d25842fef35 100644
>>>--- a/libstdc++-v3/configure.ac
>>>+++ b/libstdc++-v3/configure.ac
>>>@@ -421,12 +425,43 @@ case "$target" in
>>>     port_specific_symbol_files="\$(top_srcdir)/config/os/gnu-linux/ldbl-extra.ver"
>>>     case "$target" in
>>>       powerpc*-*-linux*)
>>>-	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute" ;;
>>>+	LONG_DOUBLE_COMPAT_FLAGS="$LONG_DOUBLE_COMPAT_FLAGS -mno-gnu-attribute"
>>>+        # Check for IEEE128 support in libm:
>>>+        AC_CHECK_LIB(m, frexpf128,
>>
>>I suggest to replace frexpf128 with __frexpieee128.
>>
>>The former is available on a glibc that support _Float128 (since glibc 2.26).
>>The later is available on a glibc that supports binary128 long double (since
>>glibc 2.32)
>
>Hmm, yes, you pointed me to __frexpieee128 a few months ago, but for
>some reason I either didn't switch to using it, or lost a patch when
>squashing and rebasing branches. Hopefully I just forgot to change it,
>but I'll double check to make sure I haven't left any work on an old
>branch. Thanks for suggesting it (again!)

As expected, it still works with a check for __frexpieee128 instead.

So are you happy for me to push this to master with that change?

(It won't be until Tuesday now, as I have some time off).



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-10 16:14           ` Jonathan Wakely
@ 2020-12-10 17:14             ` Peter Bergner
  2020-12-10 17:27               ` Jonathan Wakely
  2020-12-15  0:57             ` Tulio Magno Quites Machado Filho
  1 sibling, 1 reply; 19+ messages in thread
From: Peter Bergner @ 2020-12-10 17:14 UTC (permalink / raw)
  To: Jonathan Wakely, Tulio Magno Quites Machado Filho
  Cc: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool

On 12/10/20 10:14 AM, Jonathan Wakely wrote:
> On 04/12/20 00:35 +0000, Jonathan Wakely wrote:
>> On 03/12/20 20:07 -0300, Tulio Magno Quites Machado Filho via Libstdc++ wrote:
>>> I suggest to replace frexpf128 with __frexpieee128.
>>>
>>> The former is available on a glibc that support _Float128 (since glibc 2.26).
>>> The later is available on a glibc that supports binary128 long double (since
>>> glibc 2.32)
>>
>> Hmm, yes, you pointed me to __frexpieee128 a few months ago, but for
>> some reason I either didn't switch to using it, or lost a patch when
>> squashing and rebasing branches. Hopefully I just forgot to change it,
>> but I'll double check to make sure I haven't left any work on an old
>> branch. Thanks for suggesting it (again!)
> 
> As expected, it still works with a check for __frexpieee128 instead.
> 
> So are you happy for me to push this to master with that change?
> 
> (It won't be until Tuesday now, as I have some time off).

FYI, Tulio is on vacation through December 22nd and I'm not sure how
closely he is watching his email, if at all.  Given Tulio mentioned
the change in the first place, I think he's ok with the change.
He can beat me later if I'm wrong! :-)

Peter



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-10 17:14             ` Peter Bergner
@ 2020-12-10 17:27               ` Jonathan Wakely
  0 siblings, 0 replies; 19+ messages in thread
From: Jonathan Wakely @ 2020-12-10 17:27 UTC (permalink / raw)
  To: Peter Bergner
  Cc: Tulio Magno Quites Machado Filho, Michael Meissner,
	Segher Boessenkool, libstdc++,
	Bill Schmidt, gcc-patches, David Edelsohn

On 10/12/20 11:14 -0600, Peter Bergner via Libstdc++ wrote:
>On 12/10/20 10:14 AM, Jonathan Wakely wrote:
>> On 04/12/20 00:35 +0000, Jonathan Wakely wrote:
>>> On 03/12/20 20:07 -0300, Tulio Magno Quites Machado Filho via Libstdc++ wrote:
>>>> I suggest to replace frexpf128 with __frexpieee128.
>>>>
>>>> The former is available on a glibc that support _Float128 (since glibc 2.26).
>>>> The later is available on a glibc that supports binary128 long double (since
>>>> glibc 2.32)
>>>
>>> Hmm, yes, you pointed me to __frexpieee128 a few months ago, but for
>>> some reason I either didn't switch to using it, or lost a patch when
>>> squashing and rebasing branches. Hopefully I just forgot to change it,
>>> but I'll double check to make sure I haven't left any work on an old
>>> branch. Thanks for suggesting it (again!)
>>
>> As expected, it still works with a check for __frexpieee128 instead.
>>
>> So are you happy for me to push this to master with that change?
>>
>> (It won't be until Tuesday now, as I have some time off).
>
>FYI, Tulio is on vacation through December 22nd and I'm not sure how
>closely he is watching his email, if at all.  Given Tulio mentioned
>the change in the first place, I think he's ok with the change.
>He can beat me later if I'm wrong! :-)

The question was more about pushing the entire patch for ieee128
support, which isn't on master yet.

Do we want this done now for gcc 11? It adds a ton of new symbols to
libstdc++.so which would be a pain to remove again if we decide it's
not ready.

Currently the new features will be enabled by default if the support
is detected in the compiler and glibc. Do we want to gate it behind a
new --enable-something-something option? (I'm assuming not).


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format
  2020-12-10 16:14           ` Jonathan Wakely
  2020-12-10 17:14             ` Peter Bergner
@ 2020-12-15  0:57             ` Tulio Magno Quites Machado Filho
  1 sibling, 0 replies; 19+ messages in thread
From: Tulio Magno Quites Machado Filho @ 2020-12-15  0:57 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Michael Meissner, libstdc++,
	gcc-patches, Bill Schmidt, David Edelsohn, Segher Boessenkool,
	Peter Bergner

Jonathan Wakely <jwakely@redhat.com> writes:

>>Hmm, yes, you pointed me to __frexpieee128 a few months ago, but for
>>some reason I either didn't switch to using it, or lost a patch when
>>squashing and rebasing branches. Hopefully I just forgot to change it,
>>but I'll double check to make sure I haven't left any work on an old
>>branch. Thanks for suggesting it (again!)
>
> As expected, it still works with a check for __frexpieee128 instead.
>
> So are you happy for me to push this to master with that change?

LGTM.
I have no objections.

Thank you!

-- 
Tulio Magno

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2020-12-15  0:57 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-11 21:50 [PATCH] libstdc++: Add C++ runtime support for new 128-bit long double format Jonathan Wakely
2020-11-30 21:30 ` Michael Meissner
2020-12-01 15:10   ` Jonathan Wakely
2020-12-01 16:04     ` Jonathan Wakely
2020-12-01 19:10       ` Michael Meissner
2020-12-01 21:10         ` Jonathan Wakely
2020-12-01 21:41           ` Jonathan Wakely
     [not found]           ` <20201201222501.GA18971@ibm-toto.the-meissners.org>
2020-12-01 22:36             ` Jonathan Wakely
2020-12-01 23:24               ` Michael Meissner
2020-12-02 15:14               ` Michael Meissner
2020-12-01 23:32           ` Michael Meissner
2020-12-03 23:07       ` Tulio Magno Quites Machado Filho
2020-12-04  0:35         ` Jonathan Wakely
2020-12-10 16:14           ` Jonathan Wakely
2020-12-10 17:14             ` Peter Bergner
2020-12-10 17:27               ` Jonathan Wakely
2020-12-15  0:57             ` Tulio Magno Quites Machado Filho
2020-11-30 23:29 ` Segher Boessenkool
2020-12-01 15:04   ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).