[PATCH] Add C++ runtime support for new 128-bit long double format

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Add C++ runtime support for new 128-bit long double format

Jonathan Wakely-3
This adds support for the new 128-bit long double format on powerpc64,
see https://fedoraproject.org/wiki/Changes/PPC64LE_Float128_Transition
for more details.

Most of the required changes are to the locale facets that parse and
print long doubles, as used by iostreams for reading/writing numbers.

I followed the same design as is used for the existing
-mlong-double-64 compatibility, i.e. adding extra virtual functions to
the facet classes so that they are capable of handling the old and new
formats, using different virtual functions. For example, std::num_get
only handles 64-bit long double, and has only the virtual functions
described by the standard. For floating point types these are the
following:

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, float& v ) const;

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, double& v ) const;

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, long double& v ) const;


The __gnu_cxx_ldbl128::num_get class has an extra virtual function:

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, float& v ) const;

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, double& v ) const;

// Handles 64-bit long double, which has the same representation as
// double:
iter_type __do_get( iter_type in, iter_type end, std::ios_base& str,
                    std::ios_base::iostate& err, double& v ) const;

// Handles 128-bit long double:
iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, long double& v ) const;


The __gnu_cxx_ieee128::num_get class added by this patch has another
extra virtual function:

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, float& v ) const;

iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, double& v ) const;

// Handles 64-bit long double, which has the same representation as
// double:
iter_type __do_get( iter_type in, iter_type end, std::ios_base& str,
                    std::ios_base::iostate& err, double& v ) const;

// Handles old IBM 128-bit long double:
iter_type __do_get( iter_type in, iter_type end, std::ios_base& str,
                    std::ios_base::iostate& err, __ibm128& v ) const;

// Handles new IEEE 128-bit long double:
iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                  std::ios_base::iostate& err, long double& v ) const;

However, I'm not really sure if we want to do this. I don't understand
the purpose of having a new facet type that has virtual functions for
handling alternative long double formats. The facet can never be used
because std::use_facet<std::num_get> will resolve to std::num_get when
-mlong-double-64 is used, and that facet isn't installed in any
locales by default (only __gnu_cxx_ldbl128::num_get is).

Maybe I should not have bothered to copy this technique this for the
new long double formats. I'm not sure.

Currently this patch causes a few regressions, due to the facets for
the IBM 128-bit long double format no longer being installed in the
locales. That means that 100% conforming behaviour is only possible
for the new IEEE 128-bit long double. I'm not sure what the migration
plan is for that type, and whether both formats need to work
equivalently. That would require installing both the
__gnu_cxx_ldbl128::num_get and __gnu_cxx_ieee128::num_get facets (and
similarly for num_put, money_get and money_put).

So this patch probably isn't in its final form, but I'm posting it now
to make the stage 1 deadline, and will complete it ASAP.

        * config.h.in: Regenerate.
        * config/abi/pre/gnu.ver: Make patterns less greedy. Add CXXABI_1.3.12
        symbol version.
        * 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.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.



patch.txt (84K) Download Attachment