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
|
## 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**
|
**M5.A.next.2a.D — inline-return uses CFG terminator, not block_terminated**
|
||||||
(commit `e6d6903`, lock-in `6b7a66b`).
|
(commit `e6d6903`, lock-in `6b7a66b`).
|
||||||
|
|
||||||
@@ -526,11 +583,12 @@ plus 2 codegen fixes surfaced along the way.**
|
|||||||
|
|
||||||
## Current state
|
## 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.
|
- 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 1 done (1c.A → 1d.B; commits bb6eca6 → 08feb60).
|
||||||
- Pack feature step 2a done — typed `args[$i]` at literal indices
|
- Pack feature step 2 done — typed `args[$i]` at literal indices
|
||||||
(cd36784) + control-flow CFG terminator fix (e6d6903).
|
(cd36784) + CFG terminator fix (e6d6903) + per-call-shape
|
||||||
|
mono (7989618).
|
||||||
- issue-0045 (comptime-fn-with-return verifier crash) fixed (9e78790).
|
- issue-0045 (comptime-fn-with-return verifier crash) fixed (9e78790).
|
||||||
- issue-0046 (nested-comptime-call + return) FILED, not blocking
|
- issue-0046 (nested-comptime-call + return) FILED, not blocking
|
||||||
next slices since builders run inside `#insert`, not inside
|
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
|
## Pack feature — next slice options
|
||||||
|
|
||||||
Step 2 ("Runtime indexing + mono expansion") is functionally
|
Step 2 done. Pack-fns monomorphise per call shape; typed
|
||||||
sufficient for the impl-matching payoff (step 5) thanks to step
|
indexing + arity work end-to-end.
|
||||||
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 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,
|
- `$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.
|
- `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
|
Step 4 (`#insert` pack passthrough + `compile_error`) is a
|
||||||
parser/interp tweak letting builders raise build-time
|
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
|
Steps 5 and 6 are stdlib refactors gated on step 3's
|
||||||
type-position substitution landing.
|
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):
|
**M4.0 — context.allocator threading** (4 commits this session):
|
||||||
- `__sx_allocator: Allocator` prepended at field index 0 of every
|
- `__sx_allocator: Allocator` prepended at field index 0 of every
|
||||||
sx-defined class's state struct
|
sx-defined class's state struct
|
||||||
|
|||||||
Reference in New Issue
Block a user