[RFC] PR61300 K&R incoming args

From: Alan Modra <amodra at gmail dot com>

To: gcc at gcc dot gnu dot org

Date: Mon, 26 May 2014 17:08:09 +0930

Subject: [RFC] PR61300 K&R incoming args

Authentication-results: sourceware.org; auth=none

PR61300 shows a need to differentiate between incoming and outgoing
REG_PARM_STACK_SPACE for the PowerPC64 ELFv2 ABI, due to code like
function.c:assign_parm_is_stack_parm determining that a stack home
is available for incoming args if REG_PARM_STACK_SPACE is non-zero.
Background: The ELFv2 ABI requires a parameter save area only when
stack is actually used to pass parameters, and since varargs are
passed on the stack, unprototyped calls must pass both on the stack
and in registers. OK, easy you say, !prototype_p(fun) means a
parameter save area is needed. However, a prototype might not be in
scope when compiling an old K&R style C function body, but this does
*not* mean a parameter save area has necesasrily been allocated. A
caller may well have a prototype in scope at the point of the call.
So I wrote a patch to define INCOMING_REG_PARM_STACK_SPACE and use
this in function.c, as attached. It's just a quick and dirty patch, I
know I'll need to document it in tm.texi and it would be better to
use INCOMING_REG_PARM_STACK_SPACE throughout function.c. Also I'm
happy to rename OUTGOING_REG_PARM_STACK_SPACE to
CALLER_ALLOCATES_REG_PARM_STACK everywhere if that seems like a good
idea to those with power to approve such a patch.
The question I have is whether there's a better way to do this? Years
ago it was possible for a backend to determine whether a function body
was being compiled by looking at TYPE_ACTUAL_ARG_TYPES(fun), but
that's now a C only flag, and it seems like it wouldn't be a good idea
to try to use the flag..
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 210919)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -10485,7 +10485,7 @@ rs6000_parm_needs_stack (cumulative_args_t args_so
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;
@@ -10499,7 +10499,7 @@ static bool
fun = TREE_TYPE (fun);
/* Varargs functions need the parameter save area. */
- if (!prototype_p (fun) || stdarg_p (fun))
+ if ((!incoming && !prototype_p (fun)) || stdarg_p (fun))
return true;
INIT_CUMULATIVE_INCOMING_ARGS (args_so_far_v, fun, NULL_RTX);
@@ -10525,7 +10525,7 @@ static bool
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;
@@ -10543,7 +10543,7 @@ int
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: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h (revision 210919)
+++ gcc/config/rs6000/rs6000.h (working copy)
@@ -1602,7 +1602,10 @@ extern enum reg_class rs6000_constraints[RS6000_CO
/* 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 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: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h (revision 210919)
+++ gcc/config/rs6000/rs6000-protos.h (working copy)
@@ -163,7 +163,7 @@ extern tree altivec_resolve_overloaded_builtin (lo
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: gcc/function.c
===================================================================
--- gcc/function.c (revision 210919)
+++ gcc/function.c (working copy)
@@ -1348,6 +1348,11 @@ static int cfa_offset;
#define STACK_POINTER_OFFSET 0
#endif
+#ifdef INCOMING_REG_PARM_STACK_SPACE
+#undef REG_PARM_STACK_SPACE
+#define REG_PARM_STACK_SPACE INCOMING_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. */
--
Alan Modra
Australia Development Lab, IBM