Am 03.12.25 um 13:21 schrieb Richard Biener:
On Wed, Dec 3, 2025 at 10:32 AM Georg-Johann Lay via Gcc
<[email protected]> wrote:
Am 02.12.25 um 23:40 schrieb Andrew Pinski:
On Tue, Dec 2, 2025 at 12:45 PM Georg-Johann Lay via Gcc
<[email protected]> wrote:
Playing with a new avr function attribute, I stumbled upon this problem:
On avr, all varargs arguments are passed on the stack, even the named
ones. So I added a "rargs" function attribute that passes named args in
registers if possible. One test case looks like this:
#define RA __attribute__((rargs))
void call_rafun_cast1 (void (*f)(char, ...))
{
((RA void(*)(char,...)) f) (10);
}
void call_rafun_cast0 (RA void (*f)(char, ...))
{
((void(*)(char,...)) f) (20);
}
The code compiles as expected:
// rargs: no push/pop
call_rafun_cast1:
movw r30,r24 ; 20 [c=4 l=1] *movhi/0
ldi r24,lo8(10) ; 14 [c=4 l=1] movqi_insn/1
ijmp ; 7 [c=0 l=1] call_insn/2
// default: push/pop.
call_rafun_cast0:
ldi r18,lo8(20) ; 15 [c=4 l=1] movqi_insn/1
push r18 ; 7 [c=4 l=1] pushqi1/0
movw r30,r24 ; 23 [c=4 l=1] *movhi/0
icall ; 8 [c=0 l=1] call_insn/0
; SP += 1 ; 9 [c=8 l=1] *addhi3_sp
pop __tmp_reg__
ret ; 19 [c=0 l=1] return
Notice that cast0 has a push / pop of the argument as expected, while
cast1 hasn't, also as expected. This is all fine. Now change the code
slightly so that the function bodies become the same (pass 10 instead of
20):
void call_rafun_cast0 (RA void (*f)(char, ...))
{
((void(*)(char,...)) f) (10);
}
The code compiles to:
call_rafun_cast0:
rjmp call_rafun_cast1 ; 7 [c=0 l=1] call_insn/3
which is wrong IMO. The bodies of the functions are the same, but the
prototypes are not, so performing ICF is wrong.
I am not completely sure about a function pointer cast adding / removing
a function attribute. Though GCC seems to compile it as expected
without ICF.
So is this an ICF bug or am I missing some target hook?
Looking into the code, and looking into how fastcall works for i686
(since replacing rargs with fastcall works there), the target hook
comp_type_attributes is needed to make sure to return false for the
attribute mismatch on the types with/without the attribute.
Thanks,
Andrew Pinski
Hi Andrew,
thank you for the pointer. Though it doesn't help. For the test
program, the TARGET_COMP_TYPE_ATTRIBUTES hook isn't even called.
You likely made it a decl attribute then? I suggest to only allow the attribute
on function types.
Richard.
Ah, now I found it. The TARGET_GNU_ATTRIBUTES has an
affects_type_identity, which was false. When setting that to true,
then TARGET_COMP_TYPE_ATTRIBUTES is called as expected. Now it works.
Many thanks,
Johann
For now I only changed the cumulative args hooks, but there are some
VA_LIST and VA_ARG hooks in
https://gcc.gnu.org/onlinedocs/gccint/Register-Arguments.html where I
don't know what to do with them.
All unnamed args are passed the same way in either case; the attribute
only affects passing of named args.
GCC is current trunk.
Johann