So I was reading the SYSTEM V AMD64 ABI and there it was written that we have to use vector registers to save the stdargs and set AL to the number of registers that has been used to put the arguments.
Why do I need to use vector registers? Can't we just put them into stack and set the AL register to the number of arguments that has been in stack?
- 33,889
- 7
- 43
- 76
-
where is it written? – koo5 Nov 27 '21 at 13:28
-
You use vector registers under certain circumstances outlined in the ABI. In those cases, if you intend to follow the ABI e.g. because you need to interoperate with other functions that expect you to, you must of course adhere to the rules. The called function will look for the arguments in the vector registers so if you push to the stack they won't be found. Between your own functions you can do whatever you want. – Jester Nov 27 '21 at 13:33
-
1Technically the compiler author is free to choose whatever ABI they like, including a stack based one. Stack based is slower and consumes more memory making it less desirable. When interfacing with a specific compiler and version you must conform to the calling convention for that compiler. – old_timer Nov 27 '21 at 19:13
-
2If you pass parameters differently for varargs functions, then calling unprototyped functions becomes expensive since the caller has to pass parameters *twice*, once as fixed-arity and once as vararg, since it doesn't know whether the unprototyped function is fixed-arity or vararg. In this example, it means that calls to unprototyped functions would have to spill floating point variables to the stack **and** put them in vector registers. Forced spilling would negate any benefits of a register-based calling convention. – Raymond Chen Nov 28 '21 at 13:09
1 Answers
Because that's where the callee will look for them, obviously.
Did you mean to ask why the calling convention was designed that way, rather than using stack args for variadic functions like I think MacOS does? (At least for AArch64, I forget if MacOS changed anything for x86-64)
Note that only FP values are passed in XMM regs, which for non-variadic functions is where the caller will want them.
x86-64 SysV just passes args the same was as for non-variadic functions, with AL as an optimization so callees can avoid dumping all 8 possible arg-passing registers to the stack if there are no FP args. (You can't put your FP args on the stack and pass AL=0; callees don't have to support looking in different places for the first FP vararg depending on the incoming AL value.)
Old GCC used to make code that did a computed jump into a sequence of movaps stores to save the actually-used XMM regs. Modern GCC just saves all or nothing with a test/jcc over the block of 8 stores. With older GCC, the ABI requirement that AL had to be in [0..8] mattered, and breaking that could lead to wild jumps. With modern GCC, the only bad thing that can happen is incorrectly passing AL=0 when there are FP args, so the function reads whatever garbage got left in the save area.
Probably it would have been better for callers to pass FP varargs on the stack for variadic functions, maybe even for integer, too, so they'd form an array the function could index without a bunch of extra logic.
As I mentioned, I think that's what MacOS does on ARM64.
- 45,431
- 5
- 48
- 98
- 328,167
- 45
- 605
- 847
-
Yes I meant to say why the ABI was designed that way... I got that I need to use XMM registers for FPN, but why use it for ints too? Can't you just move it to stack? If it were a normal function and 6th args are also passed, then the next one will be in stack. So make the same for stdargs so, why pass them to XMM regs? FP should be passed to XMM, I got that, but why ints too? – Nov 28 '21 at 11:39
-
@MostofaHimal: x86-64 SysV never passes ints in XMM regs, except for SIMD integer vector types like `__m128i`. See https://godbolt.org/z/4vvsqb351 for example passing ten `int` args to printf after the format string. No XMM regs, AL=0. My answer on [Why not store function parameters in XMM vector registers?](https://stackoverflow.com/q/33707228) explains why that would indeed have been a poor design for most use-cases, one which the designers of x86-64 SysV (gcc devs including Jan Hubicka) didn't make. – Peter Cordes Nov 28 '21 at 11:47
-
oh thnx, I was thinking maybe int params have to be passed to xmm registers. Now it makes sense. Thanks again for the answer and replies up – Nov 28 '21 at 13:14