+2018-10-24 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (TARGET_MANGLE_DECL_ASSEMBLER_NAME):
+ Define as rs6000_mangle_decl_assembler_name.
+ (rs6000_mangle_decl_assembler_name): If the user switched from IBM
+ long double to IEEE long double, switch the names of the long
+ double built-in functions to be <func>f128 instead of <func>l.
+
2018-10-24 Martin Sebor <msebor@redhat.com>
* doc/extend.texi (nonnull): List no-argument form. Reference
#undef TARGET_SETJMP_PRESERVES_NONVOLATILE_REGS_P
#define TARGET_SETJMP_PRESERVES_NONVOLATILE_REGS_P hook_bool_void_true
+
+#undef TARGET_MANGLE_DECL_ASSEMBLER_NAME
+#define TARGET_MANGLE_DECL_ASSEMBLER_NAME rs6000_mangle_decl_assembler_name
\f
/* Processor table. */
}
#endif
+\f
+/* On 64-bit Linux and Freebsd systems, possibly switch the long double library
+ function names from <foo>l to <foo>f128 if the default long double type is
+ IEEE 128-bit. Typically, with the C and C++ languages, the standard math.h
+ include file switches the names on systems that support long double as IEEE
+ 128-bit, but that doesn't work if the user uses __builtin_<foo>l directly.
+ In the future, glibc will export names like __ieee128_sinf128 and we can
+ switch to using those instead of using sinf128, which pollutes the user's
+ namespace.
+
+ This will switch the names for Fortran math functions as well (which doesn't
+ use math.h). However, Fortran needs other changes to the compiler and
+ library before you can switch the real*16 type at compile time.
+
+ We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name. We
+ only do this if the default is that long double is IBM extended double, and
+ the user asked for IEEE 128-bit. */
+
+static tree
+rs6000_mangle_decl_assembler_name (tree decl, tree id)
+{
+ if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
+ && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl) )
+ {
+ size_t len = IDENTIFIER_LENGTH (id);
+ const char *name = IDENTIFIER_POINTER (id);
+
+ if (name[len - 1] == 'l')
+ {
+ bool uses_ieee128_p = false;
+ tree type = TREE_TYPE (decl);
+ machine_mode ret_mode = TYPE_MODE (type);
+
+ /* See if the function returns a IEEE 128-bit floating point type or
+ complex type. */
+ if (ret_mode == TFmode || ret_mode == TCmode)
+ uses_ieee128_p = true;
+ else
+ {
+ function_args_iterator args_iter;
+ tree arg;
+
+ /* See if the function passes a IEEE 128-bit floating point type
+ or complex type. */
+ FOREACH_FUNCTION_ARGS (type, arg, args_iter)
+ {
+ machine_mode arg_mode = TYPE_MODE (arg);
+ if (arg_mode == TFmode || arg_mode == TCmode)
+ {
+ uses_ieee128_p = true;
+ break;
+ }
+ }
+ }
+
+ /* If we passed or returned an IEEE 128-bit floating point type,
+ change the name. */
+ if (uses_ieee128_p)
+ {
+ char *name2 = (char *) alloca (len + 4);
+ memcpy (name2, name, len - 1);
+ strcpy (name2 + len - 1, "f128");
+ id = get_identifier (name2);
+ }
+ }
+ }
+
+ return id;
+}
+
\f
struct gcc_target targetm = TARGET_INITIALIZER;
--- /dev/null
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mvsx -O2 -mfloat128 -mabi=ieeelongdouble -Wno-psabi" } */
+
+/* Test whether we convert __builtin_<math>l to __builtin_<math>f128 if the
+ default long double type is IEEE 128-bit. Also test that using the explicit
+ __builtin_<math>f128 function does not interfere with the __builtin_<math>l
+ function. */
+
+extern __float128 sinf128 (__float128);
+
+void foo (__float128 *p, long double *q, long double *r)
+{
+ *p = sinf128 (*p);
+ *q = __builtin_sinl (*q);
+}
+
+/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mbl sinl\M} } } */
--- /dev/null
+! { dg-do compile { target { powerpc*-*-linux* } } }
+! { dg-require-effective-target ppc_float128_sw }
+! { dg-require-effective-target vsx_hw }
+! { dg-options "-mvsx -mabi=ieeelongdouble -mfloat128" }
+! { dg-excess-errors "expect error due to switching long double type" }
+! Since the error message is not associated with a particular line
+! number, we cannot use the dg-error directive and cannot specify a
+! regexp to describe the expected error message. The expected warning
+! message is:
+! "Warning: Using IEEE extended precision long double [-Wpsabi]"
+
+program test_qp
+ implicit none
+ real(16), volatile :: fp1, fp2;
+ fp1 = 2.0
+ fp2 = log (fp1)
+end
+
+! { dg-final { scan-assembler-not {\mbl logl\M} } }
+! { dg-final { scan-assembler {\mbl logf128\M} } }