Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ pub fn build(b: *std.Build) void {
module.addLibraryPath(dep.path("lib"));
}

const generator_exe = b.addExecutable(.{
.name = "generator",
const generator_module = b.createModule(.{
.root_source_file = b.path("generator.zig"),
.target = target,
.optimize = optimize,
});
const generator_exe = b.addExecutable(.{
.name = "generator",
.root_module = generator_module,
});
b.installArtifact(generator_exe);
}
3 changes: 2 additions & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.{
.name = "mach-objc",
.fingerprint = 0xd0611af9392648d4,
.name = .mach_objc,
.version = "0.0.0",
.paths = .{
"src",
Expand Down
2 changes: 1 addition & 1 deletion generator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,7 @@ fn Generator(comptime WriterType: type) type {
try self.writer.writeAll(", ");
try self.generateType(param_ty);
}
try self.writer.writeAll(") callconv(.C) ");
try self.writer.writeAll(") callconv(.c) ");
try self.generateType(f.return_type.*);
},
.generic => |g| {
Expand Down
46 changes: 23 additions & 23 deletions src/foundation.zig

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub const mach = struct {
method(self, block);
}
const method = @extern(
*const fn (*AppDelegate, *foundation.Block(fn () void)) callconv(.C) void,
*const fn (*AppDelegate, *foundation.Block(fn () void)) callconv(.c) void,
.{ .name = "\x01-[MACHAppDelegate setRunBlock:]" },
);
};
Expand All @@ -43,15 +43,15 @@ pub const mach = struct {
method_windowDidResize(self, block);
}
const method_windowDidResize = @extern(
*const fn (*WindowDelegate, *foundation.Block(fn () void)) callconv(.C) void,
*const fn (*WindowDelegate, *foundation.Block(fn () void)) callconv(.c) void,
.{ .name = "\x01-[MACHWindowDelegate setBlock_windowDidResize:]" },
);

pub fn setBlock_windowShouldClose(self: *WindowDelegate, block: *foundation.Block(fn () bool)) void {
method_windowShouldClose(self, block);
}
const method_windowShouldClose = @extern(
*const fn (*WindowDelegate, *foundation.Block(fn () bool)) callconv(.C) void,
*const fn (*WindowDelegate, *foundation.Block(fn () bool)) callconv(.c) void,
.{ .name = "\x01-[MACHWindowDelegate setBlock_windowShouldClose:]" },
);
};
Expand Down Expand Up @@ -85,71 +85,71 @@ pub const mach = struct {
method_keyDown(self, block);
}
const method_keyDown = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_keyDown:]" },
);

pub fn setBlock_insertText(self: *View, block: *foundation.Block(fn (*app_kit.Event, u32) void)) void {
method_insertText(self, block);
}
const method_insertText = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event, u32) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event, u32) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_insertText:]" },
);

pub fn setBlock_keyUp(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_keyUp(self, block);
}
const method_keyUp = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_keyUp:]" },
);

pub fn setBlock_flagsChanged(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_flagsChanged(self, block);
}
const method_flagsChanged = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_flagsChanged:]" },
);

pub fn setBlock_magnify(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_magnify(self, block);
}
const method_magnify = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_magnify:]" },
);

pub fn setBlock_mouseMoved(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_mouseMoved(self, block);
}
const method_mouseMoved = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_mouseMoved:]" },
);

pub fn setBlock_mouseDown(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_mouseDown(self, block);
}
const method_mouseDown = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_mouseDown:]" },
);

pub fn setBlock_mouseUp(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_mouseUp(self, block);
}
const method_mouseUp = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_mouseUp:]" },
);

pub fn setBlock_scrollWheel(self: *View, block: *foundation.Block(fn (*app_kit.Event) void)) void {
method_scrollWheel(self, block);
}
const method_scrollWheel = @extern(
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.C) void,
*const fn (*View, *foundation.Block(fn (*app_kit.Event) void)) callconv(.c) void,
.{ .name = "\x01-[MACHView setBlock_scrollWheel:]" },
);
};
Expand Down
48 changes: 18 additions & 30 deletions src/objc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -68,41 +68,29 @@ pub fn msgSend(receiver: anytype, comptime selector: []const u8, return_type: ty
// validate it against `receiver` and `args`.

const fn_type = comptime init: {
var params: []const std.builtin.Type.Fn.Param = &.{
.{
.is_generic = false,
.is_noalias = false,
.type = @TypeOf(receiver),
},
.{
.is_generic = false,
.is_noalias = false,
.type = [*:0]c_char,
},
};
for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| {
params = params ++
[_]std.builtin.Type.Fn.Param{.{
.is_generic = false,
.is_noalias = false,
.type = field.type,
}};
}
break :init std.builtin.Type{
.@"fn" = .{
.calling_convention = std.builtin.CallingConvention.c,
.is_generic = false,
.is_var_args = false,
.return_type = return_type,
.params = params,
},
};
const ParamAttrs = std.builtin.Type.Fn.Param.Attributes;
const args_fields = @typeInfo(@TypeOf(args)).@"struct".fields;
const param_len = args_fields.len + 2;
var param_types: [param_len]type = undefined;
var param_attrs: [param_len]ParamAttrs = undefined;

param_types[0] = @TypeOf(receiver);
param_attrs[0] = .{};
param_types[1] = [*:0]c_char;
param_attrs[1] = .{};

for (args_fields, 0..) |field, i| {
param_types[i + 2] = field.type;
param_attrs[i + 2] = .{};
}

break :init @Fn(&param_types, &param_attrs, return_type, .{ .@"callconv" = .c });
};

const needs_fpret = comptime builtin.target.cpu.arch == .x86 and (return_type == f32 or return_type == f64);
const needs_stret = comptime builtin.target.cpu.arch == .x86 and @sizeOf(return_type) > 16;
const msg_send_fn_name = comptime if (needs_stret) "objc_msgSend_stret" else if (needs_fpret) "objc_msgSend_fpret" else "objc_msgSend";
const msg_send_fn = @extern(*const @Type(fn_type), .{ .name = msg_send_fn_name ++ "$" ++ selector });
const msg_send_fn = @extern(*const fn_type, .{ .name = msg_send_fn_name ++ "$" ++ selector });
return @call(.auto, msg_send_fn, .{ receiver, undefined } ++ args);
}

Expand Down
62 changes: 42 additions & 20 deletions src/system.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const builtin = @import("builtin");
const std = @import("std");

pub extern "System" fn dispatch_async(queue: *anyopaque, work: *const Block(fn (*BlockLiteral(void)) void)) void;
pub extern "System" fn dispatch_async_f(queue: *anyopaque, context: ?*anyopaque, work: *const fn (context: ?*anyopaque) callconv(.C) void) void;
pub extern "System" fn dispatch_async_f(queue: *anyopaque, context: ?*anyopaque, work: *const fn (context: ?*anyopaque) callconv(.c) void) void;
pub extern "System" fn @"dispatch_assert_queue$V2"(queue: *anyopaque) void;
pub extern "System" var _dispatch_main_q: anyopaque;

Expand All @@ -13,20 +13,28 @@ pub fn Block(comptime Signature: type) type {
const signature_fn_info = @typeInfo(Signature).@"fn";
return opaque {
pub fn invoke(self: *@This(), args: std.meta.ArgsTuple(Signature)) signature_fn_info.return_type.? {
const self_param = std.builtin.Type.Fn.Param{
.is_generic = false,
.is_noalias = false,
.type = *@This(),
};
const SignatureForInvoke = @Type(.{
.@"fn" = .{
.calling_convention = std.builtin.CallingConvention.c,
.is_generic = signature_fn_info.is_generic,
.is_var_args = signature_fn_info.is_var_args,
.return_type = signature_fn_info.return_type,
.params = .{self_param} ++ signature_fn_info.params,
},
});
if (signature_fn_info.is_generic) {
@compileError("Block signatures must be non-generic");
}

const ParamAttrs = std.builtin.Type.Fn.Param.Attributes;
const param_len = signature_fn_info.params.len + 1;
var param_types: [param_len]type = undefined;
var param_attrs: [param_len]ParamAttrs = undefined;

param_types[0] = *@This();
param_attrs[0] = .{};
inline for (signature_fn_info.params, 0..) |param, i| {
param_types[i + 1] = param.type orelse @compileError("Block signatures must be concrete");
param_attrs[i + 1] = .{ .@"noalias" = param.is_noalias };
}

const SignatureForInvoke = @Fn(
&param_types,
&param_attrs,
signature_fn_info.return_type orelse @compileError("Block signatures must return a concrete type"),
.{ .@"callconv" = .c, .varargs = signature_fn_info.is_var_args },
);

const offset = @offsetOf(BlockLiteral(void), "invoke");
const invoke_ptr: *const SignatureForInvoke = @ptrCast(self + offset);
Expand Down Expand Up @@ -100,8 +108,8 @@ fn CopyDisposeBlockDescriptor(comptime Context: type) type {
copy: *const CopyFn,
dispose: *const DisposeFn,

pub const CopyFn = fn (dst: *BlockLiteral(Context), src: *const BlockLiteral(Context)) callconv(.C) void;
pub const DisposeFn = fn (block: *const BlockLiteral(Context)) callconv(.C) void;
pub const CopyFn = fn (dst: *BlockLiteral(Context), src: *const BlockLiteral(Context)) callconv(.c) void;
pub const DisposeFn = fn (block: *const BlockLiteral(Context)) callconv(.c) void;

fn static(comptime size: c_ulong, comptime copy: CopyFn, comptime dispose: DisposeFn) *const CopyDisposeBlockDescriptor {
const Static = struct {
Expand All @@ -120,7 +128,21 @@ fn SignatureWithoutBlockLiteral(comptime Signature: type) type {
var type_info = @typeInfo(Signature);
type_info.@"fn".calling_convention = .auto;
type_info.@"fn".params = type_info.@"fn".params[1..];
return @Type(type_info);
const ParamAttrs = std.builtin.Type.Fn.Param.Attributes;
const params = type_info.@"fn".params;
const param_len = params.len;
var param_types: [param_len]type = undefined;
var param_attrs: [param_len]ParamAttrs = undefined;
inline for (params, 0..) |param, i| {
param_types[i] = param.type orelse @compileError("Block signatures must be concrete");
param_attrs[i] = .{ .@"noalias" = param.is_noalias };
}
return @Fn(
&param_types,
&param_attrs,
type_info.@"fn".return_type orelse @compileError("Block signatures must return a concrete type"),
.{ .@"callconv" = .auto, .varargs = type_info.@"fn".is_var_args },
);
}

fn validateBlockSignature(comptime Invoke: type, comptime ExpectedLiteralType: type) void {
Expand All @@ -143,8 +165,8 @@ fn validateBlockSignature(comptime Invoke: type, comptime ExpectedLiteralType: t
pub fn stackBlockLiteral(
invoke: anytype,
context: anytype,
comptime copy: ?fn (dst: *BlockLiteral(@TypeOf(context)), src: *const BlockLiteral(@TypeOf(context))) callconv(.C) void,
comptime dispose: ?fn (block: *const BlockLiteral(@TypeOf(context))) callconv(.C) void,
comptime copy: ?fn (dst: *BlockLiteral(@TypeOf(context)), src: *const BlockLiteral(@TypeOf(context))) callconv(.c) void,
comptime dispose: ?fn (block: *const BlockLiteral(@TypeOf(context))) callconv(.c) void,
) BlockLiteralWithSignature(@TypeOf(context), SignatureWithoutBlockLiteral(@TypeOf(invoke))) {
const Context = @TypeOf(context);
const Literal = BlockLiteral(Context);
Expand Down