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:
37
src/core.zig
37
src/core.zig
@@ -208,28 +208,21 @@ pub const Compilation = struct {
|
||||
/// invoke it later without name lookup.
|
||||
pub fn invokeByFuncId(self: *Compilation, id: ir.FuncId, args: []const ir.Value) !ir.Value {
|
||||
const mod = self.ir_module orelse return error.NoIRModule;
|
||||
var interp = ir.Interpreter.init(mod, self.allocator);
|
||||
defer interp.deinit();
|
||||
interp.setSourceMap(&self.import_sources);
|
||||
if (self.ir_emitter) |*e| interp.build_config = &e.build_config;
|
||||
ir.Interpreter.last_bail_op = null;
|
||||
ir.Interpreter.last_bail_builtin = null;
|
||||
ir.Interpreter.last_bail_detail = null;
|
||||
const result = interp.call(id, args) catch |err| {
|
||||
flushInterpOutput(interp.output.items);
|
||||
return err;
|
||||
};
|
||||
flushInterpOutput(interp.output.items);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// #run / post-link callback `print` output lands here. Routes to
|
||||
/// fd 1 (stdout) so it joins the JIT-executed runtime's output
|
||||
/// stream — the user wrote `print(...)` in both call sites, so
|
||||
/// the stream split is invisible to them. issue-0047.
|
||||
fn flushInterpOutput(bytes: []const u8) void {
|
||||
if (bytes.len == 0) return;
|
||||
_ = std.c.write(1, bytes.ptr, bytes.len);
|
||||
// The build driver (post-link callback) runs on the comptime VM — NOT
|
||||
// the legacy interp. The driver allocates Lists, which the legacy interp
|
||||
// cannot grow at comptime (issue 0141: `struct_get: base has no fields`);
|
||||
// the VM can. There is **no fallback**: 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. The bail reason is in
|
||||
// `comptime_vm.last_bail_reason` (surfaced by `main.printInterpBailDiag`).
|
||||
// Post-link callbacks are nullary today (the implicit `*Context` is
|
||||
// materialized by the VM's `runEntry`); a non-empty `args` would need a
|
||||
// VM entry that marshals them, which arrives with the `on_build(config)`
|
||||
// slot (Phase 5.3) — reject it loudly rather than silently drop.
|
||||
if (args.len != 0) return error.ComptimeVmArgsUnsupported;
|
||||
const build_config = if (self.ir_emitter) |*e| &e.build_config else null;
|
||||
return ir.comptime_vm.tryEval(self.allocator, mod, id, build_config, &self.import_sources) orelse
|
||||
error.ComptimeVmBail;
|
||||
}
|
||||
|
||||
/// Get link flags accumulated from #run build blocks.
|
||||
|
||||
@@ -462,6 +462,13 @@ fn deriveOutputName(input_path: []const u8) []const u8 {
|
||||
/// and the source location (line:col) when the interpreter captured them.
|
||||
fn printInterpBailDiag(comp: *const sx.core.Compilation, label: []const u8, err: anyerror) void {
|
||||
const op = sx.ir.Interpreter.last_bail_op orelse {
|
||||
// The post-link build driver runs on the comptime VM (core.invokeByFuncId),
|
||||
// so a bail there sets `comptime_vm.last_bail_reason`, not the legacy
|
||||
// interp's statics. Surface that reason when present.
|
||||
if (sx.ir.comptime_vm.last_bail_reason) |reason| {
|
||||
std.debug.print("error: {s} failed: {s}: {s}\n", .{ label, @errorName(err), reason });
|
||||
return;
|
||||
}
|
||||
std.debug.print("error: {s} failed: {s}\n", .{ label, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user