P5.1: post-link build driver runs on the comptime VM (no fallback)

core.invokeByFuncId routes the post-link callback through comptime_vm.tryEval
instead of the legacy Interpreter. REQUIRED because the sx build driver
allocates/grows Lists, which the legacy interp can't do at comptime (issue
0141: struct_get: base has no fields); the VM can. No fallback (a
side-effecting post-link callback can't double-execute): a VM bail is a hard
build error (comptime_vm.last_bail_reason, surfaced by printInterpBailDiag).
BuildConfig + import_sources threaded in; non-empty args rejected loudly.
flushInterpOutput deleted (VM out writes direct via host-FFI).

Smoke test examples/1661-platform-post-link-vm-list (AOT): a post-link
callback grows a List to 3 + returns len==3, so the build succeeds (exit 0)
only via the VM. First corpus coverage of the post-link path.

702/0 both gates.
This commit is contained in:
agra
2026-06-19 07:20:42 +03:00
parent 2060373c16
commit 7cba33ea6d
9 changed files with 99 additions and 30 deletions

View File

@@ -80,11 +80,18 @@ with ONE welded mechanism. Branch: `reify` (off `master`). Update after every st
> (2026-06-18, user): the 37-hook BuildOptions port is DEAD — DRIVE THE BUILD PIPELINE FROM SX** (newest Log
> entry + `PLAN-COMPILER-VM.md` → Phase 5). `BuildConfig` becomes plain sx data; the compiler shrinks to a few
> `abi(.compiler)` primitives (`emit_object`/`link`/queries, explicit args, `-> !` not bool) + an `on_build`
> slot (stdlib `default_build`, user override `#run on_build = build;`). **NEXT — P5.1 (= 4E):** route the
> post-codegen / `on_build` invocation through the VM (`core.invokeByFuncId` → VM) — REQUIRED (the sx driver
> allocates `List`s; legacy interp can't — 0141, verified) — + dedicated bundle smoke tests. Then P5.2
> (primitives) · P5.3 (`on_build` slot) · P5.4 (sx `default_build` + delete `#compiler`/`compiler_call`/
> `compiler_hooks` + the S5a `build_options`/`set_post_link_callback`).
> slot (stdlib `default_build`, user override `#run on_build = build;`). **P5.1 (= 4E) DONE (2026-06-19, newest
> Log entry):** `core.invokeByFuncId` (the post-link build-driver invocation) now runs the callback on the VM
> with **NO fallback** (a side-effecting callback can't double-execute); `BuildConfig` + `import_sources` threaded
> in; VM bail → hard build error (`comptime_vm.last_bail_reason` surfaced by `main.printInterpBailDiag`). Smoke
> test `1661-platform-post-link-vm-list` (AOT) — a post-link callback that GROWS a `List` (0141: works on VM,
> bails on legacy with `struct_get`); build succeeds (exit 0) only via the VM. `flushInterpOutput` deleted (VM
> writes `out` direct via host-FFI). **702/0 both gates.** **NEXT — P5.2:** expose `emit_object` + `link`
> (reuse `target.zig`) + metadata queries (`c_object_paths`/`link_libraries`/host-triple) as `abi(.compiler)`
> primitives taking EXPLICIT args. Then P5.3 (`on_build` slot — invoke WITH the `BuildConfig` arg; needs a VM
> entry that marshals args, the gap `invokeByFuncId` rejects today) · P5.4 (sx `default_build` + delete
> `#compiler`/`compiler_call`/`compiler_hooks` + the S5a `build_options`/`set_post_link_callback`) — P5.4 kills
> the 4 strict `compiler_call` bails (1609/1614/1615/1616).
> **FINAL atomic step (4F):** (`out` already done — VM-native via libc `write`) handle `interp_print_frames` +
> flip strict-to-default (remove the fallback) + delete `interp.zig`/`Value` + re-express `define`/`make_enum`.
> See `PLAN-COMPILER-VM.md` → Phase 4 for the full plan + top risks (bundler test coverage).
@@ -396,6 +403,27 @@ when reached (sentinels or accessor fns; see the design doc Risks).
`List` growth; orthogonal, see `current/CHECKPOINT-METATYPE.md`.)
## Log
- **P5.1 (= 4E) — the post-link build driver runs on the VM (NO fallback); smoke test 1661 (2026-06-19).**
Phase 5 step 1: `core.invokeByFuncId` — the post-codegen / post-link callback invocation `main.zig` fires after
`target.link` — now routes the callback through the **comptime VM** (`comptime_vm.tryEval`) instead of the
legacy `Interpreter`. **REQUIRED** because the sx build driver allocates/grows `List`s, which the legacy interp
can't do at comptime (issue 0141: `struct_get: base has no fields`); the VM can. **NO fallback** (user
directive): a side-effecting post-link callback can't safely re-run on a second evaluator (double execution),
so a VM bail is a HARD build error — `error.ComptimeVmBail`, with the reason in `comptime_vm.last_bail_reason`
(now surfaced by `main.printInterpBailDiag`, which previously only read the legacy interp's `last_bail_*`
statics). `BuildConfig` (`&emitter.build_config`) + `import_sources` are threaded into the VM call. Deleted the
now-dead `flushInterpOutput` (the VM writes `out` directly via host-FFI — no buffer to flush). Non-empty `args`
rejected loudly (`error.ComptimeVmArgsUnsupported`) — the `on_build(config)` arg-passing entry arrives in P5.3.
**Verification:** a probe with a List-growing post-link callback FAILS on the pre-change legacy path
(`sx build` exit 1, `OutOfBounds (op=struct_get)`) and SUCCEEDS after the change (exit 0). Formalized as
`examples/1661-platform-post-link-vm-list` (`{ "aot": true }`): the callback grows a `List` to 3 + returns
`len == 3`; the build links cleanly (exit 0) and the binary prints `runtime main`. AOT snapshots the binary's
streams (build stdout discarded), so the VM-success is pinned via exit 0 + `runtime main` — a legacy regression
would flip the build to exit 1 and mismatch. **No corpus example fires post-link** (none had AOT sidecars; the
platform examples register a callback at `#run` time but run JIT) — so `invokeByFuncId` was previously untested
by the corpus; 1661 is the first coverage. The 4 strict `compiler_call` bails (1609/1614/1615/1616) are
UNAFFECTED — they bail at `#run configure()` on still-`#compiler` accessors (`set_bundle_path` etc.), killed by
P5.4, not here. **702/0 both gates.**
- **4B (VM-native diagnostics) — the metatype negative tests (1179/1180) render proper diagnostics under strict; strict gap-bails now ONLY `compiler_call` (2026-06-19).**
The legacy and VM both BAIL on a `define()` validation failure with an identical detail string; only the
host's STRICT rendering differed (generic "bailed on the VM (strict)" vs the proper "comptime type