Variadic arguments and x64
Asked Answered
S

1

6

How do the va_arg \ va_start \ va_list \ va_end macros work under the hood in x64?

The calling convention in i386 passes parameters on the stack, hence the macro just increments some pointer that points to the stack base and forwards it. However, in x64, all parameters are passed by registers.... so what happens there? How does the called function know which registers were used to pass arguments to ensure it doesn't clobber them?

Samaniego answered 24/10, 2016 at 10:29 Comment(4)
Some (many?) compilers might pass arguments in registers in x64 mode, but this won't be an inherent x86 vs. x64 difference, it's their choice. Also, they cannot always pass all arguments in registers (a function with 100 parameters?). The va_list could hold details of how many arguments were passed in registers, and which one it has got to, but my guess is that variadic parameters are simply passed on the stack in all cases.Cresting
This blog post describes itCy
@Cresting It's not up to the compiler. Why do people believe this myth and spread it? While a compiler could do whatever it wants, a compiler like that would be worthless. A compiler targets an architecture with a pretty well defined ABI. And the currently existing x64 ABIs both specify registers for passing function arguments. Even for variadic functions (no difference between those and normal functions).Ioves
@Ioves Sorry, I was sloppy. In my mind I meant "compiler and the ABI it is targetting". One situation where a compiler that made its own choice might not be worthless would be for an embedded system, which may not follow any standard ABI. From this MSDN page it looks like Microsoft pass the first 4 arguments in registers (but the caller must leave space on the stack to act as a shadow copy if needed) and the remainder are on the stack. For unprototyped or varargs functions, FP-values in the first four are passed as both FP and integer.Cresting
I
4

This is defined by the ABI for the architecture. On the SysV ABI for amd64 (so pretty much everything other than Windows), the ABI document says (page 56 and forward):

The prologue of a function taking a variable argument list and known to call the macro va_start is expected to save the argument registers to the register save area.

Then va_list is a struct with a pointer to the register save area and the place on the stack where some additional arguments could have been passed (not all function arguments fit in registers).

Ioves answered 24/10, 2016 at 14:6 Comment(3)
this means that this needs compiler support and every variadic function should save all registers on stack?Samaniego
@DrPrItay: The ABI specifies which registers can be used for what. Only 6 of the 16 integer regs are ever used for arg-passing (in the SysV calling convention), while other registers are always allowed to be clobbered by function calls.Tnt
some explanation can be found in this blogTudor

© 2022 - 2024 — McMap. All rights reserved.