@@ -23,7 +23,6 @@ comptime {
2323 // Until then, we have simplified logic here for self-hosted. TODO remove this once
2424 // self-hosted is capable enough to handle all of the real start.zig logic.
2525 if (builtin .zig_backend == .stage2_wasm or
26- builtin .zig_backend == .stage2_c or
2726 builtin .zig_backend == .stage2_x86_64 or
2827 builtin .zig_backend == .stage2_x86 or
2928 builtin .zig_backend == .stage2_aarch64 or
@@ -265,75 +264,104 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
265264}
266265
267266fn _start () callconv (.Naked ) noreturn {
268- switch (native_arch ) {
269- .x86_64 = > {
270- argc_argv_ptr = asm volatile (
271- \\ xor %%rbp, %%rbp
272- : [argc ] "={rsp}" (- > [* ]usize ),
273- );
274- },
275- .i386 = > {
276- argc_argv_ptr = asm volatile (
277- \\ xor %%ebp, %%ebp
278- : [argc ] "={esp}" (- > [* ]usize ),
279- );
280- },
281- .aarch64 , .aarch64_be , .arm , .armeb , .thumb = > {
282- argc_argv_ptr = asm volatile (
283- \\ mov fp, #0
284- \\ mov lr, #0
285- : [argc ] "={sp}" (- > [* ]usize ),
286- );
287- },
288- .riscv64 = > {
289- argc_argv_ptr = asm volatile (
290- \\ li s0, 0
291- \\ li ra, 0
292- : [argc ] "={sp}" (- > [* ]usize ),
293- );
294- },
295- .mips , .mipsel = > {
296- // The lr is already zeroed on entry, as specified by the ABI.
297- argc_argv_ptr = asm volatile (
298- \\ move $fp, $0
299- : [argc ] "={sp}" (- > [* ]usize ),
300- );
301- },
302- .powerpc = > {
303- // Setup the initial stack frame and clear the back chain pointer.
304- argc_argv_ptr = asm volatile (
305- \\ mr 4, 1
306- \\ li 0, 0
307- \\ stwu 1,-16(1)
308- \\ stw 0, 0(1)
309- \\ mtlr 0
310- : [argc ] "={r4}" (- > [* ]usize ),
311- :
312- : "r0"
313- );
314- },
315- .powerpc64le = > {
316- // Setup the initial stack frame and clear the back chain pointer.
317- // TODO: Support powerpc64 (big endian) on ELFv2.
318- argc_argv_ptr = asm volatile (
319- \\ mr 4, 1
320- \\ li 0, 0
321- \\ stdu 0, -32(1)
322- \\ mtlr 0
323- : [argc ] "={r4}" (- > [* ]usize ),
324- :
325- : "r0"
326- );
267+ switch (builtin .zig_backend ) {
268+ .stage2_c = > {
269+ @export (argc_argv_ptr , .{ .name = "argc_argv_ptr" });
270+ @export (posixCallMainAndExit , .{ .name = "_posixCallMainAndExit" });
271+ switch (native_arch ) {
272+ .x86_64 = > asm volatile (
273+ \\ xorl %%ebp, %%ebp
274+ \\ movq %%rsp, argc_argv_ptr
275+ \\ andq $-16, %%rsp
276+ \\ call _posixCallMainAndExit
277+ ),
278+ .i386 = > asm volatile (
279+ \\ xorl %%ebp, %%ebp
280+ \\ movl %%esp, argc_argv_ptr
281+ \\ andl $-16, %%esp
282+ \\ jmp _posixCallMainAndExit
283+ ),
284+ .aarch64 , .aarch64_be , .arm , .armeb , .thumb = > asm volatile (
285+ \\ mov fp, #0
286+ \\ mov lr, #0
287+ \\ str sp, argc_argv_ptr
288+ \\ and sp, #-16
289+ \\ b _posixCallMainAndExit
290+ ),
291+ else = > @compileError ("unsupported arch" ),
292+ }
293+ unreachable ;
327294 },
328- .sparc64 = > {
329- // argc is stored after a register window (16 registers) plus stack bias
330- argc_argv_ptr = asm (
331- \\ mov %%g0, %%i6
332- \\ add %%o6, 2175, %[argc]
333- : [argc ] "=r" (- > [* ]usize ),
334- );
295+ else = > switch (native_arch ) {
296+ .x86_64 = > {
297+ argc_argv_ptr = asm volatile (
298+ \\ xor %%ebp, %%ebp
299+ : [argc ] "={rsp}" (- > [* ]usize ),
300+ );
301+ },
302+ .i386 = > {
303+ argc_argv_ptr = asm volatile (
304+ \\ xor %%ebp, %%ebp
305+ : [argc ] "={esp}" (- > [* ]usize ),
306+ );
307+ },
308+ .aarch64 , .aarch64_be , .arm , .armeb , .thumb = > {
309+ argc_argv_ptr = asm volatile (
310+ \\ mov fp, #0
311+ \\ mov lr, #0
312+ : [argc ] "={sp}" (- > [* ]usize ),
313+ );
314+ },
315+ .riscv64 = > {
316+ argc_argv_ptr = asm volatile (
317+ \\ li s0, 0
318+ \\ li ra, 0
319+ : [argc ] "={sp}" (- > [* ]usize ),
320+ );
321+ },
322+ .mips , .mipsel = > {
323+ // The lr is already zeroed on entry, as specified by the ABI.
324+ argc_argv_ptr = asm volatile (
325+ \\ move $fp, $0
326+ : [argc ] "={sp}" (- > [* ]usize ),
327+ );
328+ },
329+ .powerpc = > {
330+ // Setup the initial stack frame and clear the back chain pointer.
331+ argc_argv_ptr = asm volatile (
332+ \\ mr 4, 1
333+ \\ li 0, 0
334+ \\ stwu 1,-16(1)
335+ \\ stw 0, 0(1)
336+ \\ mtlr 0
337+ : [argc ] "={r4}" (- > [* ]usize ),
338+ :
339+ : "r0"
340+ );
341+ },
342+ .powerpc64le = > {
343+ // Setup the initial stack frame and clear the back chain pointer.
344+ // TODO: Support powerpc64 (big endian) on ELFv2.
345+ argc_argv_ptr = asm volatile (
346+ \\ mr 4, 1
347+ \\ li 0, 0
348+ \\ stdu 0, -32(1)
349+ \\ mtlr 0
350+ : [argc ] "={r4}" (- > [* ]usize ),
351+ :
352+ : "r0"
353+ );
354+ },
355+ .sparc64 = > {
356+ // argc is stored after a register window (16 registers) plus stack bias
357+ argc_argv_ptr = asm (
358+ \\ mov %%g0, %%i6
359+ \\ add %%o6, 2175, %[argc]
360+ : [argc ] "=r" (- > [* ]usize ),
361+ );
362+ },
363+ else = > @compileError ("unsupported arch" ),
335364 },
336- else = > @compileError ("unsupported arch" ),
337365 }
338366 // If LLVM inlines stack variables into _start, they will overwrite
339367 // the command line argument data.
@@ -363,7 +391,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
363391 std .os .windows .kernel32 .ExitProcess (@bitCast (std .os .windows .UINT , result ));
364392}
365393
366- fn posixCallMainAndExit () noreturn {
394+ fn posixCallMainAndExit () callconv ( .C ) noreturn {
367395 @setAlignStack (16 );
368396
369397 const argc = argc_argv_ptr [0 ];
@@ -462,7 +490,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
462490 return initEventLoopAndCallMain ();
463491}
464492
465- fn main (c_argc : i32 , c_argv : [* ][* : 0 ]u8 , c_envp : [* : null ] ? [ * : 0 ]u8 ) callconv (.C ) i32 {
493+ fn main (c_argc : c_int , c_argv : [* c ][* c ]u8 , c_envp : [* c ][ * c ]u8 ) callconv (.C ) c_int {
466494 var env_count : usize = 0 ;
467495 while (c_envp [env_count ] != null ) : (env_count += 1 ) {}
468496 const envp = @ptrCast ([* ][* :0 ]u8 , c_envp )[0.. env_count ];
@@ -474,11 +502,11 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)
474502 expandStackSize (phdrs );
475503 }
476504
477- return @call (.{ .modifier = .always_inline }, callMainWithArgs , .{ @intCast (usize , c_argc ), c_argv , envp });
505+ return @call (.{ .modifier = .always_inline }, callMainWithArgs , .{ @intCast (usize , c_argc ), @ptrCast ([ * ][ * : 0 ] u8 , c_argv ) , envp });
478506}
479507
480- fn mainWithoutEnv (c_argc : i32 , c_argv : [* ][* : 0 ]u8 ) callconv (.C ) usize {
481- std .os .argv = c_argv [0.. @intCast (usize , c_argc )];
508+ fn mainWithoutEnv (c_argc : c_int , c_argv : [* c ][* c ]u8 ) callconv (.C ) c_int {
509+ std .os .argv = @ptrCast ([ * ][ * : 0 ] u8 , c_argv ) [0.. @intCast (usize , c_argc )];
482510 return @call (.{ .modifier = .always_inline }, callMain , .{});
483511}
484512
0 commit comments