Bug 104172 - [9/10 Regression] ppc64le mangling ICE with -flto -ffat-lto-objects
Summary: [9/10 Regression] ppc64le mangling ICE with -flto -ffat-lto-objects
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 12.0
: P2 normal
Target Milestone: 11.3
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code, wrong-code
Depends on:
Blocks:
 
Reported: 2022-01-21 21:26 UTC by Jakub Jelinek
Modified: 2022-01-28 11:51 UTC (History)
14 users (show)

See Also:
Host:
Target: powerpc64le
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-01-21 00:00:00


Attachments
gcc12-pr104172.patch (2.98 KB, patch)
2022-01-24 11:57 UTC, Jakub Jelinek
Details | Diff
gcc12-pr104172.patch (2.05 KB, patch)
2022-01-24 18:36 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2022-01-21 21:26:57 UTC
// { dg-do compile { target { powerpc*-*-* && lp64 && le } } }
// { dg-options "-O2 -flto=auto -ffat-lto-objects -mabi=ieeelongdouble" }

struct A { A(int); };
struct B { float b; };
struct C : B { C(); };
C::C() { A(b * 25.4L); }

ICEs
PagePrinter.C: In member function 'C::C()':
PagePrinter.C:7:1: internal compiler error: tree check: expected class 'type', have 'declaration' (translation_unit_decl) in base_ctor_omit_inherited_parms, at cp/method.c:568
    7 | C::C() { A(b * 25.4L); }
      | ^
0x101fbd8b tree_class_check_failed(tree_node const*, tree_code_class, char const*, int, char const*)
	../../gcc/tree.c:8752
0x104073bf tree_class_check(tree_node*, tree_code_class, char const*, int, char const*)
	../../gcc/tree.h:3564
0x104073bf base_ctor_omit_inherited_parms(tree_node*)
	../../gcc/cp/method.c:568
0x104073bf base_ctor_omit_inherited_parms(tree_node*)
	../../gcc/cp/method.c:560
0x103eda0b write_method_parms
	../../gcc/cp/mangle.c:2798
0x103edd73 write_bare_function_type
	../../gcc/cp/mangle.c:2758
0x103edecf write_encoding
	../../gcc/cp/mangle.c:832
0x103eec7f mangle_decl_string
	../../gcc/cp/mangle.c:4034
0x103ef003 get_mangled_id
	../../gcc/cp/mangle.c:4055
0x103ef003 mangle_decl(tree_node*)
	../../gcc/cp/mangle.c:4093
0x1142297f rs6000_globalize_decl_name
	../../gcc/config/rs6000/rs6000.c:28190
0x113d8c43 globalize_decl
	../../gcc/varasm.c:6146
0x113e112b assemble_start_function(tree_node*, char const*)
	../../gcc/varasm.c:1965
0x10a01a8f rest_of_handle_final
	../../gcc/final.c:4281
0x10a01a8f execute
	../../gcc/final.c:4363
(for GCC configured to default to --with-long-double-format=ieee that is a pretty serious regression breaking lots of builds).

The bug is in:
/* Create an alias for a mangled name where we have changed the mangling (in
   GCC 8.1, we used U10__float128, and now we use u9__ieee128).  This is called
   via the target hook TARGET_ASM_GLOBALIZE_DECL_NAME.  */

#if TARGET_ELF && RS6000_WEAK
static void
rs6000_globalize_decl_name (FILE * stream, tree decl)
{
  const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);

  targetm.asm_out.globalize_label (stream, name);
  
  if (rs6000_passes_ieee128 && name[0] == '_' && name[1] == 'Z')
    {
      tree save_asm_name = DECL_ASSEMBLER_NAME (decl);
      const char *old_name;

      ieee128_mangling_gcc_8_1 = true;
      lang_hooks.set_decl_assembler_name (decl);
      old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
      SET_DECL_ASSEMBLER_NAME (decl, save_asm_name);
      ieee128_mangling_gcc_8_1 = false;

      if (strcmp (name, old_name) != 0)
        {
          fprintf (stream, "\t.weak %s\n", old_name);
          fprintf (stream, "\t.set %s,%s\n", old_name, name);
        }
    }
}
#endif

This is just wrong, mangling is only possible before free_lang_data, not after that, everything should be mangled by then.
So, IMHO the backend should note that during mangling that it emitted some u9__ieee128 (when rs6000_mangle_type returns it)
and through some hook should cooperate with the C++ FE to create a mangling alias like the FE creates mangling aliases for -fabi-version*.
Comment 1 Jakub Jelinek 2022-01-21 21:30:05 UTC
Wonder what it does in lto1 (e.g. without -ffat-lto-objects) if adapted such that it actually links.  Because lto1 certainly doesn't have the C++ mangler, so it must be emitting something really weird in that case.
Comment 2 Jakub Jelinek 2022-01-21 21:31:25 UTC
Was -mabi=ieeelongdouble support even remotely usable in GCC 8 (do we really need to care about compatibility with it)?
Comment 3 Jakub Jelinek 2022-01-21 21:33:31 UTC
E.g. I think all the libstdc++ work is only in GCC 11, so yes, one could use C++, but couldn't use the standard C++ library in GCC 8.
Comment 4 Marek Polacek 2022-01-21 21:45:45 UTC
Confirmed.
Comment 5 Bill Schmidt 2022-01-21 22:00:39 UTC
(In reply to Jakub Jelinek from comment #3)
> E.g. I think all the libstdc++ work is only in GCC 11, so yes, one could use
> C++, but couldn't use the standard C++ library in GCC 8.

Yes, that's true.
Comment 6 Jakub Jelinek 2022-01-22 10:39:23 UTC
From my side, I think best would be just to partially revert
r9-1033-gc765c8cb73b0bb91e9f0401ab6567b6218b910e5
(all the rs6000_passes_ieee128 and ieee128_mangling_gcc_8_1 related stuff in there, don't set those and when testing assume false).
Rationale, -mabi=ieeelongdouble has been an undocumented unsupported option before GCC 8, it is true it was "supported" option in 8.1, but still far from being fully usable both because of the missing libstdc++ support and important bugfixes.  And in 8.2 the ABI we have now has been backported -
r8-8265-gd8f96ab114a977d9 .  So, we are taking a lot of pain for compatibility with something that likely nobody used, glibc support wasn't there until the 2.32 release done after 8.2 was released.

If not and we do want the pain, then all the mangling has to be done before free_lang_data (so can't be driven by rs6000_passes_ieee128 which is RTL-ish time, but on whether u9__ieee128 has been emitted into the mangled name), ideally through a target hook in mangle_decl where it also does the
          record_mangling (decl, G.need_abi_warning);

          if (!G.need_abi_warning)
            return;
  
          flag_abi_version = flag_abi_compat_version;
          id2 = mangle_decl_string (decl);
          id2 = targetm.mangle_decl_assembler_name (decl, id2);
          flag_abi_version = save_ver;
  
          if (id2 != id)
            note_mangling_alias (decl, id2);
stuff (perhaps right before that if (!G.need_abi_warning) spot).

Note, some Fedora packages fail with weirdo errors like:
{standard input}: Assembler messages:
{standard input}:43720: Error: junk at end of line, first unrecognized character is `['
{standard input}:43721: Error: expected comma after "operator"
{standard input}:45644: Error: junk at end of line, first unrecognized character is `.'
{standard input}:45645: Error: expected comma after "__ct_base"
{standard input}:46051: Error: junk at end of line, first unrecognized character is `.'
{standard input}:46052: Error: expected comma after "__ct_base"
{standard input}:46794: Error: junk at end of line, first unrecognized character is `.'
{standard input}:46795: Error: expected comma after "__ct_base"
{standard input}:48803: Error: junk at end of line, first unrecognized character is `='
{standard input}:48804: Error: expected comma after "operator"
{standard input}:49232: Error: junk at end of line, first unrecognized character is `.'
{standard input}:49233: Error: expected comma after "__ct_base"
and I strongly believe it is the same thing, lto1 and the identifier being mangled in a weirdo way.
Comment 7 Orion Poplawski 2022-01-22 22:37:37 UTC
I believe this is causing the ccache compile failure in Fedora rawhide: https://koji.fedoraproject.org/koji/buildinfo?buildID=1881086
Comment 8 Richard Biener 2022-01-24 08:59:54 UTC
lto1 sees pre-mangled symbols
Comment 9 Jakub Jelinek 2022-01-24 09:02:58 UTC
That is what it should do.  But it also has a mangling langhook and the backend uses it in the hope that it is a C++ FE langhook that will mangle the names like they were previously except with the s/u9__ieee128/U10__float128/g changes, but it of course doesn't do that.
Comment 10 Jakub Jelinek 2022-01-24 11:57:03 UTC
Created attachment 52276 [details]
gcc12-pr104172.patch

Untested patch to do the mangling aliases inside of the C++ FE.
My preference is still to remove that 8.1 compatibility support, this is just
in case Michael and the IBM backend maintainers strongly prefer to keep it.
If we keep it, an open question is about the other C++ FE mangling aliases,
shall we also do these backend specific mangling aliases on top of those -fabi-compat-version= compatibility aliases?
Comment 11 Jakub Jelinek 2022-01-24 18:36:57 UTC
Created attachment 52279 [details]
gcc12-pr104172.patch

Variant patch that just removes the GCC 8.1 compatibility mangling aliases.
Comment 12 Jason Merrill 2022-01-24 23:13:53 UTC
I'm persuaded by your argument that we don't need to care about compatibility with the 8.1 handling of these types, which weren't yet really usable, so we can go with the simpler patch.  But I'd like to hear from IBM.
Comment 13 Bill Schmidt 2022-01-24 23:17:32 UTC
We discussed this with Jakub today, and we concur.
Comment 14 Segher Boessenkool 2022-01-25 00:16:22 UTC
I already approved the patch.
Comment 15 GCC Commits 2022-01-25 04:49:52 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:f4ee27d3262fc4fc3e5d3535f195fdcf87d7ec77

commit r12-6853-gf4ee27d3262fc4fc3e5d3535f195fdcf87d7ec77
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Jan 25 05:49:05 2022 +0100

    rs6000: Remove GCC 8.1 U10__float128 mangling compatibility [PR104172]
    
    In GCC 7.x and earlier, while it had -mabi=ieeelongdouble option, that option
    was undocumented and unsupported.
    In GCC 8.1 that option got documented and -mabi=ieeelongdouble long double started
    to be mangled as U10__float128.
    In GCC 9 and backported to before 8.2 release, that mangling changed to
    u9__ieee128 and a support for emitting compatibility mangling aliases have
    been added.
    Unfortunately, as mentioned in the PR, those don't really work well in many
    cases, the free_lang_data pass throws away important trees, so e.g. with
    -flto -ffat-lto-objects the compiler often ICEs on templates that involve
    IEEE quad long double arguments etc. because the mangling was done too late
    (at final time).
    Furthermore, lto1's mangler is not the C++ mangler, so with -flto it would
    often emit as "mangled identifiers" something that wasn't a valid assembler
    identifier, e.g. operator+ etc.
    While it is possible to do such mangling earlier, e.g. at the same time when
    the C++ FE emits its mangling aliases and untested proof of concept is in
    the PR, there seems to be agreement that we shouldn't bother with this
    ABI compatibility with something that probably nobody really used.
    GCC 8.2 already uses the new mangling, it was just a few months, but more
    importantly, libstdc++ support for IEEE quad long double on
    powerpc64le-linux was only added in GCC 11, and glibc support for that some
    weeks after 8.2 got released.
    
    So, the following patch just drops those aliases.
    
    2022-01-25  Jakub Jelinek  <jakub@redhat.com>
    
            PR target/104172
    gcc/
            * config/rs6000/rs6000-internal.h (rs6000_passes_ieee128): Don't
            declare.
            * config/rs6000/rs6000.cc (rs6000_passes_ieee128,
            ieee128_mangling_gcc_8_1): Remove.
            (TARGET_ASM_GLOBALIZE_DECL_NAME): Don't redefine.
            (rs6000_mangle_type): Return "u9__ieee128" instead of
            ieee128_mangling_gcc_8_1 ? "U10__float128" : "u9__ieee128".
            (rs6000_globalize_decl_name): Remove.
            * config/rs6000/rs6000-call.cc (init_cumulative_args,
            rs6000_function_arg_advance_1): Don't set rs6000_passes_ieee128.
Comment 16 GCC Commits 2022-01-25 13:57:30 UTC
The releases/gcc-11 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:79b0091b13eb7dce0294407d9bd78750df10180d

commit r11-9510-g79b0091b13eb7dce0294407d9bd78750df10180d
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Jan 25 05:49:05 2022 +0100

    rs6000: Remove GCC 8.1 U10__float128 mangling compatibility [PR104172]
    
    In GCC 7.x and earlier, while it had -mabi=ieeelongdouble option, that option
    was undocumented and unsupported.
    In GCC 8.1 that option got documented and -mabi=ieeelongdouble long double started
    to be mangled as U10__float128.
    In GCC 9 and backported to before 8.2 release, that mangling changed to
    u9__ieee128 and a support for emitting compatibility mangling aliases have
    been added.
    Unfortunately, as mentioned in the PR, those don't really work well in many
    cases, the free_lang_data pass throws away important trees, so e.g. with
    -flto -ffat-lto-objects the compiler often ICEs on templates that involve
    IEEE quad long double arguments etc. because the mangling was done too late
    (at final time).
    Furthermore, lto1's mangler is not the C++ mangler, so with -flto it would
    often emit as "mangled identifiers" something that wasn't a valid assembler
    identifier, e.g. operator+ etc.
    While it is possible to do such mangling earlier, e.g. at the same time when
    the C++ FE emits its mangling aliases and untested proof of concept is in
    the PR, there seems to be agreement that we shouldn't bother with this
    ABI compatibility with something that probably nobody really used.
    GCC 8.2 already uses the new mangling, it was just a few months, but more
    importantly, libstdc++ support for IEEE quad long double on
    powerpc64le-linux was only added in GCC 11, and glibc support for that some
    weeks after 8.2 got released.
    
    So, the following patch just drops those aliases.
    
    2022-01-25  Jakub Jelinek  <jakub@redhat.com>
    
            PR target/104172
    gcc/
            * config/rs6000/rs6000-internal.h (rs6000_passes_ieee128): Don't
            declare.
            * config/rs6000/rs6000.c (rs6000_passes_ieee128,
            ieee128_mangling_gcc_8_1): Remove.
            (TARGET_ASM_GLOBALIZE_DECL_NAME): Don't redefine.
            (rs6000_mangle_type): Return "u9__ieee128" instead of
            ieee128_mangling_gcc_8_1 ? "U10__float128" : "u9__ieee128".
            (rs6000_globalize_decl_name): Remove.
            * config/rs6000/rs6000-call.c (init_cumulative_args,
            rs6000_function_arg_advance_1): Don't set rs6000_passes_ieee128.
    
    (cherry picked from commit f4ee27d3262fc4fc3e5d3535f195fdcf87d7ec77)
Comment 17 Jakub Jelinek 2022-01-28 11:51:38 UTC
Fixed for 11.3/trunk, not going to backport further.