From 617718f72d0736e5f8630012d3276a276b9e153f Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 7 Mar 2011 18:20:23 +1030 Subject: [PATCH] linux.h (TARGET_ASM_FILE_END): Don't define. * config/rs6000/linux.h (TARGET_ASM_FILE_END): Don't define. * config/rs6000/linux64.h (TARGET_ASM_FILE_END): Don't define. * config/rs6000/sysv4.h (TARGET_ASM_FILE_END): Define. * config/rs6000/rs6000-protos.h (init_cumulative_args): Add fndecl and return_mode args. * config/rs6000/rs6000.h (CUMULATIVE_ARGS): Add "escapes". (INIT_CUMULATIVE_ARGS): Pass FNDECL, VOIDmode. (INIT_CUMULATIVE_INCOMING_ARGS): Pass current_function_decl, VOIDmode. (INIT_CUMULATIVE_LIBCALL_ARGS): Pass NULL_TREE, MODE. * config/rs6000/rs6000.c (rs6000_elf_end_indicate_exec_stack): Rename to.. (rs6000_elf_file_end): ..this. Only call file_end_indicate_exec_stack for POWERPC_LINUX. Move code emitting .gnu_attribute to here, from.. (rs6000_file_start): ..here. (rs6000_passes_float, rs6000_passes_vector, rs6000_returns_struct): New file scope variables. (call_ABI_of_interest): New function. (init_cumulative_args): Set above vars when function return value is a float, vector, or small struct. (rs6000_function_arg_advance_1): Likewise for function args. (rs6000_va_start): Set rs6000_passes_float if variable arg function references float args. From-SVN: r170734 --- gcc/ChangeLog | 25 ++++++ gcc/config/rs6000/linux.h | 4 +- gcc/config/rs6000/linux64.h | 2 - gcc/config/rs6000/rs6000-protos.h | 3 +- gcc/config/rs6000/rs6000.c | 142 +++++++++++++++++++++++++----- gcc/config/rs6000/rs6000.h | 12 ++- gcc/config/rs6000/sysv4.h | 2 + 7 files changed, 158 insertions(+), 32 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c47c312591..0918f7a60fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2011-03-07 Alan Modra + + * config/rs6000/linux.h (TARGET_ASM_FILE_END): Don't define. + * config/rs6000/linux64.h (TARGET_ASM_FILE_END): Don't define. + * config/rs6000/sysv4.h (TARGET_ASM_FILE_END): Define. + * config/rs6000/rs6000-protos.h (init_cumulative_args): Add fndecl and + return_mode args. + * config/rs6000/rs6000.h (CUMULATIVE_ARGS): Add "escapes". + (INIT_CUMULATIVE_ARGS): Pass FNDECL, VOIDmode. + (INIT_CUMULATIVE_INCOMING_ARGS): Pass current_function_decl, VOIDmode. + (INIT_CUMULATIVE_LIBCALL_ARGS): Pass NULL_TREE, MODE. + * config/rs6000/rs6000.c + (rs6000_elf_end_indicate_exec_stack): Rename to.. + (rs6000_elf_file_end): ..this. Only call file_end_indicate_exec_stack + for POWERPC_LINUX. Move code emitting .gnu_attribute to here, from.. + (rs6000_file_start): ..here. + (rs6000_passes_float, rs6000_passes_vector, rs6000_returns_struct): New + file scope variables. + (call_ABI_of_interest): New function. + (init_cumulative_args): Set above vars when function return value + is a float, vector, or small struct. + (rs6000_function_arg_advance_1): Likewise for function args. + (rs6000_va_start): Set rs6000_passes_float if variable arg function + references float args. + 2011-03-07 Mingjie Xing * doc/cfg.texi: Remove "See" before @ref. diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h index ed1d09ec14d..77c8f61035b 100644 --- a/gcc/config/rs6000/linux.h +++ b/gcc/config/rs6000/linux.h @@ -1,7 +1,7 @@ /* Definitions of target machine for GNU compiler, for PowerPC machines running Linux. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2010, 2011 Free Software Foundation, Inc. Contributed by Michael Meissner (meissner@cygnus.com). This file is part of GCC. @@ -114,8 +114,6 @@ #define RELOCATABLE_NEEDS_FIXUP \ (target_flags & target_flags_explicit & MASK_RELOCATABLE) -#define TARGET_ASM_FILE_END file_end_indicate_exec_stack - #define TARGET_POSIX_IO #define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h" diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index e57a6c67a25..e6840d63e80 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -537,8 +537,6 @@ extern int dot_symbols; #undef DRAFT_V4_STRUCT_RET #define DRAFT_V4_STRUCT_RET (!TARGET_64BIT) -#define TARGET_ASM_FILE_END rs6000_elf_end_indicate_exec_stack - #define TARGET_POSIX_IO #define LINK_GCC_C_SEQUENCE_SPEC \ diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index d9b6bd70cad..3b0d1dab7db 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -28,7 +28,8 @@ #ifdef RTX_CODE #ifdef TREE_CODE -extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int); +extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int, + tree, enum machine_mode); #endif /* TREE_CODE */ extern bool easy_altivec_constant (rtx, enum machine_mode); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index fd80f8b8ac2..8609c63d3c0 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -184,6 +184,14 @@ unsigned rs6000_pmode; /* Width in bits of a pointer. */ unsigned rs6000_pointer_size; +#ifdef HAVE_AS_GNU_ATTRIBUTE +/* Flag whether floating point values have been passed/returned. */ +static bool rs6000_passes_float; +/* Flag whether vector values have been passed/returned. */ +static bool rs6000_passes_vector; +/* Flag whether small (<= 8 byte) structures have been returned. */ +static bool rs6000_returns_struct; +#endif /* Value is TRUE if register/mode pair is acceptable. */ bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; @@ -940,7 +948,7 @@ static void rs6000_file_start (void); static int rs6000_elf_reloc_rw_mask (void); static void rs6000_elf_asm_out_constructor (rtx, int) ATTRIBUTE_UNUSED; static void rs6000_elf_asm_out_destructor (rtx, int) ATTRIBUTE_UNUSED; -static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED; +static void rs6000_elf_file_end (void) ATTRIBUTE_UNUSED; static void rs6000_elf_asm_init_sections (void); static section *rs6000_elf_select_rtx_section (enum machine_mode, rtx, unsigned HOST_WIDE_INT); @@ -4695,23 +4703,6 @@ rs6000_file_start (void) putc ('\n', file); } -#ifdef HAVE_AS_GNU_ATTRIBUTE - if (TARGET_32BIT && DEFAULT_ABI == ABI_V4) - { - fprintf (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)); - fprintf (file, "\t.gnu_attribute 8, %d\n", - (TARGET_ALTIVEC_ABI ? 2 - : TARGET_SPE_ABI ? 3 - : 1)); - fprintf (file, "\t.gnu_attribute 12, %d\n", - aix_struct_return ? 2 : 1); - - } -#endif - if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2)) { switch_to_section (toc_section); @@ -7865,9 +7856,36 @@ rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) return false; } +#ifdef HAVE_AS_GNU_ATTRIBUTE +/* Return TRUE if a call to function FNDECL may be one that + potentially affects the function calling ABI of the object file. */ + +static bool +call_ABI_of_interest (tree fndecl) +{ + if (cgraph_state == CGRAPH_STATE_EXPANSION) + { + struct cgraph_node *c_node; + + /* Libcalls are always interesting. */ + if (fndecl == NULL_TREE) + return true; + + /* Any call to an external function is interesting. */ + if (DECL_EXTERNAL (fndecl)) + return true; + + /* Interesting functions that we are emitting in this object file. */ + c_node = cgraph_node (fndecl); + return !cgraph_only_called_directly_p (c_node); + } + return false; +} +#endif + /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. + For a library call, FNTYPE is 0 and RETURN_MODE the return value mode. For incoming args we set the number of arguments in the prototype large so we never return a PARALLEL. */ @@ -7875,7 +7893,9 @@ rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) void init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname ATTRIBUTE_UNUSED, int incoming, - int libcall, int n_named_args) + int libcall, int n_named_args, + tree fndecl ATTRIBUTE_UNUSED, + enum machine_mode return_mode ATTRIBUTE_UNUSED) { static CUMULATIVE_ARGS zero_cumulative; @@ -7917,6 +7937,45 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, cum->prototype, cum->nargs_prototype); } +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (DEFAULT_ABI == ABI_V4) + { + cum->escapes = call_ABI_of_interest (fndecl); + if (cum->escapes) + { + tree return_type; + + if (fntype) + { + return_type = TREE_TYPE (fntype); + return_mode = TYPE_MODE (return_type); + } + else + return_type = lang_hooks.types.type_for_mode (return_mode, 0); + + if (return_type != NULL) + { + if (TREE_CODE (return_type) == RECORD_TYPE + && TYPE_TRANSPARENT_AGGR (return_type)) + { + return_type = TREE_TYPE (first_field (return_type)); + return_mode = TYPE_MODE (return_type); + } + if (AGGREGATE_TYPE_P (return_type) + && ((unsigned HOST_WIDE_INT) int_size_in_bytes (return_type) + <= 8)) + rs6000_returns_struct = true; + } + if (SCALAR_FLOAT_MODE_P (return_mode)) + rs6000_passes_float = true; + else if (ALTIVEC_VECTOR_MODE (return_mode) + || VSX_VECTOR_MODE (return_mode) + || SPE_VECTOR_MODE (return_mode)) + rs6000_passes_vector = true; + } + } +#endif + if (fntype && !TARGET_ALTIVEC && TARGET_ALTIVEC_ABI @@ -8235,11 +8294,25 @@ static void rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type, bool named, int depth) { - /* Only tick off an argument if we're not recursing. */ if (depth == 0) cum->nargs_prototype--; +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (DEFAULT_ABI == ABI_V4 + && cum->escapes) + { + if (SCALAR_FLOAT_MODE_P (mode)) + rs6000_passes_float = true; + else if (named && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))) + rs6000_passes_vector = true; + else if (SPE_VECTOR_MODE (mode) + && !cum->stdarg + && cum->sysv_gregno <= GP_ARG_MAX_REG) + rs6000_passes_vector = true; + } +#endif + if (TARGET_ALTIVEC_ABI && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode) @@ -9504,6 +9577,11 @@ rs6000_va_start (tree valist, rtx nextarg) build_int_cst (NULL_TREE, n_fpr)); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (call_ABI_of_interest (cfun->decl)) + rs6000_passes_float = true; +#endif } /* Find the overflow area. */ @@ -25786,10 +25864,30 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl) } static void -rs6000_elf_end_indicate_exec_stack (void) +rs6000_elf_file_end (void) { +#ifdef HAVE_AS_GNU_ATTRIBUTE + 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 + : TARGET_SPE_ABI ? 3 + : 1)); + if (rs6000_returns_struct) + fprintf (asm_out_file, "\t.gnu_attribute 12, %d\n", + aix_struct_return ? 2 : 1); + } +#endif +#ifdef POWERPC_LINUX if (TARGET_32BIT) file_end_indicate_exec_stack (); +#endif } #endif diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 8c76d7ce101..98ec24c75eb 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1570,25 +1570,29 @@ typedef struct rs6000_args int floats_in_gpr; /* count of SFmode floats taking up GPR space (darwin64) */ int named; /* false for varargs params */ + int escapes; /* if function visible outside tu */ } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, FALSE, N_NAMED_ARGS) +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \ + init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, FALSE, \ + N_NAMED_ARGS, FNDECL, VOIDmode) /* Similar, but when scanning the definition of a procedure. We always set NARGS_PROTOTYPE large so we never return an EXPR_LIST. */ #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE, FALSE, 1000) + init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE, FALSE, \ + 1000, current_function_decl, VOIDmode) /* Like INIT_CUMULATIVE_ARGS' but only used for outgoing libcalls. */ #define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \ - init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, 0) + init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, \ + 0, NULL_TREE, MODE) /* If defined, a C expression which determines whether, and in which direction, to pad out an argument with extra space. The value diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 113ddd02bd7..aeb934f6ed5 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -1031,6 +1031,8 @@ ncrtn.o%s" /* Generate entries in .fixup for relocatable addresses. */ #define RELOCATABLE_NEEDS_FIXUP 1 +#define TARGET_ASM_FILE_END rs6000_elf_file_end + /* This target uses the sysv4.opt file. */ #define TARGET_USES_SYSV4_OPT 1 -- 2.30.2