News for hackers. Stuff that matters.
Re:Dissecting objc_msgSend on ARM64 by revelation on Saturday July 01, 2017 @08:00PM (#14679850)
This is C, I'm talking C calling convention (and x64, which is the same). Caller cleans up the stack, so va_list is a zero cost abstraction.

Citing the bastard architecture of iOS isn't really making the case for "usually".

Re:Dissecting objc_msgSend on ARM64 by mikeash on Saturday July 01, 2017 @08:37PM (#14680030)
Requiring the caller to put all arguments on the stack isn't "zero cost." For a non-variadic call on ARM64, the first eight parameters (or more, if some are floats) will be passed in registers without ever touching the stack.

On x86-64, the caller also has to set %al to the number of vector registers used for the call, and the compilers I've seen always check %al and conditionally save those registers as part of the function prologue. Cheap, but not "zero cost."

Re:Dissecting objc_msgSend on ARM64 by revelation on Saturday July 01, 2017 @09:07PM (#14680165)
va_ doesn't change the calling convention. Parameters passed as registers continue to be passed as registers.

We could probably argue this some more but I suggest you simply try it with a compiler..

Re:Dissecting objc_msgSend on ARM64 by mikeash on Saturday July 01, 2017 @10:20PM (#14680475)
Good idea!

https://gist.github.com/mikeash/ce38d3a77b88734a9e0e9dc3f352...

You'll notice how `normal` takes all of its arguments out of registers `x0` through `x7` and places them on the stack for the call to `printf`. And you'll notice how `vararg` plays a bunch of games with the stack and never touches registers `x1` through `x7`. (It still uses `x0` because the first argument is not variadic.)

On the caller side, observe how `call_normal` places its values into `x0` through `x7` sequentially and then invokes the target function, while `call_vararg` places one value into `x0` and places everything else on the stack.

So, no, it looks to me like varargs very much change the calling convention.