| ... | ... | @@ -28,8 +28,16 @@ comptime { |
| 28 | 28 | } else if (builtin.os.tag == .windows) { |
| 29 | 29 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 30 | 30 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) |
| 31 | { |
| 32 | @export(WinStartup, .{ .name = "WinMainCRTStartup" }); |
| 33 | } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 34 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) |
| 31 | 35 | { |
| 32 | 36 | @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); |
| 37 | } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and |
| 38 | !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) |
| 39 | { |
| 40 | @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); |
| 33 | 41 | } |
| 34 | 42 | } else if (builtin.os.tag == .uefi) { |
| 35 | 43 | if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); |
| ... | ... | @@ -143,6 +151,17 @@ fn _start() callconv(.Naked) noreturn { |
| 143 | 151 | @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 144 | 152 | } |
| 145 | 153 | |
| 154 | fn WinStartup() callconv(.Stdcall) noreturn { |
| 155 | @setAlignStack(16); |
| 156 | if (!builtin.single_threaded) { |
| 157 | _ = @import("start_windows_tls.zig"); |
| 158 | } |
| 159 | |
| 160 | std.debug.maybeEnableSegfaultHandler(); |
| 161 | |
| 162 | std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain(u8, callMain)); |
| 163 | } |
| 164 | |
| 146 | 165 | fn WinMainCRTStartup() callconv(.Stdcall) noreturn { |
| 147 | 166 | @setAlignStack(16); |
| 148 | 167 | if (!builtin.single_threaded) { |
| ... | ... | @@ -151,7 +170,20 @@ fn WinMainCRTStartup() callconv(.Stdcall) noreturn { |
| 151 | 170 | |
| 152 | 171 | std.debug.maybeEnableSegfaultHandler(); |
| 153 | 172 | |
| 154 | | std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain()); |
| 173 | const result = initEventLoopAndCallMain(std.os.windows.INT, callWinMain); |
| 174 | std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result)); |
| 175 | } |
| 176 | |
| 177 | fn wWinMainCRTStartup() callconv(.Stdcall) noreturn { |
| 178 | @setAlignStack(16); |
| 179 | if (!builtin.single_threaded) { |
| 180 | _ = @import("start_windows_tls.zig"); |
| 181 | } |
| 182 | |
| 183 | std.debug.maybeEnableSegfaultHandler(); |
| 184 | |
| 185 | const result = initEventLoopAndCallMain(std.os.windows.INT, callWWinMain); |
| 186 | std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result)); |
| 155 | 187 | } |
| 156 | 188 | |
| 157 | 189 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -205,7 +237,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 { |
| 205 | 237 | |
| 206 | 238 | std.debug.maybeEnableSegfaultHandler(); |
| 207 | 239 | |
| 208 | | return initEventLoopAndCallMain(); |
| 240 | return initEventLoopAndCallMain(u8, callMain); |
| 209 | 241 | } |
| 210 | 242 | |
| 211 | 243 | fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 { |
| ... | ... | @@ -220,7 +252,7 @@ const bad_main_ret = "expected return type of main to be 'void', '!void', 'noret |
| 220 | 252 | |
| 221 | 253 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 222 | 254 | // and we want fewer call frames in stack traces. |
| 223 | | inline fn initEventLoopAndCallMain() u8 { |
| 255 | inline fn initEventLoopAndCallMain(comptime Out: type, comptime mainFunc: fn () Out) Out { |
| 224 | 256 | if (std.event.Loop.instance) |loop| { |
| 225 | 257 | if (!@hasDecl(root, "event_loop")) { |
| 226 | 258 | loop.init() catch |err| { |
| ... | ... | @@ -234,7 +266,7 @@ inline fn initEventLoopAndCallMain() u8 { |
| 234 | 266 | |
| 235 | 267 | var result: u8 = undefined; |
| 236 | 268 | var frame: @Frame(callMainAsync) = undefined; |
| 237 | | _ = @asyncCall(&frame, &result, callMainAsync, .{loop}); |
| 269 | _ = @asyncCall(&frame, &result, callMainAsync, .{u8, mainFunc, loop}); |
| 238 | 270 | loop.run(); |
| 239 | 271 | return result; |
| 240 | 272 | } |
| ... | ... | @@ -242,13 +274,13 @@ inline fn initEventLoopAndCallMain() u8 { |
| 242 | 274 | |
| 243 | 275 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 244 | 276 | // and we want fewer call frames in stack traces. |
| 245 | | return @call(.{ .modifier = .always_inline }, callMain, .{}); |
| 277 | return @call(.{ .modifier = .always_inline }, mainFunc, .{}); |
| 246 | 278 | } |
| 247 | | fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 { |
| 279 | fn callMainAsync(comptime Out: type, comptime mainProc: fn () Out, loop: *std.event.Loop) callconv(.Async) Out { |
| 248 | 280 | // This prevents the event loop from terminating at least until main() has returned. |
| 249 | 281 | loop.beginOneEvent(); |
| 250 | 282 | defer loop.finishOneEvent(); |
| 251 | | return callMain(); |
| 283 | return mainProc(); |
| 252 | 284 | } |
| 253 | 285 | |
| 254 | 286 | // This is not marked inline because it is called with @asyncCall when |
| ... | ... | @@ -290,3 +322,25 @@ pub fn callMain() u8 { |
| 290 | 322 | else => @compileError(bad_main_ret), |
| 291 | 323 | } |
| 292 | 324 | } |
| 325 | |
| 326 | pub fn callWinMain() std.os.windows.INT { |
| 327 | const hInstance = std.os.windows.kernel32.GetModuleHandleA(null); |
| 328 | const lpCmdLine = std.os.windows.kernel32.GetCommandLineA(); |
| 329 | |
| 330 | // There's no (documented) way to get the nCmdShow parameter, so we're |
| 331 | // using this fairly standard default. |
| 332 | const nCmdShow = std.os.windows.user32.SW_SHOW; |
| 333 | |
| 334 | return root.WinMain(hInstance, null, lpCmdLine, nCmdShow); |
| 335 | } |
| 336 | |
| 337 | pub fn callWWinMain() std.os.windows.INT { |
| 338 | const hInstance = std.os.windows.kernel32.GetModuleHandleA(null); |
| 339 | const lpCmdLine = std.os.windows.kernel32.GetCommandLineW(); |
| 340 | |
| 341 | // There's no (documented) way to get the nCmdShow parameter, so we're |
| 342 | // using this fairly standard default. |
| 343 | const nCmdShow = std.os.windows.user32.SW_SHOW; |
| 344 | |
| 345 | return root.wWinMain(hInstance, null, lpCmdLine, nCmdShow); |
| 346 | } |