The new mangling scheme for PowerPC now uses "u9__ieee128" as the mangled name
instead of "U10__float128".  This would break old code that used __float128 and
called to libraries built with the new compiler.

This patch adds a hook to emit a weak reference for the old mangled name when
we are creating the new mangled name with a different spelling.  I added an
undocumented switch (-malias-old-name-mangling) to not create the weak
reference if it is a problem.

This patch also makes __ibm128 or __float128 use the long double mode if long
double uses the IBM extended double or IEEE 128-bit representations.  This
allows templates to work again with those types (the template code aborts if
you have two distinct types use the same mangling).  However, overloaded types
won't work, but I suspect these days people use templates over overloaded
functions.  I fixed up the test case for this (pr85657.C) so that it only tests
for templates.

I have tested it on a little endian power8 system and there were no
regressions.  It does fix the error in pr85657.C that was due to the previous
name mangling changes.  Can I check this into the trunk?  We will need to
backport the name mangling changes and these patches back to GCC 8.2 as well.

I will need to re-issue the patch for __builtin_{,un}pack_longdouble and
__builtin_{,un}pack_ibm128 due to changes made by these patches.

[gcc]
2018-06-01  Michael Meissner  <meiss...@linux.ibm.com>

        * config/rs6000/rs6000.c (rs6000_passes_ieee128): New static
        boolean to remember if we passed or returned IEEE 128-bit values.
        (old_mangling): New static boolean to say whether to use the old
        mangling strings for IEEE 128-bit floating point or the new
        mangling.
        (TARGET_ASM_GLOBALIZE_DECL_NAME): Define target hook.
        (rs6000_debug_reg_global): Print whether we support creating weak
        references for the old mangling name.
        (rs6000_option_override_internal): Add support for
        -malias-old-name-mangling.
        (init_cumulative_args): Note if we ever have passed or returned
        IEEE 128-bit floating point.
        (rs6000_function_arg_advance_1): Likewise.
        (rs6000_init_builtins): If long double is IBM extended double,
        make __int128 use the TFmode type.  If long double is IEEE 128-bit
        floating point, make __float128 use the TFmode type.
        (rs6000_mangle_type): Return either the old mangling or new
        mangling string for IEEE 128-bit floating point types.
        (rs6000_globalize_decl_name): If we are putting out a .globl for a
        C++ mangled name that contains an IEEE 128-bit floating point
        value, put out a weak reference for the old name if it was
        different.
        * config/rs6000/rs6000.opt (-malias-old-name-mangling): Add
        undocumented switch to control whether weak references are put out
        for the old mangled name if the mangling changed.

[gcc/testsuite]
2018-06-01  Michael Meissner  <meiss...@linux.ibm.com>

        * g++.dg/pr85657.C: Update test, only test whether templates can
        be used on all 3 128-bit floating point types.

-- 
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
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 261078)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -200,6 +200,15 @@ int dot_symbols;
    of this machine mode.  */
 scalar_int_mode rs6000_pmode;
 
+/* Note whether IEEE 128-bit floating point was passed or returned, either as
+   the __float128/_Float128 explicit type, or when long double is IEEE 128-bit
+   floating point.  We changed the default C++ mangling for these types and we
+   may want to generate a weak alias to the old mangling.  */
+static bool rs6000_passes_ieee128;
+
+/* Generate old manged name, not new name.  */
+static bool old_mangling;
+
 /* Width in bits of a pointer.  */
 unsigned rs6000_pointer_size;
 
@@ -1973,6 +1982,11 @@ static const struct attribute_spec rs600
 
 #undef TARGET_STARTING_FRAME_OFFSET
 #define TARGET_STARTING_FRAME_OFFSET rs6000_starting_frame_offset
+
+#if TARGET_ELF && RS6000_WEAK
+#undef TARGET_ASM_GLOBALIZE_DECL_NAME
+#define TARGET_ASM_GLOBALIZE_DECL_NAME rs6000_globalize_decl_name
+#endif
 
 
 /* Processor table.  */
@@ -2835,6 +2849,9 @@ rs6000_debug_reg_global (void)
 
   fprintf (stderr, DEBUG_FMT_S, "abi", abi_str);
 
+  if (TARGET_OLD_NAME_MANGLING)
+    fprintf (stderr, DEBUG_FMT_S, "old name mangling", "true");
+
   if (rs6000_altivec_abi)
     fprintf (stderr, DEBUG_FMT_S, "altivec_abi", "true");
 
@@ -4635,6 +4652,16 @@ rs6000_option_override_internal (bool gl
       rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
     }
 
+  /* Enable making an alias by default to map old mangled names to the new
+     names on systems that support float128.  */
+  if (TARGET_OLD_NAME_MANGLING && !TARGET_FLOAT128_TYPE)
+    {
+      if (TARGET_OLD_NAME_MANGLING < 0)
+       TARGET_OLD_NAME_MANGLING = 0;
+      else
+       error ("%qs needs %qs", "-malias-old-name-mangling", "-mfloat128");
+    }
+
   /* Print the options after updating the defaults.  */
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
@@ -11108,6 +11135,12 @@ init_cumulative_args (CUMULATIVE_ARGS *c
                          && (TYPE_MAIN_VARIANT (return_type)
                              == long_double_type_node))))
                rs6000_passes_long_double = true;
+
+             /* Note if we passed or return a IEEE 128-bit type.  We changed
+                the mangling for these types, and we may need to make an alias
+                with the old mangling.  */
+             if (TARGET_OLD_NAME_MANGLING && FLOAT128_IEEE_P (return_mode))
+               rs6000_passes_ieee128 = true;
            }
          if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode))
            rs6000_passes_vector = true;
@@ -11559,6 +11592,12 @@ rs6000_function_arg_advance_1 (CUMULATIV
                  || (type != NULL
                      && TYPE_MAIN_VARIANT (type) == long_double_type_node)))
            rs6000_passes_long_double = true;
+
+         /* Note if we passed or return a IEEE 128-bit type.  We changed the
+            mangling for these types, and we may need to make an alias with
+            the old mangling.  */
+         if (TARGET_OLD_NAME_MANGLING && FLOAT128_IEEE_P (mode))
+           rs6000_passes_ieee128 = true;
        }
       if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
        rs6000_passes_vector = true;
@@ -16355,14 +16394,21 @@ rs6000_init_builtins (void)
      __ieee128.  */
   if (TARGET_FLOAT128_TYPE)
     {
-      ibm128_float_type_node = make_node (REAL_TYPE);
-      TYPE_PRECISION (ibm128_float_type_node) = 128;
-      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
-      layout_type (ibm128_float_type_node);
+      if (TARGET_IEEEQUAD || !TARGET_LONG_DOUBLE_128)
+       {
+         ibm128_float_type_node = make_node (REAL_TYPE);
+         TYPE_PRECISION (ibm128_float_type_node) = 128;
+         SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+         layout_type (ibm128_float_type_node);
+       }
+      else
+       ibm128_float_type_node = long_double_type_node;
+
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
                                              "__ibm128");
 
-      ieee128_float_type_node = float128_type_node;
+      ieee128_float_type_node
+       = TARGET_IEEEQUAD ? long_double_type_node : float128_type_node;
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
                                              "__ieee128");
     }
@@ -32117,7 +32163,7 @@ rs6000_mangle_type (const_tree type)
   if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IBM_P (TYPE_MODE (type)))
     return "g";
   if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IEEE_P (TYPE_MODE (type)))
-    return "u9__ieee128";
+    return old_mangling ? "U10__float128" : "u9__ieee128";
 
   /* For all other types, use the default mangling.  */
   return NULL;
@@ -38727,6 +38773,41 @@ rs6000_starting_frame_offset (void)
   return RS6000_STARTING_FRAME_OFFSET;
 }
 
+
+/* Implement -malias-old-name-mangling to create an alias for a mangled name
+   where we have changed the mangling.  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 (TARGET_OLD_NAME_MANGLING && rs6000_passes_ieee128
+      && name[0] == '_' && name[1] == 'Z')
+    {
+      tree save_asm_name = DECL_ASSEMBLER_NAME (decl);
+      const char *old_name;
+
+      old_mangling = true;
+      lang_hooks.set_decl_assembler_name (decl);
+      old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+      SET_DECL_ASSEMBLER_NAME (decl, save_asm_name);
+      old_mangling = 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
+
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-rs6000.h"
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt        (revision 261078)
+++ gcc/config/rs6000/rs6000.opt        (working copy)
@@ -574,3 +574,8 @@ long rs6000_stack_protector_guard_offset
 ;; branches via the CTR.
 mspeculate-indirect-jumps
 Target Undocumented Var(rs6000_speculate_indirect_jumps) Init(1) Save
+
+;; -malias-old-name-mangling: implement an alias to map old C++ mangled names
+;; to the new version of the name
+malias-old-name-mangling
+Target Undocumented Var(TARGET_OLD_NAME_MANGLING) Init(-1) Save
Index: gcc/testsuite/g++.dg/pr85657.C
===================================================================
--- gcc/testsuite/g++.dg/pr85657.C      (revision 261078)
+++ gcc/testsuite/g++.dg/pr85657.C      (working copy)
@@ -13,35 +13,17 @@ iszero (__T __val)
 }
 
 int
-use_template (void)
+use_template (long double *p_ld,
+             __ibm128 *p_ibm128,
+             __float128 *p_flt128)
 {
-  long double ld = 0.0;
-  __ibm128 ibm = 0.0;
+  long double ld = *p_ld;
+  __ibm128 ibm = *p_ibm128;
+  __float128 flt = *p_flt128;
 
 #ifdef _ARCH_PWR7
-  __asm__ (" # %x0, %x1" : "+d" (ld), "+d" (ibm));
+  __asm__ (" # %x0, %x1, %x2" : "+d" (ld), "+d" (ibm), "+wa" (flt));
 #endif
 
-  return iszero (ld) + iszero (ibm);
-}
-
-class foo {
-public:
-  foo () {}
-  ~foo () {}
-  inline bool iszero (long double ld) { return ld == 0.0; }
-  inline bool iszero (__ibm128 i128) { return i128 == 0.0; }
-} st;
-
-int
-use_class (void)
-{
-  long double ld = 0.0;
-  __ibm128 ibm = 0.0;
-
-#ifdef _ARCH_PWR7
-  __asm__ (" # %x0, %x1" : "+d" (ld), "+d" (ibm));
-#endif
-
-  return st.iszero (ld) + st.iszero (ibm);
+  return iszero (ld) + iszero (ibm) + iszero (flt);
 }

Reply via email to