On Wed, Sep 09, 2020 at 02:42:36PM +0100, Jonathan Wakely wrote:
> Sorry for the slow reply to this.
> 
> On Fri, 7 Aug 2020 at 22:14, Michael Meissner <meiss...@linux.ibm.com> wrote:
> >
> > One issue with doing the transition is what mangling should be used with the
> > new long double.
> >
> > At the moment, the current mangling is:
> >         long double     "g"
> >         __float128      "u9__ieee128"
> >         __ibm128        "g"
> >
> > Obviously this will have to change in the future.  It is unfortunate that we
> > choose "g" to mean IBM extended double many many years ago, when it should 
> > have
> > been used for IEEE 128-bit floating point.  But that is long ago, so I 
> > think we
> > need to keep it.
> >
> > But assuming we want compatibility with libraries like glibc and libstdc++, 
> > I
> > think we will have to continue to use "g" for __ibm128.
> >
> > With the long double change, I tend to view this as an ABI change.  But if 
> > the
> > user doesn't use long double, they should be able to link without changes.
> >
> > I would propose using a new mangling for IEEE 128-bit long double.  I would
> > prefer to get agreement on what the new mangling should be so we don't have 
> > an
> > issue like we had in GCC 8.1 going to GCC 8.2, where we changed the 
> > mangling,
> > and had to provide aliases for the old name.
> >
> > At the moment I think the mangling should be:
> >         long double     "g"                     if long double is IBM
> >         long double     "u12_ieee128_ld"        if long double is IEEE
> >         __float128      "u9__ieee128"
> >         __ibm128        "g"
> 
> What's the benefit of having __float128 and IEEE long double be
> distinct types? That complicates things for libraries like libstdc++.
> If we want to support using "__float128" with C++ iostreams then we
> need yet another set of I/O routines, even though it's identical to
> one of the types we already handle. Why not just keep __float128 and
> __ieee128 and "long double when long double is IEEE" as three
> different aliases for the same type, so that C++ code like
> _Z4funcu9__ieee128 works for all of them, instead of needing to also
> define _Z4funcu12__ieee128_ld?

The Boost library has methods that have both long double and __float128 in it.
My main concern is not to break user code like Boost that the users may added
__float128.  Obviously with glibc and libstdc++ we have people who understand
the issues, but who knows what other libraries people have come up with.

So if we configure long double to be IEEE 128-bit, under the current code it
would be an error.  Consider this silly code.  Yes it likely would be a
template, but the issue is if the user mixes __float128 and long double, is it
an error if long double has the same representation as IEEE 128-bit:

        class foo {
        public:
          double add (double a, double b) { return a+b; }
          long double add (long double a, long double b) { return a+b; }
          __float128 add (__float128 a, __float128 b) { return a+b; }
        };

        foo x;

        __float128
        bletch_f128 (__float128 a, __float128 b)
        {
          return x.add (a, b);
        }

        long double
        bletch_ld (long double a, long double b)
        {
          return x.add (a, b);
        }

If we compile this with the current compiler, it compiles fine if long double
uses the IBM extended double.

But if we compile it with -Wno-psabi -mabi=ieeelongdouble, we get:

        In file included from foo-class.cpp:1:
        foo-class.h:5:14: error: ‘long double foo::add(long double, long 
double)’ cannot be overloaded with ‘long double foo::add(long double, long 
double)’
            5 |   __float128 add (__float128 a, __float128 b) { return a+b; }
              |              ^~~
        foo-class.h:4:15: note: previous declaration ‘long double foo::add(long 
double, long double)’
            4 |   long double add (long double a, long double b) { return a+b; }
              |               ^~~

Because right now the compiler only has two types, whatever long double is, and
whatever is not long double.  You have the same issue right now with __ibm128
and the current long double, but I'm not convinced anybody outside of glibc and
libstdc++ really uses it.

Since people do use __float128, since the x86_64 port supports it, it is an
issue.

If you use the -mlong-double-128 option on the X86_64 compiler, you get an
error, though in this case it is a more cryptic error message (compiler used
was a 10.2 compiler):

        foo-class.cpp:15:1: error: Two symbols with same comdat_group are not 
linked by the same_comdat_group list.
           15 | }
              | ^
        _ZN3foo3addEgg/2 (__float128 foo::add(__float128, __float128)) 
@0x7f0068b922d0
          Type: function definition analyzed
          Visibility: public weak comdat comdat_group:_ZN3foo3addEgg one_only
          previous sharing asm name: 1
          References: 
          Referring: 
          Function flags: body
          Called by: _Z7bletch1gg/4 
          Calls: 
        _ZN3foo3addEgg/1 (long double foo::add(long double, long double)) 
@0x7f0068b92168
          Type: function definition analyzed
          Visibility: public weak comdat comdat_group:_ZN3foo3addEgg one_only
          next sharing asm name: 2
          References: 
          Referring: 
          Function flags: body
          Called by: _Z7bletch2gg/5 
          Calls: 
        foo-class.cpp:15:1: internal compiler error: symtab_node::verify failed
        0xb9f9d9 symtab_node::verify_symtab_nodes()
                /home/meissner/fsf-src/gcc-10.2.0/gcc/symtab.c:1354
        0xbb2444 symtab_node::checking_verify_symtab_nodes()
                /home/meissner/fsf-src/gcc-10.2.0/gcc/cgraph.h:667
        0xbb2444 symbol_table::compile()
                /home/meissner/fsf-src/gcc-10.2.0/gcc/cgraphunit.c:2738
        0xbb450c symbol_table::compile()
                /home/meissner/fsf-src/gcc-10.2.0/gcc/cgraphunit.c:2735
        0xbb450c symbol_table::finalize_compilation_unit()
                /home/meissner/fsf-src/gcc-10.2.0/gcc/cgraphunit.


> What about the "__ieee128" type, would that be mangled as
> "u12_ieee128_ld" or "u9__ieee128"?

Please use __float128 and not __ieee128 in public code.  The user visible
keyword is __float128, not __ieee128.

Internally within the compiler, the real keyword is __ieee128, and there is a
macro '__float128'.  This uglyness was needed in previous compilers to allow
disabling __float128 as a public keyword, but to allow the libraries to still
use it (due to Boost's usage of __float128).


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

Reply via email to