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:
agra
2026-05-27 15:45:03 +03:00
parent 79896188eb
commit a39437261d

View File

@@ -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.0M1.3 + M2.1M2.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