

Amd64 and va_arg - Splines
http://blog.nelhage.com/2010/10/amd64-and-va_arg/

======
tptacek
Wow. Gross. On x86-64, caller args hit callee functions via registers, not the
stack like they do on i386. This is a performance win. But functions like
printf that take variable numbers of arguments need to go through contortions,
saving copies of register arguments and painstakingly calculating which args
would be on the stack versus registers (and their offset into the register
save area) to work the same way on x86-64 than i386.

~~~
paulbaumgart
Seems like the right trade-off to make. Variadic functions are so rarely used
in performance-critical code that a couple of extra hoops for making printf
and company work is probably worth it

It sounds like structs (at least the small ones?) get passed in registers
also. I don't really understand that. Isn't it kinda a rule of C-programming
that if you want your code to be fast, don't pass around structs? If structs
just always went onto the stack, you wouldn't have to mess around figuring out
whether its members are on the integer or floating point registers.

~~~
nelhage
The Linux kernel, for example, uses the following definitions for page-table
entries in different levels of amd64's four-level page tables:

    
    
        typedef struct { unsigned long pte; } pte_t;
        typedef struct { unsigned long pmd; } pmd_t;
        typedef struct { unsigned long pud; } pud_t;
        typedef struct { unsigned long pgd; } pgd_t;
    

That way, even though they're all represented as 64-bit values, the compiler
will catch you if you try to mix-and-match different types without doing
appropriate work.

Passing small structs in registers means that Linux can do that, and pass
around `pte_t`s as parameters, without having to worry about paying a runtime
cost for their typechecking.

~~~
caf
This is a nice demonstration that C _is_ actually (moderately) strongly typed
- it's just that the keyword that introduces a new type is "struct", not
"typedef".

------
CamperBob
I've never heard of variadic functions not being declared cdecl (_cdecl,
__cdecl, whatever). This is also the first time I've ever heard that "C
requires that code be able to call functions even if their prototype is not
visible, which means the compiler doesn’t necessarily know if it’s calling a
variadic function at any given call site." Can someone point to an
authoritative reference for this?

On Win32 (and presumably most other systems as well) it's perfectly kosher to
require variadic functions to be declared cdecl. This all sounds like a giant
nonissue to me. Add support for cdecl functions and move on.

~~~
caf
The comment about C requiring functions to be able to be called without a
prototype in scope is _not_ true, in the case of variadic functions. Calling a
variadic function without a correct prototype in scope is undefined behaviour
- so it's open to an ABI to specify a different calling convention for them.

(The relevant part of C99 is §6.5.2.2 Function Calls, p6).

