@@ -64,7 +64,7 @@
#include "ppc-auxv.h"
#include "targhooks.h"
#include "opts.h"
-
+#include "tree-dfa.h"
#include "rs6000-internal.h"
#ifndef TARGET_PROFILE_KERNEL
@@ -584,6 +584,32 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
if (incoming || cum->prototype)
cum->nargs_prototype = n_named_args;
+ /* When the buggy C/C++ wrappers call the function with fewer arguments
+ than it actually has. Check whether this function contains any unused
+ hidden parameters and record how many there are for use in
+ rs6000_function_arg() to determine whether its callers
+ have allocated a parameter save area or not. See PR100799 for
+ details. */
+ unsigned int num_args = 0;
+ unsigned int hidden_length = 0;
+
+ for (tree arg = DECL_ARGUMENTS (current_function_decl);
+ arg; arg = DECL_CHAIN (arg))
+ {
+ num_args++;
+ if (DECL_HIDDEN_STRING_LENGTH (arg))
+ {
+ tree parmdef = ssa_default_def (cfun, arg);
+ if (parmdef == NULL || has_zero_uses (parmdef))
+ {
+ cum->hidden_string_length = 1;
+ hidden_length++;
+ }
+ }
+ }
+
+ cum->actual_parm_length = num_args - hidden_length;
+
/* Check for a longcall attribute. */
if ((!fntype && rs6000_default_long_calls)
|| (fntype
@@ -1857,7 +1883,15 @@ rs6000_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
return rs6000_finish_function_arg (mode, rvec, k);
}
- else if (align_words < GP_ARG_NUM_REG)
+ /* When the buggy C/C++ wrappers call the function with fewer arguments
+ than it actually has. Check whether this function contains any unused
+ hidden parameters and record how many there are for use in
+ rs6000_function_arg() to determine whether its callers
+ have allocated a parameter save area or not. See PR100799 for
+ details. */
+ else if (align_words < GP_ARG_NUM_REG
+ || (cum->hidden_string_length
+ && cum->actual_parm_length <= GP_ARG_NUM_REG))
{
if (TARGET_32BIT && TARGET_POWERPC64)
return rs6000_mixed_function_arg (mode, type, align_words);
@@ -1490,6 +1490,10 @@ typedef struct rs6000_args
int named; /* false for varargs params */
int escapes; /* if function visible outside tu */
int libcall; /* If this is a compiler generated call. */
+ /* Actual parameter count ignoring unused hidden parameters. */
+ unsigned int actual_parm_length;
+ /* Set if there is hidden unused parameters. */
+ unsigned int hidden_string_length : 1;
} CUMULATIVE_ARGS;
/* Initialize a variable CUM of type CUMULATIVE_ARGS