# IRBackend to IRVM Lowering Specification Status: Draft v1 (Backend Baseline) Applies to: executable-backend lowering from the common `IRBackend` handoff into `IRVM` ## 1. Purpose This document defines the normative lowering contract from executable `IRBackend` to `IRVM`. Its purpose is to make backend lowering deterministic, reviewable, and compatible with runtime ISA/verification authority. `IRBackend` is the common frontend-to-backend executable handoff. It is emitted by frontends and consumed by common backend stages. Backend lowering MUST NOT require PBS AST nodes, PBS tokens, PBS parser structures, PBS semantic objects, PBS editorial objects, or equivalent language-owned objects from future frontends. ## 2. Scope This document defines: - required backend preconditions before `IRBackend -> IRVM` starts, - allowed language-neutral `IRBackend` contract concepts at the backend boundary, - `IRVM` structural obligations needed before optimization/emission, - deterministic function-id assignment and control-flow lowering obligations, - callsite lowering obligations across function, host-backed, and VM-owned intrinsic paths, - mandatory compiler-side structural pre-verification before bytecode emission, - and deterministic rejection obligations for backend-originated failures. This document does not define: - binary PBX layout details, - loader patching internals, - runtime execution internals, - one mandatory optimizer implementation, - or frontend-specific lowering rules before `IRBackend` emission. ## 3. Authority and Precedence Normative precedence: 1. Runtime authority (`docs/specs/hardware/topics/chapter-2.md`, `chapter-3.md`, `chapter-9.md`, `chapter-12.md`, `chapter-16.md`) 2. Bytecode authority (`docs/specs/bytecode/ISA_CORE.md`) 3. This document 4. Frontend-specific lowering specifications, including `docs/specs/compiler-languages/pbs/13. Lowering IRBackend Specification.md` If a rule here conflicts with higher-precedence authorities, it is invalid. ## 4. Normative Inputs This document depends on: - `docs/specs/compiler-languages/pbs/6.1. Intrinsics and Builtin Types Specification.md` - `docs/specs/compiler-languages/pbs/6.2. Host ABI Binding and Loader Resolution Specification.md` - frontend-specific lowering specifications that emit the common `IRBackend` handoff - `15. Bytecode and PBX Mapping Specification.md` - `21. IRVM Optimization Pipeline Specification.md` ## 4.1 Common IRBackend Contract At this boundary, `IRBackend` may contain only language-neutral compiler concepts required by executable backend lowering: 1. source identity and spans, 2. modules and module identifiers, 3. callable identities, signatures, names, arity, and type-shape surfaces, 4. executable functions, 5. instruction kinds and instruction metadata, 6. globals and global origins, 7. synthetic executable functions and synthetic origins, 8. host-call metadata, 9. intrinsic metadata, 10. reserved metadata required for backend lowering, 11. and required runtime or platform capabilities. The common backend contract MUST express these concepts as backend obligations, not as PBS syntax or PBS semantic rules. When a concept currently originates from PBS, the backend contract still owns only the language-neutral obligation carried by `IRBackend`. The common backend contract MUST NOT expose or require: 1. `PbsExpression`, `PbsStatement`, `PbsToken`, or equivalent PBS-owned syntax objects, 2. PBS parser cursors, parse contexts, parse nodes, or token kinds, 3. PBS semantic validator internals, 4. PBS editorial or language-service objects, 5. or any type under a language frontend package as part of the public backend handoff. ## 5. Backend Entry Preconditions Lowering from `IRBackend` to `IRVM` may start only when: 1. frontend admission to `IRBackend` is complete for the active slice, 2. required callsite categories (`CALL_FUNC`/`CALL_HOST`/`CALL_INTRINSIC`) are available, 3. required canonical host/intrinsic metadata is available for admitted callsites, 4. dependency-scoped fail-fast exclusions have already been applied at the `IRBackend` boundary, 5. compiler-selected published-wrapper entrypoint identity is present and unambiguous, 6. and target `vm_profile` is selected deterministically. ## 6. IRVM Model Obligations `IRVM` v1 is a quasi-ISA backend form: 1. it may contain Core ISA ops and internal extension ops (`IRVM_EXT`), 2. each `IRVM_EXT` must declare structural metadata equivalent to opcode-spec needs: - `pops`, - `pushes`, - `is_branch`, - `is_terminator`, 3. and `IRVM_EXT` must be eliminable before bytecode emission. `IRVM` must preserve, per function: 1. `param_slots`, 2. `local_slots`, 3. `return_slots`, 4. `max_stack_slots`, 5. function entry mapping and deterministic identity. ## 7. Control-Flow Lowering Obligations Control-flow lowering must satisfy: 1. symbolic labels are allowed internally in lowering, 2. final jump immediates must be resolved to `u32` offsets relative to function start before emission, 3. jump targets must be instruction-boundary-valid within function ranges, 4. and reachable fallthrough beyond function end without terminator is rejected. ## 8. Deterministic Function-ID Assignment Function indexing must be deterministic: 1. the compiler-selected published wrapper is the physical entrypoint, 2. the published wrapper function id is `0`, 3. remaining functions are ordered by `(moduleId -> modulePool canonical key, callable_name, source_start)`, 4. manifest-owned or name-only entrypoint fallback is forbidden, 5. and identical admitted input graphs must produce identical function-id assignments. For PBS executable lowering: - the userland callable marked with `[Frame]` remains the logical frame root, - the wrapper path must contain final `FRAME_RET`, - and lowering must preserve that distinction through `IRVM`. These PBS-facing names describe the current frontend source of the lifecycle structure. The backend-owned obligation is the neutral requirement that the compiler-selected published wrapper be the physical entrypoint and that lifecycle state remain explicit in `IRBackend`. ## 9. Callsite Lowering Obligations ### 9.1 Function calls `CALL_FUNC` lowers to `CALL ` with valid index and arity-consistent signature contracts. ### 9.2 Host-backed calls `CALL_HOST` lowers to pre-load `HOSTCALL `, not raw `SYSCALL`. When a host-backed callsite carries backend-owned symbolic asset lowering metadata: 1. the backend must validate the symbolic asset operand against the backend-owned admitted surface, 2. the backend must resolve the symbolic identity to canonical runtime-facing `asset_id`, 3. and the final host-backed lowering path must consume the resolved `asset_id`, not the original symbolic address. ### 9.3 VM-owned intrinsic calls `CALL_INTRINSIC` lowers to VM-owned intrinsic path and must remain distinct from host-binding paths. Final intrinsic id resolution rules: 1. compiler must resolve final intrinsic ids from the canonical ISA-scoped intrinsic registry artifact, 2. compiler-local hardcoded maps or runtime-source parsing must not be authoritative identity sources, 3. runtime and compiler consumers must validate parity against the same canonical artifact in strict CI mode. ### 9.4 Closure and coroutine constraints (v1) 1. closure calls with unknown static callee are rejected in v1, 2. `SPAWN` and `YIELD` are outside the executable `core-v1` claim scope and MUST be rejected as unsupported forms in v1 backend admission, 3. `SPAWN` argument-count and `YIELD` stack-shape invariants remain reserved for a future profile that explicitly admits these opcodes, 4. and any profile that admits `SPAWN`/`YIELD` MUST publish dedicated conformance evidence before claiming support. ## 10. Mandatory Compiler-Side Pre-Verification Before bytecode emission, backend must run structural pre-verification on lowered `IRVM` (after resolving to Core-ISA-compatible form), covering at minimum: 1. jump target validity, 2. stack-depth join consistency, 3. underflow/overflow against declared limits, 4. return-shape consistency, 5. function-id validity, 6. callsite arity consistency, 7. and structural validity of host/intrinsic call forms. 8. and structural validity of backend-owned symbolic-to-operational rewrites such as `Addressable -> asset_id`. For host-backed asset calls in v1, this validation includes backend-owned symbolic-to-operational rewrites selected by preserved host metadata. PBS currently emits this designation from metadata such as `[AssetLowering(param = N)]`, but final operational resolution is a common backend obligation. This pre-verification does not replace runtime verifier authority. ## 11. Deterministic Rejection Policy When backend lowering fails at this boundary: 1. rejection must be deterministic, 2. diagnostics identity and phase must remain stable, 3. and source attribution must be preserved whenever the failure remains source-attributable and user-actionable. ## 12. Explicit Deferrals The following are intentionally deferred: - optimizer pass catalog and tuning policy, - richer internal IR analysis models beyond v1 obligations, - advanced closure/lifetime optimizations beyond v1 constraints, - and executable support for `SPAWN`/`YIELD` in `core-v1`. ## 13. Non-Goals - Defining one in-memory IR implementation graph. - Redefining runtime verifier/loader internals. - Defining PBX binary chunk policy in this document. ## 14. Exit Criteria This document is healthy when: 1. `IRBackend -> IRVM` obligations are explicit and testable, 2. deterministic function/call/control-flow lowering rules are explicit, 3. mandatory pre-verification boundary is explicit, 4. common backend obligations are not described as owned by PBS, 5. frontend-specific lowering specs only own emission into `IRBackend`, 6. and scope boundaries with optimization/emission specs are explicit.