On Tue, Feb 27, 2024 at 04:41:32PM +0000, Richard Earnshaw wrote: > > 2023-01-09 Jakub Jelinek <ja...@redhat.com> > > > > PR target/107453 > > * calls.cc (expand_call): For calls with > > TYPE_NO_NAMED_ARGS_STDARG_P (funtype) use zero for n_named_args. > > Formatting fix. > > This one has been festering for a while; both Alexandre and Torbjorn have > attempted to fix it recently, but I'm not sure either is really right... > > On Arm this is causing all anonymous arguments to be passed on the stack, > which is incorrect per the ABI. On a target that uses > 'pretend_outgoing_vararg_named', why is it correct to set n_named_args to > zero? Is it enough to guard both the statements you've added with > !targetm.calls.pretend_outgoing_args_named?
I'm afraid I haven't heard of that target hook before. All I was doing with that change was fixing a regression reported in the PR for ppc64le/sparc/nvptx/loongarch at least. The TYPE_NO_NAMED_ARGS_STDARG_P functions (C23 fns like void foo (...) {}) have NULL type_arg_types, so the list_length (type_arg_types) isn't done for it, but it should be handled as if it was non-NULL but list length was 0. So, for the if (type_arg_types != 0) n_named_args = (list_length (type_arg_types) /* Count the struct value address, if it is passed as a parm. */ + structure_value_addr_parm); else if (TYPE_NO_NAMED_ARGS_STDARG_P (funtype)) n_named_args = 0; else /* If we know nothing, treat all args as named. */ n_named_args = num_actuals; case, I think guarding it by any target hooks is wrong, although I guess it should have been n_named_args = structure_value_addr_parm; instead of n_named_args = 0; For the second if (type_arg_types != 0 && targetm.calls.strict_argument_naming (args_so_far)) ; else if (type_arg_types != 0 && ! targetm.calls.pretend_outgoing_varargs_named (args_so_far)) /* Don't include the last named arg. */ --n_named_args; else if (TYPE_NO_NAMED_ARGS_STDARG_P (funtype)) n_named_args = 0; else /* Treat all args as named. */ n_named_args = num_actuals; bet (but no testing done, don't even know which targets return what for those hooks) we should treat those as if type_arg_types was non-NULL with 0 elements in the list, except the --n_named_args doesn't make sense because that would decrease it to -1. So perhaps if ((type_arg_types != 0 || TYPE_NO_NAMED_ARGS_STDARG_P (funtype)) && targetm.calls.strict_argument_naming (args_so_far)) ; else if (type_arg_types != 0 && ! targetm.calls.pretend_outgoing_varargs_named (args_so_far)) /* Don't include the last named arg. */ --n_named_args; else if (TYPE_NO_NAMED_ARGS_STDARG_P (funtype) && ! targetm.calls.pretend_outgoing_varargs_named (args_so_far))) ; else /* Treat all args as named. */ n_named_args = num_actuals; (or n_named_args = 0; instead of ; before the final else? Dunno). I guess we need some testsuite coverage for caller/callee ABI match of struct S { char p[64]; }; struct S foo (...); Jakub