aboutsummaryrefslogtreecommitdiff
path: root/std/bootstrap.zig
blob: 074f06557e75d36b66a5a993d68cc7d147f2f998 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// This file is in a package which has the root source file exposed as "@root".
// It is included in the compilation unit when exporting an executable.

const root = @import("@root");
const std = @import("std");

const want_main_symbol = std.build.linkingLibrary("c");
const want_start_symbol = !want_main_symbol;

const exit = switch(@compileVar("os")) {
    Os.linux => std.linux.exit,
    Os.darwin => std.darwin.exit,
    else => @compileError("Unsupported OS"),
};

var argc: usize = undefined;
var argv: &&u8 = undefined;

export nakedcc fn _start() -> unreachable {
    @setFnVisible(this, want_start_symbol);

    switch (@compileVar("arch")) {
        Arch.x86_64 => {
            argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize));
            argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8));
        },
        Arch.i386 => {
            argc = asm("mov (%%esp), %[argc]": [argc] "=r" (-> usize));
            argv = asm("lea 0x4(%%esp), %[argv]": [argv] "=r" (-> &&u8));
        },
        else => @compileError("unsupported arch"),
    }
    callMainAndExit()
}

fn callMain() -> %void {
    const args = @alloca([]u8, argc);
    for (args) |_, i| {
        const ptr = argv[i];
        args[i] = ptr[0...std.cstr.len(ptr)];
    }
    return root.main(args);
}

fn callMainAndExit() -> unreachable {
    callMain() %% exit(1);
    exit(0);
}

export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
    @setFnVisible(this, want_main_symbol);

    argc = usize(c_argc);
    argv = c_argv;
    callMain() %% return 1;
    return 0;
}