[RS6000] .gnu.attributes Tag_GNU_Power_ABI_FP

Extend this attribute to cover long double ABIs, for 64-bit too.

This patch also corrects an error that crept in to code setting
rs6000_passes_float.  See the added comment.  Passing IEEE128 values
in vsx regs ought to set both Tag_GNU_Power_ABI_FP and
Tag_GNU_Power_ABI_Vector.  Also adds a new option, default on, that
disables output of .gnu_attribute assembly directives.

	* config/rs6000/sysv4.opt (mgnu-attribute): New option.
	* doc/invoke.texi: Document it.
	* config/rs6000/rs6000.c (HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE): Define.
	(rs6000_passes_float): Comment.
	(rs6000_passes_long_double): New static var.
	(call_ABI_of_interest): Return false unless rs6000_gnu_attr is set.
	(init_cumulative_args): Set up to emit fp .gnu_attribute for
	ELF 64-bit ABIs as well as 32-bit ELF.  Correct rs6000_passes_float
	to include fp values returned in vectors.
	Set rs6000_passes_long_double.
	(rs6000_function_arg_advance_1): Likewise for function args.
	(rs6000_elf_file_end): Emit fp .gnu_attribute for ELF 64-bit ABIs,
	and SPE.  Emit long double tag value too.
	(rs6000_opt_vars): Add gnu-attr.
	* configure.ac (HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE): New ppc32 test.
	* configure: Regenerate.
	* config.in: Regenerate.

From-SVN: r240601
This commit is contained in:
Alan Modra 2016-09-29 07:31:48 +09:30 committed by Alan Modra
parent 91eaca5e32
commit e9dda04f07
7 changed files with 203 additions and 20 deletions

View file

@ -1,3 +1,23 @@
2016-09-29 Alan Modra <amodra@gmail.com>
* config/rs6000/sysv4.opt (mgnu-attribute): New option.
* doc/invoke.texi: Document it.
* config/rs6000/rs6000.c (HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE): Define.
(rs6000_passes_float): Comment.
(rs6000_passes_long_double): New static var.
(call_ABI_of_interest): Return false unless rs6000_gnu_attr is set.
(init_cumulative_args): Set up to emit fp .gnu_attribute for
ELF 64-bit ABIs as well as 32-bit ELF. Correct rs6000_passes_float
to include fp values returned in vectors.
Set rs6000_passes_long_double.
(rs6000_function_arg_advance_1): Likewise for function args.
(rs6000_elf_file_end): Emit fp .gnu_attribute for ELF 64-bit ABIs,
and SPE. Emit long double tag value too.
(rs6000_opt_vars): Add gnu-attr.
* configure.ac (HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE): New ppc32 test.
* configure: Regenerate.
* config.in: Regenerate.
2016-09-28 Jakub Jelinek <jakub@redhat.com>
* gimple-ssa-sprintf.c (pass_sprintf_length::gate): Use x > 0 instead

View file

@ -1538,6 +1538,12 @@
#endif
/* Define if your PowerPC linker has .gnu.attributes long double support. */
#ifndef USED_FOR_TARGET
#undef HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE
#endif
/* Define if your linker supports --push-state/--pop-state */
#ifndef USED_FOR_TARGET
#undef HAVE_LD_PUSHPOPSTATE_SUPPORT

View file

@ -183,8 +183,16 @@ unsigned rs6000_pmode;
unsigned rs6000_pointer_size;
#ifdef HAVE_AS_GNU_ATTRIBUTE
/* Flag whether floating point values have been passed/returned. */
# ifndef HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE
# define HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE 0
# endif
/* Flag whether floating point values have been passed/returned.
Note that this doesn't say whether fprs are used, since the
Tag_GNU_Power_ABI_FP .gnu.attributes value this flag controls
should be set for soft-float values passed in gprs and ieee128
values passed in vsx registers. */
static bool rs6000_passes_float;
static bool rs6000_passes_long_double;
/* Flag whether vector values have been passed/returned. */
static bool rs6000_passes_vector;
/* Flag whether small (<= 8 byte) structures have been returned. */
@ -10920,7 +10928,7 @@ rs6000_return_in_msb (const_tree valtype)
static bool
call_ABI_of_interest (tree fndecl)
{
if (symtab->state == EXPANSION)
if (rs6000_gnu_attr && symtab->state == EXPANSION)
{
struct cgraph_node *c_node;
@ -10997,7 +11005,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
}
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (DEFAULT_ABI == ABI_V4)
if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4))
{
cum->escapes = call_ABI_of_interest (fndecl);
if (cum->escapes)
@ -11025,10 +11033,19 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
<= 8))
rs6000_returns_struct = true;
}
if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (return_mode))
rs6000_passes_float = true;
else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
|| SPE_VECTOR_MODE (return_mode))
if (SCALAR_FLOAT_MODE_P (return_mode))
{
rs6000_passes_float = true;
if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT)
&& (FLOAT128_IBM_P (return_mode)
|| FLOAT128_IEEE_P (return_mode)
|| (return_type != NULL
&& (TYPE_MAIN_VARIANT (return_type)
== long_double_type_node))))
rs6000_passes_long_double = true;
}
if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
|| SPE_VECTOR_MODE (return_mode))
rs6000_passes_vector = true;
}
}
@ -11475,16 +11492,23 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode,
cum->nargs_prototype--;
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (DEFAULT_ABI == ABI_V4
if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4)
&& cum->escapes)
{
if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode))
rs6000_passes_float = true;
else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
rs6000_passes_vector = true;
else if (SPE_VECTOR_MODE (mode)
&& !cum->stdarg
&& cum->sysv_gregno <= GP_ARG_MAX_REG)
if (SCALAR_FLOAT_MODE_P (mode))
{
rs6000_passes_float = true;
if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT)
&& (FLOAT128_IBM_P (mode)
|| FLOAT128_IEEE_P (mode)
|| (type != NULL
&& TYPE_MAIN_VARIANT (type) == long_double_type_node)))
rs6000_passes_long_double = true;
}
if ((named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
|| (SPE_VECTOR_MODE (mode)
&& !cum->stdarg
&& cum->sysv_gregno <= GP_ARG_MAX_REG))
rs6000_passes_vector = true;
}
#endif
@ -34292,13 +34316,33 @@ static void
rs6000_elf_file_end (void)
{
#ifdef HAVE_AS_GNU_ATTRIBUTE
/* ??? The value emitted depends on options active at file end.
Assume anyone using #pragma or attributes that might change
options knows what they are doing. */
if ((TARGET_64BIT || DEFAULT_ABI == ABI_V4)
&& rs6000_passes_float)
{
int fp;
if (TARGET_DF_FPR | TARGET_DF_SPE)
fp = 1;
else if (TARGET_SF_FPR | TARGET_SF_SPE)
fp = 3;
else
fp = 2;
if (rs6000_passes_long_double)
{
if (!TARGET_LONG_DOUBLE_128)
fp |= 2 * 4;
else if (TARGET_IEEEQUAD)
fp |= 3 * 4;
else
fp |= 1 * 4;
}
fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n", fp);
}
if (TARGET_32BIT && DEFAULT_ABI == ABI_V4)
{
if (rs6000_passes_float)
fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n",
((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT) ? 1
: (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT) ? 3
: 2));
if (rs6000_passes_vector)
fprintf (asm_out_file, "\t.gnu_attribute 8, %d\n",
(TARGET_ALTIVEC_ABI ? 2
@ -37085,6 +37129,9 @@ static struct rs6000_opt_var const rs6000_opt_vars[] =
{ "warn-cell-microcode",
offsetof (struct gcc_options, x_rs6000_warn_cell_microcode),
offsetof (struct cl_target_option, x_rs6000_warn_cell_microcode), },
{ "gnu-attr",
offsetof (struct gcc_options, x_rs6000_gnu_attr),
offsetof (struct cl_target_option, x_rs6000_gnu_attr), },
};
/* Inner function to handle attribute((target("..."))) and #pragma GCC target

View file

@ -155,3 +155,7 @@ Generate code to use a non-exec PLT and GOT.
mbss-plt
Target Report RejectNegative Var(secure_plt, 0) Save
Generate code for old exec BSS PLT.
mgnu-attribute
Target Report Var(rs6000_gnu_attr) Init(1) Save
Emit .gnu_attribute tags.

52
gcc/configure vendored
View file

@ -28322,6 +28322,58 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_clearcap" >&5
$as_echo "$gcc_cv_ld_clearcap" >&6; }
case "$target" in
powerpc*-*-*)
case "$target" in
*le-*-linux*)
emul_name="-melf32lppc"
;;
*)
emul_name="-melf32ppc"
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker .gnu.attributes long double support" >&5
$as_echo_n "checking linker .gnu.attributes long double support... " >&6; }
if test "${gcc_cv_ld_ppc_attr+set}" = set; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_ld_ppc_attr=no
if test x"$ld_is_gold" = xyes; then
gcc_cv_ld_ppc_attr=yes
elif test $in_tree_ld = yes ; then
if test "$gcc_cv_gld_major_version" -eq 2 \
-a "$gcc_cv_gld_minor_version" -ge 28 \
-o "$gcc_cv_gld_major_version" -gt 2; then
gcc_cv_ld_ppc_attr=yes
fi
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
# check that merging the long double .gnu_attribute doesn't warn
cat > conftest1.s <<EOF
.gnu_attribute 4,1
EOF
cat > conftest2.s <<EOF
.gnu_attribute 4,9
EOF
if $gcc_cv_as -a32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
&& $gcc_cv_as -a32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
&& $gcc_cv_ld $emul_name -r -o conftest.o conftest1.o conftest2.o > /dev/null 2> conftest.err \
&& test ! -s conftest.err; then
gcc_cv_ld_ppc_attr=yes
fi
rm -f conftest.err conftest.o conftest1.o conftest2.o conftest1.s conftest2.s
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_ppc_attr" >&5
$as_echo "$gcc_cv_ld_ppc_attr" >&6; }
if test x$gcc_cv_ld_ppc_attr = xyes; then
$as_echo "#define HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE 1" >>confdefs.h
fi
;;
esac
case "$target:$tm_file" in
powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in

View file

@ -5322,6 +5322,51 @@ if test "x$gcc_cv_ld_clearcap" = xyes; then
fi
AC_MSG_RESULT($gcc_cv_ld_clearcap)
case "$target" in
powerpc*-*-*)
case "$target" in
*le-*-linux*)
emul_name="-melf32lppc"
;;
*)
emul_name="-melf32ppc"
;;
esac
AC_CACHE_CHECK(linker .gnu.attributes long double support,
gcc_cv_ld_ppc_attr,
[gcc_cv_ld_ppc_attr=no
if test x"$ld_is_gold" = xyes; then
gcc_cv_ld_ppc_attr=yes
elif test $in_tree_ld = yes ; then
if test "$gcc_cv_gld_major_version" -eq 2 \
-a "$gcc_cv_gld_minor_version" -ge 28 \
-o "$gcc_cv_gld_major_version" -gt 2; then
gcc_cv_ld_ppc_attr=yes
fi
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
# check that merging the long double .gnu_attribute doesn't warn
cat > conftest1.s <<EOF
.gnu_attribute 4,1
EOF
cat > conftest2.s <<EOF
.gnu_attribute 4,9
EOF
if $gcc_cv_as -a32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
&& $gcc_cv_as -a32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
&& $gcc_cv_ld $emul_name -r -o conftest.o conftest1.o conftest2.o > /dev/null 2> conftest.err \
&& test ! -s conftest.err; then
gcc_cv_ld_ppc_attr=yes
fi
rm -f conftest.err conftest.o conftest1.o conftest2.o conftest1.s conftest2.s
fi
])
if test x$gcc_cv_ld_ppc_attr = xyes; then
AC_DEFINE(HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE, 1,
[Define if your PowerPC linker has .gnu.attributes long double support.])
fi
;;
esac
case "$target:$tm_file" in
powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in

View file

@ -1017,6 +1017,7 @@ See RS/6000 and PowerPC Options.
-mupper-regs-di -mno-upper-regs-di @gol
-mupper-regs -mno-upper-regs @gol
-mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol
-mgnu-attribute -mno-gnu-attribute @gol
-mlra -mno-lra}
@emph{RX Options}
@ -21299,6 +21300,14 @@ This is the default ABI for little-endian PowerPC 64-bit Linux.
Overriding the default ABI requires special system support and is
likely to fail in spectacular ways.
@item -mgnu-attribute
@itemx -mno-gnu-attribute
@opindex mgnu-attribute
@opindex mno-gnu-attribute
Emit .gnu_attribute assembly directives to set tag/value pairs in a
.gnu.attributes section that specify ABI variations in function
parameters or return values.
@item -mprototype
@itemx -mno-prototype
@opindex mprototype