From patchwork Fri Mar 4 04:35:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 85368 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id D154AB7043 for ; Fri, 4 Mar 2011 15:35:54 +1100 (EST) Received: (qmail 17217 invoked by alias); 4 Mar 2011 04:35:49 -0000 Received: (qmail 16726 invoked by uid 22791); 4 Mar 2011 04:35:45 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_FN, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-iy0-f175.google.com (HELO mail-iy0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 04 Mar 2011 04:35:38 +0000 Received: by iyb26 with SMTP id 26so1771274iyb.20 for ; Thu, 03 Mar 2011 20:35:36 -0800 (PST) Received: by 10.42.11.207 with SMTP id v15mr189611icv.22.1299213336836; Thu, 03 Mar 2011 20:35:36 -0800 (PST) Received: from bubble.grove.modra.org ([115.187.252.19]) by mx.google.com with ESMTPS id c4sm1300635ict.7.2011.03.03.20.35.34 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 03 Mar 2011 20:35:36 -0800 (PST) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id D386B170C1FA; Fri, 4 Mar 2011 15:05:29 +1030 (CST) Date: Fri, 4 Mar 2011 15:05:29 +1030 From: Alan Modra To: gcc-patches@gcc.gnu.org Cc: David Edelsohn Subject: Re: PowerPC32 .gnu.attributes Message-ID: <20110304043529.GX13094@bubble.grove.modra.org> Mail-Followup-To: gcc-patches@gcc.gnu.org, David Edelsohn References: <20110223110721.GA5959@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20110223110721.GA5959@bubble.grove.modra.org> User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Re http://gcc.gnu.org/ml/gcc-patches/2011-02/msg01525.html Updated patch, using cgraph to decide whether a function is visible outside of the object file. Bootstrapped and regression tested powerpc-linux. OK for 4.6? * 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. Index: gcc/config/rs6000/linux.h =================================================================== --- gcc/config/rs6000/linux.h (revision 170665) +++ gcc/config/rs6000/linux.h (working copy) @@ -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" Index: gcc/config/rs6000/linux64.h =================================================================== --- gcc/config/rs6000/linux64.h (revision 170665) +++ gcc/config/rs6000/linux64.h (working copy) @@ -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 \ Index: gcc/config/rs6000/sysv4.h =================================================================== --- gcc/config/rs6000/sysv4.h (revision 170665) +++ gcc/config/rs6000/sysv4.h (working copy) @@ -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 Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 170665) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -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); Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 170665) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -1570,25 +1598,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 Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 170665) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -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); @@ -7859,9 +7849,36 @@ rs6000_return_in_memory (const_tree type 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. */ @@ -7869,7 +7886,9 @@ rs6000_return_in_memory (const_tree type 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; @@ -7911,6 +7930,45 @@ init_cumulative_args (CUMULATIVE_ARGS *c 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 @@ -8229,11 +8287,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) @@ -9498,6 +9570,11 @@ rs6000_va_start (tree valist, rtx nextar 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. */ @@ -25780,10 +25868,30 @@ rs6000_elf_declare_function_name (FILE * } 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