0x0LearnReferenceLibrariesMigration0x0.jmp0x1b.com

ABI Guide

0x0 ABI version 0.1 is the first native runtime boundary for direct ELF

programs, compiler-emitted relocatable objects, compatibility object output,

linked executables, and the current lib0x0 archive object slice. It is

intentionally small and Linux x86-64 only. A release may claim ABI 0.1 only

when make abi-check passes for the released compiler artifacts.

Target

segment; linked executable output uses separate PT_LOAD segments for RX

text/read-only data and RW data/zero-filled .bss.

object slice; compatibility GAS assembly remains comparison coverage.

Version Marker

Generated direct ELF binaries append a NUL-terminated marker:


0x0 ABI 0.1

Compatibility object assembly emits:


.section .note.0x0.abi,"a",@note
  .asciz "0x0 ABI 0.1"

Compiler-emitted ELF64 ET_REL objects carry the same marker in

.note.0x0.abi.

The marker is the enforced ABI identity for version 0.1. Direct ELF binaries,

released compiler binaries, compiler-emitted objects, compatibility object

assembly, and linked executable outputs must contain it. Later ABI versions may

add structured metadata, but they must not weaken marker enforcement.

The independent compiler's direct ELF packager uses the same marker for every

supported runtime executable slice. Its backend gate inspects the marker with

zero-elf-info before running each emitted runtime executable.

The 0x0 linker rejects input objects with a different marker and appends the

accepted marker to linked executable output, so linked artifacts remain

auditable without re-reading their input objects.

Value Model

Runtime values are represented as a payload plus a tag:


payload: rax
tag:     r15

Current tags:


0 = Unit / nil
1 = I64 or Bool payload
2 = NUL-terminated UTF-8 Text pointer
3 = list/cons pointer

Unit uses payload 0 and tag 0.

I64 uses tag 1 and the signed 64-bit payload in rax or the corresponding

argument/stack payload slot.

Bool uses tag 1 with payload 0 for false and 1 for true.

Byte values are represented as I64 in ABI 0.1. Dedicated byte-array values

belong to the lib0x0/runtime milestone.

Source-level Option, Result, and Error values are list-backed library

conventions in ABI 0.1. They do not yet have separate runtime object tags.

Calls

Function return values use rax and r15.

The direct ELF backend passes up to six arguments as payload/tag register pairs.

The current source compiler rejects direct ELF calls or function definitions

with more than six arguments. This rejection is part of ABI 0.1; stack-passed

arguments are reserved for a future ABI version.

Payload registers:


arg0 rdi
arg1 rsi
arg2 rdx
arg3 rcx
arg4 r8
arg5 r9

Tag registers:


arg0 r10
arg1 r11
arg2 r12
arg3 r13
arg4 r14
arg5 r15

Function prologues save argument payloads and tags to stack slots. Stack slots

store payload and tag separately.

Caller-owned registers are all argument registers plus rax, r10, r11, and

r15 after a call. Callee code may use them while producing the return

payload/tag pair. Callee prologues preserve only the stack frame state needed by

the generated function body.

The generated code keeps the stack 16-byte aligned at process entry and adjusts

stack space in 16-byte payload/tag pairs for locals and saved arguments.

Text

Text values are pointers to NUL-terminated UTF-8 bytes. Current runtime text

operations scan to NUL for length and equality. Embedded NUL text is not part of

ABI 0.1.

Text-producing runtime helpers allocate writable buffers from the direct ELF

runtime arena. There is no garbage collector in ABI 0.1; allocated runtime

values are process lifetime allocations.

If the direct ELF arena cannot grow with mmap, the generated process exits

with status 1 before exposing a partial runtime value. ABI 0.1 does not

provide recoverable allocation errors at the source level.

Text ownership is immutable by convention once a value is returned. Runtime

helpers may allocate new text but must not mutate caller-provided text.

Lists

Lists use tag 3. Empty list is payload 0 with tag 3.

Cons nodes are 24-byte records:


offset 0  = car payload
offset 8  = car tag
offset 16 = cdr payload

Cons nodes are allocated from the direct ELF runtime arena.

List ownership follows the same process-lifetime rule as text. Cons nodes are

immutable after construction.

Symbols And Modules

Source imports are resolved before backend emission. Unaliased imports append

the imported functions to the compile unit. Aliased imports expose exported

functions under alias.name.

ABI 0.1 has no dynamic module initialization hook. Module forms identify the

source module for emitted OISA and diagnostics; direct ELF output lays out

functions in deterministic source/import order and enters the wrapper for

main.

Legacy object assembly names functions with zfn_ plus a sanitized source

symbol. Direct ELF whole-program output uses absolute intra-image addresses

rather than exported symbol names.

Process Boundary

Program startup preserves process metadata for argv and env. Current direct

ELF startup records the initial stack frame and runtime helpers read arguments

and environment variables from that state.

Program result printing is part of the executable wrapper, not the user

function ABI. User functions return value/tag pairs; the wrapper prints integer

or text results for current examples.

Compiler artifacts have a different executable wrapper: they read source and

output paths from process arguments, compile through the ABI 0.1 value model,

write the output file, and exit with status 0 on success.

Errors

Runtime panic exits the process with status 1. Normal generated compiler

artifacts exit with status 0 after writing output.

Structured error values in lib/core/error.0x0 are source-level conventions in

ABI 0.1; they are not yet separate runtime object layouts.

Syscall Boundary

Direct ELF output uses Linux syscalls directly for process exit, file open,

file read/write, stdin, stdout, mmap-backed allocation, and stack-limit growth.

The syscall boundary is not exposed as a stable source-level FFI in ABI 0.1;

it is a runtime implementation detail guarded by ABI tests.

Compatibility

ABI 0.1 may be consumed only by artifacts that declare the same ABI marker.

The object/linker path rejects incompatible ABI markers instead of attempting

best-effort linking.

The compatibility rule for this release is exact match: 0.1 links or imports

only with 0.1. Older or newer markers must produce a clear incompatibility

diagnostic in the current object linker.

The current object/linker ABI mismatch diagnostic is:


abi mismatch: <object> has <actual-marker>, expected 0x0 ABI 0.1

make abi-object-mismatch-check mutates a deterministic compiler-compatible

ELF64 relocatable object to ABI 9.9 and requires zero-link to reject it with

that diagnostic. The gate does not invoke the compiler; it is a lightweight

diagnostic compatibility check.

make abi-source-check is the lightweight source contract gate. It does not

compile; it verifies that abi/VERSION, this document, compiler ABI emitters,

object/assembly ABI note spellings, linker expectations, and ABI mismatch

diagnostics all agree on the same marker.

The machine-checked compatibility matrix lives at compat/abi-matrix.tsv.

make compatibility-matrix-check verifies that the matrix records ABI 0.1 as

the supported direct/object ABI and records non-0.1 object-link input as

rejected by the mismatch gate.