On 27/02/2024 17:25, Jakub Jelinek wrote:
> 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;

I tried the above on arm, aarch64 and x86_64 and that seems fine, including the 
new testcase you added.

R.

> 
> (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
> 

Reply via email to