Hello All: This is version-2 of the patch with review comments addressed.
When using FlexiBLAS with OpenBLAS we noticed corruption of the parameters passed to OpenBLAS functions. FlexiBLAS basically provides a BLAS interface where each function is a stub that forwards the arguments to a real BLAS lib, like OpenBLAS. Fixes the corruption of caller frame checking number of arguments is less than equal to GP_ARG_NUM_REG (8) excluding hidden unused DECLS. Bootstrapped and regtested for powerpc64-linux.gnu. Thanks & Regards Ajit rs6000: Stackoverflow in optimized code on PPC [PR100799] When using FlexiBLAS with OpenBLAS we noticed corruption of the parameters passed to OpenBLAS functions. FlexiBLAS basically provides a BLAS interface where each function is a stub that forwards the arguments to a real BLAS lib, like OpenBLAS. Fixes the corruption of caller frame checking number of arguments is less than equal to GP_ARG_NUM_REG (8) excluding hidden unused DECLS. 2024-03-22 Ajit Kumar Agarwal <aagar...@linux.ibm.com> gcc/ChangeLog: PR rtk-optimization/100799 * config/rs6000/rs6000-calls.cc (rs6000_function_arg): Don't generate parameter save area if number of arguments passed less than equal to GP_ARG_NUM_REG (8) excluding hidden parameter. (init_cumulative_args): Check for hidden parameter in fortran routine and set the flag hidden_string_length and actual parameter passed excluding hidden unused DECLS. * config/rs6000/rs6000.h (rs6000_args): Add new field hidden_string_length and actual_parm_length. --- gcc/config/rs6000/rs6000-call.cc | 36 ++++++++++++++++++++++++++++++-- gcc/config/rs6000/rs6000.h | 7 +++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc index 1f8f93a2ee7..fd823c66ea2 100644 --- a/gcc/config/rs6000/rs6000-call.cc +++ b/gcc/config/rs6000/rs6000-call.cc @@ -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,31 @@ 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 and doesn't expect the parameter save area on the + caller side because of that while the callee expects it and the callee + actually stores something in the parameter save area, it corrupts + whatever is in the caller stack frame at that location. */ + 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 +1882,14 @@ 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 and doesn't expect the parameter save area on the + caller side because of that while the callee expects it and the callee + actually stores something in the parameter save area, it corrupts + whatever is in the caller stack frame at that location. */ + 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); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 68bc45d65ba..60f23f33879 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1490,6 +1490,13 @@ 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 length ignoring hidden parameter. + This is done to C++ wrapper calling fortran procedures + which has hidden parameter that are not used. */ + unsigned int actual_parm_length; + /* Set if there is hidden parameters while calling C++ wrapper to + fortran procedure. */ + unsigned int hidden_string_length : 1; } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS -- 2.39.3