aboutsummaryrefslogtreecommitdiff
path: root/lib/std/start.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2022-10-19 07:56:02 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2022-10-25 05:11:29 -0400
commit4765294ca4bd7dd54207892b199f3053702d9a2a (patch)
tree678317de9d228b5d4532805fd7457af240cc0110 /lib/std/start.zig
parent912b84bbad698d18a6b844f9c05c074d2880e35b (diff)
downloadzig-4765294ca4bd7dd54207892b199f3053702d9a2a.tar.gz
zig-4765294ca4bd7dd54207892b199f3053702d9a2a.zip
cbe: get enough things working to support basic programs
* Enable advanced start support. * Enable advanced test_runner support. * Zig Language Reference's Hello World now works.
Diffstat (limited to 'lib/std/start.zig')
-rw-r--r--lib/std/start.zig158
1 files changed, 86 insertions, 72 deletions
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 9f70cce1ea..0563e2adad 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -23,7 +23,6 @@ comptime {
// Until then, we have simplified logic here for self-hosted. TODO remove this once
// self-hosted is capable enough to handle all of the real start.zig logic.
if (builtin.zig_backend == .stage2_wasm or
- builtin.zig_backend == .stage2_c or
builtin.zig_backend == .stage2_x86_64 or
builtin.zig_backend == .stage2_x86 or
builtin.zig_backend == .stage2_aarch64 or
@@ -265,75 +264,90 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
}
fn _start() callconv(.Naked) noreturn {
- switch (native_arch) {
- .x86_64 => {
- argc_argv_ptr = asm volatile (
- \\ xor %%rbp, %%rbp
- : [argc] "={rsp}" (-> [*]usize),
- );
- },
- .i386 => {
- argc_argv_ptr = asm volatile (
- \\ xor %%ebp, %%ebp
- : [argc] "={esp}" (-> [*]usize),
- );
- },
- .aarch64, .aarch64_be, .arm, .armeb, .thumb => {
- argc_argv_ptr = asm volatile (
- \\ mov fp, #0
- \\ mov lr, #0
- : [argc] "={sp}" (-> [*]usize),
- );
- },
- .riscv64 => {
- argc_argv_ptr = asm volatile (
- \\ li s0, 0
- \\ li ra, 0
- : [argc] "={sp}" (-> [*]usize),
- );
- },
- .mips, .mipsel => {
- // The lr is already zeroed on entry, as specified by the ABI.
- argc_argv_ptr = asm volatile (
- \\ move $fp, $0
- : [argc] "={sp}" (-> [*]usize),
- );
- },
- .powerpc => {
- // Setup the initial stack frame and clear the back chain pointer.
- argc_argv_ptr = asm volatile (
- \\ mr 4, 1
- \\ li 0, 0
- \\ stwu 1,-16(1)
- \\ stw 0, 0(1)
- \\ mtlr 0
- : [argc] "={r4}" (-> [*]usize),
- :
- : "r0"
- );
- },
- .powerpc64le => {
- // Setup the initial stack frame and clear the back chain pointer.
- // TODO: Support powerpc64 (big endian) on ELFv2.
- argc_argv_ptr = asm volatile (
- \\ mr 4, 1
- \\ li 0, 0
- \\ stdu 0, -32(1)
- \\ mtlr 0
- : [argc] "={r4}" (-> [*]usize),
- :
- : "r0"
- );
+ switch (builtin.zig_backend) {
+ .stage2_c => switch (native_arch) {
+ .x86_64 => {
+ @export(argc_argv_ptr, .{ .name = "argc_argv_ptr" });
+ @export(posixCallMainAndExit, .{ .name = "_posixCallMainAndExit" });
+ asm volatile (
+ \\ xor %%rbp, %%rbp
+ \\ mov %%rsp, argc_argv_ptr
+ \\ call _posixCallMainAndExit
+ );
+ unreachable;
+ },
+ else => @compileError("unsupported arch"),
},
- .sparc64 => {
- // argc is stored after a register window (16 registers) plus stack bias
- argc_argv_ptr = asm (
- \\ mov %%g0, %%i6
- \\ add %%o6, 2175, %[argc]
- : [argc] "=r" (-> [*]usize),
- );
+ else => switch (native_arch) {
+ .x86_64 => {
+ argc_argv_ptr = asm volatile (
+ \\ xor %%rbp, %%rbp
+ : [argc] "={rsp}" (-> [*]usize),
+ );
+ },
+ .i386 => {
+ argc_argv_ptr = asm volatile (
+ \\ xor %%ebp, %%ebp
+ : [argc] "={esp}" (-> [*]usize),
+ );
+ },
+ .aarch64, .aarch64_be, .arm, .armeb, .thumb => {
+ argc_argv_ptr = asm volatile (
+ \\ mov fp, #0
+ \\ mov lr, #0
+ : [argc] "={sp}" (-> [*]usize),
+ );
+ },
+ .riscv64 => {
+ argc_argv_ptr = asm volatile (
+ \\ li s0, 0
+ \\ li ra, 0
+ : [argc] "={sp}" (-> [*]usize),
+ );
+ },
+ .mips, .mipsel => {
+ // The lr is already zeroed on entry, as specified by the ABI.
+ argc_argv_ptr = asm volatile (
+ \\ move $fp, $0
+ : [argc] "={sp}" (-> [*]usize),
+ );
+ },
+ .powerpc => {
+ // Setup the initial stack frame and clear the back chain pointer.
+ argc_argv_ptr = asm volatile (
+ \\ mr 4, 1
+ \\ li 0, 0
+ \\ stwu 1,-16(1)
+ \\ stw 0, 0(1)
+ \\ mtlr 0
+ : [argc] "={r4}" (-> [*]usize),
+ :
+ : "r0"
+ );
+ },
+ .powerpc64le => {
+ // Setup the initial stack frame and clear the back chain pointer.
+ // TODO: Support powerpc64 (big endian) on ELFv2.
+ argc_argv_ptr = asm volatile (
+ \\ mr 4, 1
+ \\ li 0, 0
+ \\ stdu 0, -32(1)
+ \\ mtlr 0
+ : [argc] "={r4}" (-> [*]usize),
+ :
+ : "r0"
+ );
+ },
+ .sparc64 => {
+ // argc is stored after a register window (16 registers) plus stack bias
+ argc_argv_ptr = asm (
+ \\ mov %%g0, %%i6
+ \\ add %%o6, 2175, %[argc]
+ : [argc] "=r" (-> [*]usize),
+ );
+ },
+ else => @compileError("unsupported arch"),
},
- else => @compileError("unsupported arch"),
}
// If LLVM inlines stack variables into _start, they will overwrite
// the command line argument data.
@@ -363,7 +377,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result));
}
-fn posixCallMainAndExit() noreturn {
+fn posixCallMainAndExit() callconv(.C) noreturn {
@setAlignStack(16);
const argc = argc_argv_ptr[0];
@@ -462,7 +476,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
return initEventLoopAndCallMain();
}
-fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 {
+fn main(c_argc: c_int, c_argv: [*c][*c]u8, c_envp: [*c][*c]u8) callconv(.C) c_int {
var env_count: usize = 0;
while (c_envp[env_count] != null) : (env_count += 1) {}
const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
@@ -474,10 +488,10 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)
expandStackSize(phdrs);
}
- return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
+ return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), @ptrCast([*][*:0]u8, c_argv), envp });
}
-fn mainWithoutEnv(c_argc: i32, c_argv: [*][*:0]u8) callconv(.C) usize {
+fn mainWithoutEnv(c_argc: c_int, c_argv: [*c][*c]u8) callconv(.C) c_int {
std.os.argv = c_argv[0..@intCast(usize, c_argc)];
return @call(.{ .modifier = .always_inline }, callMain, .{});
}