Skip to content

Commit

Permalink
[Docs] Added a calling convention summary document.
Browse files Browse the repository at this point in the history
Added a summary of x86-64 and ARM64 calling conventions, with links.
  • Loading branch information
al45tair committed Jul 19, 2021
1 parent 27a992e commit 2dab086
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 16 deletions.
206 changes: 206 additions & 0 deletions docs/ABI/CallConvSummary.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
Calling Convention Summary
==========================

Below is a summary of the calling conventions used on macOS and iOS.

The `ABI stability manifesto <../ABIStabilityManifesto.md>`_ gives more details
on the use of the Swift error return and ``self`` registers, while `The Swift
Calling Convention <CallingConvention.rst>`_ covers the specifics in more
details. (The Swift ``self`` register is known in other documents as the
"Context register".)

x86-64
------

See `Apple x86-64 Documentation`_, `System V ABI AMD64 Processor Supplement`_.

.. _Apple x86-64 Documentation: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html
.. _System V ABI AMD64 Processor Supplement: https://www.uclibc.org/docs/psABI-x86_64.pdf

Register usage
^^^^^^^^^^^^^^

+-----------+----------------------------------+----------+----------+----------+
| Register | Purpose | C++ | ObjC | Swift |
+===========+==================================+==========+==========+==========+
| ``rax`` | Return value; also, for varargs, | | | |
| | number of ``xmm`` registers used | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``rbx`` | Callee-saved register | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``rdi`` | Integer argument 1 | ``this`` | ``self`` | |
+-----------+----------------------------------+----------+----------+----------+
| ``rsi`` | Integer argument 2 | | ``_cmd`` | |
+-----------+----------------------------------+----------+----------+----------+
| ``rdx`` | Integer argument 3 | | | |
| | (2nd return value) | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``rcx`` | Integer argument 4 | | | |
| | (3rd return value) | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``r8`` | Integer argument 5 | | | |
| | (4th return value) | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``r9`` | Integer argument 6 | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``r12`` | Callee-saved register | | | Error |
| | | | | return |
+-----------+----------------------------------+----------+----------+----------+
| ``r13`` | Callee-saved register | | | ``self`` |
+-----------+----------------------------------+----------+----------+----------+
| ``r14`` | Callee-saved register | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``r15`` | Callee-saved register | | | |
| | (other platforms use as GOT ptr) | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``st0`` | Used to return ``long double`` | | | |
| | values | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``st1`` | Used to return ``long double`` | | | |
| | values | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``xmm0``- | Floating point arguments 1-8 | | | |
| ``xmm7`` | (``xmm0``-``xmm3`` also used | | | |
| | for return) | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``rsp`` | Stack pointer | | | |
+-----------+----------------------------------+----------+----------+----------+
| ``rbp`` | Callee-saved register, | | | |
| | used as frame pointer | | | |
+-----------+----------------------------------+----------+----------+----------+

Stack frame
^^^^^^^^^^^

On function entry, ``rsp+8`` is **16-byte aligned**, i.e. the start of the memory
arguments is 16-byte aligned; the initial stack pointer is shown below as "entry
``rsp``", but a typical non-leaf function will start by doing::

push %rbp
mov %rsp, %rbp
sub <local-size>, %rsp

Frameless leaf functions, however, will often not set up the frame pointer,
``rbp``, in which case they may refer to arguments relative to ``rsp`` instead.

+---------------+---------------+------------------------+
| | ``rbp+8n+16`` | memory argument *n* |
| | | |
| | ... | ... |
| | | |
| | ``rbp+16`` | memory argument 0 |
+---------------+-----------+---+------------------------+
| ↓ Current Frame | ↑ Previous Frame |
+---------------+-----------+---+------------------------+
| | ``rbp+8`` | return address |
| | | |
+---------------+---------------+------------------------+
| entry ``rsp`` | ``rbp`` | previous ``rbp`` value |
+---------------+---------------+------------------------+
| | ``rbp-8`` | |
| | | |
| | ... | local storage |
| | | |
| | ``rsp`` | |
+---------------+---------------+------------------------+
| | ``rsp-8`` | |
| | | |
| | ... | red zone |
| | | |
| | ``rsp-128`` | |
+---------------+---------------+------------------------+


ARM64
-----

See `Apple ARM64 Documentation`_, `Procedure Call Standard for the Arm 64-bit Architecture`_.

.. _Apple ARM64 Documentation: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
.. _Procedure Call Standard for the Arm 64-bit Architecture: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst

Register usage
^^^^^^^^^^^^^^

+----------+---------+-------------------------+----------+----------+----------+
| Register | Special | Purpose | C++ | ObjC | Swift |
+==========+=========+=========================+==========+==========+==========+
| ``x0`` | | Integer argument 1 | ``this`` | ``self`` | |
| | | (1st return value) | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x1`` | | Integer argument 2 | | ``_cmd`` | |
| | | (2nd return value) | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x2``- | | Integer arguments 3-8 | | | |
| ``x7`` | | (3rd-8th return values) | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x8`` | | Indirect result | | | |
| | | location register | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x16`` | ``ip0`` | Scratch registers (used | | | |
+----------+---------+ by dyld, can be used | | | |
| ``x17`` | ``ip1`` | freely otherwise) | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x18`` | | RESERVED **DO NOT USE** | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x19`` | | Callee-saved register | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x20`` | | Callee-saved register | | | ``self`` |
+----------+---------+-------------------------+----------+----------+----------+
| ``x21`` | | Callee-saved register | | | Error |
| | | | | | return |
+----------+---------+-------------------------+----------+----------+----------+
| ``x22``- | | Callee-saved registers | | | |
| ``x28`` | | | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x29`` | ``fp`` | Frame pointer | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``x30`` | ``lr`` | Link register | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``sp`` | | Stack pointer | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``v0``- | | Floating point/SIMD | | | |
| ``v7`` | | arguments 1-8 | | | |
| | | (also for return) | | | |
+----------+---------+-------------------------+----------+----------+----------+
| ``v8``- | | Callee-saved registers | | | |
| ``v15`` | | (**lower 64-bits only**)| | | |
+----------+---------+-------------------------+----------+----------+----------+

Stack frame
^^^^^^^^^^^

The stack pointer is **16-byte aligned**; on function entry, ``sp`` points at
the location shown by "entry ``sp``" below. As with x86, frameless leaf
functions may not set up ``fp``, in which case they will use ``sp`` relative
accesses.

+--------------+---------------+------------------------+
| | ``fp+8n+16`` | last memory argument |
| | | |
| | ... | ... |
| | | |
| | ``fp+16`` | memory argument 0 [1]_ |
+--------------+------------+--+------------------------+
| ↓ Current Frame | ↑ Previous Frame |
+--------------+------------+--+------------------------+
| entry ``sp`` | ``fp+8`` | saved ``lr`` |
| | | (return address) |
+--------------+---------------+------------------------+
| | ``fp`` | previous ``fp`` value |
+--------------+---------------+------------------------+
| | ``fp-8`` | |
| | | |
| | ... | local storage |
| | | |
| | ``sp`` | |
+--------------+---------------+------------------------+
| | ``sp-8`` | |
| | | |
| | ... | red zone |
| | | |
| | ``sp-128`` | |
+--------------+---------------+------------------------+

.. [1] See Apple documentation, however. Unlike the official ARM64 ABI, we pack
arguments, so this might also hold argument 1, argument 2 and so on.
14 changes: 3 additions & 11 deletions docs/ABI/RegisterUsage.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
## 64-Bit Architecture Register Usage

From Swift 5, the calling convention register allocation for 64-bit architectures is largely based on [existing](https://developer.apple.com/library/content/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html) [standards](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html), with the addition of the context and error return registers discussed in the [ABI stability manifesto](https://github.com/apple/swift/blob/main/docs/ABIStabilityManifesto.md):

| Register Purpose | ARM64 | x86_64 |
| ------------- |:-------------:| ----- |
| Context register (self) | x20 | r13 |
| Error return register | x21 | r12 |
| Struct return pointer | x8 | rax |
| Float call arguments | v0 … v7 | xmm0 … xmm7 |
| Integer call arguments | x0 … x7 | rdi, rsi, rdx, rcx, r8, r9 |
| Float return | v0 … v3 | xmm0 … xmm3 |
| Integer return | x0 … x3 | rax, rdx, rcx, r8 |
This file has been replaced by [CallConvSummary.rst](CallConvSummary.rst),
which gives information about register usage and also shows the stack frame
layouts for the 64-bit architectures.
2 changes: 1 addition & 1 deletion docs/ABIStabilityManifesto.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ Having the call context register be callee-saved is advantageous. It keeps the r

Throwing functions communicate error values to their callers through the *error* register on some platforms. The error register holds a pointer to the error value if an error occurred, otherwise 0. The caller of a throwing function is expected to quickly check for 0 before continuing on with non-error code, otherwise branching to code to handle or propagate the error. Using a callee-saved register for the error register enables free conversion from non-throwing to throwing functions, which is required to honor the subtyping relationship.

The specific registers used in these roles are documented in [another document on register usage](https://github.com/apple/swift/blob/main/docs/ABI/RegisterUsage.md).
The specific registers used in these roles are documented in [the calling convention summary document](ABI/CallConvSummary.rst).

### <a name="function-signature-lowering"></a>Function Signature Lowering

Expand Down
11 changes: 7 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,15 @@ documentation, please create a thread on the Swift forums under the
<!-- NOTE: Outdated -->
- [Lexicon.md](/docs/Lexicon.md):
Canonical reference for terminology used throughout the project.

### ABI

- [CallConvSummary.rst](/docs/ABI/CallConvSummary.rst):
A concise summary of the calling conventions used for C/C++, Objective-C
and Swift on Apple platforms. Contains references to source documents,
where further detail is required.
- [CallingConvention.rst](/docs/ABI/CallingConvention.rst):
Describes in detail the Swift calling convention.
- [GenericSignature.md](/docs/ABI/GenericSignature.md):
Describes what generic signatures are and how they are used in the ABI,
including the algorithms for minimization and canonicalization.
Expand All @@ -191,9 +197,6 @@ documentation, please create a thread on the Swift forums under the
- [Mangling.rst](/docs/ABI/Mangling.rst):
Describes the stable mangling scheme, which produces unique symbols for
ABI-public declarations.
- [RegisterUsage.md](/docs/ABI/RegisterUsage.md):
Summarizes the register allocation for ARM64 and x86_64 calling conventions,
including the context register (self) and error return register.
- [TypeLayout.rst](/docs/ABI/TypeLayout.rst):
Describes the algorithms/strategies for fragile struct and tuple layout;
class layout; fragile enum layout; and existential container layout.
Expand Down

0 comments on commit 2dab086

Please sign in to comment.