[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:
parent
91eaca5e32
commit
e9dda04f07
7 changed files with 203 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
52
gcc/configure
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue