]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/61300 (powerpc64le miscompile with K&R-style function definition at...
authorAlan Modra <amodra@gmail.com>
Wed, 11 Jun 2014 23:50:16 +0000 (09:20 +0930)
committerAlan Modra <amodra@gcc.gnu.org>
Wed, 11 Jun 2014 23:50:16 +0000 (09:20 +0930)
PR target/61300
* doc/tm.texi.in (INCOMING_REG_PARM_STACK_SPACE): Document.
* doc/tm.texi: Regenerate.
* function.c (INCOMING_REG_PARM_STACK_SPACE): Provide default.
Use throughout in place of REG_PARM_STACK_SPACE.
* config/rs6000/rs6000.c (rs6000_reg_parm_stack_space): Add
"incoming" param.  Pass to rs6000_function_parms_need_stack.
(rs6000_function_parms_need_stack): Add "incoming" param, ignore
prototype_p when incoming.  Use function decl when incoming
to handle K&R style functions.
* config/rs6000/rs6000.h (REG_PARM_STACK_SPACE): Adjust.
(INCOMING_REG_PARM_STACK_SPACE): Define.

From-SVN: r211483

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/function.c

index f147e93d32eef6a0ff1b37a105b82fb599e32677..ab05e7c9fa4e9fbb4b018b1f0eef25e470a2ed84 100644 (file)
@@ -1,3 +1,18 @@
+2014-06-12  Alan Modra  <amodra@gmail.com>
+
+       PR target/61300
+       * doc/tm.texi.in (INCOMING_REG_PARM_STACK_SPACE): Document.
+       * doc/tm.texi: Regenerate.
+       * function.c (INCOMING_REG_PARM_STACK_SPACE): Provide default.
+       Use throughout in place of REG_PARM_STACK_SPACE.
+       * config/rs6000/rs6000.c (rs6000_reg_parm_stack_space): Add
+       "incoming" param.  Pass to rs6000_function_parms_need_stack.
+       (rs6000_function_parms_need_stack): Add "incoming" param, ignore
+       prototype_p when incoming.  Use function decl when incoming
+       to handle K&R style functions.
+       * config/rs6000/rs6000.h (REG_PARM_STACK_SPACE): Adjust.
+       (INCOMING_REG_PARM_STACK_SPACE): Define.
+
 2014-06-06  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        Back port from trunk
index 71d5d0a7301ef56bd53ec782537e521946258c70..d330951bf852f3afa27cba0992daa5a825ad6c9a 100644 (file)
@@ -161,7 +161,7 @@ extern tree altivec_resolve_overloaded_builtin (location_t, tree, void *);
 extern rtx rs6000_libcall_value (enum machine_mode);
 extern rtx rs6000_va_arg (tree, tree);
 extern int function_ok_for_sibcall (tree);
-extern int rs6000_reg_parm_stack_space (tree);
+extern int rs6000_reg_parm_stack_space (tree, bool);
 extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
 extern bool rs6000_elf_in_small_data_p (const_tree);
 #ifdef ARGS_SIZE_RTX
index 29f1a32dd8a28bcbff347fb5a7fa243563417712..4cf2589db8b57c7f5e0156999d132967fa6b49dd 100644 (file)
@@ -10498,35 +10498,65 @@ rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
    list, or passes any parameter in memory.  */
 
 static bool
-rs6000_function_parms_need_stack (tree fun)
+rs6000_function_parms_need_stack (tree fun, bool incoming)
 {
-  function_args_iterator args_iter;
-  tree arg_type;
+  tree fntype, result;
   CUMULATIVE_ARGS args_so_far_v;
   cumulative_args_t args_so_far;
 
   if (!fun)
     /* Must be a libcall, all of which only use reg parms.  */
     return false;
+
+  fntype = fun;
   if (!TYPE_P (fun))
-    fun = TREE_TYPE (fun);
+    fntype = TREE_TYPE (fun);
 
   /* Varargs functions need the parameter save area.  */
-  if (!prototype_p (fun) || stdarg_p (fun))
+  if ((!incoming && !prototype_p (fntype)) || stdarg_p (fntype))
     return true;
 
-  INIT_CUMULATIVE_INCOMING_ARGS (args_so_far_v, fun, NULL_RTX);
+  INIT_CUMULATIVE_INCOMING_ARGS (args_so_far_v, fntype, NULL_RTX);
   args_so_far = pack_cumulative_args (&args_so_far_v);
 
-  if (aggregate_value_p (TREE_TYPE (fun), fun))
+  /* When incoming, we will have been passed the function decl.
+     It is necessary to use the decl to handle K&R style functions,
+     where TYPE_ARG_TYPES may not be available.  */
+  if (incoming)
     {
-      tree type = build_pointer_type (TREE_TYPE (fun));
-      rs6000_parm_needs_stack (args_so_far, type);
+      gcc_assert (DECL_P (fun));
+      result = DECL_RESULT (fun);
     }
+  else
+    result = TREE_TYPE (fntype);
 
-  FOREACH_FUNCTION_ARGS (fun, arg_type, args_iter)
-    if (rs6000_parm_needs_stack (args_so_far, arg_type))
-      return true;
+  if (result && aggregate_value_p (result, fntype))
+    {
+      if (!TYPE_P (result))
+       result = TREE_TYPE (result);
+      result = build_pointer_type (result);
+      rs6000_parm_needs_stack (args_so_far, result);
+    }
+
+  if (incoming)
+    {
+      tree parm;
+
+      for (parm = DECL_ARGUMENTS (fun);
+          parm && parm != void_list_node;
+          parm = TREE_CHAIN (parm))
+       if (rs6000_parm_needs_stack (args_so_far, TREE_TYPE (parm)))
+         return true;
+    }
+  else
+    {
+      function_args_iterator args_iter;
+      tree arg_type;
+
+      FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
+       if (rs6000_parm_needs_stack (args_so_far, arg_type))
+         return true;
+    }
 
   return false;
 }
@@ -10538,7 +10568,7 @@ rs6000_function_parms_need_stack (tree fun)
    all parameters in registers.  */
 
 int
-rs6000_reg_parm_stack_space (tree fun)
+rs6000_reg_parm_stack_space (tree fun, bool incoming)
 {
   int reg_parm_stack_space;
 
@@ -10556,7 +10586,7 @@ rs6000_reg_parm_stack_space (tree fun)
     case ABI_ELFv2:
       /* ??? Recomputing this every time is a bit expensive.  Is there
         a place to cache this information?  */
-      if (rs6000_function_parms_need_stack (fun))
+      if (rs6000_function_parms_need_stack (fun, incoming))
        reg_parm_stack_space = TARGET_64BIT ? 64 : 32;
       else
        reg_parm_stack_space = 0;
index cd9db8fe41d96988bd2f831a8b3115646ea9b2b0..2855ec5f4c43fe17d4bdbc3c28fbc0c7c42cda3a 100644 (file)
@@ -1593,7 +1593,14 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
 /* Define this if stack space is still allocated for a parameter passed
    in a register.  The value is the number of bytes allocated to this
    area.  */
-#define REG_PARM_STACK_SPACE(FNDECL) rs6000_reg_parm_stack_space((FNDECL))
+#define REG_PARM_STACK_SPACE(FNDECL) \
+  rs6000_reg_parm_stack_space ((FNDECL), false)
+
+/* Define this macro if space guaranteed when compiling a function body
+   is different to space required when making a call, a situation that
+   can arise with K&R style function definitions.  */
+#define INCOMING_REG_PARM_STACK_SPACE(FNDECL) \
+  rs6000_reg_parm_stack_space ((FNDECL), true)
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
index cbbc82dfe39f3c0163793acaa439c6131b623ed2..53b2a7a7a7c1877e1a708b57a15e6870d4731e2a 100644 (file)
@@ -3930,6 +3930,13 @@ which.
 @c above is overfull.  not sure what to do.  --mew 5feb93  did
 @c something, not sure if it looks good.  --mew 10feb93
 
+@defmac INCOMING_REG_PARM_STACK_SPACE (@var{fndecl})
+Like @code{REG_PARM_STACK_SPACE}, but for incoming register arguments.
+Define this macro if space guaranteed when compiling a function body
+is different to space required when making a call, a situation that
+can arise with K&R style function definitions.
+@end defmac
+
 @defmac OUTGOING_REG_PARM_STACK_SPACE (@var{fntype})
 Define this to a nonzero value if it is the responsibility of the
 caller to allocate the area reserved for arguments passed in registers
index dfba947f51bb1bcf974ac8b1a5311b03b6276f8d..f2e7ab8bf1e094e82ac305b7887482ac3b6c0a25 100644 (file)
@@ -3898,6 +3898,13 @@ which.
 @c above is overfull.  not sure what to do.  --mew 5feb93  did
 @c something, not sure if it looks good.  --mew 10feb93
 
+@defmac INCOMING_REG_PARM_STACK_SPACE (@var{fndecl})
+Like @code{REG_PARM_STACK_SPACE}, but for incoming register arguments.
+Define this macro if space guaranteed when compiling a function body
+is different to space required when making a call, a situation that
+can arise with K&R style function definitions.
+@end defmac
+
 @defmac OUTGOING_REG_PARM_STACK_SPACE (@var{fntype})
 Define this to a nonzero value if it is the responsibility of the
 caller to allocate the area reserved for arguments passed in registers
index bc04dcb9d8d748abb6f2345cbdf4d61e28935013..c96e6e2ece31c25751fb70c6ddd24037be3c9b48 100644 (file)
@@ -1354,9 +1354,13 @@ static int cfa_offset;
 #define STACK_POINTER_OFFSET   0
 #endif
 
+#if defined (REG_PARM_STACK_SPACE) && !defined (INCOMING_REG_PARM_STACK_SPACE)
+#define INCOMING_REG_PARM_STACK_SPACE REG_PARM_STACK_SPACE
+#endif
+
 /* If not defined, pick an appropriate default for the offset of dynamically
    allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,
-   REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */
+   INCOMING_REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */
 
 #ifndef STACK_DYNAMIC_OFFSET
 
@@ -1368,12 +1372,12 @@ static int cfa_offset;
    `crtl->outgoing_args_size'.  Nevertheless, we must allow
    for it when allocating stack dynamic objects.  */
 
-#if defined(REG_PARM_STACK_SPACE)
+#ifdef INCOMING_REG_PARM_STACK_SPACE
 #define STACK_DYNAMIC_OFFSET(FNDECL)   \
 ((ACCUMULATE_OUTGOING_ARGS                                                   \
   ? (crtl->outgoing_args_size                                \
      + (OUTGOING_REG_PARM_STACK_SPACE ((!(FNDECL) ? NULL_TREE : TREE_TYPE (FNDECL))) ? 0 \
-                                              : REG_PARM_STACK_SPACE (FNDECL))) \
+                                              : INCOMING_REG_PARM_STACK_SPACE (FNDECL))) \
   : 0) + (STACK_POINTER_OFFSET))
 #else
 #define STACK_DYNAMIC_OFFSET(FNDECL)   \
@@ -2211,8 +2215,9 @@ assign_parms_initialize_all (struct assign_parm_data_all *all)
 #endif
   all->args_so_far = pack_cumulative_args (&all->args_so_far_v);
 
-#ifdef REG_PARM_STACK_SPACE
-  all->reg_parm_stack_space = REG_PARM_STACK_SPACE (current_function_decl);
+#ifdef INCOMING_REG_PARM_STACK_SPACE
+  all->reg_parm_stack_space
+    = INCOMING_REG_PARM_STACK_SPACE (current_function_decl);
 #endif
 }