re PR target/85657 (Make __ibm128 a separate type, even if long double uses the IBM...
authorMichael Meissner <meissner@linux.ibm.com>
Wed, 6 Jun 2018 21:11:15 +0000 (21:11 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Wed, 6 Jun 2018 21:11:15 +0000 (21:11 +0000)
[gcc]
2018-06-06  Michael Meissner  <meissner@linux.ibm.com>

* config/rs6000/rs6000.c (rs6000_passes_ieee128): New boolean to
track if we pass or return IEEE 128-bit floating point.
(ieee128_mangling_gcc_8_1): New boolean to say whether to generate
C++ mangling that is compatible with GCC 8.1.
(TARGET_ASM_GLOBALIZE_DECL_NAME): Override target hook.
(init_cumulative_args): Note if we pass or return IEEE 128-bit
floating point types.
(rs6000_function_arg_advance_1): Likewise.
(rs6000_mangle_type): Optionally generate mangled names that match
what GCC 8.1 generated for IEEE 128-bit floating point types.
(rs6000_globalize_decl_name): If we have an external function that
passes or returns IEEE 128-bit types, generate a weak reference
from the mangled name used in GCC 8.1 to the current mangled
name.

[gcc]
2018-06-05  Michael Meissner  <meissner@linux.ibm.com>

* config/rs6000/rs6000.c (rs6000_init_builtins): Make __ibm128 use
the long double type if long double is IBM extended double.  Make
__float128 use the long double type if long double is IEEE 128-bit.

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

PR target/85657
* g++.dg/pr85657.C: Only test whether __ibm128 and long double can
be used in templates.  Don't check for them in overloaded functions.

From-SVN: r261246

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr85657.C

index bf56e891c77174b0c85024746014e02c4e1bc6e9..f82ccb3d6e85e39e2c277754983b5e24baaec186 100644 (file)
@@ -1,3 +1,23 @@
+2018-06-05  Michael Meissner  <meissner@linux.ibm.com>
+
+       * config/rs6000/rs6000.c (rs6000_passes_ieee128): New boolean to
+       track if we pass or return IEEE 128-bit floating point.
+       (ieee128_mangling_gcc_8_1): New boolean to say whether to generate
+       C++ mangling that is compatible with GCC 8.1.
+       (TARGET_ASM_GLOBALIZE_DECL_NAME): Override target hook.
+       (init_cumulative_args): Note if we pass or return IEEE 128-bit
+       floating point types.
+       (rs6000_function_arg_advance_1): Likewise.
+       (rs6000_mangle_type): Optionally generate mangled names that match
+       what GCC 8.1 generated for IEEE 128-bit floating point types.
+       (rs6000_globalize_decl_name): If we have an external function that
+       passes or returns IEEE 128-bit types, generate a weak reference
+       from the mangled name used in GCC 8.1 to the current mangled
+       name.
+       (rs6000_init_builtins): Make __ibm128 use the long double type if
+       long double is IBM extended double.  Make __float128 use the long
+       double type if long double is IEEE 128-bit.
+
 2018-06-06  Jim Wilson  <jimw@sifive.com>
 
        * config/riscv/riscv.c (enum riscv_privilege_levels): New.
index c5c9821aeb0c2001a621d0b91d2f15beac01e280..bbee6cbc1e3e0f2ad0438ddc79cbe0d420001860 100644 (file)
@@ -200,6 +200,17 @@ 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 of the old mangling (U10__float128) to the
+   new mangling (u9__ieee128).  */
+static bool rs6000_passes_ieee128;
+
+/* Generate the manged name (i.e. U10__float128) used in GCC 8.1, and not the
+   name used in current releases (i.e. u9__ieee128).  */
+static bool ieee128_mangling_gcc_8_1;
+
 /* Width in bits of a pointer.  */
 unsigned rs6000_pointer_size;
 
@@ -1973,6 +1984,11 @@ static const struct attribute_spec rs6000_attribute_table[] =
 
 #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
 \f
 
 /* Processor table.  */
@@ -11108,6 +11124,12 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
                          && (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 (FLOAT128_IEEE_P (return_mode))
+               rs6000_passes_ieee128 = true;
            }
          if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode))
            rs6000_passes_vector = true;
@@ -11559,6 +11581,12 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode,
                  || (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 (FLOAT128_IEEE_P (mode))
+           rs6000_passes_ieee128 = true;
        }
       if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
        rs6000_passes_vector = true;
@@ -16355,14 +16383,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 +32152,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 ieee128_mangling_gcc_8_1 ? "U10__float128" : "u9__ieee128";
 
   /* For all other types, use the default mangling.  */
   return NULL;
@@ -38726,6 +38761,40 @@ rs6000_starting_frame_offset (void)
     return 0;
   return RS6000_STARTING_FRAME_OFFSET;
 }
+\f
+
+/* 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
+
 \f
 struct gcc_target targetm = TARGET_INITIALIZER;
 
index aa24adfbbd6054f20eb812dc3698146fc011ec0a..04d7628e8ed0b88b6d166464ef115f456d4bb15d 100644 (file)
@@ -1,3 +1,9 @@
+2018-06-06  Michael Meissner  <meissner@linux.ibm.com>
+
+       PR target/85657
+       * g++.dg/pr85657.C: Only test whether __ibm128 and long double can
+       be used in templates.  Don't check for them in overloaded functions.
+
 2018-06-06  Jim Wilson  <jimw@sifive.com>
 
        * gcc.target/riscv/interrupt-5.c (sub3): Add new test.
index 6b81bc2284fdf65c5ad85550decbcadae8c5b07c..e62b62abcc5a10f230f361c633c1109e6e665bf0 100644 (file)
@@ -3,8 +3,8 @@
 // { dg-options "-mvsx -mfloat128 -O2 -mabi=ibmlongdouble -Wno-psabi" }
 
 // PR 85657
-// Check that __ibm128 and long double are represented as different types, even
-// if long double is currently using the same representation as __ibm128.
+// Check that __ibm128 and long double can be used in the same template,
+// even if long double uses the IBM extended double representation.
 
 template <class __T> inline bool
 iszero (__T __val)
@@ -18,30 +18,7 @@ use_template (void)
   long double ld = 0.0;
   __ibm128 ibm = 0.0;
 
-#ifdef _ARCH_PWR7
   __asm__ (" # %x0, %x1" : "+d" (ld), "+d" (ibm));
-#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);
-}