ffi checkpoint: step 2b done — per-call-shape pack monomorphisation
Logs commit 7989618 (the 2b shift from inline expansion to real
shared mono fns) and updates the test count to 197/197.
Pack feature step 2 is fully done — typed indexing, control-flow,
and per-call-shape mono all land. Step 3 (type-reflection
intrinsics) is the next slice and unlocks the stdlib payoff
(generic Into(Block) for Closure(..$args) -> $R) by enabling
$args[$i] substitution in type positions.
Documented follow-ups: mixed $fmt+..$args shapes, generic $R
binding, bare args reference, runtime indexing, and issue-0046
fix all remain deferred — none block step 3.
This commit is contained in:
@@ -6,6 +6,63 @@ add a test and make it pass — that's two commits).
|
||||
|
||||
## Last completed step
|
||||
|
||||
**M5.A.next.2b — per-call-shape monomorphisation for pack-fns**
|
||||
(commit `7989618`).
|
||||
|
||||
Pack-fns (detected by `isPackFn(fd)` — last param is the only
|
||||
comptime param AND is variadic) now emit ONE shared mono per
|
||||
unique call-site signature. Repeat calls with the same
|
||||
arg-type tuple share the mono; distinct shapes get distinct
|
||||
symbols. Pre-2b each call inlined a fresh body copy into the
|
||||
caller's basic block.
|
||||
|
||||
`examples/158-pack-mono-dedup.sx` confirms end-to-end:
|
||||
`count(), count(1), count(2), count(1,2,3), count("x", true)`
|
||||
produces `0 1 1 3 2` at runtime AND emits exactly 4 monos in
|
||||
IR — the two `s64` calls share one mono.
|
||||
|
||||
Plumbing in `src/ir/lower.zig`:
|
||||
- `isPackFn(fd)` — true when the only comptime param is a
|
||||
trailing pack. Mixed `($fmt, ..$args)` shapes stay on the
|
||||
inline `lowerComptimeCall` path (different substitution
|
||||
mechanism for the non-pack comptime; deferred).
|
||||
- `lowerPackFnCall` — builds mangled name
|
||||
`<fn_name>__pack__<arg_types>`, cache-checks
|
||||
`lowered_functions`, calls `monomorphizePackFn` on miss,
|
||||
emits a direct call.
|
||||
- `monomorphizePackFn` — mirrors `monomorphizeFunction`'s
|
||||
save/restore + param/scope setup, with N synthesised pack
|
||||
params (`__pack_<name>_<i>`) and AST-ident substitution
|
||||
installed via `pack_arg_nodes`. `pack_param_count` makes
|
||||
`args.len` resolve to the comptime N via new intercepts in
|
||||
`lowerFieldAccess` + `inferExprType`. `inline_return_target`
|
||||
is nulled out so the mono body emits real `ret X` instead
|
||||
of the inline-slot routing — it's a real fn now.
|
||||
- Routed at three call sites: each `hasComptimeParams(fd)
|
||||
→ lowerComptimeCall` now first checks `isPackFn` and routes
|
||||
to `lowerPackFnCall` when true.
|
||||
|
||||
Lifetime gotcha caught and fixed: `Function.init` stores
|
||||
`params.items` by reference (no copy). The local
|
||||
`ArrayList(Function.Param)` must NOT be deinit'd — matches the
|
||||
leak convention in `monomorphizeFunction`. Symptom of getting
|
||||
this wrong: `0xAAAAAAAA` poison-pattern TypeIds in
|
||||
`coerceCallArgs`.
|
||||
|
||||
`examples/156-pack-typed-index.sx` (typed indexing) and
|
||||
`examples/157-pack-if-return.sx` (control flow) continue to
|
||||
pass unchanged on the new path.
|
||||
|
||||
Out of scope (deferred to follow-up slices):
|
||||
- Mixed `$fmt + ..$args` shapes.
|
||||
- Generic `$R` return types.
|
||||
- Bare `args` reference (passing the pack-slice as a whole).
|
||||
- `args[<runtime_int>]` non-literal indexing.
|
||||
|
||||
197/197 example tests + `zig build test` green.
|
||||
|
||||
---
|
||||
|
||||
**M5.A.next.2a.D — inline-return uses CFG terminator, not block_terminated**
|
||||
(commit `e6d6903`, lock-in `6b7a66b`).
|
||||
|
||||
@@ -526,11 +583,12 @@ plus 2 codegen fixes surfaced along the way.**
|
||||
|
||||
## Current state
|
||||
|
||||
- 196/196 example tests pass; `zig build test` green.
|
||||
- 197/197 example tests pass; `zig build test` green.
|
||||
- Phase 3.0/3.1/3.2 + M1.0–M1.3 + M2.1–M2.3 + M3 + M4.0 + M4.A all landed.
|
||||
- Pack feature step 1 done (1c.A → 1d.B; commits bb6eca6 → 08feb60).
|
||||
- Pack feature step 2a done — typed `args[$i]` at literal indices
|
||||
(cd36784) + control-flow CFG terminator fix (e6d6903).
|
||||
- Pack feature step 2 done — typed `args[$i]` at literal indices
|
||||
(cd36784) + CFG terminator fix (e6d6903) + per-call-shape
|
||||
mono (7989618).
|
||||
- issue-0045 (comptime-fn-with-return verifier crash) fixed (9e78790).
|
||||
- issue-0046 (nested-comptime-call + return) FILED, not blocking
|
||||
next slices since builders run inside `#insert`, not inside
|
||||
@@ -539,21 +597,16 @@ plus 2 codegen fixes surfaced along the way.**
|
||||
|
||||
## Pack feature — next slice options
|
||||
|
||||
Step 2 ("Runtime indexing + mono expansion") is functionally
|
||||
sufficient for the impl-matching payoff (step 5) thanks to step
|
||||
1d.B's per-mono mangling on `<src>.convert__<dst>` keys.
|
||||
Remaining within step 2 is real per-call-shape monomorphisation
|
||||
(today pack-fns inline at every call site) — performance/IR-size
|
||||
concern, not correctness. Defer until a real workload demands it.
|
||||
Step 2 done. Pack-fns monomorphise per call shape; typed
|
||||
indexing + arity work end-to-end.
|
||||
|
||||
Step 3 ("Type-reflection intrinsics") is the natural next slice:
|
||||
Step 3 ("Type-reflection intrinsics") is the natural next:
|
||||
- `$args[$i]` in TYPE positions (param types, return types,
|
||||
fn-pointer types, struct fields).
|
||||
fn-pointer types, struct fields). Unlocks the block-trampoline
|
||||
body in stdlib's generic `Into(Block) for Closure(..$args) ->
|
||||
$R` impl — the body needs `typed_fn : (*void, $args[0],
|
||||
$args[1]) -> $R = xx ...` per-position type interpolation.
|
||||
- `type_name`, `type_eq`, `has_impl` comptime intrinsics.
|
||||
- Unlocks the block-trampoline body in stdlib's generic
|
||||
`Into(Block) for Closure(..$args) -> $R` impl — the body
|
||||
needs `typed_fn : (*void, $args[0], $args[1]) -> $R = xx ...`
|
||||
per-position type interpolation.
|
||||
|
||||
Step 4 (`#insert` pack passthrough + `compile_error`) is a
|
||||
parser/interp tweak letting builders raise build-time
|
||||
@@ -562,6 +615,14 @@ diagnostics from inside `#insert` bodies.
|
||||
Steps 5 and 6 are stdlib refactors gated on step 3's
|
||||
type-position substitution landing.
|
||||
|
||||
Pack feature follow-ups (deferred):
|
||||
- Mixed `$fmt + ..$args` shapes through the mono path.
|
||||
- Generic `$R` return type binding.
|
||||
- Bare `args` reference (materialise an `[]Any` slice on demand
|
||||
inside the mono).
|
||||
- `args[<runtime_int>]` non-literal indexing.
|
||||
- issue-0046 fix (nested-comptime-call + return).
|
||||
|
||||
**M4.0 — context.allocator threading** (4 commits this session):
|
||||
- `__sx_allocator: Allocator` prepended at field index 0 of every
|
||||
sx-defined class's state struct
|
||||
|
||||
Reference in New Issue
Block a user