Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support stack and global blocks #17

Merged
merged 1 commit into from
Aug 18, 2024
Merged

Support stack and global blocks #17

merged 1 commit into from
Aug 18, 2024

Conversation

mjbshaw
Copy link
Contributor

@mjbshaw mjbshaw commented Aug 18, 2024

There are five objectives here:

  1. Make it so methods take the same number of parameters between Objective-C and Zig code. It's not a huge deal but it marginally simplifies parameter matching.
  2. Make it easy to create block literals and consume them/invoke them.
  3. Make it so users can manage resources with their blocks by providing copy/release functions.
  4. Support global blocks, which have no-op copy/release implementations.
  5. Reduce the number of levels of indirection and register shuffling with each invocation. This was done by making the invocation function take the block literal as a parameter instead of the previous implementation that used a dedicated helper to hide it.

General usage is something kinda like this:

const Context = extern struct {
    foo: i32,
    bar = f32,
};

const ctx = Context { .foo = 42, bar = 13.0 };
var block_literal = ns.stackBlockLiteral(function, ctx, null, null); // No resources to free, so no copy/release functions.
someFunctionThatConsumesBlocks(block_literal.asBlock());

// Can pass more parameters if block takes args, or return a value too.
fn function(block:  *ns.BlockLiteral(Context)) callconv(.C) void {
  std.debug.print("foo = {}, bar = {}\n", .{block.context.foo, block.context.bar});
}

There are two mildly annoying things here:

  1. The function must be callconv(.C). There's no way to avoid this without introducing additional indirection.
  2. The block's context must be compatible with the C ABI (e.g., it can't be a tuple). We could work around this by making the context an (aligned) array of bytes and then provide a context() helper method that just returns @as(*ContextType, @ptrCast(&block.context_bytes)).

Note that this PR will require a corresponding update to the main Mach repo to consume the new block-related APIs.

Also note that I don't intend on publicly exposing the libSystem bindings. It's fine to do it, though. They're just low-level enough that they're not enjoyable to work with so wrapper APIs are better IMO.

  • By selecting this checkbox, I agree to license my contributions to this project under the license(s) described in the LICENSE file, and I have the right to do so or have received permission to do so by an employer or client I am producing work for whom has this right.

@mjbshaw mjbshaw mentioned this pull request Aug 18, 2024
1 task
Copy link
Member

@slimsag slimsag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a great improvement!

@slimsag slimsag merged commit dac41fb into hexops:main Aug 18, 2024
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants