Open ostannard opened 1 month ago
@llvm/issue-subscribers-backend-aarch64
Author: Oliver Stannard (ostannard)
CC @antangelo, who added preserve_none
support in #91046.
The issue seems to be that AArch64TargetLowering::saveVarArgRegisters
assumes that GPR arguments are only passed in X0-X7, in that order. preserve_none
(as well as ghccc
) will use the callee save registers X20-X28 before X0-X7, so the implementation incorrectly assumes that the variadic arguments passed in registers start at X0. Changing the register assignment order to begin with X0-X7 produces correct code for up to 8 supplied arguments (after which it breaks due to the above assumption being incorrect again).
I haven't looked as deeply into how this behaves on the X86 implementation, but it seems to be broken in a similar way.
To properly support varargs for preserve_none
, saveVarArgRegisters
will need to be reworked to follow the register assignment ordering from tablegen.
Can you just make varargs preserve_nonecc pass arguments the same way as the C calling convention? We could theoretically make va_start work the way you're suggesting, I guess (unlike the x86 va_list, the AAPCS64 va_list doesn't hardcode the number of registers), but it seems like a lot of complexity for little benefit.
When using the
preserve_none
calling convention attribute, we generate incorrect code for variadic arguments:The two constants of
-64
in the assembly correspond to thegr_offs
field in theva_list
, so this ends up loading the argument from the saved copy ofx0
, which the first (non-variadic) argument was passed in, instead ofx1
.Without the
preserve_none
attribute, that constant is-56
, so the argument is correctly loaded fromx1
: