[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> 2016-09-28 Jakub Jelinek <jakub@redhat.com>
* gimple-ssa-sprintf.c (pass_sprintf_length::gate): Use x > 0 instead * gimple-ssa-sprintf.c (pass_sprintf_length::gate): Use x > 0 instead

View File

@ -1538,6 +1538,12 @@
#endif #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 */ /* Define if your linker supports --push-state/--pop-state */
#ifndef USED_FOR_TARGET #ifndef USED_FOR_TARGET
#undef HAVE_LD_PUSHPOPSTATE_SUPPORT #undef HAVE_LD_PUSHPOPSTATE_SUPPORT

View File

@ -183,8 +183,16 @@ unsigned rs6000_pmode;
unsigned rs6000_pointer_size; unsigned rs6000_pointer_size;
#ifdef HAVE_AS_GNU_ATTRIBUTE #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_float;
static bool rs6000_passes_long_double;
/* Flag whether vector values have been passed/returned. */ /* Flag whether vector values have been passed/returned. */
static bool rs6000_passes_vector; static bool rs6000_passes_vector;
/* Flag whether small (<= 8 byte) structures have been returned. */ /* Flag whether small (<= 8 byte) structures have been returned. */
@ -10920,7 +10928,7 @@ rs6000_return_in_msb (const_tree valtype)
static bool static bool
call_ABI_of_interest (tree fndecl) call_ABI_of_interest (tree fndecl)
{ {
if (symtab->state == EXPANSION) if (rs6000_gnu_attr && symtab->state == EXPANSION)
{ {
struct cgraph_node *c_node; struct cgraph_node *c_node;
@ -10997,7 +11005,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
} }
#ifdef HAVE_AS_GNU_ATTRIBUTE #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); cum->escapes = call_ABI_of_interest (fndecl);
if (cum->escapes) if (cum->escapes)
@ -11025,10 +11033,19 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
<= 8)) <= 8))
rs6000_returns_struct = true; rs6000_returns_struct = true;
} }
if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (return_mode)) if (SCALAR_FLOAT_MODE_P (return_mode))
rs6000_passes_float = true; {
else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode) rs6000_passes_float = true;
|| SPE_VECTOR_MODE (return_mode)) 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; rs6000_passes_vector = true;
} }
} }
@ -11475,16 +11492,23 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode,
cum->nargs_prototype--; cum->nargs_prototype--;
#ifdef HAVE_AS_GNU_ATTRIBUTE #ifdef HAVE_AS_GNU_ATTRIBUTE
if (DEFAULT_ABI == ABI_V4 if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4)
&& cum->escapes) && cum->escapes)
{ {
if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode)) if (SCALAR_FLOAT_MODE_P (mode))
rs6000_passes_float = true; {
else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) rs6000_passes_float = true;
rs6000_passes_vector = true; if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT)
else if (SPE_VECTOR_MODE (mode) && (FLOAT128_IBM_P (mode)
&& !cum->stdarg || FLOAT128_IEEE_P (mode)
&& cum->sysv_gregno <= GP_ARG_MAX_REG) || (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; rs6000_passes_vector = true;
} }
#endif #endif
@ -34292,13 +34316,33 @@ static void
rs6000_elf_file_end (void) rs6000_elf_file_end (void)
{ {
#ifdef HAVE_AS_GNU_ATTRIBUTE #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 (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) if (rs6000_passes_vector)
fprintf (asm_out_file, "\t.gnu_attribute 8, %d\n", fprintf (asm_out_file, "\t.gnu_attribute 8, %d\n",
(TARGET_ALTIVEC_ABI ? 2 (TARGET_ALTIVEC_ABI ? 2
@ -37085,6 +37129,9 @@ static struct rs6000_opt_var const rs6000_opt_vars[] =
{ "warn-cell-microcode", { "warn-cell-microcode",
offsetof (struct gcc_options, x_rs6000_warn_cell_microcode), offsetof (struct gcc_options, x_rs6000_warn_cell_microcode),
offsetof (struct cl_target_option, 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 /* 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 mbss-plt
Target Report RejectNegative Var(secure_plt, 0) Save Target Report RejectNegative Var(secure_plt, 0) Save
Generate code for old exec BSS PLT. 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 "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_clearcap" >&5
$as_echo "$gcc_cv_ld_clearcap" >&6; } $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 case "$target:$tm_file" in
powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*) powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in case "$target" in

View File

@ -5322,6 +5322,51 @@ if test "x$gcc_cv_ld_clearcap" = xyes; then
fi fi
AC_MSG_RESULT($gcc_cv_ld_clearcap) 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 case "$target:$tm_file" in
powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*) powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in 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-di -mno-upper-regs-di @gol
-mupper-regs -mno-upper-regs @gol -mupper-regs -mno-upper-regs @gol
-mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol -mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol
-mgnu-attribute -mno-gnu-attribute @gol
-mlra -mno-lra} -mlra -mno-lra}
@emph{RX Options} @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 Overriding the default ABI requires special system support and is
likely to fail in spectacular ways. 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 @item -mprototype
@itemx -mno-prototype @itemx -mno-prototype
@opindex mprototype @opindex mprototype