all: remove support for stage1

With almost all tests/examples working on all platforms now with the new compiler,
https://github.com/hexops/mach/issues/180, it's time to remove stage1 support.

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2022-09-10 00:04:36 -07:00
parent 4c3a19fc26
commit 8113ca370d
22 changed files with 86 additions and 1907 deletions

View file

@ -72,18 +72,16 @@ Mach is still early stages, so far we have support for building from the followi
## Supported Zig version
Zig has switched to the self-hosted compiler recently. This is a huge milestone, but currently means that Zig nightly versions are a little bit unstable. For now, we suggest using a slightly older Zig version before the switch to the self-hosted compiler.
Mach works with the new self-hosted Zig compiler only. This means you'll need to use the latest Zig nightly version.
Currently tested with: 0.10.0-dev.3952+9e070b653
You can download binary releases of this version at:
Currently we test using `0.10.0-dev.3952+9e070b653`. Newer is generally better, but you can download this version here:
* **linux-x86_64**: https://ziglang.org/builds/zig-linux-x86_64-0.10.0-dev.3952+9e070b653.tar.xz)
* **windows-x86_64**: https://ziglang.org/builds/zig-windows-x86_64-0.10.0-dev.3952+9e070b653.zip
* **macos-x86_64** (Intel): https://ziglang.org/builds/zig-macos-x86_64-0.10.0-dev.3952+9e070b653.tar.xz
* **macos-aarch64** (Apple Silicon): https://ziglang.org/builds/zig-macos-aarch64-0.10.0-dev.3952+9e070b653.tar.xz
You can subscribe to [issue #180](https://github.com/hexops/mach/issues/180) for how we're tracking towards support for the latest nightly version of Zig.
`mach/ecs` and WebAssembly examples have known issues unless using `-fstage1`, see [issue #180](https://github.com/hexops/mach/issues/180) for details.
## Contributing

View file

@ -9,10 +9,6 @@ pub fn build(b: *std.build.Builder) void {
pub fn testStep(b: *std.build.Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *std.build.RunStep {
const main_tests = b.addTestExe("ecs-tests", (comptime thisDir()) ++ "/src/main.zig");
// TODO(self-hosted): remove this when tests passed with self-hosted compiler
main_tests.use_stage1 = true;
main_tests.setBuildMode(mode);
main_tests.setTarget(target);
main_tests.install();

View file

@ -47,6 +47,7 @@ pub fn Messages(comptime messages: anytype) type {
}};
}
// TODO(self-hosted): check if we can remove this now
// Hack to workaround stage1 compiler bug. https://github.com/ziglang/zig/issues/8114
//
// return @Type(.{

View file

@ -14,10 +14,7 @@ const BBox = @import("types.zig").BBox;
pub const Vector = c.FT_Vector;
pub const GlyphMetrics = c.FT_Glyph_Metrics;
pub const Span = c.FT_Span;
pub const SpanFunc = if (builtin.zig_backend == .stage1)
fn (y: c_int, count: c_int, spans: [*]const Span, user: *anyopaque) callconv(.C) void
else
*const fn (y: c_int, count: c_int, spans: [*]const Span, user: *anyopaque) callconv(.C) void;
pub const SpanFunc = *const fn (y: c_int, count: c_int, spans: [*]const Span, user: *anyopaque) callconv(.C) void;
pub const PixelMode = enum(u3) {
none = c.FT_PIXEL_MODE_NONE,
@ -204,10 +201,10 @@ pub const Outline = struct {
pub fn Funcs(comptime Context: type) type {
return struct {
move_to: if (builtin.zig_backend == .stage1 or builtin.zig_backend == .other) fn (ctx: Context, to: Vector) Error!void else *const fn (ctx: Context, to: Vector) Error!void,
line_to: if (builtin.zig_backend == .stage1 or builtin.zig_backend == .other) fn (ctx: Context, to: Vector) Error!void else *const fn (ctx: Context, to: Vector) Error!void,
conic_to: if (builtin.zig_backend == .stage1 or builtin.zig_backend == .other) fn (ctx: Context, control: Vector, to: Vector) Error!void else *const fn (ctx: Context, control: Vector, to: Vector) Error!void,
cubic_to: if (builtin.zig_backend == .stage1 or builtin.zig_backend == .other) fn (ctx: Context, control_0: Vector, control_1: Vector, to: Vector) Error!void else *const fn (ctx: Context, control_0: Vector, control_1: Vector, to: Vector) Error!void,
move_to: *const fn (ctx: Context, to: Vector) Error!void,
line_to: *const fn (ctx: Context, to: Vector) Error!void,
conic_to: *const fn (ctx: Context, control: Vector, to: Vector) Error!void,
cubic_to: *const fn (ctx: Context, control_0: Vector, control_1: Vector, to: Vector) Error!void,
shift: i32,
delta: i32,
};
@ -295,34 +292,13 @@ pub const Outline = struct {
pub const Raster = struct {
handle: c.FT_Raster,
pub const NewFunc = if (builtin.zig_backend == .stage1)
fn (memory: ?*anyopaque, raster: [*c]c.FT_Raster) callconv(.C) c_int
else
*const fn (memory: ?*anyopaque, raster: [*c]c.FT_Raster) callconv(.C) c_int;
pub const DoneFunc = if (builtin.zig_backend == .stage1)
fn (raster: [*c]c.FT_Raster) callconv(.C) void
else
*const fn (raster: [*c]c.FT_Raster) callconv(.C) void;
pub const ResetFunc = if (builtin.zig_backend == .stage1)
fn (raster: c.FT_Raster, pool_base: [*c]u8, pool_size: c_ulong) callconv(.C) void
else
*const fn (raster: c.FT_Raster, pool_base: [*c]u8, pool_size: c_ulong) callconv(.C) void;
pub const SetModeFunc = if (builtin.zig_backend == .stage1)
fn (raster: c.FT_Raster, mode: c_ulong, args: ?*anyopaque) callconv(.C) c_int
else
*const fn (raster: c.FT_Raster, mode: c_ulong, args: ?*anyopaque) callconv(.C) c_int;
pub const RenderFunc = if (builtin.zig_backend == .stage1)
fn (raster: c.FT_Raster, params: Params) callconv(.C) c_int
else
*const fn (raster: c.FT_Raster, params: Params) callconv(.C) c_int;
pub const BitTestFunc = if (builtin.zig_backend == .stage1)
fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) c_int
else
*const fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) c_int;
pub const BitSetFunc = if (builtin.zig_backend == .stage1)
fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) void
else
*const fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) void;
pub const NewFunc = *const fn (memory: ?*anyopaque, raster: [*c]c.FT_Raster) callconv(.C) c_int;
pub const DoneFunc = *const fn (raster: [*c]c.FT_Raster) callconv(.C) void;
pub const ResetFunc = *const fn (raster: c.FT_Raster, pool_base: [*c]u8, pool_size: c_ulong) callconv(.C) void;
pub const SetModeFunc = *const fn (raster: c.FT_Raster, mode: c_ulong, args: ?*anyopaque) callconv(.C) c_int;
pub const RenderFunc = *const fn (raster: c.FT_Raster, params: Params) callconv(.C) c_int;
pub const BitTestFunc = *const fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) c_int;
pub const BitSetFunc = *const fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) void;
pub const Params = extern struct {
target: [*c]const c.FT_Bitmap,

View file

@ -1,10 +1,7 @@
//! Note: All the above requests can be blocking - dbus requests can and will block while the daemon
//! handles the request. It is not recommended to make these calls in performance critical code
const builtin = @import("builtin");
pub const c = if (builtin.zig_backend == .stage1)
@import("gamemode_client_stage1.zig")
else
@import("gamemode_client.zig");
pub const c = @import("gamemode_client.zig");
pub const GamemodeError = error{
RequestFailed,

File diff suppressed because it is too large Load diff

View file

@ -153,7 +153,7 @@ const builtin = @import("builtin");
/// Generic function pointer used for returning client API function pointers.
///
/// see also: context_glext, glfwGetProcAddress
pub const GLProc = if (builtin.zig_backend == .stage1 or builtin.zig_backend == .other) fn () callconv(.C) void else *const fn () callconv(.C) void;
pub const GLProc = *const fn () callconv(.C) void;
/// Returns the address of the specified function for the current context.
///

View file

@ -34,10 +34,7 @@ pub fn initVulkanLoader(loader_function: ?VKGetInstanceProcAddr) void {
c.glfwInitVulkanLoader(loader_function orelse null);
}
pub const VKGetInstanceProcAddr = if (@import("builtin").zig_backend == .stage1)
fn (vk_instance: c.VkInstance, name: [*c]const u8) callconv(.C) ?VKProc
else
*const fn (vk_instance: c.VkInstance, name: [*c]const u8) callconv(.C) ?VKProc;
pub const VKGetInstanceProcAddr = *const fn (vk_instance: c.VkInstance, name: [*c]const u8) callconv(.C) ?VKProc;
/// Returns whether the Vulkan loader and an ICD have been found.
///
@ -106,10 +103,7 @@ pub inline fn getRequiredInstanceExtensions() error{APIUnavailable}![][*:0]const
/// Generic function pointer used for returning Vulkan API function pointers.
///
/// see also: vulkan_proc, glfw.getInstanceProcAddress
pub const VKProc = if (@import("builtin").zig_backend == .stage1)
fn () callconv(.C) void
else
*const fn () callconv(.C) void;
pub const VKProc = *const fn () callconv(.C) void;
/// Returns the address of the specified Vulkan instance function.
///

View file

@ -233,16 +233,7 @@ pub const AutoReleasePool = if (!@import("builtin").target.isDarwin()) opaque {
pub fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime ReturnType: type) ReturnType {
const args_meta = @typeInfo(@TypeOf(args)).Struct.fields;
const FnType = if (@import("builtin").zig_backend == .stage1)
switch (args_meta.len) {
0 => fn (@TypeOf(obj), objc.SEL) callconv(.C) ReturnType,
1 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type) callconv(.C) ReturnType,
2 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type) callconv(.C) ReturnType,
3 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type, args_meta[2].field_type) callconv(.C) ReturnType,
4 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type, args_meta[2].field_type, args_meta[3].field_type) callconv(.C) ReturnType,
else => @compileError("Unsupported number of args"),
}
else switch (args_meta.len) {
const FnType = switch (args_meta.len) {
0 => *const fn (@TypeOf(obj), objc.SEL) callconv(.C) ReturnType,
1 => *const fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type) callconv(.C) ReturnType,
2 => *const fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type) callconv(.C) ReturnType,
@ -252,10 +243,7 @@ pub fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime Ret
};
// NOTE: func is a var because making it const causes a compile error which I believe is a compiler bug
var func = if (@import("builtin").zig_backend == .stage1)
@ptrCast(FnType, objc.objc_msgSend)
else
@ptrCast(FnType, &objc.objc_msgSend);
var func = @ptrCast(FnType, &objc.objc_msgSend);
const sel = objc.sel_getUid(@ptrCast([*c]const u8, sel_name));
return @call(.{}, func, .{ obj, sel } ++ args);

View file

@ -4,10 +4,7 @@ const MapModeFlags = @import("types.zig").MapModeFlags;
const Impl = @import("interface.zig").Impl;
pub const Buffer = opaque {
pub const MapCallback = if (@import("builtin").zig_backend == .stage1)
fn (status: MapAsyncStatus, userdata: ?*anyopaque) callconv(.C) void
else
*const fn (status: MapAsyncStatus, userdata: ?*anyopaque) callconv(.C) void;
pub const MapCallback = *const fn (status: MapAsyncStatus, userdata: ?*anyopaque) callconv(.C) void;
pub const BindingType = enum(u32) {
undef = 0x00000000,

View file

@ -10,101 +10,48 @@ const Adapter = @import("adapter.zig").Adapter;
const ComputePipeline = @import("compute_pipeline.zig").ComputePipeline;
const RenderPipeline = @import("render_pipeline.zig").RenderPipeline;
pub const CompilationInfoCallback = if (@import("builtin").zig_backend == .stage1)
fn (
status: CompilationInfoRequestStatus,
compilation_info: *const CompilationInfo,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
status: CompilationInfoRequestStatus,
compilation_info: *const CompilationInfo,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const CompilationInfoCallback = *const fn (
status: CompilationInfoRequestStatus,
compilation_info: *const CompilationInfo,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const ErrorCallback = if (@import("builtin").zig_backend == .stage1)
fn (
typ: ErrorType,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
typ: ErrorType,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const ErrorCallback = *const fn (
typ: ErrorType,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const LoggingCallback = if (@import("builtin").zig_backend == .stage1)
fn (
typ: LoggingType,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
typ: LoggingType,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const LoggingCallback = *const fn (
typ: LoggingType,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const RequestDeviceCallback = if (@import("builtin").zig_backend == .stage1)
fn (
status: RequestDeviceStatus,
device: *Device,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
status: RequestDeviceStatus,
device: *Device,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const RequestDeviceCallback = *const fn (
status: RequestDeviceStatus,
device: *Device,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const RequestAdapterCallback = if (@import("builtin").zig_backend == .stage1)
fn (
status: RequestAdapterStatus,
adapter: *Adapter,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
status: RequestAdapterStatus,
adapter: *Adapter,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const RequestAdapterCallback = *const fn (
status: RequestAdapterStatus,
adapter: *Adapter,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const CreateComputePipelineAsyncCallback = if (@import("builtin").zig_backend == .stage1)
fn (
status: CreatePipelineAsyncStatus,
compute_pipeline: *ComputePipeline,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
status: CreatePipelineAsyncStatus,
compute_pipeline: *ComputePipeline,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const CreateComputePipelineAsyncCallback = *const fn (
status: CreatePipelineAsyncStatus,
compute_pipeline: *ComputePipeline,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const CreateRenderPipelineAsyncCallback = if (@import("builtin").zig_backend == .stage1)
fn (
status: CreatePipelineAsyncStatus,
pipeline: *RenderPipeline,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
status: CreatePipelineAsyncStatus,
pipeline: *RenderPipeline,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const CreateRenderPipelineAsyncCallback = *const fn (
status: CreatePipelineAsyncStatus,
pipeline: *RenderPipeline,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;

View file

@ -1,18 +1,9 @@
const gpu = @import("main.zig");
const c = if (@import("builtin").zig_backend == .stage1 or !@import("builtin").target.isDarwin())
@cImport({
@cInclude("dawn/webgpu.h");
@cInclude("mach_dawn.h");
})
else
// TODO(self-hosted): HACK: workaround https://github.com/ziglang/zig/issues/12483
//
// cd gpu/src/
// echo '#include <dawn/webgpu.h>' > tmp.c
// echo '#include "mach_dawn.h"' >> tmp.c
// zig translate-c tmp.c -I ../zig-cache/mach/gpu-dawn/release-777728f/include/ > dawn_webgpu_h.zig
@import("dawn_webgpu_h.zig");
const c = @cImport({
@cInclude("dawn/webgpu.h");
@cInclude("mach_dawn.h");
});
var procs: c.DawnProcTable = undefined;

View file

@ -31,18 +31,11 @@ const Impl = @import("interface.zig").Impl;
const dawn = @import("dawn.zig");
pub const Device = opaque {
pub const LostCallback = if (@import("builtin").zig_backend == .stage1)
fn (
reason: LostReason,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
reason: LostReason,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const LostCallback = *const fn (
reason: LostReason,
message: [*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const LostReason = enum(u32) {
undef = 0x00000000,

View file

@ -9,16 +9,10 @@ const CopyTextureForBrowserOptions = @import("types.zig").CopyTextureForBrowserO
const Impl = @import("interface.zig").Impl;
pub const Queue = opaque {
pub const WorkDoneCallback = if (@import("builtin").zig_backend == .stage1)
fn (
status: WorkDoneStatus,
userdata: ?*anyopaque,
) callconv(.C) void
else
*const fn (
status: WorkDoneStatus,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const WorkDoneCallback = *const fn (
status: WorkDoneStatus,
userdata: ?*anyopaque,
) callconv(.C) void;
pub const WorkDoneStatus = enum(u32) {
success = 0x00000000,

View file

@ -17,10 +17,7 @@ pub const whole_size = 0xffffffffffffffff;
/// Generic function pointer type, used for returning API function pointers. Must be
/// cast to the right `fn (...) callconv(.C) T` type before use.
pub const Proc = if (@import("builtin").zig_backend == .stage1)
fn () callconv(.C) void
else
*const fn () callconv(.C) void;
pub const Proc = *const fn () callconv(.C) void;
pub const ComputePassTimestampWrite = extern struct {
query_set: *QuerySet,

View file

@ -6,10 +6,7 @@ const ChannelLayout = @import("ChannelLayout.zig");
const InStream = @This();
pub const WriteCallback = if (@import("builtin").zig_backend == .stage1)
fn (stream: ?[*]c.SoundIoInStream, frame_count_min: c_int, frame_count_max: c_int) callconv(.C) void
else
*const fn (stream: ?[*]c.SoundIoInStream, frame_count_min: c_int, frame_count_max: c_int) callconv(.C) void;
pub const WriteCallback = *const fn (stream: ?[*]c.SoundIoInStream, frame_count_min: c_int, frame_count_max: c_int) callconv(.C) void;
handle: *c.SoundIoInStream,

View file

@ -6,10 +6,7 @@ const ChannelLayout = @import("ChannelLayout.zig");
const OutStream = @This();
pub const WriteCallback = if (@import("builtin").zig_backend == .stage1)
fn (stream: ?[*]c.SoundIoOutStream, frame_count_min: c_int, frame_count_max: c_int) callconv(.C) void
else
*const fn (stream: ?[*]c.SoundIoOutStream, frame_count_min: c_int, frame_count_max: c_int) callconv(.C) void;
pub const WriteCallback = *const fn (stream: ?[*]c.SoundIoOutStream, frame_count_min: c_int, frame_count_max: c_int) callconv(.C) void;
handle: *c.SoundIoOutStream,

View file

@ -16,10 +16,7 @@ const SoundIoStream = union(Mode) {
const Audio = @This();
pub const DataCallback = if (@import("builtin").zig_backend == .stage1)
fn (device: *Device, user_data: ?*anyopaque, buffer: []u8) void
else
*const fn (device: *Device, user_data: ?*anyopaque, buffer: []u8) void;
pub const DataCallback = *const fn (device: *Device, user_data: ?*anyopaque, buffer: []u8) void;
const default_buffer_size_per_channel = 1024; // 21.33ms

View file

@ -5,10 +5,7 @@ const js = @import("sysjs");
const Audio = @This();
pub const DataCallback = if (@import("builtin").zig_backend == .stage1)
fn (device: *Device, user_data: ?*anyopaque, buffer: []u8) void
else
*const fn (device: *Device, user_data: ?*anyopaque, buffer: []u8) void;
pub const DataCallback = *const fn (device: *Device, user_data: ?*anyopaque, buffer: []u8) void;
pub const Device = struct {
properties: Properties,

View file

@ -208,12 +208,8 @@ export fn wasmCallFunction(id: *anyopaque, args: u32, len: u32, captures: [*]Val
captures_slice.len = captures_len;
const obj = Object{ .ref = args };
if (builtin.zig_backend == .stage1) {
obj.set("return_value", functions.items[@ptrToInt(id) - 1](obj, len, captures_slice));
} else {
var func = @ptrCast(FunType, @alignCast(std.meta.alignment(FunType), id));
obj.set("return_value", func(obj, len, captures_slice));
}
var func = @ptrCast(FunType, @alignCast(std.meta.alignment(FunType), id));
obj.set("return_value", func(obj, len, captures_slice));
}
pub fn global() Object {
@ -248,18 +244,9 @@ pub fn createUndefined() Value {
return .{ .tag = .undef, .val = undefined };
}
const FunType = if (@import("builtin").zig_backend == .stage1)
fn (args: Object, args_len: u32, captures: []Value) Value
else
*const fn (args: Object, args_len: u32, captures: []Value) Value;
var functions: std.ArrayListUnmanaged(FunType) = .{};
const FunType = *const fn (args: Object, args_len: u32, captures: []Value) Value;
pub fn createFunction(fun: FunType, captures: []Value) Function {
if (builtin.zig_backend == .stage1) {
functions.append(std.heap.page_allocator, fun) catch unreachable;
return .{ .ref = js.zigCreateFunction(@intToPtr(*anyopaque, functions.items.len), captures.ptr, @intCast(u32, captures.len)) };
}
return .{ .ref = js.zigCreateFunction(fun, captures.ptr, captures.len) };
}

View file

@ -639,10 +639,7 @@ pub fn coreDeinit(core: *Core, allocator: std.mem.Allocator) void {
allocator.destroy(core);
}
pub const CoreResizeCallback = if (@import("builtin").zig_backend == .stage1)
fn (*Core, u32, u32) callconv(.C) void
else
*const fn (*Core, u32, u32) callconv(.C) void;
pub const CoreResizeCallback = *const fn (*Core, u32, u32) callconv(.C) void;
pub fn coreUpdate(core: *Core, resize: ?CoreResizeCallback) !void {
if (core.internal.wait_event_timeout > 0.0) {

View file

@ -167,16 +167,7 @@ pub const AutoReleasePool = if (!@import("builtin").target.isDarwin()) opaque {
pub fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime ReturnType: type) ReturnType {
const args_meta = @typeInfo(@TypeOf(args)).Struct.fields;
const FnType = if (@import("builtin").zig_backend == .stage1)
switch (args_meta.len) {
0 => fn (@TypeOf(obj), objc.SEL) callconv(.C) ReturnType,
1 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type) callconv(.C) ReturnType,
2 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type) callconv(.C) ReturnType,
3 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type, args_meta[2].field_type) callconv(.C) ReturnType,
4 => fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type, args_meta[2].field_type, args_meta[3].field_type) callconv(.C) ReturnType,
else => @compileError("Unsupported number of args"),
}
else switch (args_meta.len) {
const FnType = switch (args_meta.len) {
0 => *const fn (@TypeOf(obj), objc.SEL) callconv(.C) ReturnType,
1 => *const fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type) callconv(.C) ReturnType,
2 => *const fn (@TypeOf(obj), objc.SEL, args_meta[0].field_type, args_meta[1].field_type) callconv(.C) ReturnType,
@ -186,10 +177,7 @@ pub fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime Ret
};
// NOTE: func is a var because making it const causes a compile error which I believe is a compiler bug
var func = if (@import("builtin").zig_backend == .stage1)
@ptrCast(FnType, objc.objc_msgSend)
else
@ptrCast(FnType, &objc.objc_msgSend);
var func = @ptrCast(FnType, &objc.objc_msgSend);
const sel = objc.sel_getUid(@ptrCast([*c]const u8, sel_name));
return @call(.{}, func, .{ obj, sel } ++ args);