ffi M5.A.next.5.3: delete hand-rolled __block_invoke trampolines
Removes `__block_invoke_void` / `__block_invoke_bool` and their companion `Into(Block)` impls from `library/modules/std/objc_block.sx`. The generic `Into(Block) for Closure(..$args) -> $R` impl from step 5.2 now covers both shapes (and every other closure shape) via per-mono `#insert build_block_convert($args, $R)` source emission. Net stdlib shrinkage: ~52 lines, two trampolines + two per-shape impls down to zero. Adding a new block-shape consumer no longer requires touching stdlib — the impl emits per-call-shape on demand. `examples/95-objc-block-noop.sx` (zero-arg closure) and `examples/96-objc-block-multi-arg.sx` (user-declared per-shape impl for `Closure(s32, *void) -> void`) still pass: 95 routes through the new generic, 96 keeps its in-file impl as a documentation example of the user-declares-their-own path. Suite at 217/217.
This commit is contained in:
@@ -52,70 +52,14 @@ __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.
|
||||
//
|
||||
// Adding a new signature: write a `__block_invoke_<sig>` trampoline
|
||||
// matching the closure's calling convention and an
|
||||
// `impl Into(Block) for Closure(<sig>)` that points its `invoke`
|
||||
// field at the trampoline. The `xx closure : Block` cast finds the
|
||||
// impl via `Into` protocol dispatch.
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Generic impl: covers any closure shape not handled by the
|
||||
// hand-rolled per-signature impls above. The compiler
|
||||
// Single generic impl covers every closure shape. The compiler
|
||||
// monomorphises this body per call shape; inside each mono,
|
||||
// `$args` is the bound pack of arg types and `$R` is the bound
|
||||
// return type. The `#insert` evaluates `build_block_convert` at
|
||||
// comptime and substitutes the resulting source — a nested
|
||||
// `callconv(.c)` trampoline + the Block literal that points its
|
||||
// `invoke` slot at it.
|
||||
// `invoke` slot at it. One impl in stdlib replaces every per-
|
||||
// signature hand-rolled `__block_invoke_*` + `Into(Block)` pair.
|
||||
impl Into(Block) for Closure(..$args) -> $R {
|
||||
convert :: (self: Closure(..$args) -> $R) -> Block {
|
||||
#insert build_block_convert($args, $R);
|
||||
|
||||
Reference in New Issue
Block a user