prometeu-runtime/docs/runtime/specs/16-host-abi-and-syscalls.md

5.0 KiB

Host ABI and Syscalls

Domain: host ABI structure Function: normative

This chapter defines the structural ABI between the PVM and the host environment.

It focuses on:

  • syscall identity;
  • load-time resolution;
  • instruction-level call semantics;
  • metadata shape;
  • argument and return-slot contract.

Operational policies such as capabilities, fault classes, determinism, GC interaction, budgeting, and blocking are split into a companion chapter.

1 Design Principles

The syscall ABI follows these rules:

  1. Stack-based ABI: arguments and return values are passed through VM slots.
  2. Canonical identity: host services are named by stable (module, name, version).
  3. Load-time resolution: symbolic host bindings are resolved before execution.
  4. Metadata-driven execution: arity and result shape come from syscall metadata.
  5. Not first-class: syscalls are callable but not ordinary function values.

2 Canonical Syscall Identity

Syscalls are identified by a canonical triple:

(module, name, version)

Example:

("gfx", "present", 1)
("audio", "play", 2)

This identity is:

  • language-independent;
  • toolchain-stable;
  • used for linking and capability gating.

Input queries are VM-owned intrinsic calls in v1 and are outside the syscall identity space.

3 Syscall Resolution

The host maintains a registry:

(module, name, version) -> syscall_id

At load time:

  1. the cartridge declares required syscalls by canonical identity;
  2. bytecode encodes host-backed call sites as HOSTCALL <sysc_index>;
  3. the loader validates and resolves those identities;
  4. the loader rewrites HOSTCALL <sysc_index> into SYSCALL <id>;
  5. the executable image uses only numeric syscall ids at runtime.

Raw SYSCALL <id> is not valid in a PBX pre-load artifact and must be rejected there.

4 Syscall Instruction Semantics

Pre-load artifact form:

HOSTCALL <sysc_index>

Final executable form:

SYSCALL <id>

Where:

  • <sysc_index> indexes the program-declared syscall table;
  • <id> is the final numeric host syscall id.

Execution steps:

  1. the VM looks up syscall metadata by <id>;
  2. the VM ensures the argument contract is satisfiable;
  3. the syscall executes in the host environment;
  4. the syscall produces exactly the declared ret_slots.

5 Syscall Metadata Table

Each syscall is defined by metadata.

Conceptual structure:

SyscallMeta {
    id: u32
    module: string
    name: string
    version: u16
    arg_slots: u8
    ret_slots: u8
    capability: CapabilityId
    may_allocate: bool
    cost_hint: u32
}

Fields:

Field Description
id Unique numeric syscall identifier
module Canonical module name
name Canonical syscall name
version ABI version of the syscall
arg_slots Number of input stack slots
ret_slots Number of return stack slots
capability Required capability
may_allocate Whether the syscall may allocate VM heap objects
cost_hint Expected cycle cost

The loader uses this table to resolve identities and validate declared ABI shape.

6 Arguments and Return Values

Syscalls use the same slot-oriented argument/return philosophy as ordinary calls.

Argument passing

Arguments are pushed before the syscall.

Example:

push a
push b
SYSCALL X

Return values

After execution, the syscall leaves exactly ret_slots values on the stack.

Composite results use multiple stack slots rather than implicit hidden structures.

Return shape must also follow the operational policy in 16a-syscall-policies.md:

  • operations with observable operational failure paths should expose an explicit status:int return;
  • operations with no real operational error path may remain void (ret_slots = 0);
  • stack shape remains strict in both cases and must match syscall metadata exactly.

7 Syscalls as Callable Entities (Not First-Class)

Syscalls behave like call sites, not like first-class guest values.

This means:

  • syscalls can be invoked;
  • syscalls cannot be stored in variables;
  • syscalls cannot be passed as function values;
  • syscalls cannot be returned as closures.

Only user-defined functions and closures are first-class.

8 Relationship to Other Specs