OSDN Git Service

* config/rs6000/linux.h (TARGET_ASM_FILE_END): Don't define.
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Mar 2011 07:50:23 +0000 (07:50 +0000)
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Mar 2011 07:50:23 +0000 (07:50 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@170734 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/linux.h
gcc/config/rs6000/linux64.h
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/sysv4.h

index 9c47c31..0918f7a 100644 (file)
@@ -1,3 +1,28 @@
+2011-03-07  Alan Modra  <amodra@gmail.com>
+
+       * 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  <mingjie.xing@gmail.com>
 
        * doc/cfg.texi: Remove "See" before @ref.
 2011-03-07  Mingjie Xing  <mingjie.xing@gmail.com>
 
        * doc/cfg.texi: Remove "See" before @ref.
index ed1d09e..77c8f61 100644 (file)
@@ -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,
 /* 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.
    Contributed by Michael Meissner (meissner@cygnus.com).
 
    This file is part of GCC.
 #define RELOCATABLE_NEEDS_FIXUP \
   (target_flags & target_flags_explicit & MASK_RELOCATABLE)
 
 #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"
 #define TARGET_POSIX_IO
 
 #define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
index e57a6c6..e6840d6 100644 (file)
@@ -537,8 +537,6 @@ extern int dot_symbols;
 #undef DRAFT_V4_STRUCT_RET
 #define DRAFT_V4_STRUCT_RET (!TARGET_64BIT)
 
 #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 \
 #define TARGET_POSIX_IO
 
 #define LINK_GCC_C_SEQUENCE_SPEC \
index d9b6bd7..3b0d1da 100644 (file)
@@ -28,7 +28,8 @@
 #ifdef RTX_CODE
 
 #ifdef TREE_CODE
 #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);
 #endif /* TREE_CODE */
 
 extern bool easy_altivec_constant (rtx, enum machine_mode);
index fd80f8b..8609c63 100644 (file)
@@ -184,6 +184,14 @@ unsigned rs6000_pmode;
 /* Width in bits of a pointer.  */
 unsigned rs6000_pointer_size;
 
 /* 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];
 
 /* 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 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);
 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);
     }
 
        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);
   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;
 }
 
   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.
 /* 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.  */
 
    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,
 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;
 
 {
   static CUMULATIVE_ARGS zero_cumulative;
 
@@ -7917,6 +7937,45 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
               cum->prototype, cum->nargs_prototype);
     }
 
               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
   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)
 {
 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--;
 
   /* 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)
   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);
                  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.  */
     }
 
   /* Find the overflow area.  */
@@ -25786,10 +25864,30 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
 }
 
 static void
 }
 
 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 ();
   if (TARGET_32BIT)
     file_end_indicate_exec_stack ();
+#endif
 }
 #endif
 
 }
 #endif
 
index 8c76d7c..98ec24c 100644 (file)
@@ -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 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.  */
 
 } 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) \
 
 /* 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) \
 
 /* 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
 
 /* If defined, a C expression which determines whether, and in which
    direction, to pad out an argument with extra space.  The value
index 113ddd0..aeb934f 100644 (file)
@@ -1031,6 +1031,8 @@ ncrtn.o%s"
 /* Generate entries in .fixup for relocatable addresses.  */
 #define RELOCATABLE_NEEDS_FIXUP 1
 
 /* 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
 
 /* This target uses the sysv4.opt file.  */
 #define TARGET_USES_SYSV4_OPT 1