diff options
author | Alan Modra <amodra@gmail.com> | 2016-09-29 07:31:48 +0930 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2016-09-29 07:31:48 +0930 |
commit | e9dda04f0760e78c5834b1beddab39cd562ad7c1 (patch) | |
tree | 7d561e18cf4ecf2d793c4c34f392eac627e6209d | |
parent | 91eaca5e32abab6179fba0e2543daf1cc1f64bde (diff) | |
download | gcc-e9dda04f0760e78c5834b1beddab39cd562ad7c1.zip gcc-e9dda04f0760e78c5834b1beddab39cd562ad7c1.tar.gz gcc-e9dda04f0760e78c5834b1beddab39cd562ad7c1.tar.bz2 |
[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
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/config.in | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 87 | ||||
-rw-r--r-- | gcc/config/rs6000/sysv4.opt | 4 | ||||
-rwxr-xr-x | gcc/configure | 52 | ||||
-rw-r--r-- | gcc/configure.ac | 45 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 |
7 files changed, 203 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 588f2d1..f2c8fe4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config.in b/gcc/config.in index a736de3..8470456 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -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 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4d3706c..c7ba617 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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 diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt index 581fcde..cb5d7ea 100644 --- a/gcc/config/rs6000/sysv4.opt +++ b/gcc/config/rs6000/sysv4.opt @@ -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. diff --git a/gcc/configure b/gcc/configure index 96eba9e..47f70e6 100755 --- a/gcc/configure +++ b/gcc/configure @@ -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 diff --git a/gcc/configure.ac b/gcc/configure.ac index 534f22e..a702f17 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -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 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6767462..8a84e4f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 |