P5.2: emit_object() -> string query primitive
The compiler emits the sx object eagerly (the Zig driver, before the post-link callback), so emit_object is a QUERY (not an action): it returns the path from a new BuildConfig.object_path field main.zig forwards — no driver vtable. This completes the build-pipeline QUERY primitives (emit_object / c_object_paths / link_libraries); only link (the genuine action) remains for the vtable step. Extended examples/1662 to also assert emit_object().len > 0. 703/0 both gates.
This commit is contained in:
@@ -94,11 +94,14 @@ with ONE welded mechanism. Branch: `reify` (off `master`). Update after every st
|
|||||||
> the call's result type (`ins.ty`). Legacy handlers bail loudly (VM-only by nature — post-link). Smoke test
|
> the call's result type (`ins.ty`). Legacy handlers bail loudly (VM-only by nature — post-link). Smoke test
|
||||||
> `1662-platform-build-pipeline-queries` (AOT, C companion → 1 object): a post-link callback checks the VM-built
|
> `1662-platform-build-pipeline-queries` (AOT, C companion → 1 object): a post-link callback checks the VM-built
|
||||||
> list is well-formed; build exit 0 ONLY if so (negative-probe verified: wrong count → "post-link callback
|
> list is well-formed; build exit 0 ONLY if so (negative-probe verified: wrong count → "post-link callback
|
||||||
> returned false", exit 1). **703/0 both gates.** **NEXT — P5.2b: `emit_object` + `link` (the ACTIONS).** These
|
> returned false", exit 1). **`emit_object() -> string` ALSO landed** (a QUERY — the Zig driver emits eagerly, the
|
||||||
> are NOT data reads — in the end state the Zig driver stops auto-emitting/auto-linking and the sx driver calls
|
> primitive returns `BuildConfig.object_path`; NO vtable). So all three QUERY primitives are done. **703/0 both
|
||||||
> them, so they need the driver-restructuring (a callback vtable the host installs into the VM, since
|
> gates.** **NEXT — P5.2b: `link(...) -> !` (the one genuine ACTION).** In the end state the Zig driver stops
|
||||||
> `comptime_vm.zig` can't depend on `core`/`main`/`target`). `link` is fallible (`-> !`) — its failable return
|
> auto-linking and the sx driver calls `link`, so it needs the driver-restructuring (a callback vtable the host
|
||||||
> shape is the new VM piece. Then P5.3 (`on_build` slot — invoke WITH the `BuildConfig` arg; needs a VM entry
|
> installs into the VM, since `comptime_vm.zig` can't depend on `core`/`main`/`target`) + a List(string)-arg
|
||||||
|
> READER (inverse of `makeStringList`) + the fallible `-> !` return shape (a `(value…, tag=0)` tuple, since `!T`
|
||||||
|
> is a tuple — `makeOkFailable`). Build it tested via a post-link callback linking to a TEMP output (avoids
|
||||||
|
> clobbering the real binary; the Zig driver still links until P5.4). 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
|
> 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
|
> `#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).
|
> the 4 strict `compiler_call` bails (1609/1614/1615/1616).
|
||||||
@@ -429,7 +432,12 @@ when reached (sentinels or accessor fns; see the design doc Risks).
|
|||||||
`examples/1662-platform-build-pipeline-queries` (AOT + a 1-line C `#source` → exactly one C object): a post-link
|
`examples/1662-platform-build-pipeline-queries` (AOT + a 1-line C `#source` → exactly one C object): a post-link
|
||||||
callback asserts `c_object_paths().len == 1`, `items[0].len > 0`, and iterates `link_libraries()` (liveness
|
callback asserts `c_object_paths().len == 1`, `items[0].len > 0`, and iterates `link_libraries()` (liveness
|
||||||
touch) — build exit 0 only if the VM-built list is well-formed. **Negative-probe verified** a real guard (forcing
|
touch) — build exit 0 only if the VM-built list is well-formed. **Negative-probe verified** a real guard (forcing
|
||||||
`len != 2` → "post-link callback returned false", build exit 1). **No unit test for `makeStringList`** —
|
`len != 2` → "post-link callback returned false", build exit 1). **`emit_object() -> string` ALSO landed (same
|
||||||
|
step):** a QUERY, not an action — the compiler emits the object eagerly (the Zig driver, before the callback),
|
||||||
|
so the primitive just returns the path from a new `BuildConfig.object_path` field `main.zig` forwards (no
|
||||||
|
driver vtable needed). 1662's callback now also asserts `emit_object().len > 0`. So ALL THREE query primitives
|
||||||
|
(`emit_object`/`c_object_paths`/`link_libraries`) are done; only `link` (the genuine ACTION) remains. **No unit
|
||||||
|
test for `makeStringList`** —
|
||||||
constructing a `List(string)` `TypeId` in the test harness needs generic instantiation; the corpus test
|
constructing a `List(string)` `TypeId` in the test harness needs generic instantiation; the corpus test
|
||||||
exercises the real stdlib type end-to-end with a non-empty list + a negative guard instead. **`emit_object` +
|
exercises the real stdlib type end-to-end with a non-empty list + a negative guard instead. **`emit_object` +
|
||||||
`link` (the ACTIONS) deferred to P5.2b** — they must replace the Zig driver's auto-emit/auto-link (not duplicate
|
`link` (the ACTIONS) deferred to P5.2b** — they must replace the Zig driver's auto-emit/auto-link (not duplicate
|
||||||
|
|||||||
@@ -509,10 +509,13 @@ The compiler's whole post-IR role: codegen → build the CLI-derived `BuildConfi
|
|||||||
serviced by `comptime_vm.callCompilerFn` over `BuildConfig` fields `main.zig` forwards; new VM `makeStringList`
|
serviced by `comptime_vm.callCompilerFn` over `BuildConfig` fields `main.zig` forwards; new VM `makeStringList`
|
||||||
builds the `List(string)` in flat memory from the call's result type (`ins.ty` now threaded through
|
builds the `List(string)` in flat memory from the call's result type (`ins.ty` now threaded through
|
||||||
`invoke`/`callCompilerFn`). Smoke test `1662-platform-build-pipeline-queries` (AOT + C companion). 703/0 both
|
`invoke`/`callCompilerFn`). Smoke test `1662-platform-build-pipeline-queries` (AOT + C companion). 703/0 both
|
||||||
gates. **P5.2b — the ACTIONS (`emit_object -> !string`, `link(...) -> !`, reuse `target.zig`):** still TODO —
|
gates. **`emit_object() -> string` is also DONE (2026-06-19)** as a QUERY (not an action): the Zig driver emits
|
||||||
they replace the Zig driver's auto-emit/auto-link, so they need the driver restructuring + a host-installed
|
the object eagerly, so the primitive just returns the path from `BuildConfig.object_path` (no vtable). So all
|
||||||
callback vtable (`comptime_vm.zig` can't depend on `core`/`main`/`target`); `link`'s fallible `-> !` return is
|
three QUERY primitives are done. **P5.2b — `link(...) -> !` (the one genuine ACTION):** still TODO — it replaces
|
||||||
the new VM shape.
|
the Zig driver's auto-link, so it needs the driver restructuring + a host-installed callback vtable
|
||||||
|
(`comptime_vm.zig` can't depend on `core`/`main`/`target`) + a `List(string)`-arg reader (inverse of
|
||||||
|
`makeStringList`) + the fallible `-> !` return (a `(value…, tag=0)` tuple, since `!T` is a tuple). Test it via a
|
||||||
|
post-link callback linking to a TEMP output (the Zig driver still links until P5.4).
|
||||||
- **P5.3 — `on_build` slot:** a comptime-assignable compiler slot (GENERALIZES today's `post_link_callback_fn`:
|
- **P5.3 — `on_build` slot:** a comptime-assignable compiler slot (GENERALIZES today's `post_link_callback_fn`:
|
||||||
an assignable typed global with a stdlib default, vs a setter). `#run on_build = build;` captures the
|
an assignable typed global with a stdlib default, vs a setter). `#run on_build = build;` captures the
|
||||||
`FuncId`; the compiler invokes it post-codegen with the CLI-derived `BuildConfig`.
|
`FuncId`; the compiler invokes it post-codegen with the CLI-derived `BuildConfig`.
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
#import "modules/build.sx";
|
#import "modules/build.sx";
|
||||||
#import "modules/std/build.sx";
|
#import "modules/std/build.sx";
|
||||||
|
|
||||||
// P5.2 smoke test — the build-pipeline metadata queries (`c_object_paths` /
|
// P5.2 smoke test — the build-pipeline query primitives (`c_object_paths` /
|
||||||
// `link_libraries`) run on the comptime VM and return a `List(string)` the VM
|
// `link_libraries` / `emit_object`) run on the comptime VM: the list queries
|
||||||
// builds in flat memory. Registered as a post-link callback (which runs on the
|
// return a `List(string)` the VM builds in flat memory; `emit_object` returns
|
||||||
// VM — core.invokeByFuncId), so the lists are live there.
|
// the compiler-emitted object path. Registered as a post-link callback (which
|
||||||
|
// runs on the VM — core.invokeByFuncId), so the build state is live there.
|
||||||
//
|
//
|
||||||
// The `#import c` source compiles to one `.o`, so `c_object_paths()` must return
|
// The `#import c` source compiles to one `.o`, so `c_object_paths()` must return
|
||||||
// a one-element list whose single string is the (non-empty) object path. AOT
|
// a one-element list whose single string is the (non-empty) object path. AOT
|
||||||
@@ -21,6 +22,8 @@ c_marker :: () -> i64 extern;
|
|||||||
check :: () -> bool abi(.compiler) {
|
check :: () -> bool abi(.compiler) {
|
||||||
objs := c_object_paths();
|
objs := c_object_paths();
|
||||||
libs := link_libraries();
|
libs := link_libraries();
|
||||||
|
obj := emit_object(); // the compiler-emitted sx object path
|
||||||
|
if obj.len == 0 { return false; }
|
||||||
if objs.len != 1 { return false; }
|
if objs.len != 1 { return false; }
|
||||||
if objs.items[0].len == 0 { return false; }
|
if objs.items[0].len == 0 { return false; }
|
||||||
// `link_libraries` must be a well-formed (possibly empty) list — touch each
|
// `link_libraries` must be a well-formed (possibly empty) list — touch each
|
||||||
|
|||||||
@@ -15,3 +15,8 @@
|
|||||||
// the linker. Answered from the compiler's accumulated build state.
|
// the linker. Answered from the compiler's accumulated build state.
|
||||||
c_object_paths :: () -> List(string) abi(.compiler);
|
c_object_paths :: () -> List(string) abi(.compiler);
|
||||||
link_libraries :: () -> List(string) abi(.compiler);
|
link_libraries :: () -> List(string) abi(.compiler);
|
||||||
|
|
||||||
|
// The object file the compiler emitted for this build. The compiler emits it
|
||||||
|
// eagerly; this returns its path (a query, not an action). The sx driver passes
|
||||||
|
// it to `link` alongside the C objects.
|
||||||
|
emit_object :: () -> string abi(.compiler);
|
||||||
|
|||||||
@@ -66,6 +66,12 @@ pub const BuildConfig = struct {
|
|||||||
c_object_paths: []const []const u8 = &.{},
|
c_object_paths: []const []const u8 = &.{},
|
||||||
link_libraries: []const []const u8 = &.{},
|
link_libraries: []const []const u8 = &.{},
|
||||||
|
|
||||||
|
/// Path of the object file the compiler emitted for this build (`.sx-tmp/main.o`
|
||||||
|
/// or the cached `.o`). Forwarded by main.zig before the post-link callback so
|
||||||
|
/// the sx build driver can read it via the `emit_object()` compiler primitive
|
||||||
|
/// (the compiler emits the object eagerly; the primitive returns its path).
|
||||||
|
object_path: ?[]const u8 = null,
|
||||||
|
|
||||||
/// Frameworks the binary links against (`-framework` names) and
|
/// Frameworks the binary links against (`-framework` names) and
|
||||||
/// the search paths to look them up in (`-F` directories), forwarded
|
/// the search paths to look them up in (`-F` directories), forwarded
|
||||||
/// from the link step so the sx bundler can embed them into
|
/// from the link step so the sx bundler can embed them into
|
||||||
|
|||||||
@@ -69,14 +69,15 @@ pub const bound_fns = [_]BoundFn{
|
|||||||
// recognizes the names as compiler-API functions.
|
// recognizes the names as compiler-API functions.
|
||||||
.{ .sx_name = "c_object_paths", .handler = handleBuildPipelineQuery },
|
.{ .sx_name = "c_object_paths", .handler = handleBuildPipelineQuery },
|
||||||
.{ .sx_name = "link_libraries", .handler = handleBuildPipelineQuery },
|
.{ .sx_name = "link_libraries", .handler = handleBuildPipelineQuery },
|
||||||
|
.{ .sx_name = "emit_object", .handler = handleBuildPipelineQuery },
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Legacy-path stub for the Phase 5 build-pipeline metadata queries — see the
|
/// Legacy-path stub for the Phase 5 build-pipeline primitives — see the
|
||||||
/// `bound_fns` comment. These return a `List(string)` the legacy `Value` model
|
/// `bound_fns` comment. The only caller (the post-link build driver) runs on the
|
||||||
/// can't faithfully build (issue 0141), and the only caller (the post-link
|
/// VM (`core.invokeByFuncId`), so these legacy handlers are never reached; they
|
||||||
/// callback) runs on the VM, so bail loudly here instead of guessing.
|
/// bail loudly instead of fabricating a silent result.
|
||||||
fn handleBuildPipelineQuery(_: *Interpreter, _: []const Value) InterpError!Value {
|
fn handleBuildPipelineQuery(_: *Interpreter, _: []const Value) InterpError!Value {
|
||||||
Interpreter.last_bail_detail = "build-pipeline query (c_object_paths/link_libraries) is VM-only (post-link); not available on the legacy interpreter";
|
Interpreter.last_bail_detail = "build-pipeline primitive (emit_object/c_object_paths/link_libraries) is VM-only (post-link); not available on the legacy interpreter";
|
||||||
return error.CannotEvalComptime;
|
return error.CannotEvalComptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1469,6 +1469,17 @@ pub const Vm = struct {
|
|||||||
return self.failMsg("comptime link_libraries: no build config threaded into the VM");
|
return self.failMsg("comptime link_libraries: no build config threaded into the VM");
|
||||||
return try self.makeStringList(table, result_ty, bc.link_libraries);
|
return try self.makeStringList(table, result_ty, bc.link_libraries);
|
||||||
}
|
}
|
||||||
|
// `emit_object() -> string` — the compiler emits the object eagerly (the Zig
|
||||||
|
// driver, before the post-link callback); this returns its path. A query,
|
||||||
|
// not an action — so no driver callback is needed (unlike `link`).
|
||||||
|
if (std.mem.eql(u8, name, "emit_object")) {
|
||||||
|
if (args.len != 0) return self.failMsg("comptime emit_object: expected no args");
|
||||||
|
const bc = self.build_config orelse
|
||||||
|
return self.failMsg("comptime emit_object: no build config threaded into the VM");
|
||||||
|
const path = bc.object_path orelse
|
||||||
|
return self.failMsg("comptime emit_object: no object was emitted (object_path unset)");
|
||||||
|
return try self.makeStringValue(table, path);
|
||||||
|
}
|
||||||
return null; // not a known compiler function → caller bails to legacy
|
return null; // not a known compiler function → caller bails to legacy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -722,6 +722,7 @@ fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []cons
|
|||||||
// slices reference compileWithTimer locals that outlive the callback.
|
// slices reference compileWithTimer locals that outlive the callback.
|
||||||
e.build_config.c_object_paths = c_obj_paths;
|
e.build_config.c_object_paths = c_obj_paths;
|
||||||
e.build_config.link_libraries = libs;
|
e.build_config.link_libraries = libs;
|
||||||
|
e.build_config.object_path = obj_path;
|
||||||
// Android-specific bundling state.
|
// Android-specific bundling state.
|
||||||
if (e.build_config.manifest_path == null) e.build_config.manifest_path = merged_config.manifest_path;
|
if (e.build_config.manifest_path == null) e.build_config.manifest_path = merged_config.manifest_path;
|
||||||
if (e.build_config.keystore_path == null) e.build_config.keystore_path = merged_config.keystore_path;
|
if (e.build_config.keystore_path == null) e.build_config.keystore_path = merged_config.keystore_path;
|
||||||
|
|||||||
Reference in New Issue
Block a user