aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-11-15 17:40:04 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-12-06 12:15:04 -0700
commit39fd77bc163f0d7fc7408cbb4e48f960b4739448 (patch)
treef32d6bbf639cf5840e72bb4a5ed6f5c56dc6165f
parentef447c3ecac4211a0a03f487e84acc61160d7ede (diff)
downloadzig-39fd77bc163f0d7fc7408cbb4e48f960b4739448.tar.gz
zig-39fd77bc163f0d7fc7408cbb4e48f960b4739448.zip
interpret the WASI blob to produce zig2.c and compiler_rt.c
* synchronize zig1.c from zig-wasi external project * change the way argv works to avoid absolute paths * autodetect isatty * compiler_rt: disable some functions when object format is C * add missing flag from config.zig.in The next problem is that compiling compiler_rt.c with gcc gives "conflicting types" errors for `__eqhf2` and friends.
-rw-r--r--CMakeLists.txt24
-rw-r--r--lib/compiler_rt.zig26
-rw-r--r--stage1/config.zig.in1
-rwxr-xr-xstage1/zig1.c675
4 files changed, 491 insertions, 235 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9fd5614bc..d48187a90f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -702,29 +702,24 @@ if(MSVC)
set(ZIG2_COMPILE_FLAGS "/std:c99")
set(ZIG2_LINK_FLAGS "/STACK:16777216")
else()
- #set(ZIG1_COMPILE_FLAGS "-std=c99 -O2 -march=native")
- set(ZIG1_COMPILE_FLAGS "-std=c99 -march=native")
+ set(ZIG1_COMPILE_FLAGS "-std=c99 -O2 -march=native")
set(ZIG2_COMPILE_FLAGS "-std=c99 -O2 -march=native")
set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000")
endif()
add_executable(zig1 ${STAGE1_SOURCES})
set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})
-#target_include_directories(zig1 PUBLIC "${CMAKE_SOURCE_DIR}/lib")
target_link_libraries(zig1 LINK_PUBLIC m)
set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")
set(BUILD_ZIG2_ARGS
"${CMAKE_SOURCE_DIR}/lib"
- "${CMAKE_BINARY_DIR}/zig1-cache"
+ "${CMAKE_BINARY_DIR}"
+ zig2
"${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"
build-exe src/main.zig -ofmt=c -lc
- --name zig2
- --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"
- --pkg-end
-target x86_64-linux-musl # TODO: autodetect in zig1.c
- --color on # TODO: autodetect in zig1.c
-OReleaseFast
)
@@ -739,12 +734,11 @@ add_custom_command(
set(ZIG_COMPILER_RT_C_SOURCE "${CMAKE_BINARY_DIR}/compiler_rt.c")
set(BUILD_COMPILER_RT_ARGS
"${CMAKE_SOURCE_DIR}/lib"
- "${CMAKE_BINARY_DIR}/zig1-cache"
+ "${CMAKE_BINARY_DIR}"
+ compiler_rt
"${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"
build-obj lib/compiler_rt.zig -ofmt=c
- --name compiler_rt
-target x86_64-linux-musl # TODO: autodetect in zig1.c
- --color on # TODO: autodetect in zig1.c
-OReleaseFast
)
@@ -757,13 +751,9 @@ add_custom_command(
)
-add_executable(zig2 ${ZIG2_C_SOURCE})
+add_executable(zig2 ${ZIG2_C_SOURCE} ${ZIG_COMPILER_RT_C_SOURCE})
set_target_properties(zig2 PROPERTIES
COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}
LINK_FLAGS ${ZIG2_LINK_FLAGS}
)
-
-
-
-
-
+target_include_directories(zig2 PUBLIC "${CMAKE_SOURCE_DIR}/lib")
diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig
index 44146d04e9..3ffaf9f0e5 100644
--- a/lib/compiler_rt.zig
+++ b/lib/compiler_rt.zig
@@ -3,13 +3,6 @@ const builtin = @import("builtin");
pub const panic = @import("compiler_rt/common.zig").panic;
comptime {
- _ = @import("compiler_rt/atomics.zig");
-
- // macOS has these functions inside libSystem.
- if (builtin.cpu.arch.isAARCH64() and !builtin.os.tag.isDarwin()) {
- _ = @import("compiler_rt/aarch64_outline_atomics.zig");
- }
-
_ = @import("compiler_rt/addf3.zig");
_ = @import("compiler_rt/addhf3.zig");
_ = @import("compiler_rt/addsf3.zig");
@@ -216,9 +209,18 @@ comptime {
_ = @import("compiler_rt/aullrem.zig");
_ = @import("compiler_rt/clear_cache.zig");
- _ = @import("compiler_rt/memcpy.zig");
- _ = @import("compiler_rt/memset.zig");
- _ = @import("compiler_rt/memmove.zig");
- _ = @import("compiler_rt/memcmp.zig");
- _ = @import("compiler_rt/bcmp.zig");
+ if (@import("builtin").object_format != .c) {
+ _ = @import("compiler_rt/atomics.zig");
+
+ // macOS has these functions inside libSystem.
+ if (builtin.cpu.arch.isAARCH64() and !builtin.os.tag.isDarwin()) {
+ _ = @import("compiler_rt/aarch64_outline_atomics.zig");
+ }
+
+ _ = @import("compiler_rt/memcpy.zig");
+ _ = @import("compiler_rt/memset.zig");
+ _ = @import("compiler_rt/memmove.zig");
+ _ = @import("compiler_rt/memcmp.zig");
+ _ = @import("compiler_rt/bcmp.zig");
+ }
}
diff --git a/stage1/config.zig.in b/stage1/config.zig.in
index 48d1f75adb..347c757f93 100644
--- a/stage1/config.zig.in
+++ b/stage1/config.zig.in
@@ -11,3 +11,4 @@ pub const value_tracing = false;
pub const have_stage1 = false;
pub const skip_non_native = false;
pub const only_c = true;
+pub const force_gpa = false;
diff --git a/stage1/zig1.c b/stage1/zig1.c
index 1cdac5a52b..34df5230f5 100755
--- a/stage1/zig1.c
+++ b/stage1/zig1.c
@@ -10,11 +10,16 @@
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <time.h>
#include <unistd.h>
+#ifdef __linux__
+#include <sys/random.h>
+#endif
+
enum wasi_errno_t {
WASI_ESUCCESS = 0,
WASI_E2BIG = 1,
@@ -131,15 +136,12 @@ static uint64_t rotr64(uint64_t n, unsigned c) {
static void *arena_alloc(size_t n) {
void *ptr = malloc(n);
if (!ptr) panic("out of memory");
+#ifndef NDEBUG
+ memset(ptr, 0xaa, n); // to match the zig version
+#endif
return ptr;
}
-static void *arena_realloc(void *ptr, size_t new_n) {
- void *new_ptr = realloc(ptr, new_n);
- if (!new_ptr) panic("out of memory");
- return new_ptr;
-}
-
static int err_wrap(const char *prefix, int rc) {
if (rc == -1) {
perror(prefix);
@@ -152,7 +154,7 @@ static bool bs_isSet(const uint32_t *bitset, uint32_t index) {
return (bitset[index >> 5] >> (index & 0x1f)) & 1;
}
static void bs_set(uint32_t *bitset, uint32_t index) {
- bitset[index >> 5] |= ((uint32_t)1 << (index & 0x1f));
+ bitset[index >> 5] |= ((uint32_t)1 << (index & 0x1f));
}
static void bs_unset(uint32_t *bitset, uint32_t index) {
bitset[index >> 5] &= ~((uint32_t)1 << (index & 0x1f));
@@ -213,7 +215,7 @@ static const struct Preopen *find_preopen(int32_t wasi_fd) {
return NULL;
}
-static const size_t max_memory = 2ul * 1024ul * 1024ul * 1024ul; // 2 GiB
+static const uint32_t max_memory = 2ul * 1024ul * 1024ul * 1024ul; // 2 GiB
static uint16_t read_u16_le(const char *ptr) {
const uint8_t *u8_ptr = (const uint8_t *)ptr;
@@ -655,6 +657,7 @@ struct VirtualMachine {
/// Points to one after the last stack item.
uint32_t stack_top;
struct ProgramCounter pc;
+ /// Actual memory usage of the WASI code. The capacity is max_memory.
uint32_t memory_len;
const char *mod_ptr;
uint8_t *opcodes;
@@ -666,7 +669,7 @@ struct VirtualMachine {
char *memory;
struct Import *imports;
uint32_t imports_len;
- char **args;
+ const char **args;
uint32_t *table;
};
@@ -678,22 +681,156 @@ static int to_host_fd(int32_t wasi_fd) {
static enum wasi_errno_t to_wasi_err(int err) {
switch (err) {
+ case E2BIG: return WASI_E2BIG;
case EACCES: return WASI_EACCES;
+ case EADDRINUSE: return WASI_EADDRINUSE;
+ case EADDRNOTAVAIL: return WASI_EADDRNOTAVAIL;
+ case EAFNOSUPPORT: return WASI_EAFNOSUPPORT;
+ case EAGAIN: return WASI_EAGAIN;
+ case EALREADY: return WASI_EALREADY;
+ case EBADF: return WASI_EBADF;
+ case EBADMSG: return WASI_EBADMSG;
+ case EBUSY: return WASI_EBUSY;
+ case ECANCELED: return WASI_ECANCELED;
+ case ECHILD: return WASI_ECHILD;
+ case ECONNABORTED: return WASI_ECONNABORTED;
+ case ECONNREFUSED: return WASI_ECONNREFUSED;
+ case ECONNRESET: return WASI_ECONNRESET;
+ case EDEADLK: return WASI_EDEADLK;
+ case EDESTADDRREQ: return WASI_EDESTADDRREQ;
+ case EDOM: return WASI_EDOM;
case EDQUOT: return WASI_EDQUOT;
- case EIO: return WASI_EIO;
+ case EEXIST: return WASI_EEXIST;
+ case EFAULT: return WASI_EFAULT;
case EFBIG: return WASI_EFBIG;
+ case EHOSTUNREACH: return WASI_EHOSTUNREACH;
+ case EIDRM: return WASI_EIDRM;
+ case EILSEQ: return WASI_EILSEQ;
+ case EINPROGRESS: return WASI_EINPROGRESS;
+ case EINTR: return WASI_EINTR;
+ case EINVAL: return WASI_EINVAL;
+ case EIO: return WASI_EIO;
+ case EISCONN: return WASI_EISCONN;
+ case EISDIR: return WASI_EISDIR;
+ case ELOOP: return WASI_ELOOP;
+ case EMFILE: return WASI_EMFILE;
+ case EMLINK: return WASI_EMLINK;
+ case EMSGSIZE: return WASI_EMSGSIZE;
+ case EMULTIHOP: return WASI_EMULTIHOP;
+ case ENAMETOOLONG: return WASI_ENAMETOOLONG;
+ case ENETDOWN: return WASI_ENETDOWN;
+ case ENETRESET: return WASI_ENETRESET;
+ case ENETUNREACH: return WASI_ENETUNREACH;
+ case ENFILE: return WASI_ENFILE;
+ case ENOBUFS: return WASI_ENOBUFS;
+ case ENODEV: return WASI_ENODEV;
+ case ENOENT: return WASI_ENOENT;
+ case ENOEXEC: return WASI_ENOEXEC;
+ case ENOLCK: return WASI_ENOLCK;
+ case ENOLINK: return WASI_ENOLINK;
+ case ENOMEM: return WASI_ENOMEM;
+ case ENOMSG: return WASI_ENOMSG;
+ case ENOPROTOOPT: return WASI_ENOPROTOOPT;
case ENOSPC: return WASI_ENOSPC;
+ case ENOSYS: return WASI_ENOSYS;
+ case ENOTCONN: return WASI_ENOTCONN;
+ case ENOTDIR: return WASI_ENOTDIR;
+ case ENOTEMPTY: return WASI_ENOTEMPTY;
+ case ENOTRECOVERABLE: return WASI_ENOTRECOVERABLE;
+ case ENOTSOCK: return WASI_ENOTSOCK;
+ case EOPNOTSUPP: return WASI_EOPNOTSUPP;
+ case ENOTTY: return WASI_ENOTTY;
+ case ENXIO: return WASI_ENXIO;
+ case EOVERFLOW: return WASI_EOVERFLOW;
+ case EOWNERDEAD: return WASI_EOWNERDEAD;
+ case EPERM: return WASI_EPERM;
case EPIPE: return WASI_EPIPE;
- case EBADF: return WASI_EBADF;
- case ENOMEM: return WASI_ENOMEM;
- case ENOENT: return WASI_ENOENT;
- case EEXIST: return WASI_EEXIST;
+ case EPROTO: return WASI_EPROTO;
+ case EPROTONOSUPPORT: return WASI_EPROTONOSUPPORT;
+ case EPROTOTYPE: return WASI_EPROTOTYPE;
+ case ERANGE: return WASI_ERANGE;
+ case EROFS: return WASI_EROFS;
+ case ESPIPE: return WASI_ESPIPE;
+ case ESRCH: return WASI_ESRCH;
+ case ESTALE: return WASI_ESTALE;
+ case ETIMEDOUT: return WASI_ETIMEDOUT;
+ case ETXTBSY: return WASI_ETXTBSY;
+ case EXDEV: return WASI_EXDEV;
default:
fprintf(stderr, "unexpected errno: %s\n", strerror(err));
abort();
};
}
+enum wasi_filetype_t {
+ wasi_filetype_t_UNKNOWN,
+ wasi_filetype_t_BLOCK_DEVICE,
+ wasi_filetype_t_CHARACTER_DEVICE,
+ wasi_filetype_t_DIRECTORY,
+ wasi_filetype_t_REGULAR_FILE,
+ wasi_filetype_t_SOCKET_DGRAM,
+ wasi_filetype_t_SOCKET_STREAM,
+ wasi_filetype_t_SYMBOLIC_LINK,
+};
+
+static const uint16_t WASI_O_CREAT = 0x0001;
+static const uint16_t WASI_O_DIRECTORY = 0x0002;
+static const uint16_t WASI_O_EXCL = 0x0004;
+static const uint16_t WASI_O_TRUNC = 0x0008;
+
+static const uint16_t WASI_FDFLAG_APPEND = 0x0001;
+static const uint16_t WASI_FDFLAG_DSYNC = 0x0002;
+static const uint16_t WASI_FDFLAG_NONBLOCK = 0x0004;
+static const uint16_t WASI_FDFLAG_SYNC = 0x0010;
+
+static const uint64_t WASI_RIGHT_FD_READ = 0x0000000000000002ull;
+static const uint64_t WASI_RIGHT_FD_WRITE = 0x0000000000000040ull;
+
+static enum wasi_filetype_t to_wasi_filetype(mode_t st_mode) {
+ switch (st_mode & S_IFMT) {
+ case S_IFBLK:
+ return wasi_filetype_t_BLOCK_DEVICE;
+ case S_IFCHR:
+ return wasi_filetype_t_CHARACTER_DEVICE;
+ case S_IFDIR:
+ return wasi_filetype_t_DIRECTORY;
+ case S_IFLNK:
+ return wasi_filetype_t_SYMBOLIC_LINK;
+ case S_IFREG:
+ return wasi_filetype_t_REGULAR_FILE;
+ default:
+ return wasi_filetype_t_UNKNOWN;
+ }
+}
+
+static uint64_t to_wasi_timestamp(struct timespec ts) {
+ return ts.tv_sec * 1000000000ull + ts.tv_nsec;
+}
+
+/// const filestat_t = extern struct {
+/// dev: device_t, u64
+/// ino: inode_t, u64
+/// filetype: filetype_t, u8
+/// nlink: linkcount_t, u64
+/// size: filesize_t, u64
+/// atim: timestamp_t, u64
+/// mtim: timestamp_t, u64
+/// ctim: timestamp_t, u64
+/// };
+static enum wasi_errno_t finish_wasi_stat(struct VirtualMachine *vm,
+ uint32_t buf, struct stat st)
+{
+ write_u64_le(vm->memory + buf + 0x00, 0); // device
+ write_u64_le(vm->memory + buf + 0x08, st.st_ino);
+ write_u64_le(vm->memory + buf + 0x10, to_wasi_filetype(st.st_mode));
+ write_u64_le(vm->memory + buf + 0x18, 1); // nlink
+ write_u64_le(vm->memory + buf + 0x20, st.st_size);
+ write_u64_le(vm->memory + buf + 0x28, to_wasi_timestamp(st.st_atim));
+ write_u64_le(vm->memory + buf + 0x30, to_wasi_timestamp(st.st_mtim));
+ write_u64_le(vm->memory + buf + 0x38, to_wasi_timestamp(st.st_ctim));
+ return WASI_ESUCCESS;
+}
+
/// fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,
uint32_t argc, uint32_t argv_buf_size)
@@ -713,17 +850,19 @@ static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,
static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,
uint32_t argv, uint32_t argv_buf)
{
- panic("TODO implement wasi_args_get");
- //var argv_buf_i: usize = 0;
- //for (vm->args) |arg, arg_i| {
- // // Write the arg to the buffer.
- // const argv_ptr = argv_buf + argv_buf_i;
- // const arg_len = mem.span(arg).len + 1;
- // mem.copy(u8, vm->memory[argv_buf + argv_buf_i ..], arg[0..arg_len]);
- // argv_buf_i += arg_len;
-
- // write_u32_le(vm->memory[argv + 4 * arg_i ..][0..4], @intCast(u32, argv_ptr));
- //}
+ uint32_t argv_buf_i = 0;
+ uint32_t arg_i = 0;
+ for (;; arg_i += 1) {
+ const char *arg = vm->args[arg_i];
+ if (!arg) break;
+ // Write the arg to the buffer.
+ uint32_t argv_ptr = argv_buf + argv_buf_i;
+ uint32_t arg_len = strlen(arg) + 1;
+ memcpy(vm->memory + argv_buf + argv_buf_i, arg, arg_len);
+ argv_buf_i += arg_len;
+
+ write_u32_le(vm->memory + argv + 4 * arg_i , argv_ptr);
+ }
return WASI_ESUCCESS;
}
@@ -731,9 +870,15 @@ static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,
static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,
uint32_t buf, uint32_t buf_len)
{
- panic("TODO implement wasi_random_get");
- //const host_buf = vm->memory[buf..][0..buf_len];
- //std.crypto.random.bytes(host_buf);
+#ifdef __linux__
+ if (getrandom(vm->memory + buf, buf_len, 0) != buf_len) {
+ panic("getrandom failed");
+ }
+#else
+ for (uint32_t i = 0; i < buf_len; i += 1) {
+ vm->memory[buf + i] = rand();
+ }
+#endif
return WASI_ESUCCESS;
}
@@ -745,10 +890,10 @@ static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,
static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,
int32_t fd, uint32_t buf)
{
- panic("TODO implement wasi_fd_prestat_get");
- //const preopen = findPreopen(fd) orelse return .BADF;
- //write_u32_le(vm->memory[buf + 0 ..][0..4], 0);
- //write_u32_le(vm->memory[buf + 4 ..][0..4], @intCast(u32, preopen.name.len));
+ const struct Preopen *preopen = find_preopen(fd);
+ if (!preopen) return WASI_EBADF;
+ write_u32_le(vm->memory + buf + 0, 0);
+ write_u32_le(vm->memory + buf + 4, preopen->name_len);
return WASI_ESUCCESS;
}
@@ -756,19 +901,18 @@ static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,
static enum wasi_errno_t wasi_fd_prestat_dir_name(struct VirtualMachine *vm,
int32_t fd, uint32_t path, uint32_t path_len)
{
- panic("TODO implement wasi_fd_prestat_dir_name");
- //const preopen = findPreopen(fd) orelse return .BADF;
- //assert(path_len == preopen.name.len);
- //mem.copy(u8, vm->memory[path..], preopen.name);
+ const struct Preopen *preopen = find_preopen(fd);
+ if (!preopen) return WASI_EBADF;
+ if (path_len != preopen->name_len)
+ panic("wasi_fd_prestat_dir_name expects correct name_len");
+ memcpy(vm->memory + path, preopen->name, path_len);
return WASI_ESUCCESS;
}
/// extern fn fd_close(fd: fd_t) errno_t;
static enum wasi_errno_t wasi_fd_close(struct VirtualMachine *vm, int32_t fd) {
- panic("TODO implement wasi_fd_close");
- //_ = vm;
- //const host_fd = toHostFd(fd);
- //os.close(host_fd);
+ int host_fd = to_host_fd(fd);
+ close(host_fd);
return WASI_ESUCCESS;
}
@@ -779,20 +923,18 @@ static enum wasi_errno_t wasi_fd_read(
uint32_t iovs_len, // usize
uint32_t nread // *usize
) {
- panic("TODO implement wasi_fd_read");
- //const host_fd = toHostFd(fd);
- //var i: u32 = 0;
- //var total_read: usize = 0;
- //while (i < iovs_len) : (i += 1) {
- // uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
- // uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
- // const buf = vm->memory[ptr..][0..len];
- // const read = os.read(host_fd, buf) catch |err| return toWasiError(err);
- // trace_log.debug("read {d} bytes out of {d}", .{ read, buf.len });
- // total_read += read;
- // if (read != buf.len) break;
- //}
- //write_u32_le(vm->memory[nread..][0..4], @intCast(u32, total_read));
+ int host_fd = to_host_fd(fd);
+ uint32_t i = 0;
+ size_t total_read = 0;
+ for (; i < iovs_len; i += 1) {
+ uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
+ uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
+ ssize_t amt_read = read(host_fd, vm->memory + ptr, len);
+ if (amt_read < 0) return to_wasi_err(errno);
+ total_read += amt_read;
+ if (amt_read != len) break;
+ }
+ write_u32_le(vm->memory + nread, total_read);
return WASI_ESUCCESS;
}
@@ -826,19 +968,18 @@ static enum wasi_errno_t wasi_fd_pwrite(
uint64_t offset, // wasi.filesize_t,
uint32_t written_ptr // *usize
) {
- panic("TODO implement wasi_fd_pwrite");
- //const host_fd = toHostFd(fd);
- //var i: u32 = 0;
- //var written: usize = 0;
- //while (i < iovs_len) : (i += 1) {
- // uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
- // uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
- // const buf = vm->memory[ptr..][0..len];
- // const w = os.pwrite(host_fd, buf, offset + written) catch |err| return toWasiError(err);
- // written += w;
- // if (w != buf.len) break;
- //}
- //write_u32_le(vm->memory[written_ptr..][0..4], @intCast(u32, written));
+ int host_fd = to_host_fd(fd);
+ uint32_t i = 0;
+ size_t written = 0;
+ for (; i < iovs_len; i += 1) {
+ uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
+ uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
+ ssize_t w = pwrite(host_fd, vm->memory + ptr, len, offset + written);
+ if (w < 0) return to_wasi_err(errno);
+ written += w;
+ if (w != len) break;
+ }
+ write_u32_le(vm->memory + written_ptr, written);
return WASI_ESUCCESS;
}
@@ -865,29 +1006,34 @@ static enum wasi_errno_t wasi_path_open(
uint16_t fs_flags, // wasi.fdflags_t,
uint32_t fd
) {
- panic("TODO implement wasi_path_open");
- //const sub_path = vm->memory[path..][0..path_len];
- //const host_fd = toHostFd(dirfd);
- //var flags: u32 = @as(u32, if (oflags & wasi.O.CREAT != 0) os.O.CREAT else 0) |
- // @as(u32, if (oflags & wasi.O.DIRECTORY != 0) os.O.DIRECTORY else 0) |
- // @as(u32, if (oflags & wasi.O.EXCL != 0) os.O.EXCL else 0) |
- // @as(u32, if (oflags & wasi.O.TRUNC != 0) os.O.TRUNC else 0) |
- // @as(u32, if (fs_flags & wasi.FDFLAG.APPEND != 0) os.O.APPEND else 0) |
- // @as(u32, if (fs_flags & wasi.FDFLAG.DSYNC != 0) os.O.DSYNC else 0) |
- // @as(u32, if (fs_flags & wasi.FDFLAG.NONBLOCK != 0) os.O.NONBLOCK else 0) |
- // @as(u32, if (fs_flags & wasi.FDFLAG.SYNC != 0) os.O.SYNC else 0);
- //if ((fs_rights_base & wasi.RIGHT.FD_READ != 0) and
- // (fs_rights_base & wasi.RIGHT.FD_WRITE != 0))
- //{
- // flags |= os.O.RDWR;
- //} else if (fs_rights_base & wasi.RIGHT.FD_WRITE != 0) {
- // flags |= os.O.WRONLY;
- //} else if (fs_rights_base & wasi.RIGHT.FD_READ != 0) {
- // flags |= os.O.RDONLY; // no-op because O_RDONLY is 0
- //}
- //const mode = 0o644;
- //const res_fd = os.openat(host_fd, sub_path, flags, mode) catch |err| return toWasiError(err);
- //mem.writeIntLittle(i32, vm->memory[fd..][0..4], res_fd);
+ char sub_path[PATH_MAX];
+ memcpy(sub_path, vm->memory + path, path_len);
+ sub_path[path_len] = 0;
+
+ int host_fd = to_host_fd(dirfd);
+ uint32_t flags =
+ (((oflags & WASI_O_CREAT) != 0) ? O_CREAT : 0) |
+ (((oflags & WASI_O_DIRECTORY) != 0) ? O_DIRECTORY : 0) |
+ (((oflags & WASI_O_EXCL) != 0) ? O_EXCL : 0) |
+ (((oflags & WASI_O_TRUNC) != 0) ? O_TRUNC : 0) |
+ (((fs_flags & WASI_FDFLAG_APPEND) != 0) ? O_APPEND : 0) |
+ (((fs_flags & WASI_FDFLAG_DSYNC) != 0) ? O_DSYNC : 0) |
+ (((fs_flags & WASI_FDFLAG_NONBLOCK) != 0) ? O_NONBLOCK : 0) |
+ (((fs_flags & WASI_FDFLAG_SYNC) != 0) ? O_SYNC : 0);
+
+ if (((fs_rights_base & WASI_RIGHT_FD_READ) != 0) &&
+ ((fs_rights_base & WASI_RIGHT_FD_WRITE) != 0))
+ {
+ flags |= O_RDWR;
+ } else if ((fs_rights_base & WASI_RIGHT_FD_WRITE) != 0) {
+ flags |= O_WRONLY;
+ } else if ((fs_rights_base & WASI_RIGHT_FD_READ) != 0) {
+ flags |= O_RDONLY; // no-op because O_RDONLY is 0
+ }
+ mode_t mode = 0644;
+ int res_fd = openat(host_fd, sub_path, flags, mode);
+ if (res_fd == -1) return to_wasi_err(errno);
+ write_u32_le(vm->memory + fd, res_fd);
return WASI_ESUCCESS;
}
@@ -899,23 +1045,26 @@ static enum wasi_errno_t wasi_path_filestat_get(
uint32_t path_len, // usize
uint32_t buf // *filestat_t
) {
- panic("TODO implement wasi_path_filestat_get");
- //const sub_path = vm->memory[path..][0..path_len];
- //const host_fd = toHostFd(fd);
- //const dir: fs.Dir = .{ .fd = host_fd };
- //const stat = dir.statFile(sub_path) catch |err| return toWasiError(err);
- //return finishWasiStat(vm, buf, stat);
- return WASI_ESUCCESS;
+ char sub_path[PATH_MAX];
+ memcpy(sub_path, vm->memory + path, path_len);
+ sub_path[path_len] = 0;
+
+ int host_fd = to_host_fd(fd);
+ struct stat st;
+ if (fstatat(host_fd, sub_path, &st, 0) == -1) return to_wasi_err(errno);
+ return finish_wasi_stat(vm, buf, st);
}
/// extern fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
-static enum wasi_errno_t wasi_path_create_directory(struct VirtualMachine *vm, int32_t fd, uint32_t path, uint32_t path_len) {
- panic("TODO implement wasi_path_create_directory");
- //const sub_path = vm->memory[path..][0..path_len];
- //trace_log.debug("wasi_path_create_directory fd={d} path={s}", .{ fd, sub_path });
- //const host_fd = toHostFd(fd);
- //const dir: fs.Dir = .{ .fd = host_fd };
- //dir.makeDir(sub_path) catch |err| return toWasiError(err);
+static enum wasi_errno_t wasi_path_create_directory(struct VirtualMachine *vm,
+ int32_t wasi_fd, uint32_t path, uint32_t path_len)
+{
+ char sub_path[PATH_MAX];
+ memcpy(sub_path, vm->memory + path, path_len);
+ sub_path[path_len] = 0;
+
+ int host_fd = to_host_fd(wasi_fd);
+ if (mkdirat(host_fd, sub_path, 0777) == -1) return to_wasi_err(errno);
return WASI_ESUCCESS;
}
@@ -928,35 +1077,33 @@ static enum wasi_errno_t wasi_path_rename(
uint32_t new_path_ptr, // [*]const u8
uint32_t new_path_len // usize
) {
- panic("TODO implement wasi_path_rename");
- //const old_path = vm->memory[old_path_ptr..][0..old_path_len];
- //const new_path = vm->memory[new_path_ptr..][0..new_path_len];
- //trace_log.debug("wasi_path_rename old_fd={d} old_path={s} new_fd={d} new_path={s}", .{
- // old_fd, old_path, new_fd, new_path,
- //});
- //const old_host_fd = toHostFd(old_fd);
- //const new_host_fd = toHostFd(new_fd);
- //os.renameat(old_host_fd, old_path, new_host_fd, new_path) catch |err| return toWasiError(err);
+ char old_path[PATH_MAX];
+ memcpy(old_path, vm->memory + old_path_ptr, old_path_len);
+ old_path[old_path_len] = 0;
+
+ char new_path[PATH_MAX];
+ memcpy(new_path, vm->memory + new_path_ptr, new_path_len);
+ new_path[new_path_len] = 0;
+
+ int old_host_fd = to_host_fd(old_fd);
+ int new_host_fd = to_host_fd(new_fd);
+ if (renameat(old_host_fd, old_path, new_host_fd, new_path) == -1) return to_wasi_err(errno);
return WASI_ESUCCESS;
}
/// extern fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t;
static enum wasi_errno_t wasi_fd_filestat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {
- panic("TODO implement wasi_fd_filestat_get");
- //const host_fd = toHostFd(fd);
- //const file = fs.File{ .handle = host_fd };
- //const stat = file.stat() catch |err| return toWasiError(err);
- //return finishWasiStat(vm, buf, stat);
- return WASI_ESUCCESS;
+ int host_fd = to_host_fd(fd);
+ struct stat st;
+ if (fstat(host_fd, &st) == -1) return to_wasi_err(errno);
+ return finish_wasi_stat(vm, buf, st);
}
static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,
int32_t fd, uint64_t size)
{
- panic("TODO implement wasi_fd_filestat_set_size");
- //_ = vm;
- //const host_fd = toHostFd(fd);
- //os.ftruncate(host_fd, size) catch |err| return toWasiError(err);
+ int host_fd = to_host_fd(fd);
+ if (ftruncate(host_fd, size) == -1) return to_wasi_err(errno);
return WASI_ESUCCESS;
}
@@ -968,14 +1115,13 @@ static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,
/// fs_rights_inheriting: rights_t, u64
/// };
static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {
- panic("TODO implement wasi_fd_fdstat_get");
- //const host_fd = toHostFd(fd);
- //const file = fs.File{ .handle = host_fd };
- //const stat = file.stat() catch |err| return toWasiError(err);
- //mem.writeIntLittle(u16, vm->memory[buf + 0x00 ..][0..2], @enumToInt(toWasiFileType(stat.kind)));
- //mem.writeIntLittle(u16, vm->memory[buf + 0x02 ..][0..2], 0); // flags
- //mem.writeIntLittle(u64, vm->memory[buf + 0x08 ..][0..8], math.maxInt(u64)); // rights_base
- //mem.writeIntLittle(u64, vm->memory[buf + 0x10 ..][0..8], math.maxInt(u64)); // rights_inheriting
+ int host_fd = to_host_fd(fd);
+ struct stat st;
+ if (fstat(host_fd, &st) == -1) return to_wasi_err(errno);
+ write_u16_le(vm->memory + buf + 0x00, to_wasi_filetype(st.st_mode));
+ write_u16_le(vm->memory + buf + 0x02, 0); // flags
+ write_u64_le(vm->memory + buf + 0x08, UINT64_MAX); // rights_base
+ write_u64_le(vm->memory + buf + 0x10, UINT64_MAX); // rights_inheriting
return WASI_ESUCCESS;
}
@@ -983,31 +1129,24 @@ static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t f
static enum wasi_errno_t wasi_clock_time_get(struct VirtualMachine *vm,
uint32_t clock_id, uint64_t precision, uint32_t timestamp)
{
- panic("TODO implement wasi_clock_time_get");
- ////const host_clock_id = toHostClockId(clock_id);
- //_ = precision;
- //_ = clock_id;
- //const wasi_ts = toWasiTimestamp(std.time.nanoTimestamp());
- //mem.writeIntLittle(u64, vm->memory[timestamp..][0..8], wasi_ts);
+ if (clock_id != 1) panic("expected wasi_clock_time_get to use CLOCK_MONOTONIC");
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) return to_wasi_err(errno);
+ uint64_t wasi_ts = to_wasi_timestamp(ts);
+ write_u64_le(vm->memory + timestamp, wasi_ts);
return WASI_ESUCCESS;
}
///pub extern "wasi_snapshot_preview1" fn debug(string: [*:0]const u8, x: u64) void;
void wasi_debug(struct VirtualMachine *vm, uint32_t text, uint64_t n) {
- panic("TODO implement wasi_debug");
- //const s = mem.sliceTo(vm->memory[text..], 0);
- //trace_log.debug("wasi_debug: '{s}' number={d} {x}", .{ s, n, n });
+ fprintf(stderr, "wasi_debug: '%s' number=%lu %lx\n", vm->memory + text, n, n);
}
/// pub extern "wasi_snapshot_preview1" fn debug_slice(ptr: [*]const u8, len: usize) void;
void wasi_debug_slice(struct VirtualMachine *vm, uint32_t ptr, uint32_t len) {
- panic("TODO implement wasi_debug_slice");
- //const s = vm->memory[ptr..][0..len];
- //trace_log.debug("wasi_debug_slice: '{s}'", .{s});
+ fprintf(stderr, "wasi_debug_slice: '%.*s'\n", len, vm->memory + ptr);
}
-
-
struct Label {
enum WasmOp opcode;
uint32_t stack_depth;
@@ -1049,6 +1188,9 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
static uint32_t stack_types[1 << (12 - 3)];
static struct Label labels[1 << 9];
+#ifndef NDEBUG
+ memset(labels, 0xaa, sizeof(struct Label) * (1 << 9)); // to match the zig version
+#endif
uint32_t label_i = 0;
labels[label_i].opcode = WasmOp_block;
labels[label_i].stack_depth = stack_depth;
@@ -1061,6 +1203,9 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
enum WasmPrefixedOp prefixed_opcode;
if (opcode == WasmOp_prefixed) prefixed_opcode = read32_uleb128(mod_ptr, code_i);
+ //fprintf(stderr, "decodeCode opcode=0x%x pc=%u:%u\n", opcode, pc->opcode, pc->operand);
+ //struct ProgramCounter old_pc = *pc;
+
uint32_t initial_stack_depth = stack_depth;
if (unreachable_depth == 0) {
switch (opcode) {
@@ -1549,11 +1694,16 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
label->type_info.param_count = 0;
label->type_info.param_types = 0;
label->type_info.result_count = block_type != -0x40;
- label->type_info.result_types = 0;
switch (block_type) {
- case -0x40: break;
- case -1: case -3: bs_unset(&label->type_info.param_types, 0); break;
- case -2: case -4: bs_set(&label->type_info.param_types, 0); break;
+ case -0x40:
+ case -1:
+ case -3:
+ label->type_info.result_types = 0;
+ break;
+ case -2:
+ case -4:
+ label->type_info.result_types = UINT32_MAX;
+ break;
default: panic("unexpected param type");
}
} else {
@@ -1584,7 +1734,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
break;
case WasmOp_else:
- {
+ if (unreachable_depth <= 1) {
struct Label *label = &labels[label_i];
assert(label->opcode == WasmOp_if);
label->opcode = WasmOp_else;
@@ -1596,9 +1746,12 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
break;
case 1:
- switch ((int)Label_operandType(label, 0)) {
- case false: opcodes[pc->opcode] = Op_br_32; break;
- case true: opcodes[pc->opcode] = Op_br_64; break;
+ //fprintf(stderr, "label_i=%u operand_type=%d\n",
+ // label_i, Label_operandType(label, 0));
+ if (Label_operandType(label, 0)) {
+ opcodes[pc->opcode] = Op_br_64;
+ } else {
+ opcodes[pc->opcode] = Op_br_32;
}
break;
@@ -1614,7 +1767,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
operands[label->extra.else_ref + 0] = pc->opcode;
operands[label->extra.else_ref + 1] = pc->operand;
stack_depth = label->stack_depth + label->type_info.param_count;
- };
+ }
break;
case WasmOp_end:
@@ -1705,7 +1858,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
}
break;
- default: panic("unexpected opcode");
+ default: panic("unreachable");
}
pc->opcode += 1;
operands[pc->operand + 0] = stack_depth - operand_count - label->stack_depth;
@@ -1748,11 +1901,6 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
label->ref_list = pc->operand + 1;
pc->operand += 3;
}
-
- opcodes[pc->opcode] = opcode;
- pc->opcode += 1;
- operands[pc->operand] = labels_len;
- pc->operand += 1;
}
break;
@@ -1796,7 +1944,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
break;
case WasmOp_return:
- {
+ if (unreachable_depth <= 1) {
uint32_t operand_count = Label_operandCount(&labels[0]);
switch (operand_count) {
case 0:
@@ -2066,9 +2214,11 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
break;
default:
- opcodes[pc->opcode + 0] = Op_wasm;
- opcodes[pc->opcode + 1] = opcode;
- pc->opcode += 2;
+ if (unreachable_depth == 0) {
+ opcodes[pc->opcode + 0] = Op_wasm;
+ opcodes[pc->opcode + 1] = opcode;
+ pc->opcode += 2;
+ }
break;
case WasmOp_prefixed:
@@ -2125,6 +2275,13 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
default:
break;
}
+
+ //for (uint32_t i = old_pc.opcode; i < pc->opcode; i += 1) {
+ // fprintf(stderr, "decoded opcode[%u] = %u\n", i, opcodes[i]);
+ //}
+ //for (uint32_t i = old_pc.operand; i < pc->operand; i += 1) {
+ // fprintf(stderr, "decoded operand[%u] = %u\n", i, operands[i]);
+ //}
}
}
@@ -2184,7 +2341,7 @@ static float vm_pop_f32(struct VirtualMachine *vm) {
}
static double vm_pop_f64(struct VirtualMachine *vm) {
- uint32_t integer = vm_pop_u64(vm);
+ uint64_t integer = vm_pop_u64(vm);
double result;
memcpy(&result, &integer, 8);
return result;
@@ -2251,7 +2408,7 @@ static void vm_callImport(struct VirtualMachine *vm, struct Import import) {
break;
case ImpName_fd_readdir:
{
- panic("TODO implement fd_readdir");
+ panic("unexpected call to fd_readdir");
}
break;
case ImpName_fd_write:
@@ -2422,8 +2579,12 @@ static void vm_call(struct VirtualMachine *vm, uint32_t fn_id) {
uint32_t fn_idx = fn_id - vm->imports_len;
struct Function *func = &vm->functions[fn_idx];
+ //struct TypeInfo *type_info = &vm->types[func->type_idx];
+ //fprintf(stderr, "enter fn_id: %u, param_count: %u, result_count: %u, locals_count: %u\n",
+ // fn_id, type_info->param_count, type_info->result_count, func->locals_count);
+
// Push zeroed locals to stack
- memset(&vm->stack[vm->stack_top], 0, func->locals_count * sizeof(uint64_t));
+ memset(vm->stack + vm->stack_top, 0, func->locals_count * sizeof(uint64_t));
vm->stack_top += func->locals_count;
vm_push_u32(vm, vm->pc.opcode);
@@ -2504,6 +2665,10 @@ static void vm_run(struct VirtualMachine *vm) {
for (;;) {
enum Op op = opcodes[pc->opcode];
pc->opcode += 1;
+ //if (vm->stack_top > 0) {
+ // fprintf(stderr, "stack[%u]=%lx pc=%u:%u, op=%u\n",
+ // vm->stack_top - 1, vm->stack[vm->stack_top - 1], pc->opcode, pc->operand, op);
+ //}
switch (op) {
case Op_unreachable:
panic("unreachable reached");
@@ -2738,6 +2903,7 @@ static void vm_run(struct VirtualMachine *vm) {
case Op_wasm:
{
enum WasmOp wasm_op = opcodes[pc->opcode];
+ //fprintf(stderr, "op2=%x\n", wasm_op);
pc->opcode += 1;
switch (wasm_op) {
case WasmOp_unreachable:
@@ -2820,7 +2986,7 @@ static void vm_run(struct VirtualMachine *vm) {
{
uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
pc->operand += 1;
- vm_push_u32(vm, vm->memory[offset]);
+ vm_push_u32(vm, (uint8_t)vm->memory[offset]);
}
break;
case WasmOp_i32_load16_s:
@@ -2850,7 +3016,7 @@ static void vm_run(struct VirtualMachine *vm) {
{
uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
pc->operand += 1;
- vm_push_u64(vm, vm->memory[offset]);
+ vm_push_u64(vm, (uint8_t)vm->memory[offset]);
}
break;
case WasmOp_i64_load16_s:
@@ -2968,7 +3134,7 @@ static void vm_run(struct VirtualMachine *vm) {
uint32_t page_count = vm_pop_u32(vm);
uint32_t old_page_count = vm->memory_len / wasm_page_size;
uint32_t new_len = vm->memory_len + page_count * wasm_page_size;
- if (new_len > vm->memory_len) {
+ if (new_len > max_memory) {
vm_push_i32(vm, -1);
} else {
vm->memory_len = new_len;
@@ -3294,21 +3460,21 @@ static void vm_run(struct VirtualMachine *vm) {
{
uint32_t rhs = vm_pop_u32(vm);
uint32_t lhs = vm_pop_u32(vm);
- vm_push_u32(vm, lhs << rhs);
+ vm_push_u32(vm, lhs << (rhs & 0x1f));
}
break;
case WasmOp_i32_shr_s:
{
uint32_t rhs = vm_pop_u32(vm);
int32_t lhs = vm_pop_i32(vm);
- vm_push_i32(vm, lhs >> rhs);
+ vm_push_i32(vm, lhs >> (rhs & 0x1f));
}
break;
case WasmOp_i32_shr_u:
{
uint32_t rhs = vm_pop_u32(vm);
uint32_t lhs = vm_pop_u32(vm);
- vm_push_u32(vm, lhs >> rhs);
+ vm_push_u32(vm, lhs >> (rhs & 0x1f));
}
break;
case WasmOp_i32_rotl:
@@ -3421,35 +3587,35 @@ static void vm_run(struct VirtualMachine *vm) {
{
uint64_t rhs = vm_pop_u64(vm);
uint64_t lhs = vm_pop_u64(vm);
- vm_push_u64(vm, lhs << rhs);
+ vm_push_u64(vm, lhs << (rhs & 0x3f));
}
break;
case WasmOp_i64_shr_s:
{
uint64_t rhs = vm_pop_u64(vm);
int64_t lhs = vm_pop_i64(vm);
- vm_push_i64(vm, lhs >> rhs);
+ vm_push_i64(vm, lhs >> (rhs & 0x3f));
}
break;
case WasmOp_i64_shr_u:
{
uint64_t rhs = vm_pop_u64(vm);
uint64_t lhs = vm_pop_u64(vm);
- vm_push_u64(vm, lhs >> rhs);
+ vm_push_u64(vm, lhs >> (rhs & 0x3f));
}
break;
case WasmOp_i64_rotl:
{
uint64_t rhs = vm_pop_u64(vm);
uint64_t lhs = vm_pop_u64(vm);
- vm_push_u64(vm, rotl64(lhs, rhs ));
+ vm_push_u64(vm, rotl64(lhs, rhs));
}
break;
case WasmOp_i64_rotr:
{
uint64_t rhs = vm_pop_u64(vm);
uint64_t lhs = vm_pop_u64(vm);
- vm_push_u64(vm, rotr64(lhs, rhs ));
+ vm_push_u64(vm, rotr64(lhs, rhs));
}
break;
@@ -3839,19 +4005,126 @@ static void vm_run(struct VirtualMachine *vm) {
}
}
+static size_t common_prefix(const char *a, const char *b) {
+ size_t i = 0;
+ for (; a[i] == b[i]; i += 1) {}
+ return i;
+}
+
int main(int argc, char **argv) {
char *memory = mmap( NULL, max_memory, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
const char *zig_lib_dir_path = argv[1];
- const char *zig_cache_dir_path = argv[2];
- const size_t vm_argv_start = 3;
- const char *wasm_file = argv[vm_argv_start];
+ const char *cmake_binary_dir_path = argv[2];
+ const char *root_name = argv[3];
+ size_t argv_i = 4;
+ const char *wasm_file = argv[argv_i];
+
+ size_t cwd_path_len = common_prefix(zig_lib_dir_path, cmake_binary_dir_path);
+ const char *rel_cmake_bin_path = cmake_binary_dir_path + cwd_path_len;
+ size_t rel_cmake_bin_path_len = strlen(rel_cmake_bin_path);
+
+ const char *new_argv[30];
+ char new_argv_buf[PATH_MAX + 1024];
+ uint32_t new_argv_i = 0;
+ uint32_t new_argv_buf_i = 0;
+
+ int cache_dir = -1;
+ {
+ char cache_dir_buf[PATH_MAX * 2];
+ size_t i = 0;
+ size_t cmake_binary_dir_path_len = strlen(cmake_binary_dir_path);
+
+ memcpy(cache_dir_buf + i, cmake_binary_dir_path, cmake_binary_dir_path_len);
+ i += cmake_binary_dir_path_len;
+
+ cache_dir_buf[i] = '/';
+ i += 1;
+
+ memcpy(cache_dir_buf + i, "zig1-cache", strlen("zig1-cache"));
+ i += strlen("zig1-cache");
+
+ cache_dir_buf[i] = 0;
+
+ mkdir(cache_dir_buf, 0777);
+ cache_dir = err_wrap("opening cache dir",
+ open(cache_dir_buf, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
+ }
+
+ // Construct a new argv for the WASI code which has absolute paths
+ // converted to relative paths, and has the target and terminal status
+ // autodetected.
+
+ // wasm file path
+ new_argv[new_argv_i] = argv[argv_i];
+ new_argv_i += 1;
+ argv_i += 1;
+
+ for(; argv[argv_i]; argv_i += 1) {
+ new_argv[new_argv_i] = argv[argv_i];
+ new_argv_i += 1;
+ }
+
+ {
+ new_argv[new_argv_i] = "--name";
+ new_argv_i += 1;
+
+ new_argv[new_argv_i] = root_name;
+ new_argv_i += 1;
+
+ char *emit_bin_arg = new_argv_buf + new_argv_buf_i;
+ memcpy(new_argv_buf + new_argv_buf_i, "-femit-bin=", strlen("-femit-bin="));
+ new_argv_buf_i += strlen("-femit-bin=");
+ memcpy(new_argv_buf + new_argv_buf_i, rel_cmake_bin_path, rel_cmake_bin_path_len);
+ new_argv_buf_i += rel_cmake_bin_path_len;
+ new_argv_buf[new_argv_buf_i] = '/';
+ new_argv_buf_i += 1;
+ memcpy(new_argv_buf + new_argv_buf_i, root_name, strlen(root_name));
+ new_argv_buf_i += strlen(root_name);
+ memcpy(new_argv_buf + new_argv_buf_i, ".c", 3);
+ new_argv_buf_i += 3;
+
+ new_argv[new_argv_i] = emit_bin_arg;
+ new_argv_i += 1;
+ }
+
+ {
+ new_argv[new_argv_i] = "--pkg-begin";
+ new_argv_i += 1;
+
+ new_argv[new_argv_i] = "build_options";
+ new_argv_i += 1;
+
+ char *build_options_path = new_argv_buf + new_argv_buf_i;
+ memcpy(new_argv_buf + new_argv_buf_i, rel_cmake_bin_path, rel_cmake_bin_path_len);
+ new_argv_buf_i += rel_cmake_bin_path_len;
+ new_argv_buf[new_argv_buf_i] = '/';
+ new_argv_buf_i += 1;
+ memcpy(new_argv_buf + new_argv_buf_i, "config.zig", strlen("config.zig"));
+ new_argv_buf_i += strlen("config.zig");
+ new_argv_buf[new_argv_buf_i] = 0;
+ new_argv_buf_i += 1;
+
+ new_argv[new_argv_i] = build_options_path;
+ new_argv_i += 1;
+
+ new_argv[new_argv_i] = "--pkg-end";
+ new_argv_i += 1;
+ }
+
+ if (isatty(STDERR_FILENO) != 0) {
+ new_argv[new_argv_i] = "--color";
+ new_argv_i += 1;
+
+ new_argv[new_argv_i] = "on";
+ new_argv_i += 1;
+ }
+
+ new_argv[new_argv_i] = NULL;
const struct ByteSlice mod = read_file_alloc(wasm_file);
int cwd = err_wrap("opening cwd", open(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
- mkdir(zig_cache_dir_path, 0666);
- int cache_dir = err_wrap("opening cache dir", open(zig_cache_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
int zig_lib_dir = err_wrap("opening zig lib dir", open(zig_lib_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
add_preopen(0, "stdin", STDIN_FILENO);
@@ -3873,7 +4146,7 @@ int main(int argc, char **argv) {
if (version != 1) panic("bad wasm version");
uint32_t section_starts[13];
- memset(&section_starts, 0, 4 * 13);
+ memset(&section_starts, 0, sizeof(uint32_t) * 13);
while (i < mod.len) {
uint8_t section_id = mod.ptr[i];
@@ -3895,6 +4168,7 @@ int main(int argc, char **argv) {
i += 1;
info->param_count = read32_uleb128(mod.ptr, &i);
+ if (info->param_count > 32) panic("found a type with over 32 parameters");
info->param_types = 0;
for (uint32_t param_i = 0; param_i < info->param_count; param_i += 1) {
int64_t param_type = read64_ileb128(mod.ptr, &i);
@@ -4133,7 +4407,7 @@ int main(int argc, char **argv) {
uint32_t elem_count = read32_uleb128(mod.ptr, &i);
table = arena_alloc(sizeof(uint32_t) * maximum);
- memset(table, 0, maximum);
+ memset(table, 0, sizeof(uint32_t) * maximum);
for (uint32_t elem_i = 0; elem_i < elem_count; elem_i += 1) {
table[elem_i + offset] = read32_uleb128(mod.ptr, &i);
@@ -4142,6 +4416,9 @@ int main(int argc, char **argv) {
}
struct VirtualMachine vm;
+#ifndef NDEBUG
+ memset(&vm, 0xaa, sizeof(struct VirtualMachine)); // to match the zig version
+#endif
vm.stack = arena_alloc(sizeof(uint64_t) * 10000000),
vm.mod_ptr = mod.ptr;
vm.opcodes = arena_alloc(2000000);
@@ -4154,7 +4431,7 @@ int main(int argc, char **argv) {
vm.memory_len = memory_len;
vm.imports = imports;
vm.imports_len = imports_len;
- vm.args = argv + vm_argv_start;
+ vm.args = new_argv;
vm.table = table;
{
@@ -4171,18 +4448,19 @@ int main(int argc, char **argv) {
struct TypeInfo *type_info = &vm.types[func->type_idx];
func->locals_count = 0;
- func->local_types = arena_alloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
+ func->local_types = malloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
func->local_types[0] = type_info->param_types;
for (uint32_t local_sets_count = read32_uleb128(mod.ptr, &code_i);
- local_sets_count > 0; local_sets_count -= 1) {
+ local_sets_count > 0; local_sets_count -= 1)
+ {
uint32_t set_count = read32_uleb128(mod.ptr, &code_i);
int64_t local_type = read64_ileb128(mod.ptr, &code_i);
uint32_t i = type_info->param_count + func->locals_count;
func->locals_count += set_count;
if ((type_info->param_count + func->locals_count + 31) / 32 > (i + 31) / 32)
- func->local_types = arena_realloc(func->local_types, sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
+ func->local_types = realloc(func->local_types, sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
for (; i < type_info->param_count + func->locals_count; i += 1)
switch (local_type) {
case -1: case -3: bs_unset(func->local_types, i); break;
@@ -4191,26 +4469,11 @@ int main(int argc, char **argv) {
}
}
+ //fprintf(stderr, "set up func %u with pc %u:%u\n", func->type_idx, pc.opcode, pc.operand);
func->entry_pc = pc;
vm_decodeCode(&vm, func, &code_i, &pc);
if (code_i != code_begin + size) panic("bad code size");
}
-
- uint64_t opcode_counts[0x100];
- memset(opcode_counts, 0, 0x100);
- uint64_t prefixed_opcode_counts[0x100];
- memset(prefixed_opcode_counts, 0, 0x100);
- bool is_prefixed = false;
- for (uint32_t opcode_i = 0; opcode_i < pc.opcode; opcode_i += 1) {
- uint8_t opcode = vm.opcodes[opcode_i];
- if (!is_prefixed) {
- opcode_counts[opcode] += 1;
- is_prefixed = opcode == WasmOp_prefixed;
- } else {
- prefixed_opcode_counts[opcode] += 1;
- is_prefixed = false;
- }
- }
}
vm_call(&vm, start_fn_idx);