6.6 KiB

< Back | Summary >

Host ABI and Syscalls

This chapter defines the Application Binary Interface (ABI) between the Prometeu Virtual Machine (PVM) and the host environment. It specifies how syscalls are encoded, invoked, verified, and accounted for.

Syscalls provide controlled access to host-managed subsystems such as graphics, audio, input, asset banks, and persistent storage.

This chapter defines the contract. Individual subsystems (GFX, AUDIO, MEMCARD, ASSETS, etc.) define their own syscall tables that conform to this ABI.


1 Design Principles

The syscall system follows these rules:

  1. Deterministic: Syscalls must behave deterministically for the same inputs and frame state.
  2. Synchronous: Syscalls execute to completion within the current VM slice.
  3. Non-blocking: Long operations must be modeled as request + status polling.
  4. Capability-gated: Each syscall requires a declared capability.
  5. Stack-based ABI: Arguments and return values are passed via VM slots.
  6. Not first-class: Syscalls are callable but cannot be stored as values.

2 Syscall Instruction Semantics

The VM provides a single instruction:

SYSCALL <id>

Where:

  • <id> is a 32-bit integer identifying the syscall.

Execution steps:

  1. The VM looks up the syscall metadata using <id>.
  2. The VM verifies that enough arguments exist on the stack.
  3. The VM checks capability requirements.
  4. The syscall executes in the host environment.
  5. The syscall leaves exactly ret_slots values on the stack.

If any contract rule is violated, the VM traps.


3 Syscall Metadata Table

Each syscall is defined by a metadata entry.

SyscallMeta structure

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

Fields:

Field Description
id Unique syscall identifier
name Human-readable name
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 (for analysis/profiling)

The verifier uses this table to validate stack effects.


4 Arguments and Return Values

Syscalls use the same slot-based ABI as functions.

Argument passing

Arguments are pushed onto the stack before the syscall.

Example:

push a
push b
SYSCALL X   // expects 2 arguments

Return values

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

Example:

// before: []
SYSCALL input_state
// after: [held, pressed, released]

Slot types

Each slot contains one of the VM value types:

  • int
  • bool
  • float
  • handle
  • null

Composite return values are represented as multiple slots (stack tuples).


5 Syscalls as Callable Entities (Not First-Class)

Syscalls behave like functions in terms of arguments and return values, but they are not first-class values.

This means:

  • Syscalls can be invoked.
  • Syscalls cannot be stored in variables.
  • Syscalls cannot be passed as arguments.
  • Syscalls cannot be returned from functions.

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

Example declaration (conceptual)

host fn input_state() -> (int, int, int)

This represents a syscall with three return values, but it cannot be treated as a function value.


6 Error Model: Traps vs Status Codes

Syscalls use a hybrid error model.

Trap conditions (contract violations)

The VM traps when:

  • The syscall id is invalid.
  • The required capability is missing.
  • The stack does not contain enough arguments.
  • A handle is invalid or dead.

These are considered fatal contract violations.

Status returns (domain conditions)

Normal operational states are returned as values.

Examples:

  • asset not yet loaded
  • audio voice unavailable
  • memcard full

These are represented by status codes in return slots.


7 Capability System

Each syscall requires a capability.

Capabilities are declared by the cartridge manifest.

Example capability groups:

  • gfx
  • audio
  • input
  • asset
  • memcard

If a syscall is invoked without the required capability:

  • The VM traps.

8 Interaction with the Garbage Collector

The VM heap is managed by the GC. Host-managed memory is separate.

Heap vs host memory

Memory Managed by GC scanned
VM heap objects VM GC Yes
Asset banks Host No
Audio buffers Host No
Framebuffers Host No

Assets are addressed by identifiers, not VM heap handles.

Host root rule

If a syscall stores a handle to a VM heap object beyond the duration of the call, it must register that handle as a host root.

This prevents the GC from collecting objects still in use by the host.

This rule applies only to VM heap objects (such as closures or user objects), not to asset identifiers or primitive values.


9 Determinism Rules

Syscalls must obey deterministic execution rules.

Forbidden behaviors:

  • reading real-time clocks
  • accessing non-deterministic OS APIs
  • performing blocking I/O

Allowed patterns:

  • frame-based timers
  • request + poll status models
  • event delivery at frame boundaries

10 Cost Model and Budgeting

Each syscall contributes to frame cost.

The VM tracks:

  • cycles spent in syscalls
  • syscall counts
  • allocation cost (if any)

Example telemetry:

Frame 10231:
Syscalls: 12
Cycles (syscalls): 380
Allocations via syscalls: 2

Nothing is free.


11 Blocking and Long Operations

Syscalls must not block.

Long operations must use a two-phase model:

  1. Request
  2. Status polling or event notification

Example pattern:

asset.load(id)
...
status, progress = asset.status(id)

12 Summary

  • Syscalls are deterministic, synchronous, and non-blocking.
  • They use the same slot-based ABI as functions.
  • They are callable but not first-class.
  • Capabilities control access to host subsystems.
  • GC only manages VM heap objects.
  • Host-held heap objects must be registered as roots.
  • All syscall costs are tracked per frame.

< Back | Summary >