From afa9d4aa4634606046cfcb7b5607569a11919b01 Mon Sep 17 00:00:00 2001 From: agra Date: Tue, 26 May 2026 22:39:52 +0300 Subject: [PATCH] checkpoint: M4.0 + M4.A complete; M4.B remaining Snapshot of FFI progress mid-M4. Allocator-aware sx-defined-class lifecycle is done end-to-end (state struct + +alloc + -dealloc). Stdlib NSObject + autoreleasepool helper landed; defer-release pattern works at user code. Property ARC ops (M4.B) is the next slice. 185/185 example tests pass; chess on iOS-sim regression-verified at every M4 sub-commit. --- current/CHECKPOINT-FFI.md | 51 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/current/CHECKPOINT-FFI.md b/current/CHECKPOINT-FFI.md index b644514..51c0ea0 100644 --- a/current/CHECKPOINT-FFI.md +++ b/current/CHECKPOINT-FFI.md @@ -221,10 +221,55 @@ plus 2 codegen fixes surfaced along the way.** ## Current state -- 169/169 example tests pass; `zig build test` green. -- Phase 3.0/3.1/3.2 + M1.0–M1.3 + M2.1–M2.3 + M3 (full - retire-`uikit_register_classes`) all landed. +- 185/185 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. - Chess on macOS / iOS-sim / Android all build and run. + +**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 + ([src/ir/lower.zig:`objcDefinedStateStructType`](../src/ir/lower.zig)). +- Sx-side `Cls.alloc()` intercepted in `lowerObjcStaticCall` for + sx-defined classes — emits the inline alloc-and-init sequence + using the caller's `current_ctx_ref`. `push Context.{ allocator = + arena }` now backs the next `SxFoo.alloc()`. +- Runtime-side `+alloc` IMP is now a shim that reads + `__sx_default_context.allocator` and forwards to the same shared + helper. +- Shared `emitObjcDefinedAllocAndInit(fcd, cls_ref, ctx_addr)` does + the work: class_createInstance → ctx.allocator.alloc(STATE_SIZE) + via the inline-protocol fn-ptr → memset 0 → store allocator at + state[0] → object_setIvar(__sx_state). +- `-dealloc` IMP loads `state->__sx_allocator` and dispatches + `allocator.dealloc(state)` instead of the old raw `free(state)`. +- TrackingAllocator now sees sx-defined class alloc/dealloc pairs. + +**M4.A — stdlib NSObject + autoreleasepool** (1 commit): +- `NSObject :: #foreign #objc_class("NSObject")` declared in + std/objc.sx with the full inherited surface: retain/release/ + autorelease/new/alloc/init/class/description/hash/isEqual_/ + isKindOfClass_/respondsToSelector_. +- All previously-unrooted foreign classes in uikit.sx now + `#extends NSObject;` (NSValue, NSNumber, NSDictionary, etc.) so + M2.3's extends-chain dispatch finds retain/release on any UIKit + type. +- `autoreleasepool(body: Closure())` stdlib helper wraps the + push/defer-pop pair. +- Canonical idiom enabled: `view := UIView.alloc().init(); defer + view.release();`. +- Smoke test [examples/ffi-objc-arc-01-autoreleasepool.sx](../examples/ffi-objc-arc-01-autoreleasepool.sx) + exercises the retain/release + autoreleasepool round-trip. + +**M4.B remaining** (compiler-internal property ARC ops; not yet +landed): +- `objcPropertyKind(field)` helper + `ensureArcRuntimeDecls`. +- Setter wiring strong/weak/copy ops. +- Getter via objc_loadWeakRetained for weak properties. +- Dealloc property-aware cleanup (release strong/copy, destroyWeak + weak) before freeing state struct. + +**Previous-session wins still in this checkpoint:** +- M4.0 / M4.A built on top of these earlier commits this session: - `library/modules/platform/uikit.sx` follow-up cleanup just shipped: every `plat: *UIKitPlatform` helper and every `(self: *void, _cmd: *void, ...)` trampoline is now a method