From 556e4e12eaecbb850c23a3b48c216c27ff87bca9 Mon Sep 17 00:00:00 2001 From: agra Date: Wed, 27 May 2026 00:24:36 +0300 Subject: [PATCH] ffi M5.A.2: drop hand-rolled __block_invoke_* impls + Into(Block) per-sig boilerplate The compiler-synthesised trampoline path (previous commit) covers every closure signature on demand; the hand-rolled stdlib impls were only for two specific shapes (`Closure() -> void`, `Closure(bool) -> void`) and are now strictly redundant. Kept: the `Block` struct, `BlockDescriptor`, the `_NSConcreteStackBlock` extern decl, and the shared `__sx_block_descriptor` global. The compiler-emitted code references all four; users still need to `#import "modules/std/objc_block.sx";` to bring them into the module. Removed: `__block_invoke_void`, `__block_invoke_bool`, and both `impl Into(Block) for Closure(...) -> void` blocks. Replaced with a comment block explaining how the compiler now handles the cast. After this commit, `xx my_closure : Block` works for ANY closure signature with no per-signature stdlib boilerplate. 189/189 example tests pass; chess on iOS-sim green. --- library/modules/std/objc_block.sx | 61 +++++++------------------------ 1 file changed, 13 insertions(+), 48 deletions(-) diff --git a/library/modules/std/objc_block.sx b/library/modules/std/objc_block.sx index 9c9825b..b9e5c78 100644 --- a/library/modules/std/objc_block.sx +++ b/library/modules/std/objc_block.sx @@ -52,52 +52,17 @@ __sx_block_descriptor : BlockDescriptor = .{ size = 48, }; -// Per-signature invoke trampolines. Each one reads sx_env + sx_fn from -// its block_self argument and tail-calls the closure through a typed -// fn-ptr cast. One per Apple block signature we support. +// M5.A — `xx closure : Block` casts are handled by the compiler. +// For every closure signature seen at a cast site, the compiler +// synthesises: +// 1. A C-ABI trampoline `__block_invoke_` matching Apple's +// `__block_literal.invoke` calling convention. +// 2. Inline Block-struct construction at the cast site, with +// `invoke` pointing at the synthesised trampoline and +// `sx_env`/`sx_fn` taken from the closure value. // -// Signature: `void (^)(void)` — no args, no return. The single most -// common Apple block shape (UIView animation bodies, dispatch_async, etc). -__block_invoke_void :: (block_self: *Block) callconv(.c) { - // `sx_fn` is the closure trampoline — an sx-side function with the - // implicit __sx_ctx at slot 0 and env at slot 1. We're a callconv(.c) - // entry, so the call site needs ctx prepended; the typed fn-pointer - // type stays default-conv to enable that. - typed_fn : (*void) -> void = xx block_self.sx_fn; - typed_fn(block_self.sx_env); -} - -impl Into(Block) for Closure() -> void { - convert :: (self: Closure() -> void) -> Block { - .{ - isa = @_NSConcreteStackBlock, - flags = 0, - reserved = 0, - invoke = xx @__block_invoke_void, - descriptor = xx @__sx_block_descriptor, - sx_env = self.env, - sx_fn = self.fn_ptr, - }; - } -} - -// Signature: `void (^)(BOOL)` — UIView animation completion handlers and -// similar one-arg-bool callbacks. -__block_invoke_bool :: (block_self: *Block, arg0: bool) callconv(.c) { - typed_fn : (*void, bool) -> void = xx block_self.sx_fn; - typed_fn(block_self.sx_env, arg0); -} - -impl Into(Block) for Closure(bool) -> void { - convert :: (self: Closure(bool) -> void) -> Block { - .{ - isa = @_NSConcreteStackBlock, - flags = 0, - reserved = 0, - invoke = xx @__block_invoke_bool, - descriptor = xx @__sx_block_descriptor, - sx_env = self.env, - sx_fn = self.fn_ptr, - }; - } -} +// User-facing surface: `xx my_closure : Block` for ANY closure +// signature. No per-signature stdlib boilerplate. The shared +// infrastructure above (`Block`, `BlockDescriptor`, +// `_NSConcreteStackBlock`, `__sx_block_descriptor`) is referenced +// by the synthesised code; users only need to `#import` this module.