prometeu-runtime/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md
2026-03-24 13:40:45 +00:00

237 lines
5.2 KiB
Markdown

# PR-001 Runtime Builtin Registry and Intrinsic Metadata
## Goal
Introduce the runtime-owned metadata layer required for VM-owned builtin types
and intrinsic operations without touching the host syscall path.
This PR creates the semantic foundation that the frontend can target later.
## Why
Today the host-backed path already exists conceptually:
- canonical host identity,
- PBX `SYSC`,
- `HOSTCALL`,
- loader resolution,
- final `SYSCALL`.
Builtin semantics need a different ownership path:
- runtime-owned builtin type metadata,
- runtime-owned intrinsic metadata,
- flattened slot layouts,
- and VM execution that never crosses the host boundary.
Without this layer, the runtime will be forced to encode builtin behavior as
ad hoc helpers or as pseudo-syscalls, both of which conflict with the PBS model.
## Scope
Add runtime data structures and lookup APIs for:
- builtin type identity,
- builtin field layout,
- builtin constant identity,
- intrinsic identity,
- intrinsic stack layouts,
- and intrinsic implementation registration.
Do not add bytecode execution changes in this PR.
Do not add loader-side host changes in this PR.
## Required Runtime Concepts
### 1. Builtin type identity
Canonical builtin identity must be:
```text
(name, version)
```
Examples:
- `("color", 1)`
- `("vec2", 1)`
- `("pixel", 1)`
This is distinct from source-visible PBS names such as `Color` or `Vec2`.
### 2. Builtin layout descriptor
Introduce a runtime descriptor roughly shaped like:
```text
BuiltinTypeMeta {
id: u32
name: string
version: u16
fields: [BuiltinFieldMeta]
flat_slot_layout: [AbiType]
flat_slot_width: u16
}
```
with:
```text
BuiltinFieldMeta {
name: string
start_slot: u16
field_type: BuiltinLayoutType
flat_slot_width: u16
}
```
`BuiltinLayoutType` should support:
- fixed-width scalar runtime types,
- builtin nominal type references,
- and recursively flattenable aggregate builtin layouts.
### 3. Builtin constant descriptor
Introduce a constant registry keyed by:
```text
(target, name, version)
```
Examples:
- `("vec2", "zero", 1)`
This registry must return either:
- direct materialization metadata,
- or a runtime-owned constant implementation hook.
### 4. Intrinsic descriptor
Introduce an intrinsic registry keyed by:
```text
(owner, name, version)
```
Examples:
- `("vec2", "dot", 1)`
- `("vec2", "length", 1)`
Descriptor shape should include at minimum:
```text
IntrinsicMeta {
id: u32
owner: string
name: string
version: u16
arg_layout: [AbiType]
ret_layout: [AbiType]
deterministic: bool
may_allocate: bool
}
```
## Design Rules
1. This registry is runtime-owned, not host-owned.
2. It must not reuse `SYSC`.
3. It must not depend on capability grants.
4. It must not resolve through the host syscall registry.
5. It must preserve flattened slot width for verifier and executor use.
6. It must preserve nominal builtin identity even when two builtins share the same width.
## Representation Guidance
### Scalars
Support at least:
- `int`
- `float`
- `bool`
- builtin nominal scalars such as `color`
For nominal scalars like `color`, allow either:
- a dedicated runtime value variant,
- or a 1-slot carrier with explicit builtin type tagging in metadata.
The important requirement is that `color` remain semantically distinct from a
plain `int` even if it shares width.
### Aggregates
Builtin aggregates such as `vec2` and `pixel` should remain stack-shaped.
The registry must treat them as:
- fixed-width,
- finite,
- flattenable,
- and non-heap in this phase.
No heap object model is required.
## Suggested API Surface
Introduce runtime APIs along these lines:
- `lookup_builtin_type(name, version) -> BuiltinTypeMeta`
- `lookup_builtin_constant(target, name, version) -> BuiltinConstMeta`
- `lookup_intrinsic(owner, name, version) -> IntrinsicMeta`
- `lookup_intrinsic_by_id(id) -> IntrinsicMeta`
Avoid exposing host-like resolution APIs for this subsystem.
## Out of Scope
- `INTRINSIC` opcode execution
- `INTRCALL` preload resolution
- loader patching
- frontend lowering
- host integration
- HAL color adaptation
## Acceptance Criteria
1. Runtime contains a distinct builtin/intrinsic registry subsystem.
2. Registry keys use canonical builtin and intrinsic identities, not source aliases.
3. Builtin layouts support recursive flattening and expose total flat slot width.
4. Builtin constants have a dedicated registry keyed separately from intrinsics.
5. No part of the implementation routes through host syscall metadata.
6. Unit tests cover lookup and flattening for `color`, `vec2`, and `pixel`.
## Test Cases
### Builtin layout flattening
- `color` flattens to width `1`
- `vec2` flattens to width `2`
- `pixel(x: int, y: int, color: color)` flattens to width `3`
### Nested field offsets
- `vec2.x` starts at slot `0`
- `vec2.y` starts at slot `1`
- `pixel.color` starts at slot `2`
### Intrinsic metadata
- `vec2.dot` has arg width `4` and ret width `1`
- `vec2.length` has arg width `2` and ret width `1`
## Notes for Follow-up PRs
This PR should intentionally stop short of execution.
The next PR should consume these descriptors in:
- bytecode decoding,
- verifier stack-effect calculation,
- and runtime dispatch for `INTRINSIC <id>`.