237 lines
5.2 KiB
Markdown
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>`.
|