Expand description
The AAPCS64 walk, which is the SysV one counting down rather than up.
Design: spec/12-abi-and-runtime.md, and the procedure call standard’s appendix on va_arg,
which is where the layout and every step below come from.
The callee spills the argument registers the same way a SysV one does, eight general purpose registers and eight vector ones, and the list says how far into each the walk has got. What is different is how it says it. There are two pointers to the top of the two halves of the save area and two offsets that start negative and count up to zero:
offset 0 __stack the next argument that came in the caller's memory
offset 8 __gr_top the end of the general purpose half of the save area
offset 16 __vr_top the end of the vector half
offset 24 __gr_offs minus the bytes of the general purpose half not walked yet
offset 28 __vr_offs minus the bytes of the vector half not walked yetSo an argument is in the save area when its offset is still negative after the walk steps past it, and the address it is at is the top plus the offset before the step. An offset that is zero or more to start with means that half has run out, and the argument is in the caller’s memory, as is one the step takes past zero. The step is stored either way, which is what the standard does and what keeps every argument after one that did not fit in memory as well.
A general purpose slot is eight bytes and a vector one is sixteen, and neither changes with what
is in it: a float is the low four bytes of its slot and a long double is all sixteen.
§Objects
A structure of sixteen bytes or less that is not made of floats arrived in one or two general
purpose registers, and since those are next to each other in the save area the object is too, so
its address is an address in the area. One aligned to sixteen starts on an even register, which
is the offset rounded up to sixteen before the step. An __int128 is read as one of these.
A structure made of up to four floats of one kind arrived one member to a vector register, and the members are sixteen bytes apart in the area, so it is copied out into a buffer the way a SysV object split between two files is, and the answer is the buffer.
Anything larger travelled as the address of a copy the caller made, which is one general purpose slot, and the answer is what is in it.
In the caller’s memory, every argument takes a whole number of eight byte words and one aligned to sixteen starts on a boundary of sixteen.
§Apple’s platforms
Apple’s AArch64 puts every argument the signature does not name in the caller’s memory, so its
list is only the __stack pointer, at the same offset of zero, and its walk is the memory half
of this one with no question to ask first.
Constants§
- GR_OFFS
- Where the offset into the general purpose half is.
- GR_TOP
- Where the pointer to the end of the general purpose half of the save area is.
- SIZE
- How many bytes the list is, which is what a
va_copyof one moves. - STACK
- Where the pointer to the next argument in the caller’s memory is.
- VR_OFFS
- Where the offset into the vector half is.
- VR_TOP
- Where the pointer to the end of the vector half is.