Expand description
Common ABI trait and utilities for code generation backends.
A trait that all ABI implementations must follow, reducing code duplication and giving a consistent interface.
§Application Binary Interface (ABI) Overview
Lamina uses platform C ABIs for function calls. The ABI implementation is
abstracted through the Abi trait, which gives a consistent interface
across all backends.
§Common ABI Contract
§Function Name Mangling
All backends apply platform-specific symbol mangling:
- macOS: Functions are prefixed with underscore (e.g.,
main→_main) - Linux/Windows: Functions use their original names (e.g.,
main→main)
The mangle_function_name() method handles this automatically.
§Argument Passing
- Arguments are passed using the platform C ABI register order
- Overflow arguments (beyond register capacity) are spilled to the stack
- Integer arguments use 64-bit slots, even for narrower integer types (i8, i16, i32)
- Floating-point arguments follow platform-specific rules
Example: Function call with 3 arguments (RISC-V)
# Arguments: a0=arg1, a1=arg2, a2=arg3
mv a0, t0 # Load arg1 to a0
mv a1, t1 # Load arg2 to a1
mv a2, t2 # Load arg3 to a2
call my_function # Call functionExample: Function call with 10 arguments (x86_64 System V)
# First 6 args in registers: rdi, rsi, rdx, rcx, r8, r9
# Remaining 4 args on stack (16-byte aligned)
mov %rdi, %rax # arg1
mov %rsi, %rbx # arg2
# ... args 3-6 in rdx, rcx, r8, r9
push %r10 # arg7 on stack
push %r11 # arg8 on stack
push %r12 # arg9 on stack
push %r13 # arg10 on stack
call my_function
add $32, %rsp # Clean up stack§Return Values
- Integer return values use the C ABI integer return register
- Floating-point return values use the FP return register (if applicable)
- Void functions return nothing
Example: Return value handling
# RISC-V: return value in a0 (integer) or fa0 (float)
call my_function
mv t0, a0 # Save integer return value
# x86_64: return value in rax (integer) or xmm0 (float)
call my_function
mov %rax, %rbx # Save integer return value§Builtin Functions
Builtin functions can be overridden via the LAMINA_BUILTINS environment variable:
LAMINA_BUILTINS="malloc=jemalloc_malloc,dealloc=jemalloc_free"Every runtime helper the compiler calls is a RuntimeSymbol. Keys are the
C names (malloc, free, exit, memcpy, memmove, memset), plus the
legacy alias dealloc (free).
The compiler-rt routines for 128-bit integers (__divti3, __floattidf, …)
are keys too, so an embedder can supply them. Platform decoration (_free
on macOS) is applied to the override as well.
§Backend-Specific ABIs
See the documentation in each backend’s ABI module:
x86_64::abi- System V AMD64 and Microsoft x64aarch64::abi- AAPCS64riscv::abi- RISC-V calling conventionwasm::abi- WebAssembly stack-based calling
Structs§
- Builtin
Library - Resolves runtime helper names to the symbols the emitted code must reference.
Enums§
- Builtin
Override Error - Why a
LAMINA_BUILTINSvalue could not be read. - Runtime
Symbol - Runtime helpers the compiler calls by name.
Traits§
- Abi
- Trait defining the common interface for all ABI implementations.
Functions§
- common_
call_ stub - Helper function to create a common call_stub implementation.
- get_
free_ symbol - Helper function to get the platform-specific free symbol name.
- get_
malloc_ symbol - Helper function to get the platform-specific malloc symbol name.
- get_
printf_ symbol - Helper function to get the platform-specific printf symbol name.
- mangle_
macos_ name - Helper function to mangle function names for macOS (adds underscore prefix).
- parse_
builtin_ overrides - Parses
name=symbol,name=symbol.