| ... | ... | @@ -23,8 +23,16 @@ comptime { |
| 23 | 23 | } else if (builtin.os.tag == .windows) { |
| 24 | 24 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 25 | 25 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) |
| 26 | { |
| 27 | @export(WinStartup, .{ .name = "WinMainCRTStartup" }); |
| 28 | } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 29 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) |
| 26 | 30 | { |
| 27 | 31 | @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); |
| 32 | } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and |
| 33 | !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) |
| 34 | { |
| 35 | @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); |
| 28 | 36 | } |
| 29 | 37 | } else if (builtin.os.tag == .uefi) { |
| 30 | 38 | if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); |
| ... | ... | @@ -123,6 +131,17 @@ fn _start() callconv(.Naked) noreturn { |
| 123 | 131 | @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 124 | 132 | } |
| 125 | 133 | |
| 134 | fn WinStartup() callconv(.Stdcall) noreturn { |
| 135 | @setAlignStack(16); |
| 136 | if (!builtin.single_threaded) { |
| 137 | _ = @import("start_windows_tls.zig"); |
| 138 | } |
| 139 | |
| 140 | std.debug.maybeEnableSegfaultHandler(); |
| 141 | |
| 142 | std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain(u8, callMain)); |
| 143 | } |
| 144 | |
| 126 | 145 | fn WinMainCRTStartup() callconv(.Stdcall) noreturn { |
| 127 | 146 | @setAlignStack(16); |
| 128 | 147 | if (!builtin.single_threaded) { |
| ... | ... | @@ -131,7 +150,20 @@ fn WinMainCRTStartup() callconv(.Stdcall) noreturn { |
| 131 | 150 | |
| 132 | 151 | std.debug.maybeEnableSegfaultHandler(); |
| 133 | 152 | |
| 134 | | std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain()); |
| 153 | const result = initEventLoopAndCallMain(std.os.windows.INT, callWinMain); |
| 154 | std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result)); |
| 155 | } |
| 156 | |
| 157 | fn wWinMainCRTStartup() callconv(.Stdcall) noreturn { |
| 158 | @setAlignStack(16); |
| 159 | if (!builtin.single_threaded) { |
| 160 | _ = @import("start_windows_tls.zig"); |
| 161 | } |
| 162 | |
| 163 | std.debug.maybeEnableSegfaultHandler(); |
| 164 | |
| 165 | const result = initEventLoopAndCallMain(std.os.windows.INT, callWWinMain); |
| 166 | std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result)); |
| 135 | 167 | } |
| 136 | 168 | |
| 137 | 169 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -185,7 +217,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 { |
| 185 | 217 | |
| 186 | 218 | std.debug.maybeEnableSegfaultHandler(); |
| 187 | 219 | |
| 188 | | return initEventLoopAndCallMain(); |
| 220 | return initEventLoopAndCallMain(u8, callMain); |
| 189 | 221 | } |
| 190 | 222 | |
| 191 | 223 | fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 { |
| ... | ... | @@ -200,7 +232,7 @@ const bad_main_ret = "expected return type of main to be 'void', '!void', 'noret |
| 200 | 232 | |
| 201 | 233 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 202 | 234 | // and we want fewer call frames in stack traces. |
| 203 | | inline fn initEventLoopAndCallMain() u8 { |
| 235 | inline fn initEventLoopAndCallMain(comptime Out: type, comptime mainFunc: fn () Out) Out { |
| 204 | 236 | if (std.event.Loop.instance) |loop| { |
| 205 | 237 | if (!@hasDecl(root, "event_loop")) { |
| 206 | 238 | loop.init() catch |err| { |
| ... | ... | @@ -214,7 +246,7 @@ inline fn initEventLoopAndCallMain() u8 { |
| 214 | 246 | |
| 215 | 247 | var result: u8 = undefined; |
| 216 | 248 | var frame: @Frame(callMainAsync) = undefined; |
| 217 | | _ = @asyncCall(&frame, &result, callMainAsync, loop); |
| 249 | _ = @asyncCall(&frame, &result, callMainAsync, u8, mainFunc, loop); |
| 218 | 250 | loop.run(); |
| 219 | 251 | return result; |
| 220 | 252 | } |
| ... | ... | @@ -222,13 +254,13 @@ inline fn initEventLoopAndCallMain() u8 { |
| 222 | 254 | |
| 223 | 255 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 224 | 256 | // and we want fewer call frames in stack traces. |
| 225 | | return @call(.{ .modifier = .always_inline }, callMain, .{}); |
| 257 | return @call(.{ .modifier = .always_inline }, mainFunc, .{}); |
| 226 | 258 | } |
| 227 | | fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 { |
| 259 | fn callMainAsync(comptime Out: type, comptime mainProc: fn () Out, loop: *std.event.Loop) callconv(.Async) Out { |
| 228 | 260 | // This prevents the event loop from terminating at least until main() has returned. |
| 229 | 261 | loop.beginOneEvent(); |
| 230 | 262 | defer loop.finishOneEvent(); |
| 231 | | return callMain(); |
| 263 | return mainProc(); |
| 232 | 264 | } |
| 233 | 265 | |
| 234 | 266 | // This is not marked inline because it is called with @asyncCall when |
| ... | ... | @@ -270,3 +302,25 @@ pub fn callMain() u8 { |
| 270 | 302 | else => @compileError(bad_main_ret), |
| 271 | 303 | } |
| 272 | 304 | } |
| 305 | |
| 306 | pub fn callWinMain() std.os.windows.INT { |
| 307 | const hInstance = std.os.windows.kernel32.GetModuleHandleA(null); |
| 308 | const lpCmdLine = std.os.windows.kernel32.GetCommandLineA(); |
| 309 | |
| 310 | // There's no (documented) way to get the nCmdShow parameter, so we're |
| 311 | // using this fairly standard default. |
| 312 | const nCmdShow = std.os.windows.user32.SW_SHOW; |
| 313 | |
| 314 | return root.WinMain(hInstance, null, lpCmdLine, nCmdShow); |
| 315 | } |
| 316 | |
| 317 | pub fn callWWinMain() std.os.windows.INT { |
| 318 | const hInstance = std.os.windows.kernel32.GetModuleHandleA(null); |
| 319 | const lpCmdLine = std.os.windows.kernel32.GetCommandLineW(); |
| 320 | |
| 321 | // There's no (documented) way to get the nCmdShow parameter, so we're |
| 322 | // using this fairly standard default. |
| 323 | const nCmdShow = std.os.windows.user32.SW_SHOW; |
| 324 | |
| 325 | return root.wWinMain(hInstance, null, lpCmdLine, nCmdShow); |
| 326 | } |