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 <[email protected]> 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: [email protected], phone: +1 (978) 899-4797