Skip to main content

Module aapcs

Module aapcs 

Source
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 yet

So 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_copy of 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.