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

203 lines
6.5 KiB
Markdown

# 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.
6. **Status-first operational policy**: across syscall domains, operationally observable failure must surface through explicit `status` values, while only structural violations fault as `Trap` and only internal invariant breaks escalate as `Panic`.
## 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`.
The execution result must respect the canonical runtime boundary defined with [`16a-syscall-policies.md`](16a-syscall-policies.md):
- successful or operationally rejected execution returns values in the declared stack shape;
- `Trap` is reserved for structural ABI misuse or invalid call shape;
- `Panic` is reserved for runtime/host invariant failure.
## 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 transversal status-first policy in [`16a-syscall-policies.md`](16a-syscall-policies.md):
- when a syscall exposes operational failure, `status:int` is the canonical first return slot;
- operations with observable operational failure paths must expose that explicit `status:int` return;
- operations with no real operational error path may remain `void` (`ret_slots = 0`);
- if extra payload is returned together with `status`, the payload must follow the leading status slot in the declared stack shape;
- stack shape remains strict in both cases and must match syscall metadata exactly.
### MEMCARD game surface (`mem`, v1)
The game memcard profile uses module `mem` with status-first return shapes.
`mem` is a domain layer backed by runtime `fs` (it is not a separate storage backend).
Canonical operations in v1 are:
- `mem.slot_count() -> (status, count)`
- `mem.slot_stat(slot) -> (status, state, used_bytes, generation, checksum)`
- `mem.slot_read(slot, offset, max_bytes) -> (status, payload_hex, bytes_read)`
- `mem.slot_write(slot, offset, payload_hex) -> (status, bytes_written)`
- `mem.slot_commit(slot) -> status`
- `mem.slot_clear(slot) -> status`
Semantics and domain status catalog are defined by [`08-save-memory-and-memcard.md`](08-save-memory-and-memcard.md).
## 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
- [`16a-syscall-policies.md`](16a-syscall-policies.md) defines operational policies layered on top of this ABI.
- [`15-asset-management.md`](15-asset-management.md) defines asset-domain semantics behind some syscall families.
- [`08-save-memory-and-memcard.md`](08-save-memory-and-memcard.md) defines persistent save-domain semantics.
- [`02a-vm-values-and-calling-convention.md`](02a-vm-values-and-calling-convention.md) defines the slot/call philosophy reused by the syscall ABI.