| ... | ... | @@ -347,7 +347,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn { |
| 347 | 347 | |
| 348 | 348 | std.debug.maybeEnableSegfaultHandler(); |
| 349 | 349 | |
| 350 | | std.os.windows.ntdll.RtlExitUserProcess(initEventLoopAndCallMain()); |
| 350 | std.os.windows.ntdll.RtlExitUserProcess(callMain()); |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | 353 | fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn { |
| ... | ... | @@ -358,7 +358,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn { |
| 358 | 358 | |
| 359 | 359 | std.debug.maybeEnableSegfaultHandler(); |
| 360 | 360 | |
| 361 | | const result: std.os.windows.INT = initEventLoopAndCallWinMain(); |
| 361 | const result: std.os.windows.INT = call_wWinMain(); |
| 362 | 362 | std.os.windows.ntdll.RtlExitUserProcess(@as(std.os.windows.UINT, @bitCast(result))); |
| 363 | 363 | } |
| 364 | 364 | |
| ... | ... | @@ -422,7 +422,7 @@ fn posixCallMainAndExit() callconv(.C) noreturn { |
| 422 | 422 | expandStackSize(phdrs); |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | | std.os.exit(@call(.always_inline, callMainWithArgs, .{ argc, argv, envp })); |
| 425 | std.os.exit(callMainWithArgs(argc, argv, envp)); |
| 426 | 426 | } |
| 427 | 427 | |
| 428 | 428 | fn expandStackSize(phdrs: []elf.Phdr) void { |
| ... | ... | @@ -459,14 +459,14 @@ fn expandStackSize(phdrs: []elf.Phdr) void { |
| 459 | 459 | } |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | | fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 { |
| 462 | inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 { |
| 463 | 463 | std.os.argv = argv[0..argc]; |
| 464 | 464 | std.os.environ = envp; |
| 465 | 465 | |
| 466 | 466 | std.debug.maybeEnableSegfaultHandler(); |
| 467 | 467 | std.os.maybeIgnoreSigpipe(); |
| 468 | 468 | |
| 469 | | return initEventLoopAndCallMain(); |
| 469 | return callMain(); |
| 470 | 470 | } |
| 471 | 471 | |
| 472 | 472 | fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.C) c_int { |
| ... | ... | @@ -481,92 +481,18 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal |
| 481 | 481 | expandStackSize(phdrs); |
| 482 | 482 | } |
| 483 | 483 | |
| 484 | | return @call(.always_inline, callMainWithArgs, .{ @as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp }); |
| 484 | return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp); |
| 485 | 485 | } |
| 486 | 486 | |
| 487 | 487 | fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.C) c_int { |
| 488 | 488 | std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))]; |
| 489 | | return @call(.always_inline, callMain, .{}); |
| 489 | return callMain(); |
| 490 | 490 | } |
| 491 | 491 | |
| 492 | 492 | // General error message for a malformed return type |
| 493 | 493 | const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; |
| 494 | 494 | |
| 495 | | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 496 | | // and we want fewer call frames in stack traces. |
| 497 | | inline fn initEventLoopAndCallMain() u8 { |
| 498 | | if (std.event.Loop.instance) |loop| { |
| 499 | | if (loop == std.event.Loop.default_instance) { |
| 500 | | loop.init() catch |err| { |
| 501 | | std.log.err("{s}", .{@errorName(err)}); |
| 502 | | if (@errorReturnTrace()) |trace| { |
| 503 | | std.debug.dumpStackTrace(trace.*); |
| 504 | | } |
| 505 | | return 1; |
| 506 | | }; |
| 507 | | defer loop.deinit(); |
| 508 | | |
| 509 | | var result: u8 = undefined; |
| 510 | | var frame: @Frame(callMainAsync) = undefined; |
| 511 | | _ = @asyncCall(&frame, &result, callMainAsync, .{loop}); |
| 512 | | loop.run(); |
| 513 | | return result; |
| 514 | | } |
| 515 | | } |
| 516 | | |
| 517 | | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 518 | | // and we want fewer call frames in stack traces. |
| 519 | | return @call(.always_inline, callMain, .{}); |
| 520 | | } |
| 521 | | |
| 522 | | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 523 | | // and we want fewer call frames in stack traces. |
| 524 | | // TODO This function is duplicated from initEventLoopAndCallMain instead of using generics |
| 525 | | // because it is working around stage1 compiler bugs. |
| 526 | | inline fn initEventLoopAndCallWinMain() std.os.windows.INT { |
| 527 | | if (std.event.Loop.instance) |loop| { |
| 528 | | if (loop == std.event.Loop.default_instance) { |
| 529 | | loop.init() catch |err| { |
| 530 | | std.log.err("{s}", .{@errorName(err)}); |
| 531 | | if (@errorReturnTrace()) |trace| { |
| 532 | | std.debug.dumpStackTrace(trace.*); |
| 533 | | } |
| 534 | | return 1; |
| 535 | | }; |
| 536 | | defer loop.deinit(); |
| 537 | | |
| 538 | | var result: std.os.windows.INT = undefined; |
| 539 | | var frame: @Frame(callWinMainAsync) = undefined; |
| 540 | | _ = @asyncCall(&frame, &result, callWinMainAsync, .{loop}); |
| 541 | | loop.run(); |
| 542 | | return result; |
| 543 | | } |
| 544 | | } |
| 545 | | |
| 546 | | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 547 | | // and we want fewer call frames in stack traces. |
| 548 | | return @call(.always_inline, call_wWinMain, .{}); |
| 549 | | } |
| 550 | | |
| 551 | | fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 { |
| 552 | | // This prevents the event loop from terminating at least until main() has returned. |
| 553 | | // TODO This shouldn't be needed here; it should be in the event loop code. |
| 554 | | loop.beginOneEvent(); |
| 555 | | defer loop.finishOneEvent(); |
| 556 | | return callMain(); |
| 557 | | } |
| 558 | | |
| 559 | | fn callWinMainAsync(loop: *std.event.Loop) callconv(.Async) std.os.windows.INT { |
| 560 | | // This prevents the event loop from terminating at least until main() has returned. |
| 561 | | // TODO This shouldn't be needed here; it should be in the event loop code. |
| 562 | | loop.beginOneEvent(); |
| 563 | | defer loop.finishOneEvent(); |
| 564 | | return call_wWinMain(); |
| 565 | | } |
| 566 | | |
| 567 | | // This is not marked inline because it is called with @asyncCall when |
| 568 | | // there is an event loop. |
| 569 | | pub fn callMain() u8 { |
| 495 | pub inline fn callMain() u8 { |
| 570 | 496 | switch (@typeInfo(@typeInfo(@TypeOf(root.main)).Fn.return_type.?)) { |
| 571 | 497 | .NoReturn => { |
| 572 | 498 | root.main(); |