Files
sx/tests/expected/142-objc-class-method-lowering.ir
agra 92ac51445d ffi M4.0c: -dealloc frees state through captured __sx_allocator
The synthesized -dealloc IMP now loads `state->__sx_allocator` (the
slot captured at +alloc time by M4.0a + M4.0b) and dispatches
`allocator.dealloc(state)` through the inline-protocol fn-ptr at
slot 2. Old behaviour was `free(state)` — went straight to libc,
ignoring whatever allocator the instance was constructed with.

After this commit, the per-instance allocator design from M1.2 A.5
is finally end-to-end correct:

  push Context.{ allocator = arena } {
      f := SxFoo.alloc();     ← arena.alloc(STATE_SIZE) + capture
      // ... use f ...
  }
  // refcount → 0 ⇒ -dealloc:
  //   load state->__sx_allocator   = arena
  //   arena.dealloc(state)         ← same allocator round-trips

TrackingAllocator now sees the alloc/dealloc pair; the deferred M1.2
A.5 work is done. Closes the loop on M4.0.

The dealloc IMP passes `__sx_default_context` as the implicit __sx_ctx
when invoking the dealloc fn-ptr — the IMP itself has no caller-side
ctx (it's called by Apple's runtime at refcount-zero), and the
default GPA is the right baseline for any nested allocations the
dealloc body might perform.

Each compiler-internal lookup that "can't fail" (Context type,
__sx_default_context global) emits a loud diagnostic instead of
silent fall-through, per the silent-error budget.

184/184 example tests pass; chess on iOS-sim green.
2026-05-26 22:30:48 +03:00

35 KiB