6.6 KiB
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:
- Deterministic: Syscalls must behave deterministically for the same inputs and frame state.
- Synchronous: Syscalls execute to completion within the current VM slice.
- Non-blocking: Long operations must be modeled as request + status polling.
- Capability-gated: Each syscall requires a declared capability.
- Stack-based ABI: Arguments and return values are passed via VM slots.
- 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:
- The VM looks up the syscall metadata using
<id>. - The VM verifies that enough arguments exist on the stack.
- The VM checks capability requirements.
- The syscall executes in the host environment.
- The syscall leaves exactly
ret_slotsvalues 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:
gfxaudioinputassetmemcard
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:
- Request
- 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.