Skip to content

CDM ABI

Andrey Eliseev edited this page Sep 2, 2026 · 31 revisions

Note

This document describes the ABI currently used by the compiler. It is not stable and may change in the future.

1 Data types

Scalar type sizes and alignments

Type Size Alignment
void* 2 bytes 2 bytes
void(*)(void) 2 bytes 2 bytes
_Bool
bool
1 byte 1 byte
singed char
unsigned char
char
1 byte 1 byte
unsigned int
int
2 bytes 2 bytes
unsigned short
short
2 bytes 2 bytes
unsigned long
long
4 bytes 2 bytes
unsigned long long
long long
8 bytes 2 bytes
float 4 bytes 2 bytes
double 8 bytes 2 bytes
long double 16 bytes 2 bytes

Common type definitions

Type Defined as Size Alignment
size_t unsigned int 2 bytes 2 bytes
ptrdiff_t int 2 bytes 2 bytes
max_align_t int 2 bytes 2 bytes
intptr_t int 2 bytes 2 bytes
uintptr_t unsigned int 2 bytes 2 bytes
intmax_t long long 8 bytes 2 bytes
uintmax_t unsigned long long 8 bytes 2 bytes
wchar_t long 4 bytes 2 bytes
wint_t long 4 bytes 2 bytes

Other

  • Byte and word order is little-endian.
  • All scalar types at least 2 bytes large are exactly 2-byte aligned.
  • Aggregate types (structures and arrays) and unions use the strictest alignment of their fields and are padded to alignment.
  • enum types use int as their underlying type by default.
  • Floating point types use the bit representation specified by IEEE 754.

2 Calling convention

Register usage:

  • Caller-saved: r0, r1, r2, r3, processor status (PS);
  • Callee-saved: r4, r5, r6, r7 (fp), stack pointer (SP).

Parameters:

  • The first 4 GPRs (r0..r3) are used for passing function parameters.
    • Parameter order matches the numeric order of the registers.
  • If there are not enough registers, the words that don't fit are placed on the stack.
    • The caller always reserves an 8-byte space at the top of the stack (addsp -8). This space if used by the callee for spilling register parameters if the function is variadic.
    • The first word that doesn't fit is placed below the reserved bytes on the stack (SP+8 from the caller's perspective). The next word is placed below the first one (at a higher address, since the stack grows downwards), etc.
    • If a parameter consists of multiple words, it can be split between registers and stack slots.
  • Scalar types are passed directly:
    • 1- and 2-byte types are passed in one word (register or stack slot).
    • 4-byte types are passed in 2 consecutive words (low to high).
    • 8-byte types are passed in 4 consecutive words (low to high).
    • 16-byte types are passed in 8 consecutive words (low to high).
  • Aggregate types and unions are passed indirectly (by reference). The pointer must be aligned to the type's alignment. The callee must not modify the pointed-to data.

Return values:

  • Scalar types with sizes ≤ 8 bytes and pointers are returned in r0..r3 (low to high).
  • Large scalar types, aggregate types and unions: the caller allocates a buffer aligned to the type's alignment for the return value and passes a pointer to this buffer in r0 as an implicit (hidden) first parameter. The callee writes the result to this buffer and leaves the address of the buffer in r0 before returning, effectively preserving it.

Clone this wiki locally