comptime VM: general host-FFI escape — call any extern libc fn via dlsym + host_ffi (Phase 4D.1)

Replace the "extern not ported -> bail" stub in Vm.invoke with callHostExtern:
resolve the symbol via host_ffi.lookupSymbol (dlsym RTLD_DEFAULT) and dispatch
through the host_ffi trampolines, like the legacy interp.callExtern.

Marshalling is trivial now that Addr is a real host pointer (4D.0): every WORD-kind
arg passes as usize verbatim (a scalar's bits OR a pointer, no translation), and a
pointer return is a valid Addr. Picks callPtrRet (void*-ABI) for pointer-ish
returns, callIntRet (i64-ABI) otherwise; honors variadic. Non-word
(aggregate/string/float) args+returns bail loudly (4D.2 adds them). One general
mechanism for all externs, not per-builtin special cases.

New example 0636-comptime-extern-libc (#run toupper(97)/tolower(90) -> 65/122) runs
HANDLED on the VM, output byte-matching legacy. 698/0 both gates.
This commit is contained in:
agra
2026-06-18 18:00:07 +03:00
parent 625ba0fb27
commit e7a8708287
6 changed files with 106 additions and 3 deletions

View File

@@ -352,6 +352,21 @@ when reached (sentinels or accessor fns; see the design doc Risks).
`List` growth; orthogonal, see `current/CHECKPOINT-METATYPE.md`.)
## Log
- **Phase 4D.1 (VM plan) — general host-FFI escape: the VM calls any extern libc fn via dlsym + host_ffi (2026-06-18).**
Replaced the "extern not ported → bail" stub in `Vm.invoke` with `callHostExtern`: resolve the
symbol via `host_ffi.lookupSymbol` (dlsym RTLD_DEFAULT) and dispatch through the `host_ffi`
trampolines, exactly like the legacy `interp.callExtern`. **Marshalling is now trivial because
`Addr` is a real host pointer (4D.0):** every WORD-kind arg passes as `usize` verbatim — a
scalar's bits OR a pointer, no translation — and a pointer return is a valid `Addr`. Picks
`callPtrRet` (void*-ABI) for pointer-ish returns, `callIntRet` (i64-ABI) otherwise; honors
variadic (`is_variadic and args > fixed`). Non-word (aggregate/string/float) args+returns bail
loudly (no silent miscall — 4D.2 adds NUL-term cstring marshalling + float). NOT per-builtin: ONE
general mechanism for all externs. New example `0636-comptime-extern-libc` (`#run toupper(97)`/
`tolower(90)` fold to 65/122) runs **HANDLED on the VM**, output byte-matching legacy. (`abs`
doesn't dlsym-resolve on macOS — a compiler builtin — and the VM fails identically to legacy,
confirming parity.) **698/0 BOTH gates** (one new example). On `reify`. **Next (4D.2):**
string/aggregate extern args (string→NUL-term cstring) + float args/returns, then `compiler_call`
(#compiler hooks, 4D.3).
- **Phase 4D.0 (VM plan) — comptime VM memory = an ARENA of stable host allocations; `Addr` = real host pointer (2026-06-18).**
Replaced the growable `ArrayList(u8)` flat buffer (which reallocs/MOVES on growth) with a
`std.heap.ArenaAllocator`: each `allocBytes` is a separate arena allocation that never moves and