From 72bcd5a4a50787b0407c21e61d660e59fa74e449 Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 15:15:39 -0500 Subject: [PATCH 1/8] WIP: hello world --- std/os.zig | 5 +- std/os/wasi.zig | 105 ++++++++++++++++++++++++++++++++++++++ std/os/wasi/core.zig | 12 +++++ std/special/bootstrap.zig | 12 +++++ std/special/panic.zig | 5 +- 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 std/os/wasi.zig create mode 100644 std/os/wasi/core.zig diff --git a/std/os.zig b/std/os.zig index d641cf29c..c1d5aa409 100644 --- a/std/os.zig +++ b/std/os.zig @@ -23,6 +23,7 @@ test "std.os" { _ = @import("os/time.zig"); _ = @import("os/windows.zig"); _ = @import("os/uefi.zig"); + _ = @import("os/wasi.zig"); _ = @import("os/get_app_data_dir.zig"); } @@ -33,6 +34,7 @@ pub const freebsd = @import("os/freebsd.zig"); pub const netbsd = @import("os/netbsd.zig"); pub const zen = @import("os/zen.zig"); pub const uefi = @import("os/uefi.zig"); +pub const wasi = @import("os/wasi.zig"); pub const posix = switch (builtin.os) { Os.linux => linux, @@ -40,6 +42,7 @@ pub const posix = switch (builtin.os) { Os.freebsd => freebsd, Os.netbsd => netbsd, Os.zen => zen, + Os.wasi => wasi, else => @compileError("Unsupported OS"), }; @@ -187,7 +190,7 @@ pub fn abort() noreturn { c.abort(); } switch (builtin.os) { - Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { + Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd, Os.wasi => { _ = posix.raise(posix.SIGABRT); _ = posix.raise(posix.SIGKILL); while (true) {} diff --git a/std/os/wasi.zig b/std/os/wasi.zig new file mode 100644 index 000000000..458669529 --- /dev/null +++ b/std/os/wasi.zig @@ -0,0 +1,105 @@ +use @import("wasi/core.zig"); + +pub const STDIN_FILENO = 0; +pub const STDOUT_FILENO = 1; +pub const STDERR_FILENO = 2; + +pub const ESUCCESS = 0; +pub const E2BIG = 1; +pub const EACCES = 2; +pub const EADDRINUSE = 3; +pub const EADDRNOTAVAIL = 4; +pub const EAFNOSUPPORT = 5; +pub const EAGAIN = 6; +pub const EALREADY = 7; +pub const EBADF = 8; +pub const EBADMSG = 9; +pub const EBUSY = 10; +pub const ECANCELED = 11; +pub const ECHILD = 12; +pub const ECONNABORTED = 13; +pub const ECONNREFUSED = 14; +pub const ECONNRESET = 15; +pub const EDEADLK = 16; +pub const EDESTADDRREQ = 17; +pub const EDOM = 18; +pub const EDQUOT = 19; +pub const EEXIST = 20; +pub const EFAULT = 21; +pub const EFBIG = 22; +pub const EHOSTUNREACH = 23; +pub const EIDRM = 24; +pub const EILSEQ = 25; +pub const EINPROGRESS = 26; +pub const EINTR = 27; +pub const EINVAL = 28; +pub const EIO = 29; +pub const EISCONN = 30; +pub const EISDIR = 31; +pub const ELOOP = 32; +pub const EMFILE = 33; +pub const EMLINK = 34; +pub const EMSGSIZE = 35; +pub const EMULTIHOP = 36; +pub const ENAMETOOLONG = 37; +pub const ENETDOWN = 38; +pub const ENETRESET = 39; +pub const ENETUNREACH = 40; +pub const ENFILE = 41; +pub const ENOBUFS = 42; +pub const ENODEV = 43; +pub const ENOENT = 44; +pub const ENOEXEC = 45; +pub const ENOLCK = 46; +pub const ENOLINK = 47; +pub const ENOMEM = 48; +pub const ENOMSG = 49; +pub const ENOPROTOOPT = 50; +pub const ENOSPC = 51; +pub const ENOSYS = 52; +pub const ENOTCONN = 53; +pub const ENOTDIR = 54; +pub const ENOTEMPTY = 55; +pub const ENOTRECOVERABLE = 56; +pub const ENOTSOCK = 57; +pub const ENOTSUP = 58; +pub const ENOTTY = 59; +pub const ENXIO = 60; +pub const EOVERFLOW = 61; +pub const EOWNERDEAD = 62; +pub const EPERM = 63; +pub const EPIPE = 64; +pub const EPROTO = 65; +pub const EPROTONOSUPPORT = 66; +pub const EPROTOTYPE = 67; +pub const ERANGE = 68; +pub const EROFS = 69; +pub const ESPIPE = 70; +pub const ESRCH = 71; +pub const ESTALE = 72; +pub const ETIMEDOUT = 73; +pub const ETXTBSY = 74; +pub const EXDEV = 75; +pub const ENOTCAPABLE = 76; + +// TODO: figure out what's going on here +pub fn getErrno(r: usize) usize { + const signed_r = @bitCast(isize, r); + return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0; +} + +pub fn exit(status: i32) noreturn { + __wasi_proc_exit(@bitCast(__wasi_exitcode_t, isize(status))); +} + +pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { + var nwritten: usize = undefined; + + const iovs = []__wasi_ciovec_t{__wasi_ciovec_t{ + .buf = buf, + .buf_len = count, + }}; + + _ = __wasi_fd_write(@bitCast(__wasi_fd_t, isize(fd)), &iovs[0], iovs.len, &nwritten); + return nwritten; +} diff --git a/std/os/wasi/core.zig b/std/os/wasi/core.zig new file mode 100644 index 000000000..329d8f8fc --- /dev/null +++ b/std/os/wasi/core.zig @@ -0,0 +1,12 @@ +pub const __wasi_errno_t = u16; +pub const __wasi_exitcode_t = u32; +pub const __wasi_fd_t = u32; + +pub const __wasi_ciovec_t = extern struct { + buf: [*]const u8, + buf_len: usize, +}; + +pub extern fn __wasi_proc_exit(rval: __wasi_exitcode_t) noreturn; + +pub extern fn __wasi_fd_write(fd: __wasi_fd_t, iovs: *const __wasi_ciovec_t, iovs_len: usize, nwritten: *usize) __wasi_errno_t; diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index 32f913a5b..e93a85861 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -14,6 +14,8 @@ comptime { @export("main", main, strong_linkage); } else if (builtin.os == builtin.Os.windows) { @export("WinMainCRTStartup", WinMainCRTStartup, strong_linkage); + } else if (builtin.os == builtin.Os.wasi) { + @export("_start", wasiStart, strong_linkage); } else { @export("_start", _start, strong_linkage); } @@ -43,6 +45,16 @@ nakedcc fn _start() noreturn { @noInlineCall(posixCallMainAndExit); } +nakedcc fn wasiStart() noreturn { + // TODO: Decide if alloc at init is acceptable for args and env + // @llvm.wasm.mem.grow.i32 + // __wasi_args_get() + // __wasi_args_sizes_get() + // __wasi_environ_get() + // __wasi_environ_sizes_get() + std.os.posix.exit(callMain()); +} + extern fn WinMainCRTStartup() noreturn { @setAlignStack(16); if (!builtin.single_threaded) { diff --git a/std/special/panic.zig b/std/special/panic.zig index 7cb714395..1d459665c 100644 --- a/std/special/panic.zig +++ b/std/special/panic.zig @@ -9,8 +9,9 @@ const std = @import("std"); pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { @setCold(true); switch (builtin.os) { - // TODO: fix panic in zen. - builtin.Os.freestanding, builtin.Os.zen => { + // TODO: fix panic in zen + // TODO: fix panic in wasi + builtin.Os.freestanding, builtin.Os.zen, builtin.Os.wasi => { while (true) {} }, builtin.Os.uefi => { From fe9cd0b4bc9aaf108d4b226710fa3c83612b62e1 Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 21:36:53 -0500 Subject: [PATCH 2/8] wasi: use __wasi_proc_exit instead of posix.exit --- std/os/wasi.zig | 2 +- std/special/bootstrap.zig | 16 ++++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/std/os/wasi.zig b/std/os/wasi.zig index 458669529..af51b266d 100644 --- a/std/os/wasi.zig +++ b/std/os/wasi.zig @@ -1,4 +1,4 @@ -use @import("wasi/core.zig"); +pub use @import("wasi/core.zig"); pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index e93a85861..520561d54 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -14,14 +14,16 @@ comptime { @export("main", main, strong_linkage); } else if (builtin.os == builtin.Os.windows) { @export("WinMainCRTStartup", WinMainCRTStartup, strong_linkage); - } else if (builtin.os == builtin.Os.wasi) { - @export("_start", wasiStart, strong_linkage); } else { @export("_start", _start, strong_linkage); } } nakedcc fn _start() noreturn { + if (builtin.os == builtin.Os.wasi) { + std.os.wasi.__wasi_proc_exit(callMain()); + } + switch (builtin.arch) { builtin.Arch.x86_64 => { argc_ptr = asm ("lea (%%rsp), %[argc]" @@ -45,16 +47,6 @@ nakedcc fn _start() noreturn { @noInlineCall(posixCallMainAndExit); } -nakedcc fn wasiStart() noreturn { - // TODO: Decide if alloc at init is acceptable for args and env - // @llvm.wasm.mem.grow.i32 - // __wasi_args_get() - // __wasi_args_sizes_get() - // __wasi_environ_get() - // __wasi_environ_sizes_get() - std.os.posix.exit(callMain()); -} - extern fn WinMainCRTStartup() noreturn { @setAlignStack(16); if (!builtin.single_threaded) { From 93528be6b19d608b4a02944e7e599554fc9f1378 Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 21:54:50 -0500 Subject: [PATCH 3/8] wasi: sigabrt at panic --- std/os/wasi/core.zig | 5 +++++ std/special/panic.zig | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/std/os/wasi/core.zig b/std/os/wasi/core.zig index 329d8f8fc..18c32837e 100644 --- a/std/os/wasi/core.zig +++ b/std/os/wasi/core.zig @@ -1,12 +1,17 @@ pub const __wasi_errno_t = u16; pub const __wasi_exitcode_t = u32; pub const __wasi_fd_t = u32; +pub const __wasi_signal_t = u8; pub const __wasi_ciovec_t = extern struct { buf: [*]const u8, buf_len: usize, }; +pub const __WASI_SIGABRT: __wasi_signal_t = 6; + +pub extern fn __wasi_proc_raise(sig: __wasi_signal_t) __wasi_errno_t; + pub extern fn __wasi_proc_exit(rval: __wasi_exitcode_t) noreturn; pub extern fn __wasi_fd_write(fd: __wasi_fd_t, iovs: *const __wasi_ciovec_t, iovs_len: usize, nwritten: *usize) __wasi_errno_t; diff --git a/std/special/panic.zig b/std/special/panic.zig index 1d459665c..64d9bf39f 100644 --- a/std/special/panic.zig +++ b/std/special/panic.zig @@ -10,10 +10,14 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn @setCold(true); switch (builtin.os) { // TODO: fix panic in zen - // TODO: fix panic in wasi - builtin.Os.freestanding, builtin.Os.zen, builtin.Os.wasi => { + builtin.Os.freestanding, builtin.Os.zen => { while (true) {} }, + builtin.Os.wasi => { + std.debug.warn("{}", msg); + _ = std.os.wasi.__wasi_proc_raise(std.os.wasi.__WASI_SIGABRT); + unreachable; + }, builtin.Os.uefi => { // TODO look into using the debug info and logging helpful messages std.os.abort(); From a2d8f03092419853b6bbcee45ea759ae994cc2d5 Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 22:28:58 -0500 Subject: [PATCH 4/8] support extern "wasi" functions --- src/ir.cpp | 9 ++++++++- std/os/wasi/core.zig | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index de4543df4..73a24a815 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15836,6 +15836,13 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, ira->codegen->reported_bad_link_libc_error = true; } + bool is_wasi = ira->codegen->zig_target->os == OsWASI; + if (!is_wasi && buf_eql_str(lib_name, "wasi")) { + ir_add_error_node(ira, source_node, + buf_sprintf("linking against wasi libarry")); + ira->codegen->reported_bad_link_libc_error = true; + } + LinkLib *link_lib = add_link_lib(ira->codegen, lib_name); for (size_t i = 0; i < link_lib->symbols.length; i += 1) { Buf *existing_symbol_name = link_lib->symbols.at(i); @@ -15844,7 +15851,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, } } - if (!is_libc && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error) { + if (!is_libc && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error && !is_wasi) { ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("dependency on dynamic library '%s' requires enabling Position Independent Code", buf_ptr(lib_name))); diff --git a/std/os/wasi/core.zig b/std/os/wasi/core.zig index 18c32837e..cda06cdce 100644 --- a/std/os/wasi/core.zig +++ b/std/os/wasi/core.zig @@ -10,8 +10,8 @@ pub const __wasi_ciovec_t = extern struct { pub const __WASI_SIGABRT: __wasi_signal_t = 6; -pub extern fn __wasi_proc_raise(sig: __wasi_signal_t) __wasi_errno_t; +pub extern "wasi" fn __wasi_proc_raise(sig: __wasi_signal_t) __wasi_errno_t; -pub extern fn __wasi_proc_exit(rval: __wasi_exitcode_t) noreturn; +pub extern "wasi" fn __wasi_proc_exit(rval: __wasi_exitcode_t) noreturn; -pub extern fn __wasi_fd_write(fd: __wasi_fd_t, iovs: *const __wasi_ciovec_t, iovs_len: usize, nwritten: *usize) __wasi_errno_t; +pub extern "wasi" fn __wasi_fd_write(fd: __wasi_fd_t, iovs: *const __wasi_ciovec_t, iovs_len: usize, nwritten: *usize) __wasi_errno_t; From 22960a5fdf932b63dfdbec1d3cb4efd077e9a776 Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 22:45:31 -0500 Subject: [PATCH 5/8] wasi: better comments --- std/os/wasi.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/std/os/wasi.zig b/std/os/wasi.zig index af51b266d..23c3a05af 100644 --- a/std/os/wasi.zig +++ b/std/os/wasi.zig @@ -1,5 +1,8 @@ pub use @import("wasi/core.zig"); +// Based on https://github.com/CraneStation/wasi-sysroot/blob/wasi/libc-bottom-half/headers/public/wasi/core.h +// and https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md + pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; pub const STDERR_FILENO = 2; @@ -82,7 +85,7 @@ pub const ETXTBSY = 74; pub const EXDEV = 75; pub const ENOTCAPABLE = 76; -// TODO: figure out what's going on here +// TODO: implement this like darwin does pub fn getErrno(r: usize) usize { const signed_r = @bitCast(isize, r); return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0; From 93d43d45293fe1ce89007dfa4aba40e18af2d9dd Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 22:51:18 -0500 Subject: [PATCH 6/8] wasi: add std/os/wasi{,/core}.zig to CMakeLists.txt --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c34f334f..38bd9a2a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -607,6 +607,8 @@ set(ZIG_STD_FILES "os/path.zig" "os/time.zig" "os/uefi.zig" + "os/wasi.zig" + "os/wasi/core.zig" "os/windows.zig" "os/windows/advapi32.zig" "os/windows/error.zig" From ecd0f8925447074307e8795bb8d6f9f6277a1a26 Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sat, 13 Apr 2019 23:49:02 -0500 Subject: [PATCH 7/8] wasi: better extern wasi logic --- src/ir.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 73a24a815..2cafc1edd 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15836,10 +15836,10 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, ira->codegen->reported_bad_link_libc_error = true; } - bool is_wasi = ira->codegen->zig_target->os == OsWASI; - if (!is_wasi && buf_eql_str(lib_name, "wasi")) { + bool is_wasi = buf_eql_str(lib_name, "wasi"); + if (is_wasi && ira->codegen->zig_target->os != OsWASI) { ir_add_error_node(ira, source_node, - buf_sprintf("linking against wasi libarry")); + buf_sprintf("linking against wasi library")); ira->codegen->reported_bad_link_libc_error = true; } @@ -15851,7 +15851,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, } } - if (!is_libc && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error && !is_wasi) { + if (!is_libc && !is_wasi && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error) { ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("dependency on dynamic library '%s' requires enabling Position Independent Code", buf_ptr(lib_name))); From 94e0871603add796e87ac53a3271cf5b9b3d6b0e Mon Sep 17 00:00:00 2001 From: Shritesh Bhattarai Date: Sun, 14 Apr 2019 00:03:32 -0500 Subject: [PATCH 8/8] wasi: don't pass --no-entry to linker --- src/link.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/link.cpp b/src/link.cpp index 78e549c80..6c6ff07ba 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1091,7 +1091,9 @@ static void construct_linker_job_wasm(LinkJob *lj) { CodeGen *g = lj->codegen; lj->args.append("-error-limit=0"); - lj->args.append("--no-entry"); // So lld doesn't look for _start. + if (g->zig_target->os != OsWASI) { + lj->args.append("--no-entry"); // So lld doesn't look for _start. + } lj->args.append("--allow-undefined"); lj->args.append("--export-all"); lj->args.append("-o");