authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-15 17:40:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-06 12:15:04-07:00
log39fd77bc163f0d7fc7408cbb4e48f960b4739448
treef32d6bbf639cf5840e72bb4a5ed6f5c56dc6165f
parentef447c3ecac4211a0a03f487e84acc61160d7ede

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.

4 files changed, 491 insertions(+), 235 deletions(-)

CMakeLists.txt+7-17
...@@ -702,29 +702,24 @@ if(MSVC)...@@ -702,29 +702,24 @@ if(MSVC)
702 set(ZIG2_COMPILE_FLAGS "/std:c99")702 set(ZIG2_COMPILE_FLAGS "/std:c99")
703 set(ZIG2_LINK_FLAGS "/STACK:16777216")703 set(ZIG2_LINK_FLAGS "/STACK:16777216")
704else()704else()
705 #set(ZIG1_COMPILE_FLAGS "-std=c99 -O2 -march=native")705 set(ZIG1_COMPILE_FLAGS "-std=c99 -O2 -march=native")
706 set(ZIG1_COMPILE_FLAGS "-std=c99 -march=native")
707 set(ZIG2_COMPILE_FLAGS "-std=c99 -O2 -march=native")706 set(ZIG2_COMPILE_FLAGS "-std=c99 -O2 -march=native")
708 set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000")707 set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000")
709endif()708endif()
710709
711add_executable(zig1 ${STAGE1_SOURCES})710add_executable(zig1 ${STAGE1_SOURCES})
712set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})711set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})
713#target_include_directories(zig1 PUBLIC "${CMAKE_SOURCE_DIR}/lib")
714target_link_libraries(zig1 LINK_PUBLIC m)712target_link_libraries(zig1 LINK_PUBLIC m)
715713
716714
717set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")715set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")
718set(BUILD_ZIG2_ARGS716set(BUILD_ZIG2_ARGS
719 "${CMAKE_SOURCE_DIR}/lib"717 "${CMAKE_SOURCE_DIR}/lib"
720 "${CMAKE_BINARY_DIR}/zig1-cache"718 "${CMAKE_BINARY_DIR}"
719 zig2
721 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"720 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"
722 build-exe src/main.zig -ofmt=c -lc721 build-exe src/main.zig -ofmt=c -lc
723 --name zig2
724 --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"
725 --pkg-end
726 -target x86_64-linux-musl # TODO: autodetect in zig1.c722 -target x86_64-linux-musl # TODO: autodetect in zig1.c
727 --color on # TODO: autodetect in zig1.c
728 -OReleaseFast723 -OReleaseFast
729)724)
730 725
...@@ -739,12 +734,11 @@ add_custom_command(...@@ -739,12 +734,11 @@ add_custom_command(
739set(ZIG_COMPILER_RT_C_SOURCE "${CMAKE_BINARY_DIR}/compiler_rt.c")734set(ZIG_COMPILER_RT_C_SOURCE "${CMAKE_BINARY_DIR}/compiler_rt.c")
740set(BUILD_COMPILER_RT_ARGS735set(BUILD_COMPILER_RT_ARGS
741 "${CMAKE_SOURCE_DIR}/lib"736 "${CMAKE_SOURCE_DIR}/lib"
742 "${CMAKE_BINARY_DIR}/zig1-cache"737 "${CMAKE_BINARY_DIR}"
738 compiler_rt
743 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"739 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"
744 build-obj lib/compiler_rt.zig -ofmt=c740 build-obj lib/compiler_rt.zig -ofmt=c
745 --name compiler_rt
746 -target x86_64-linux-musl # TODO: autodetect in zig1.c741 -target x86_64-linux-musl # TODO: autodetect in zig1.c
747 --color on # TODO: autodetect in zig1.c
748 -OReleaseFast742 -OReleaseFast
749)743)
750 744
...@@ -757,13 +751,9 @@ add_custom_command(...@@ -757,13 +751,9 @@ add_custom_command(
757)751)
758752
759753
760add_executable(zig2 ${ZIG2_C_SOURCE})754add_executable(zig2 ${ZIG2_C_SOURCE} ${ZIG_COMPILER_RT_C_SOURCE})
761set_target_properties(zig2 PROPERTIES755set_target_properties(zig2 PROPERTIES
762 COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}756 COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}
763 LINK_FLAGS ${ZIG2_LINK_FLAGS}757 LINK_FLAGS ${ZIG2_LINK_FLAGS}
764)758)
765759target_include_directories(zig2 PUBLIC "${CMAKE_SOURCE_DIR}/lib")
766
767
768
769
lib/compiler_rt.zig+14-12
...@@ -3,13 +3,6 @@ const builtin = @import("builtin");...@@ -3,13 +3,6 @@ const builtin = @import("builtin");
3pub const panic = @import("compiler_rt/common.zig").panic;3pub const panic = @import("compiler_rt/common.zig").panic;
44
5comptime {5comptime {
6 _ = @import("compiler_rt/atomics.zig");
7
8 // macOS has these functions inside libSystem.
9 if (builtin.cpu.arch.isAARCH64() and !builtin.os.tag.isDarwin()) {
10 _ = @import("compiler_rt/aarch64_outline_atomics.zig");
11 }
12
13 _ = @import("compiler_rt/addf3.zig");6 _ = @import("compiler_rt/addf3.zig");
14 _ = @import("compiler_rt/addhf3.zig");7 _ = @import("compiler_rt/addhf3.zig");
15 _ = @import("compiler_rt/addsf3.zig");8 _ = @import("compiler_rt/addsf3.zig");
...@@ -216,9 +209,18 @@ comptime {...@@ -216,9 +209,18 @@ comptime {
216 _ = @import("compiler_rt/aullrem.zig");209 _ = @import("compiler_rt/aullrem.zig");
217 _ = @import("compiler_rt/clear_cache.zig");210 _ = @import("compiler_rt/clear_cache.zig");
218211
219 _ = @import("compiler_rt/memcpy.zig");212 if (@import("builtin").object_format != .c) {
220 _ = @import("compiler_rt/memset.zig");213 _ = @import("compiler_rt/atomics.zig");
221 _ = @import("compiler_rt/memmove.zig");214
222 _ = @import("compiler_rt/memcmp.zig");215 // macOS has these functions inside libSystem.
223 _ = @import("compiler_rt/bcmp.zig");216 if (builtin.cpu.arch.isAARCH64() and !builtin.os.tag.isDarwin()) {
217 _ = @import("compiler_rt/aarch64_outline_atomics.zig");
218 }
219
220 _ = @import("compiler_rt/memcpy.zig");
221 _ = @import("compiler_rt/memset.zig");
222 _ = @import("compiler_rt/memmove.zig");
223 _ = @import("compiler_rt/memcmp.zig");
224 _ = @import("compiler_rt/bcmp.zig");
225 }
224}226}
stage1/config.zig.in+1
...@@ -11,3 +11,4 @@ pub const value_tracing = false;...@@ -11,3 +11,4 @@ pub const value_tracing = false;
11pub const have_stage1 = false;11pub const have_stage1 = false;
12pub const skip_non_native = false;12pub const skip_non_native = false;
13pub const only_c = true;13pub const only_c = true;
14pub const force_gpa = false;
stage1/zig1.c+469-206
...@@ -10,11 +10,16 @@...@@ -10,11 +10,16 @@
10#include <stdlib.h>10#include <stdlib.h>
11#include <string.h>11#include <string.h>
1212
13#include <fcntl.h>
13#include <sys/mman.h>14#include <sys/mman.h>
14#include <sys/stat.h>15#include <sys/stat.h>
15#include <fcntl.h>16#include <time.h>
16#include <unistd.h>17#include <unistd.h>
1718
19#ifdef __linux__
20#include <sys/random.h>
21#endif
22
18enum wasi_errno_t {23enum wasi_errno_t {
19 WASI_ESUCCESS = 0,24 WASI_ESUCCESS = 0,
20 WASI_E2BIG = 1,25 WASI_E2BIG = 1,
...@@ -131,15 +136,12 @@ static uint64_t rotr64(uint64_t n, unsigned c) {...@@ -131,15 +136,12 @@ static uint64_t rotr64(uint64_t n, unsigned c) {
131static void *arena_alloc(size_t n) {136static void *arena_alloc(size_t n) {
132 void *ptr = malloc(n);137 void *ptr = malloc(n);
133 if (!ptr) panic("out of memory");138 if (!ptr) panic("out of memory");
139#ifndef NDEBUG
140 memset(ptr, 0xaa, n); // to match the zig version
141#endif
134 return ptr;142 return ptr;
135}143}
136144
137static void *arena_realloc(void *ptr, size_t new_n) {
138 void *new_ptr = realloc(ptr, new_n);
139 if (!new_ptr) panic("out of memory");
140 return new_ptr;
141}
142
143static int err_wrap(const char *prefix, int rc) {145static int err_wrap(const char *prefix, int rc) {
144 if (rc == -1) {146 if (rc == -1) {
145 perror(prefix);147 perror(prefix);
...@@ -152,7 +154,7 @@ static bool bs_isSet(const uint32_t *bitset, uint32_t index) {...@@ -152,7 +154,7 @@ static bool bs_isSet(const uint32_t *bitset, uint32_t index) {
152 return (bitset[index >> 5] >> (index & 0x1f)) & 1;154 return (bitset[index >> 5] >> (index & 0x1f)) & 1;
153}155}
154static void bs_set(uint32_t *bitset, uint32_t index) {156static void bs_set(uint32_t *bitset, uint32_t index) {
155 bitset[index >> 5] |= ((uint32_t)1 << (index & 0x1f));157 bitset[index >> 5] |= ((uint32_t)1 << (index & 0x1f));
156}158}
157static void bs_unset(uint32_t *bitset, uint32_t index) {159static void bs_unset(uint32_t *bitset, uint32_t index) {
158 bitset[index >> 5] &= ~((uint32_t)1 << (index & 0x1f));160 bitset[index >> 5] &= ~((uint32_t)1 << (index & 0x1f));
...@@ -213,7 +215,7 @@ static const struct Preopen *find_preopen(int32_t wasi_fd) {...@@ -213,7 +215,7 @@ static const struct Preopen *find_preopen(int32_t wasi_fd) {
213 return NULL;215 return NULL;
214}216}
215217
216static const size_t max_memory = 2ul * 1024ul * 1024ul * 1024ul; // 2 GiB218static const uint32_t max_memory = 2ul * 1024ul * 1024ul * 1024ul; // 2 GiB
217219
218static uint16_t read_u16_le(const char *ptr) {220static uint16_t read_u16_le(const char *ptr) {
219 const uint8_t *u8_ptr = (const uint8_t *)ptr;221 const uint8_t *u8_ptr = (const uint8_t *)ptr;
...@@ -655,6 +657,7 @@ struct VirtualMachine {...@@ -655,6 +657,7 @@ struct VirtualMachine {
655 /// Points to one after the last stack item.657 /// Points to one after the last stack item.
656 uint32_t stack_top;658 uint32_t stack_top;
657 struct ProgramCounter pc;659 struct ProgramCounter pc;
660 /// Actual memory usage of the WASI code. The capacity is max_memory.
658 uint32_t memory_len;661 uint32_t memory_len;
659 const char *mod_ptr;662 const char *mod_ptr;
660 uint8_t *opcodes;663 uint8_t *opcodes;
...@@ -666,7 +669,7 @@ struct VirtualMachine {...@@ -666,7 +669,7 @@ struct VirtualMachine {
666 char *memory;669 char *memory;
667 struct Import *imports;670 struct Import *imports;
668 uint32_t imports_len;671 uint32_t imports_len;
669 char **args;672 const char **args;
670 uint32_t *table;673 uint32_t *table;
671};674};
672675
...@@ -678,22 +681,156 @@ static int to_host_fd(int32_t wasi_fd) {...@@ -678,22 +681,156 @@ static int to_host_fd(int32_t wasi_fd) {
678681
679static enum wasi_errno_t to_wasi_err(int err) {682static enum wasi_errno_t to_wasi_err(int err) {
680 switch (err) {683 switch (err) {
684 case E2BIG: return WASI_E2BIG;
681 case EACCES: return WASI_EACCES;685 case EACCES: return WASI_EACCES;
686 case EADDRINUSE: return WASI_EADDRINUSE;
687 case EADDRNOTAVAIL: return WASI_EADDRNOTAVAIL;
688 case EAFNOSUPPORT: return WASI_EAFNOSUPPORT;
689 case EAGAIN: return WASI_EAGAIN;
690 case EALREADY: return WASI_EALREADY;
691 case EBADF: return WASI_EBADF;
692 case EBADMSG: return WASI_EBADMSG;
693 case EBUSY: return WASI_EBUSY;
694 case ECANCELED: return WASI_ECANCELED;
695 case ECHILD: return WASI_ECHILD;
696 case ECONNABORTED: return WASI_ECONNABORTED;
697 case ECONNREFUSED: return WASI_ECONNREFUSED;
698 case ECONNRESET: return WASI_ECONNRESET;
699 case EDEADLK: return WASI_EDEADLK;
700 case EDESTADDRREQ: return WASI_EDESTADDRREQ;
701 case EDOM: return WASI_EDOM;
682 case EDQUOT: return WASI_EDQUOT;702 case EDQUOT: return WASI_EDQUOT;
683 case EIO: return WASI_EIO;703 case EEXIST: return WASI_EEXIST;
704 case EFAULT: return WASI_EFAULT;
684 case EFBIG: return WASI_EFBIG;705 case EFBIG: return WASI_EFBIG;
706 case EHOSTUNREACH: return WASI_EHOSTUNREACH;
707 case EIDRM: return WASI_EIDRM;
708 case EILSEQ: return WASI_EILSEQ;
709 case EINPROGRESS: return WASI_EINPROGRESS;
710 case EINTR: return WASI_EINTR;
711 case EINVAL: return WASI_EINVAL;
712 case EIO: return WASI_EIO;
713 case EISCONN: return WASI_EISCONN;
714 case EISDIR: return WASI_EISDIR;
715 case ELOOP: return WASI_ELOOP;
716 case EMFILE: return WASI_EMFILE;
717 case EMLINK: return WASI_EMLINK;
718 case EMSGSIZE: return WASI_EMSGSIZE;
719 case EMULTIHOP: return WASI_EMULTIHOP;
720 case ENAMETOOLONG: return WASI_ENAMETOOLONG;
721 case ENETDOWN: return WASI_ENETDOWN;
722 case ENETRESET: return WASI_ENETRESET;
723 case ENETUNREACH: return WASI_ENETUNREACH;
724 case ENFILE: return WASI_ENFILE;
725 case ENOBUFS: return WASI_ENOBUFS;
726 case ENODEV: return WASI_ENODEV;
727 case ENOENT: return WASI_ENOENT;
728 case ENOEXEC: return WASI_ENOEXEC;
729 case ENOLCK: return WASI_ENOLCK;
730 case ENOLINK: return WASI_ENOLINK;
731 case ENOMEM: return WASI_ENOMEM;
732 case ENOMSG: return WASI_ENOMSG;
733 case ENOPROTOOPT: return WASI_ENOPROTOOPT;
685 case ENOSPC: return WASI_ENOSPC;734 case ENOSPC: return WASI_ENOSPC;
735 case ENOSYS: return WASI_ENOSYS;
736 case ENOTCONN: return WASI_ENOTCONN;
737 case ENOTDIR: return WASI_ENOTDIR;
738 case ENOTEMPTY: return WASI_ENOTEMPTY;
739 case ENOTRECOVERABLE: return WASI_ENOTRECOVERABLE;
740 case ENOTSOCK: return WASI_ENOTSOCK;
741 case EOPNOTSUPP: return WASI_EOPNOTSUPP;
742 case ENOTTY: return WASI_ENOTTY;
743 case ENXIO: return WASI_ENXIO;
744 case EOVERFLOW: return WASI_EOVERFLOW;
745 case EOWNERDEAD: return WASI_EOWNERDEAD;
746 case EPERM: return WASI_EPERM;
686 case EPIPE: return WASI_EPIPE;747 case EPIPE: return WASI_EPIPE;
687 case EBADF: return WASI_EBADF;748 case EPROTO: return WASI_EPROTO;
688 case ENOMEM: return WASI_ENOMEM;749 case EPROTONOSUPPORT: return WASI_EPROTONOSUPPORT;
689 case ENOENT: return WASI_ENOENT;750 case EPROTOTYPE: return WASI_EPROTOTYPE;
690 case EEXIST: return WASI_EEXIST;751 case ERANGE: return WASI_ERANGE;
752 case EROFS: return WASI_EROFS;
753 case ESPIPE: return WASI_ESPIPE;
754 case ESRCH: return WASI_ESRCH;
755 case ESTALE: return WASI_ESTALE;
756 case ETIMEDOUT: return WASI_ETIMEDOUT;
757 case ETXTBSY: return WASI_ETXTBSY;
758 case EXDEV: return WASI_EXDEV;
691 default:759 default:
692 fprintf(stderr, "unexpected errno: %s\n", strerror(err));760 fprintf(stderr, "unexpected errno: %s\n", strerror(err));
693 abort();761 abort();
694 };762 };
695}763}
696764
765enum wasi_filetype_t {
766 wasi_filetype_t_UNKNOWN,
767 wasi_filetype_t_BLOCK_DEVICE,
768 wasi_filetype_t_CHARACTER_DEVICE,
769 wasi_filetype_t_DIRECTORY,
770 wasi_filetype_t_REGULAR_FILE,
771 wasi_filetype_t_SOCKET_DGRAM,
772 wasi_filetype_t_SOCKET_STREAM,
773 wasi_filetype_t_SYMBOLIC_LINK,
774};
775
776static const uint16_t WASI_O_CREAT = 0x0001;
777static const uint16_t WASI_O_DIRECTORY = 0x0002;
778static const uint16_t WASI_O_EXCL = 0x0004;
779static const uint16_t WASI_O_TRUNC = 0x0008;
780
781static const uint16_t WASI_FDFLAG_APPEND = 0x0001;
782static const uint16_t WASI_FDFLAG_DSYNC = 0x0002;
783static const uint16_t WASI_FDFLAG_NONBLOCK = 0x0004;
784static const uint16_t WASI_FDFLAG_SYNC = 0x0010;
785
786static const uint64_t WASI_RIGHT_FD_READ = 0x0000000000000002ull;
787static const uint64_t WASI_RIGHT_FD_WRITE = 0x0000000000000040ull;
788
789static enum wasi_filetype_t to_wasi_filetype(mode_t st_mode) {
790 switch (st_mode & S_IFMT) {
791 case S_IFBLK:
792 return wasi_filetype_t_BLOCK_DEVICE;
793 case S_IFCHR:
794 return wasi_filetype_t_CHARACTER_DEVICE;
795 case S_IFDIR:
796 return wasi_filetype_t_DIRECTORY;
797 case S_IFLNK:
798 return wasi_filetype_t_SYMBOLIC_LINK;
799 case S_IFREG:
800 return wasi_filetype_t_REGULAR_FILE;
801 default:
802 return wasi_filetype_t_UNKNOWN;
803 }
804}
805
806static uint64_t to_wasi_timestamp(struct timespec ts) {
807 return ts.tv_sec * 1000000000ull + ts.tv_nsec;
808}
809
810/// const filestat_t = extern struct {
811/// dev: device_t, u64
812/// ino: inode_t, u64
813/// filetype: filetype_t, u8
814/// nlink: linkcount_t, u64
815/// size: filesize_t, u64
816/// atim: timestamp_t, u64
817/// mtim: timestamp_t, u64
818/// ctim: timestamp_t, u64
819/// };
820static enum wasi_errno_t finish_wasi_stat(struct VirtualMachine *vm,
821 uint32_t buf, struct stat st)
822{
823 write_u64_le(vm->memory + buf + 0x00, 0); // device
824 write_u64_le(vm->memory + buf + 0x08, st.st_ino);
825 write_u64_le(vm->memory + buf + 0x10, to_wasi_filetype(st.st_mode));
826 write_u64_le(vm->memory + buf + 0x18, 1); // nlink
827 write_u64_le(vm->memory + buf + 0x20, st.st_size);
828 write_u64_le(vm->memory + buf + 0x28, to_wasi_timestamp(st.st_atim));
829 write_u64_le(vm->memory + buf + 0x30, to_wasi_timestamp(st.st_mtim));
830 write_u64_le(vm->memory + buf + 0x38, to_wasi_timestamp(st.st_ctim));
831 return WASI_ESUCCESS;
832}
833
697/// fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;834/// fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
698static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,835static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,
699 uint32_t argc, uint32_t argv_buf_size)836 uint32_t argc, uint32_t argv_buf_size)
...@@ -713,17 +850,19 @@ static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,...@@ -713,17 +850,19 @@ static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,
713static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,850static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,
714 uint32_t argv, uint32_t argv_buf) 851 uint32_t argv, uint32_t argv_buf)
715{852{
716 panic("TODO implement wasi_args_get");853 uint32_t argv_buf_i = 0;
717 //var argv_buf_i: usize = 0;854 uint32_t arg_i = 0;
718 //for (vm->args) |arg, arg_i| {855 for (;; arg_i += 1) {
719 // // Write the arg to the buffer.856 const char *arg = vm->args[arg_i];
720 // const argv_ptr = argv_buf + argv_buf_i;857 if (!arg) break;
721 // const arg_len = mem.span(arg).len + 1;858 // Write the arg to the buffer.
722 // mem.copy(u8, vm->memory[argv_buf + argv_buf_i ..], arg[0..arg_len]);859 uint32_t argv_ptr = argv_buf + argv_buf_i;
723 // argv_buf_i += arg_len;860 uint32_t arg_len = strlen(arg) + 1;
724861 memcpy(vm->memory + argv_buf + argv_buf_i, arg, arg_len);
725 // write_u32_le(vm->memory[argv + 4 * arg_i ..][0..4], @intCast(u32, argv_ptr));862 argv_buf_i += arg_len;
726 //}863
864 write_u32_le(vm->memory + argv + 4 * arg_i , argv_ptr);
865 }
727 return WASI_ESUCCESS;866 return WASI_ESUCCESS;
728}867}
729868
...@@ -731,9 +870,15 @@ static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,...@@ -731,9 +870,15 @@ static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,
731static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,870static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,
732 uint32_t buf, uint32_t buf_len) 871 uint32_t buf, uint32_t buf_len)
733{872{
734 panic("TODO implement wasi_random_get");873#ifdef __linux__
735 //const host_buf = vm->memory[buf..][0..buf_len];874 if (getrandom(vm->memory + buf, buf_len, 0) != buf_len) {
736 //std.crypto.random.bytes(host_buf);875 panic("getrandom failed");
876 }
877#else
878 for (uint32_t i = 0; i < buf_len; i += 1) {
879 vm->memory[buf + i] = rand();
880 }
881#endif
737 return WASI_ESUCCESS;882 return WASI_ESUCCESS;
738}883}
739884
...@@ -745,10 +890,10 @@ static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,...@@ -745,10 +890,10 @@ static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,
745static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,890static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,
746 int32_t fd, uint32_t buf)891 int32_t fd, uint32_t buf)
747{892{
748 panic("TODO implement wasi_fd_prestat_get");893 const struct Preopen *preopen = find_preopen(fd);
749 //const preopen = findPreopen(fd) orelse return .BADF;894 if (!preopen) return WASI_EBADF;
750 //write_u32_le(vm->memory[buf + 0 ..][0..4], 0);895 write_u32_le(vm->memory + buf + 0, 0);
751 //write_u32_le(vm->memory[buf + 4 ..][0..4], @intCast(u32, preopen.name.len));896 write_u32_le(vm->memory + buf + 4, preopen->name_len);
752 return WASI_ESUCCESS;897 return WASI_ESUCCESS;
753}898}
754899
...@@ -756,19 +901,18 @@ static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,...@@ -756,19 +901,18 @@ static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,
756static enum wasi_errno_t wasi_fd_prestat_dir_name(struct VirtualMachine *vm,901static enum wasi_errno_t wasi_fd_prestat_dir_name(struct VirtualMachine *vm,
757 int32_t fd, uint32_t path, uint32_t path_len)902 int32_t fd, uint32_t path, uint32_t path_len)
758{903{
759 panic("TODO implement wasi_fd_prestat_dir_name");904 const struct Preopen *preopen = find_preopen(fd);
760 //const preopen = findPreopen(fd) orelse return .BADF;905 if (!preopen) return WASI_EBADF;
761 //assert(path_len == preopen.name.len);906 if (path_len != preopen->name_len)
762 //mem.copy(u8, vm->memory[path..], preopen.name);907 panic("wasi_fd_prestat_dir_name expects correct name_len");
908 memcpy(vm->memory + path, preopen->name, path_len);
763 return WASI_ESUCCESS;909 return WASI_ESUCCESS;
764}910}
765911
766/// extern fn fd_close(fd: fd_t) errno_t;912/// extern fn fd_close(fd: fd_t) errno_t;
767static enum wasi_errno_t wasi_fd_close(struct VirtualMachine *vm, int32_t fd) {913static enum wasi_errno_t wasi_fd_close(struct VirtualMachine *vm, int32_t fd) {
768 panic("TODO implement wasi_fd_close");914 int host_fd = to_host_fd(fd);
769 //_ = vm;915 close(host_fd);
770 //const host_fd = toHostFd(fd);
771 //os.close(host_fd);
772 return WASI_ESUCCESS;916 return WASI_ESUCCESS;
773}917}
774918
...@@ -779,20 +923,18 @@ static enum wasi_errno_t wasi_fd_read(...@@ -779,20 +923,18 @@ static enum wasi_errno_t wasi_fd_read(
779 uint32_t iovs_len, // usize923 uint32_t iovs_len, // usize
780 uint32_t nread // *usize924 uint32_t nread // *usize
781) {925) {
782 panic("TODO implement wasi_fd_read");926 int host_fd = to_host_fd(fd);
783 //const host_fd = toHostFd(fd);927 uint32_t i = 0;
784 //var i: u32 = 0;928 size_t total_read = 0;
785 //var total_read: usize = 0;929 for (; i < iovs_len; i += 1) {
786 //while (i < iovs_len) : (i += 1) {930 uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
787 // uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);931 uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
788 // uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);932 ssize_t amt_read = read(host_fd, vm->memory + ptr, len);
789 // const buf = vm->memory[ptr..][0..len];933 if (amt_read < 0) return to_wasi_err(errno);
790 // const read = os.read(host_fd, buf) catch |err| return toWasiError(err);934 total_read += amt_read;
791 // trace_log.debug("read {d} bytes out of {d}", .{ read, buf.len });935 if (amt_read != len) break;
792 // total_read += read;936 }
793 // if (read != buf.len) break;937 write_u32_le(vm->memory + nread, total_read);
794 //}
795 //write_u32_le(vm->memory[nread..][0..4], @intCast(u32, total_read));
796 return WASI_ESUCCESS;938 return WASI_ESUCCESS;
797}939}
798940
...@@ -826,19 +968,18 @@ static enum wasi_errno_t wasi_fd_pwrite(...@@ -826,19 +968,18 @@ static enum wasi_errno_t wasi_fd_pwrite(
826 uint64_t offset, // wasi.filesize_t,968 uint64_t offset, // wasi.filesize_t,
827 uint32_t written_ptr // *usize969 uint32_t written_ptr // *usize
828) {970) {
829 panic("TODO implement wasi_fd_pwrite");971 int host_fd = to_host_fd(fd);
830 //const host_fd = toHostFd(fd);972 uint32_t i = 0;
831 //var i: u32 = 0;973 size_t written = 0;
832 //var written: usize = 0;974 for (; i < iovs_len; i += 1) {
833 //while (i < iovs_len) : (i += 1) {975 uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
834 // uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);976 uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
835 // uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);977 ssize_t w = pwrite(host_fd, vm->memory + ptr, len, offset + written);
836 // const buf = vm->memory[ptr..][0..len];978 if (w < 0) return to_wasi_err(errno);
837 // const w = os.pwrite(host_fd, buf, offset + written) catch |err| return toWasiError(err);979 written += w;
838 // written += w;980 if (w != len) break;
839 // if (w != buf.len) break;981 }
840 //}982 write_u32_le(vm->memory + written_ptr, written);
841 //write_u32_le(vm->memory[written_ptr..][0..4], @intCast(u32, written));
842 return WASI_ESUCCESS;983 return WASI_ESUCCESS;
843}984}
844985
...@@ -865,29 +1006,34 @@ static enum wasi_errno_t wasi_path_open(...@@ -865,29 +1006,34 @@ static enum wasi_errno_t wasi_path_open(
865 uint16_t fs_flags, // wasi.fdflags_t,1006 uint16_t fs_flags, // wasi.fdflags_t,
866 uint32_t fd1007 uint32_t fd
867) {1008) {
868 panic("TODO implement wasi_path_open");1009 char sub_path[PATH_MAX];
869 //const sub_path = vm->memory[path..][0..path_len];1010 memcpy(sub_path, vm->memory + path, path_len);
870 //const host_fd = toHostFd(dirfd);1011 sub_path[path_len] = 0;
871 //var flags: u32 = @as(u32, if (oflags & wasi.O.CREAT != 0) os.O.CREAT else 0) |1012
872 // @as(u32, if (oflags & wasi.O.DIRECTORY != 0) os.O.DIRECTORY else 0) |1013 int host_fd = to_host_fd(dirfd);
873 // @as(u32, if (oflags & wasi.O.EXCL != 0) os.O.EXCL else 0) |1014 uint32_t flags =
874 // @as(u32, if (oflags & wasi.O.TRUNC != 0) os.O.TRUNC else 0) |1015 (((oflags & WASI_O_CREAT) != 0) ? O_CREAT : 0) |
875 // @as(u32, if (fs_flags & wasi.FDFLAG.APPEND != 0) os.O.APPEND else 0) |1016 (((oflags & WASI_O_DIRECTORY) != 0) ? O_DIRECTORY : 0) |
876 // @as(u32, if (fs_flags & wasi.FDFLAG.DSYNC != 0) os.O.DSYNC else 0) |1017 (((oflags & WASI_O_EXCL) != 0) ? O_EXCL : 0) |
877 // @as(u32, if (fs_flags & wasi.FDFLAG.NONBLOCK != 0) os.O.NONBLOCK else 0) |1018 (((oflags & WASI_O_TRUNC) != 0) ? O_TRUNC : 0) |
878 // @as(u32, if (fs_flags & wasi.FDFLAG.SYNC != 0) os.O.SYNC else 0);1019 (((fs_flags & WASI_FDFLAG_APPEND) != 0) ? O_APPEND : 0) |
879 //if ((fs_rights_base & wasi.RIGHT.FD_READ != 0) and1020 (((fs_flags & WASI_FDFLAG_DSYNC) != 0) ? O_DSYNC : 0) |
880 // (fs_rights_base & wasi.RIGHT.FD_WRITE != 0))1021 (((fs_flags & WASI_FDFLAG_NONBLOCK) != 0) ? O_NONBLOCK : 0) |
881 //{1022 (((fs_flags & WASI_FDFLAG_SYNC) != 0) ? O_SYNC : 0);
882 // flags |= os.O.RDWR;1023
883 //} else if (fs_rights_base & wasi.RIGHT.FD_WRITE != 0) {1024 if (((fs_rights_base & WASI_RIGHT_FD_READ) != 0) &&
884 // flags |= os.O.WRONLY;1025 ((fs_rights_base & WASI_RIGHT_FD_WRITE) != 0))
885 //} else if (fs_rights_base & wasi.RIGHT.FD_READ != 0) {1026 {
886 // flags |= os.O.RDONLY; // no-op because O_RDONLY is 01027 flags |= O_RDWR;
887 //}1028 } else if ((fs_rights_base & WASI_RIGHT_FD_WRITE) != 0) {
888 //const mode = 0o644;1029 flags |= O_WRONLY;
889 //const res_fd = os.openat(host_fd, sub_path, flags, mode) catch |err| return toWasiError(err);1030 } else if ((fs_rights_base & WASI_RIGHT_FD_READ) != 0) {
890 //mem.writeIntLittle(i32, vm->memory[fd..][0..4], res_fd);1031 flags |= O_RDONLY; // no-op because O_RDONLY is 0
1032 }
1033 mode_t mode = 0644;
1034 int res_fd = openat(host_fd, sub_path, flags, mode);
1035 if (res_fd == -1) return to_wasi_err(errno);
1036 write_u32_le(vm->memory + fd, res_fd);
891 return WASI_ESUCCESS;1037 return WASI_ESUCCESS;
892}1038}
8931039
...@@ -899,23 +1045,26 @@ static enum wasi_errno_t wasi_path_filestat_get(...@@ -899,23 +1045,26 @@ static enum wasi_errno_t wasi_path_filestat_get(
899 uint32_t path_len, // usize1045 uint32_t path_len, // usize
900 uint32_t buf // *filestat_t1046 uint32_t buf // *filestat_t
901) {1047) {
902 panic("TODO implement wasi_path_filestat_get");1048 char sub_path[PATH_MAX];
903 //const sub_path = vm->memory[path..][0..path_len];1049 memcpy(sub_path, vm->memory + path, path_len);
904 //const host_fd = toHostFd(fd);1050 sub_path[path_len] = 0;
905 //const dir: fs.Dir = .{ .fd = host_fd };1051
906 //const stat = dir.statFile(sub_path) catch |err| return toWasiError(err);1052 int host_fd = to_host_fd(fd);
907 //return finishWasiStat(vm, buf, stat);1053 struct stat st;
908 return WASI_ESUCCESS;1054 if (fstatat(host_fd, sub_path, &st, 0) == -1) return to_wasi_err(errno);
1055 return finish_wasi_stat(vm, buf, st);
909}1056}
9101057
911/// extern fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;1058/// extern fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
912static enum wasi_errno_t wasi_path_create_directory(struct VirtualMachine *vm, int32_t fd, uint32_t path, uint32_t path_len) {1059static enum wasi_errno_t wasi_path_create_directory(struct VirtualMachine *vm,
913 panic("TODO implement wasi_path_create_directory");1060 int32_t wasi_fd, uint32_t path, uint32_t path_len)
914 //const sub_path = vm->memory[path..][0..path_len];1061{
915 //trace_log.debug("wasi_path_create_directory fd={d} path={s}", .{ fd, sub_path });1062 char sub_path[PATH_MAX];
916 //const host_fd = toHostFd(fd);1063 memcpy(sub_path, vm->memory + path, path_len);
917 //const dir: fs.Dir = .{ .fd = host_fd };1064 sub_path[path_len] = 0;
918 //dir.makeDir(sub_path) catch |err| return toWasiError(err);1065
1066 int host_fd = to_host_fd(wasi_fd);
1067 if (mkdirat(host_fd, sub_path, 0777) == -1) return to_wasi_err(errno);
919 return WASI_ESUCCESS;1068 return WASI_ESUCCESS;
920}1069}
9211070
...@@ -928,35 +1077,33 @@ static enum wasi_errno_t wasi_path_rename(...@@ -928,35 +1077,33 @@ static enum wasi_errno_t wasi_path_rename(
928 uint32_t new_path_ptr, // [*]const u81077 uint32_t new_path_ptr, // [*]const u8
929 uint32_t new_path_len // usize1078 uint32_t new_path_len // usize
930) {1079) {
931 panic("TODO implement wasi_path_rename");1080 char old_path[PATH_MAX];
932 //const old_path = vm->memory[old_path_ptr..][0..old_path_len];1081 memcpy(old_path, vm->memory + old_path_ptr, old_path_len);
933 //const new_path = vm->memory[new_path_ptr..][0..new_path_len];1082 old_path[old_path_len] = 0;
934 //trace_log.debug("wasi_path_rename old_fd={d} old_path={s} new_fd={d} new_path={s}", .{1083
935 // old_fd, old_path, new_fd, new_path,1084 char new_path[PATH_MAX];
936 //});1085 memcpy(new_path, vm->memory + new_path_ptr, new_path_len);
937 //const old_host_fd = toHostFd(old_fd);1086 new_path[new_path_len] = 0;
938 //const new_host_fd = toHostFd(new_fd);1087
939 //os.renameat(old_host_fd, old_path, new_host_fd, new_path) catch |err| return toWasiError(err);1088 int old_host_fd = to_host_fd(old_fd);
1089 int new_host_fd = to_host_fd(new_fd);
1090 if (renameat(old_host_fd, old_path, new_host_fd, new_path) == -1) return to_wasi_err(errno);
940 return WASI_ESUCCESS;1091 return WASI_ESUCCESS;
941}1092}
9421093
943/// extern fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t;1094/// extern fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t;
944static enum wasi_errno_t wasi_fd_filestat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {1095static enum wasi_errno_t wasi_fd_filestat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {
945 panic("TODO implement wasi_fd_filestat_get");1096 int host_fd = to_host_fd(fd);
946 //const host_fd = toHostFd(fd);1097 struct stat st;
947 //const file = fs.File{ .handle = host_fd };1098 if (fstat(host_fd, &st) == -1) return to_wasi_err(errno);
948 //const stat = file.stat() catch |err| return toWasiError(err);1099 return finish_wasi_stat(vm, buf, st);
949 //return finishWasiStat(vm, buf, stat);
950 return WASI_ESUCCESS;
951}1100}
9521101
953static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,1102static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,
954 int32_t fd, uint64_t size)1103 int32_t fd, uint64_t size)
955{1104{
956 panic("TODO implement wasi_fd_filestat_set_size");1105 int host_fd = to_host_fd(fd);
957 //_ = vm;1106 if (ftruncate(host_fd, size) == -1) return to_wasi_err(errno);
958 //const host_fd = toHostFd(fd);
959 //os.ftruncate(host_fd, size) catch |err| return toWasiError(err);
960 return WASI_ESUCCESS;1107 return WASI_ESUCCESS;
961}1108}
9621109
...@@ -968,14 +1115,13 @@ static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,...@@ -968,14 +1115,13 @@ static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,
968/// fs_rights_inheriting: rights_t, u641115/// fs_rights_inheriting: rights_t, u64
969/// };1116/// };
970static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {1117static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {
971 panic("TODO implement wasi_fd_fdstat_get");1118 int host_fd = to_host_fd(fd);
972 //const host_fd = toHostFd(fd);1119 struct stat st;
973 //const file = fs.File{ .handle = host_fd };1120 if (fstat(host_fd, &st) == -1) return to_wasi_err(errno);
974 //const stat = file.stat() catch |err| return toWasiError(err);1121 write_u16_le(vm->memory + buf + 0x00, to_wasi_filetype(st.st_mode));
975 //mem.writeIntLittle(u16, vm->memory[buf + 0x00 ..][0..2], @enumToInt(toWasiFileType(stat.kind)));1122 write_u16_le(vm->memory + buf + 0x02, 0); // flags
976 //mem.writeIntLittle(u16, vm->memory[buf + 0x02 ..][0..2], 0); // flags1123 write_u64_le(vm->memory + buf + 0x08, UINT64_MAX); // rights_base
977 //mem.writeIntLittle(u64, vm->memory[buf + 0x08 ..][0..8], math.maxInt(u64)); // rights_base1124 write_u64_le(vm->memory + buf + 0x10, UINT64_MAX); // rights_inheriting
978 //mem.writeIntLittle(u64, vm->memory[buf + 0x10 ..][0..8], math.maxInt(u64)); // rights_inheriting
979 return WASI_ESUCCESS;1125 return WASI_ESUCCESS;
980}1126}
9811127
...@@ -983,31 +1129,24 @@ static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t f...@@ -983,31 +1129,24 @@ static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t f
983static enum wasi_errno_t wasi_clock_time_get(struct VirtualMachine *vm,1129static enum wasi_errno_t wasi_clock_time_get(struct VirtualMachine *vm,
984 uint32_t clock_id, uint64_t precision, uint32_t timestamp)1130 uint32_t clock_id, uint64_t precision, uint32_t timestamp)
985{1131{
986 panic("TODO implement wasi_clock_time_get");1132 if (clock_id != 1) panic("expected wasi_clock_time_get to use CLOCK_MONOTONIC");
987 ////const host_clock_id = toHostClockId(clock_id);1133 struct timespec ts;
988 //_ = precision;1134 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) return to_wasi_err(errno);
989 //_ = clock_id;1135 uint64_t wasi_ts = to_wasi_timestamp(ts);
990 //const wasi_ts = toWasiTimestamp(std.time.nanoTimestamp());1136 write_u64_le(vm->memory + timestamp, wasi_ts);
991 //mem.writeIntLittle(u64, vm->memory[timestamp..][0..8], wasi_ts);
992 return WASI_ESUCCESS;1137 return WASI_ESUCCESS;
993}1138}
9941139
995///pub extern "wasi_snapshot_preview1" fn debug(string: [*:0]const u8, x: u64) void;1140///pub extern "wasi_snapshot_preview1" fn debug(string: [*:0]const u8, x: u64) void;
996void wasi_debug(struct VirtualMachine *vm, uint32_t text, uint64_t n) {1141void wasi_debug(struct VirtualMachine *vm, uint32_t text, uint64_t n) {
997 panic("TODO implement wasi_debug");1142 fprintf(stderr, "wasi_debug: '%s' number=%lu %lx\n", vm->memory + text, n, n);
998 //const s = mem.sliceTo(vm->memory[text..], 0);
999 //trace_log.debug("wasi_debug: '{s}' number={d} {x}", .{ s, n, n });
1000}1143}
10011144
1002/// pub extern "wasi_snapshot_preview1" fn debug_slice(ptr: [*]const u8, len: usize) void;1145/// pub extern "wasi_snapshot_preview1" fn debug_slice(ptr: [*]const u8, len: usize) void;
1003void wasi_debug_slice(struct VirtualMachine *vm, uint32_t ptr, uint32_t len) {1146void wasi_debug_slice(struct VirtualMachine *vm, uint32_t ptr, uint32_t len) {
1004 panic("TODO implement wasi_debug_slice");1147 fprintf(stderr, "wasi_debug_slice: '%.*s'\n", len, vm->memory + ptr);
1005 //const s = vm->memory[ptr..][0..len];
1006 //trace_log.debug("wasi_debug_slice: '{s}'", .{s});
1007}1148}
10081149
1009
1010
1011struct Label {1150struct Label {
1012 enum WasmOp opcode;1151 enum WasmOp opcode;
1013 uint32_t stack_depth;1152 uint32_t stack_depth;
...@@ -1049,6 +1188,9 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1049,6 +1188,9 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1049 static uint32_t stack_types[1 << (12 - 3)];1188 static uint32_t stack_types[1 << (12 - 3)];
10501189
1051 static struct Label labels[1 << 9];1190 static struct Label labels[1 << 9];
1191#ifndef NDEBUG
1192 memset(labels, 0xaa, sizeof(struct Label) * (1 << 9)); // to match the zig version
1193#endif
1052 uint32_t label_i = 0;1194 uint32_t label_i = 0;
1053 labels[label_i].opcode = WasmOp_block;1195 labels[label_i].opcode = WasmOp_block;
1054 labels[label_i].stack_depth = stack_depth;1196 labels[label_i].stack_depth = stack_depth;
...@@ -1061,6 +1203,9 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1061,6 +1203,9 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1061 enum WasmPrefixedOp prefixed_opcode;1203 enum WasmPrefixedOp prefixed_opcode;
1062 if (opcode == WasmOp_prefixed) prefixed_opcode = read32_uleb128(mod_ptr, code_i);1204 if (opcode == WasmOp_prefixed) prefixed_opcode = read32_uleb128(mod_ptr, code_i);
10631205
1206 //fprintf(stderr, "decodeCode opcode=0x%x pc=%u:%u\n", opcode, pc->opcode, pc->operand);
1207 //struct ProgramCounter old_pc = *pc;
1208
1064 uint32_t initial_stack_depth = stack_depth;1209 uint32_t initial_stack_depth = stack_depth;
1065 if (unreachable_depth == 0) {1210 if (unreachable_depth == 0) {
1066 switch (opcode) {1211 switch (opcode) {
...@@ -1549,11 +1694,16 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1549,11 +1694,16 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1549 label->type_info.param_count = 0;1694 label->type_info.param_count = 0;
1550 label->type_info.param_types = 0;1695 label->type_info.param_types = 0;
1551 label->type_info.result_count = block_type != -0x40;1696 label->type_info.result_count = block_type != -0x40;
1552 label->type_info.result_types = 0;
1553 switch (block_type) {1697 switch (block_type) {
1554 case -0x40: break;1698 case -0x40:
1555 case -1: case -3: bs_unset(&label->type_info.param_types, 0); break;1699 case -1:
1556 case -2: case -4: bs_set(&label->type_info.param_types, 0); break;1700 case -3:
1701 label->type_info.result_types = 0;
1702 break;
1703 case -2:
1704 case -4:
1705 label->type_info.result_types = UINT32_MAX;
1706 break;
1557 default: panic("unexpected param type");1707 default: panic("unexpected param type");
1558 }1708 }
1559 } else {1709 } else {
...@@ -1584,7 +1734,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1584,7 +1734,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1584 break;1734 break;
15851735
1586 case WasmOp_else:1736 case WasmOp_else:
1587 {1737 if (unreachable_depth <= 1) {
1588 struct Label *label = &labels[label_i];1738 struct Label *label = &labels[label_i];
1589 assert(label->opcode == WasmOp_if);1739 assert(label->opcode == WasmOp_if);
1590 label->opcode = WasmOp_else;1740 label->opcode = WasmOp_else;
...@@ -1596,9 +1746,12 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1596,9 +1746,12 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1596 break;1746 break;
15971747
1598 case 1:1748 case 1:
1599 switch ((int)Label_operandType(label, 0)) {1749 //fprintf(stderr, "label_i=%u operand_type=%d\n",
1600 case false: opcodes[pc->opcode] = Op_br_32; break;1750 // label_i, Label_operandType(label, 0));
1601 case true: opcodes[pc->opcode] = Op_br_64; break;1751 if (Label_operandType(label, 0)) {
1752 opcodes[pc->opcode] = Op_br_64;
1753 } else {
1754 opcodes[pc->opcode] = Op_br_32;
1602 }1755 }
1603 break;1756 break;
16041757
...@@ -1614,7 +1767,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1614,7 +1767,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1614 operands[label->extra.else_ref + 0] = pc->opcode;1767 operands[label->extra.else_ref + 0] = pc->opcode;
1615 operands[label->extra.else_ref + 1] = pc->operand;1768 operands[label->extra.else_ref + 1] = pc->operand;
1616 stack_depth = label->stack_depth + label->type_info.param_count;1769 stack_depth = label->stack_depth + label->type_info.param_count;
1617 };1770 }
1618 break;1771 break;
16191772
1620 case WasmOp_end:1773 case WasmOp_end:
...@@ -1705,7 +1858,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1705,7 +1858,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1705 }1858 }
1706 break;1859 break;
17071860
1708 default: panic("unexpected opcode");1861 default: panic("unreachable");
1709 }1862 }
1710 pc->opcode += 1;1863 pc->opcode += 1;
1711 operands[pc->operand + 0] = stack_depth - operand_count - label->stack_depth;1864 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...@@ -1748,11 +1901,6 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1748 label->ref_list = pc->operand + 1;1901 label->ref_list = pc->operand + 1;
1749 pc->operand += 3;1902 pc->operand += 3;
1750 }1903 }
1751
1752 opcodes[pc->opcode] = opcode;
1753 pc->opcode += 1;
1754 operands[pc->operand] = labels_len;
1755 pc->operand += 1;
1756 }1904 }
1757 break;1905 break;
17581906
...@@ -1796,7 +1944,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -1796,7 +1944,7 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
1796 break;1944 break;
17971945
1798 case WasmOp_return:1946 case WasmOp_return:
1799 {1947 if (unreachable_depth <= 1) {
1800 uint32_t operand_count = Label_operandCount(&labels[0]);1948 uint32_t operand_count = Label_operandCount(&labels[0]);
1801 switch (operand_count) {1949 switch (operand_count) {
1802 case 0:1950 case 0:
...@@ -2066,9 +2214,11 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -2066,9 +2214,11 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
2066 break;2214 break;
20672215
2068 default:2216 default:
2069 opcodes[pc->opcode + 0] = Op_wasm;2217 if (unreachable_depth == 0) {
2070 opcodes[pc->opcode + 1] = opcode;2218 opcodes[pc->opcode + 0] = Op_wasm;
2071 pc->opcode += 2;2219 opcodes[pc->opcode + 1] = opcode;
2220 pc->opcode += 2;
2221 }
2072 break;2222 break;
20732223
2074 case WasmOp_prefixed:2224 case WasmOp_prefixed:
...@@ -2125,6 +2275,13 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint...@@ -2125,6 +2275,13 @@ static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint
2125 default:2275 default:
2126 break;2276 break;
2127 }2277 }
2278
2279 //for (uint32_t i = old_pc.opcode; i < pc->opcode; i += 1) {
2280 // fprintf(stderr, "decoded opcode[%u] = %u\n", i, opcodes[i]);
2281 //}
2282 //for (uint32_t i = old_pc.operand; i < pc->operand; i += 1) {
2283 // fprintf(stderr, "decoded operand[%u] = %u\n", i, operands[i]);
2284 //}
2128 }2285 }
2129}2286}
21302287
...@@ -2184,7 +2341,7 @@ static float vm_pop_f32(struct VirtualMachine *vm) {...@@ -2184,7 +2341,7 @@ static float vm_pop_f32(struct VirtualMachine *vm) {
2184}2341}
21852342
2186static double vm_pop_f64(struct VirtualMachine *vm) {2343static double vm_pop_f64(struct VirtualMachine *vm) {
2187 uint32_t integer = vm_pop_u64(vm);2344 uint64_t integer = vm_pop_u64(vm);
2188 double result;2345 double result;
2189 memcpy(&result, &integer, 8);2346 memcpy(&result, &integer, 8);
2190 return result;2347 return result;
...@@ -2251,7 +2408,7 @@ static void vm_callImport(struct VirtualMachine *vm, struct Import import) {...@@ -2251,7 +2408,7 @@ static void vm_callImport(struct VirtualMachine *vm, struct Import import) {
2251 break;2408 break;
2252 case ImpName_fd_readdir:2409 case ImpName_fd_readdir:
2253 {2410 {
2254 panic("TODO implement fd_readdir");2411 panic("unexpected call to fd_readdir");
2255 }2412 }
2256 break;2413 break;
2257 case ImpName_fd_write:2414 case ImpName_fd_write:
...@@ -2422,8 +2579,12 @@ static void vm_call(struct VirtualMachine *vm, uint32_t fn_id) {...@@ -2422,8 +2579,12 @@ static void vm_call(struct VirtualMachine *vm, uint32_t fn_id) {
2422 uint32_t fn_idx = fn_id - vm->imports_len;2579 uint32_t fn_idx = fn_id - vm->imports_len;
2423 struct Function *func = &vm->functions[fn_idx];2580 struct Function *func = &vm->functions[fn_idx];
24242581
2582 //struct TypeInfo *type_info = &vm->types[func->type_idx];
2583 //fprintf(stderr, "enter fn_id: %u, param_count: %u, result_count: %u, locals_count: %u\n",
2584 // fn_id, type_info->param_count, type_info->result_count, func->locals_count);
2585
2425 // Push zeroed locals to stack2586 // Push zeroed locals to stack
2426 memset(&vm->stack[vm->stack_top], 0, func->locals_count * sizeof(uint64_t));2587 memset(vm->stack + vm->stack_top, 0, func->locals_count * sizeof(uint64_t));
2427 vm->stack_top += func->locals_count;2588 vm->stack_top += func->locals_count;
24282589
2429 vm_push_u32(vm, vm->pc.opcode);2590 vm_push_u32(vm, vm->pc.opcode);
...@@ -2504,6 +2665,10 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -2504,6 +2665,10 @@ static void vm_run(struct VirtualMachine *vm) {
2504 for (;;) {2665 for (;;) {
2505 enum Op op = opcodes[pc->opcode];2666 enum Op op = opcodes[pc->opcode];
2506 pc->opcode += 1;2667 pc->opcode += 1;
2668 //if (vm->stack_top > 0) {
2669 // fprintf(stderr, "stack[%u]=%lx pc=%u:%u, op=%u\n",
2670 // vm->stack_top - 1, vm->stack[vm->stack_top - 1], pc->opcode, pc->operand, op);
2671 //}
2507 switch (op) {2672 switch (op) {
2508 case Op_unreachable:2673 case Op_unreachable:
2509 panic("unreachable reached");2674 panic("unreachable reached");
...@@ -2738,6 +2903,7 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -2738,6 +2903,7 @@ static void vm_run(struct VirtualMachine *vm) {
2738 case Op_wasm:2903 case Op_wasm:
2739 {2904 {
2740 enum WasmOp wasm_op = opcodes[pc->opcode];2905 enum WasmOp wasm_op = opcodes[pc->opcode];
2906 //fprintf(stderr, "op2=%x\n", wasm_op);
2741 pc->opcode += 1;2907 pc->opcode += 1;
2742 switch (wasm_op) {2908 switch (wasm_op) {
2743 case WasmOp_unreachable:2909 case WasmOp_unreachable:
...@@ -2820,7 +2986,7 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -2820,7 +2986,7 @@ static void vm_run(struct VirtualMachine *vm) {
2820 {2986 {
2821 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);2987 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2822 pc->operand += 1;2988 pc->operand += 1;
2823 vm_push_u32(vm, vm->memory[offset]);2989 vm_push_u32(vm, (uint8_t)vm->memory[offset]);
2824 }2990 }
2825 break;2991 break;
2826 case WasmOp_i32_load16_s:2992 case WasmOp_i32_load16_s:
...@@ -2850,7 +3016,7 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -2850,7 +3016,7 @@ static void vm_run(struct VirtualMachine *vm) {
2850 {3016 {
2851 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);3017 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2852 pc->operand += 1;3018 pc->operand += 1;
2853 vm_push_u64(vm, vm->memory[offset]);3019 vm_push_u64(vm, (uint8_t)vm->memory[offset]);
2854 }3020 }
2855 break;3021 break;
2856 case WasmOp_i64_load16_s:3022 case WasmOp_i64_load16_s:
...@@ -2968,7 +3134,7 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -2968,7 +3134,7 @@ static void vm_run(struct VirtualMachine *vm) {
2968 uint32_t page_count = vm_pop_u32(vm);3134 uint32_t page_count = vm_pop_u32(vm);
2969 uint32_t old_page_count = vm->memory_len / wasm_page_size;3135 uint32_t old_page_count = vm->memory_len / wasm_page_size;
2970 uint32_t new_len = vm->memory_len + page_count * wasm_page_size;3136 uint32_t new_len = vm->memory_len + page_count * wasm_page_size;
2971 if (new_len > vm->memory_len) {3137 if (new_len > max_memory) {
2972 vm_push_i32(vm, -1);3138 vm_push_i32(vm, -1);
2973 } else {3139 } else {
2974 vm->memory_len = new_len;3140 vm->memory_len = new_len;
...@@ -3294,21 +3460,21 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -3294,21 +3460,21 @@ static void vm_run(struct VirtualMachine *vm) {
3294 {3460 {
3295 uint32_t rhs = vm_pop_u32(vm);3461 uint32_t rhs = vm_pop_u32(vm);
3296 uint32_t lhs = vm_pop_u32(vm);3462 uint32_t lhs = vm_pop_u32(vm);
3297 vm_push_u32(vm, lhs << rhs);3463 vm_push_u32(vm, lhs << (rhs & 0x1f));
3298 }3464 }
3299 break;3465 break;
3300 case WasmOp_i32_shr_s:3466 case WasmOp_i32_shr_s:
3301 {3467 {
3302 uint32_t rhs = vm_pop_u32(vm);3468 uint32_t rhs = vm_pop_u32(vm);
3303 int32_t lhs = vm_pop_i32(vm);3469 int32_t lhs = vm_pop_i32(vm);
3304 vm_push_i32(vm, lhs >> rhs);3470 vm_push_i32(vm, lhs >> (rhs & 0x1f));
3305 }3471 }
3306 break;3472 break;
3307 case WasmOp_i32_shr_u:3473 case WasmOp_i32_shr_u:
3308 {3474 {
3309 uint32_t rhs = vm_pop_u32(vm);3475 uint32_t rhs = vm_pop_u32(vm);
3310 uint32_t lhs = vm_pop_u32(vm);3476 uint32_t lhs = vm_pop_u32(vm);
3311 vm_push_u32(vm, lhs >> rhs);3477 vm_push_u32(vm, lhs >> (rhs & 0x1f));
3312 }3478 }
3313 break;3479 break;
3314 case WasmOp_i32_rotl:3480 case WasmOp_i32_rotl:
...@@ -3421,35 +3587,35 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -3421,35 +3587,35 @@ static void vm_run(struct VirtualMachine *vm) {
3421 {3587 {
3422 uint64_t rhs = vm_pop_u64(vm);3588 uint64_t rhs = vm_pop_u64(vm);
3423 uint64_t lhs = vm_pop_u64(vm);3589 uint64_t lhs = vm_pop_u64(vm);
3424 vm_push_u64(vm, lhs << rhs);3590 vm_push_u64(vm, lhs << (rhs & 0x3f));
3425 }3591 }
3426 break;3592 break;
3427 case WasmOp_i64_shr_s:3593 case WasmOp_i64_shr_s:
3428 {3594 {
3429 uint64_t rhs = vm_pop_u64(vm);3595 uint64_t rhs = vm_pop_u64(vm);
3430 int64_t lhs = vm_pop_i64(vm);3596 int64_t lhs = vm_pop_i64(vm);
3431 vm_push_i64(vm, lhs >> rhs);3597 vm_push_i64(vm, lhs >> (rhs & 0x3f));
3432 }3598 }
3433 break;3599 break;
3434 case WasmOp_i64_shr_u:3600 case WasmOp_i64_shr_u:
3435 {3601 {
3436 uint64_t rhs = vm_pop_u64(vm);3602 uint64_t rhs = vm_pop_u64(vm);
3437 uint64_t lhs = vm_pop_u64(vm);3603 uint64_t lhs = vm_pop_u64(vm);
3438 vm_push_u64(vm, lhs >> rhs);3604 vm_push_u64(vm, lhs >> (rhs & 0x3f));
3439 }3605 }
3440 break;3606 break;
3441 case WasmOp_i64_rotl:3607 case WasmOp_i64_rotl:
3442 {3608 {
3443 uint64_t rhs = vm_pop_u64(vm);3609 uint64_t rhs = vm_pop_u64(vm);
3444 uint64_t lhs = vm_pop_u64(vm);3610 uint64_t lhs = vm_pop_u64(vm);
3445 vm_push_u64(vm, rotl64(lhs, rhs ));3611 vm_push_u64(vm, rotl64(lhs, rhs));
3446 }3612 }
3447 break;3613 break;
3448 case WasmOp_i64_rotr:3614 case WasmOp_i64_rotr:
3449 {3615 {
3450 uint64_t rhs = vm_pop_u64(vm);3616 uint64_t rhs = vm_pop_u64(vm);
3451 uint64_t lhs = vm_pop_u64(vm);3617 uint64_t lhs = vm_pop_u64(vm);
3452 vm_push_u64(vm, rotr64(lhs, rhs ));3618 vm_push_u64(vm, rotr64(lhs, rhs));
3453 }3619 }
3454 break;3620 break;
34553621
...@@ -3839,19 +4005,126 @@ static void vm_run(struct VirtualMachine *vm) {...@@ -3839,19 +4005,126 @@ static void vm_run(struct VirtualMachine *vm) {
3839 }4005 }
3840}4006}
38414007
4008static size_t common_prefix(const char *a, const char *b) {
4009 size_t i = 0;
4010 for (; a[i] == b[i]; i += 1) {}
4011 return i;
4012}
4013
3842int main(int argc, char **argv) {4014int main(int argc, char **argv) {
3843 char *memory = mmap( NULL, max_memory, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);4015 char *memory = mmap( NULL, max_memory, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
38444016
3845 const char *zig_lib_dir_path = argv[1];4017 const char *zig_lib_dir_path = argv[1];
3846 const char *zig_cache_dir_path = argv[2];4018 const char *cmake_binary_dir_path = argv[2];
3847 const size_t vm_argv_start = 3;4019 const char *root_name = argv[3];
3848 const char *wasm_file = argv[vm_argv_start];4020 size_t argv_i = 4;
4021 const char *wasm_file = argv[argv_i];
4022
4023 size_t cwd_path_len = common_prefix(zig_lib_dir_path, cmake_binary_dir_path);
4024 const char *rel_cmake_bin_path = cmake_binary_dir_path + cwd_path_len;
4025 size_t rel_cmake_bin_path_len = strlen(rel_cmake_bin_path);
4026
4027 const char *new_argv[30];
4028 char new_argv_buf[PATH_MAX + 1024];
4029 uint32_t new_argv_i = 0;
4030 uint32_t new_argv_buf_i = 0;
4031
4032 int cache_dir = -1;
4033 {
4034 char cache_dir_buf[PATH_MAX * 2];
4035 size_t i = 0;
4036 size_t cmake_binary_dir_path_len = strlen(cmake_binary_dir_path);
4037
4038 memcpy(cache_dir_buf + i, cmake_binary_dir_path, cmake_binary_dir_path_len);
4039 i += cmake_binary_dir_path_len;
4040
4041 cache_dir_buf[i] = '/';
4042 i += 1;
4043
4044 memcpy(cache_dir_buf + i, "zig1-cache", strlen("zig1-cache"));
4045 i += strlen("zig1-cache");
4046
4047 cache_dir_buf[i] = 0;
4048
4049 mkdir(cache_dir_buf, 0777);
4050 cache_dir = err_wrap("opening cache dir",
4051 open(cache_dir_buf, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
4052 }
4053
4054 // Construct a new argv for the WASI code which has absolute paths
4055 // converted to relative paths, and has the target and terminal status
4056 // autodetected.
4057
4058 // wasm file path
4059 new_argv[new_argv_i] = argv[argv_i];
4060 new_argv_i += 1;
4061 argv_i += 1;
4062
4063 for(; argv[argv_i]; argv_i += 1) {
4064 new_argv[new_argv_i] = argv[argv_i];
4065 new_argv_i += 1;
4066 }
4067
4068 {
4069 new_argv[new_argv_i] = "--name";
4070 new_argv_i += 1;
4071
4072 new_argv[new_argv_i] = root_name;
4073 new_argv_i += 1;
4074
4075 char *emit_bin_arg = new_argv_buf + new_argv_buf_i;
4076 memcpy(new_argv_buf + new_argv_buf_i, "-femit-bin=", strlen("-femit-bin="));
4077 new_argv_buf_i += strlen("-femit-bin=");
4078 memcpy(new_argv_buf + new_argv_buf_i, rel_cmake_bin_path, rel_cmake_bin_path_len);
4079 new_argv_buf_i += rel_cmake_bin_path_len;
4080 new_argv_buf[new_argv_buf_i] = '/';
4081 new_argv_buf_i += 1;
4082 memcpy(new_argv_buf + new_argv_buf_i, root_name, strlen(root_name));
4083 new_argv_buf_i += strlen(root_name);
4084 memcpy(new_argv_buf + new_argv_buf_i, ".c", 3);
4085 new_argv_buf_i += 3;
4086
4087 new_argv[new_argv_i] = emit_bin_arg;
4088 new_argv_i += 1;
4089 }
4090
4091 {
4092 new_argv[new_argv_i] = "--pkg-begin";
4093 new_argv_i += 1;
4094
4095 new_argv[new_argv_i] = "build_options";
4096 new_argv_i += 1;
4097
4098 char *build_options_path = new_argv_buf + new_argv_buf_i;
4099 memcpy(new_argv_buf + new_argv_buf_i, rel_cmake_bin_path, rel_cmake_bin_path_len);
4100 new_argv_buf_i += rel_cmake_bin_path_len;
4101 new_argv_buf[new_argv_buf_i] = '/';
4102 new_argv_buf_i += 1;
4103 memcpy(new_argv_buf + new_argv_buf_i, "config.zig", strlen("config.zig"));
4104 new_argv_buf_i += strlen("config.zig");
4105 new_argv_buf[new_argv_buf_i] = 0;
4106 new_argv_buf_i += 1;
4107
4108 new_argv[new_argv_i] = build_options_path;
4109 new_argv_i += 1;
4110
4111 new_argv[new_argv_i] = "--pkg-end";
4112 new_argv_i += 1;
4113 }
4114
4115 if (isatty(STDERR_FILENO) != 0) {
4116 new_argv[new_argv_i] = "--color";
4117 new_argv_i += 1;
4118
4119 new_argv[new_argv_i] = "on";
4120 new_argv_i += 1;
4121 }
4122
4123 new_argv[new_argv_i] = NULL;
38494124
3850 const struct ByteSlice mod = read_file_alloc(wasm_file);4125 const struct ByteSlice mod = read_file_alloc(wasm_file);
38514126
3852 int cwd = err_wrap("opening cwd", open(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));4127 int cwd = err_wrap("opening cwd", open(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
3853 mkdir(zig_cache_dir_path, 0666);
3854 int cache_dir = err_wrap("opening cache dir", open(zig_cache_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
3855 int zig_lib_dir = err_wrap("opening zig lib dir", open(zig_lib_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));4128 int zig_lib_dir = err_wrap("opening zig lib dir", open(zig_lib_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
38564129
3857 add_preopen(0, "stdin", STDIN_FILENO);4130 add_preopen(0, "stdin", STDIN_FILENO);
...@@ -3873,7 +4146,7 @@ int main(int argc, char **argv) {...@@ -3873,7 +4146,7 @@ int main(int argc, char **argv) {
3873 if (version != 1) panic("bad wasm version");4146 if (version != 1) panic("bad wasm version");
38744147
3875 uint32_t section_starts[13];4148 uint32_t section_starts[13];
3876 memset(&section_starts, 0, 4 * 13);4149 memset(&section_starts, 0, sizeof(uint32_t) * 13);
38774150
3878 while (i < mod.len) {4151 while (i < mod.len) {
3879 uint8_t section_id = mod.ptr[i];4152 uint8_t section_id = mod.ptr[i];
...@@ -3895,6 +4168,7 @@ int main(int argc, char **argv) {...@@ -3895,6 +4168,7 @@ int main(int argc, char **argv) {
3895 i += 1;4168 i += 1;
38964169
3897 info->param_count = read32_uleb128(mod.ptr, &i);4170 info->param_count = read32_uleb128(mod.ptr, &i);
4171 if (info->param_count > 32) panic("found a type with over 32 parameters");
3898 info->param_types = 0;4172 info->param_types = 0;
3899 for (uint32_t param_i = 0; param_i < info->param_count; param_i += 1) {4173 for (uint32_t param_i = 0; param_i < info->param_count; param_i += 1) {
3900 int64_t param_type = read64_ileb128(mod.ptr, &i);4174 int64_t param_type = read64_ileb128(mod.ptr, &i);
...@@ -4133,7 +4407,7 @@ int main(int argc, char **argv) {...@@ -4133,7 +4407,7 @@ int main(int argc, char **argv) {
4133 uint32_t elem_count = read32_uleb128(mod.ptr, &i);4407 uint32_t elem_count = read32_uleb128(mod.ptr, &i);
41344408
4135 table = arena_alloc(sizeof(uint32_t) * maximum);4409 table = arena_alloc(sizeof(uint32_t) * maximum);
4136 memset(table, 0, maximum);4410 memset(table, 0, sizeof(uint32_t) * maximum);
41374411
4138 for (uint32_t elem_i = 0; elem_i < elem_count; elem_i += 1) {4412 for (uint32_t elem_i = 0; elem_i < elem_count; elem_i += 1) {
4139 table[elem_i + offset] = read32_uleb128(mod.ptr, &i);4413 table[elem_i + offset] = read32_uleb128(mod.ptr, &i);
...@@ -4142,6 +4416,9 @@ int main(int argc, char **argv) {...@@ -4142,6 +4416,9 @@ int main(int argc, char **argv) {
4142 }4416 }
41434417
4144 struct VirtualMachine vm;4418 struct VirtualMachine vm;
4419#ifndef NDEBUG
4420 memset(&vm, 0xaa, sizeof(struct VirtualMachine)); // to match the zig version
4421#endif
4145 vm.stack = arena_alloc(sizeof(uint64_t) * 10000000),4422 vm.stack = arena_alloc(sizeof(uint64_t) * 10000000),
4146 vm.mod_ptr = mod.ptr;4423 vm.mod_ptr = mod.ptr;
4147 vm.opcodes = arena_alloc(2000000);4424 vm.opcodes = arena_alloc(2000000);
...@@ -4154,7 +4431,7 @@ int main(int argc, char **argv) {...@@ -4154,7 +4431,7 @@ int main(int argc, char **argv) {
4154 vm.memory_len = memory_len;4431 vm.memory_len = memory_len;
4155 vm.imports = imports;4432 vm.imports = imports;
4156 vm.imports_len = imports_len;4433 vm.imports_len = imports_len;
4157 vm.args = argv + vm_argv_start;4434 vm.args = new_argv;
4158 vm.table = table;4435 vm.table = table;
41594436
4160 {4437 {
...@@ -4171,18 +4448,19 @@ int main(int argc, char **argv) {...@@ -4171,18 +4448,19 @@ int main(int argc, char **argv) {
41714448
4172 struct TypeInfo *type_info = &vm.types[func->type_idx];4449 struct TypeInfo *type_info = &vm.types[func->type_idx];
4173 func->locals_count = 0;4450 func->locals_count = 0;
4174 func->local_types = arena_alloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));4451 func->local_types = malloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
4175 func->local_types[0] = type_info->param_types;4452 func->local_types[0] = type_info->param_types;
41764453
4177 for (uint32_t local_sets_count = read32_uleb128(mod.ptr, &code_i);4454 for (uint32_t local_sets_count = read32_uleb128(mod.ptr, &code_i);
4178 local_sets_count > 0; local_sets_count -= 1) {4455 local_sets_count > 0; local_sets_count -= 1)
4456 {
4179 uint32_t set_count = read32_uleb128(mod.ptr, &code_i);4457 uint32_t set_count = read32_uleb128(mod.ptr, &code_i);
4180 int64_t local_type = read64_ileb128(mod.ptr, &code_i);4458 int64_t local_type = read64_ileb128(mod.ptr, &code_i);
41814459
4182 uint32_t i = type_info->param_count + func->locals_count;4460 uint32_t i = type_info->param_count + func->locals_count;
4183 func->locals_count += set_count;4461 func->locals_count += set_count;
4184 if ((type_info->param_count + func->locals_count + 31) / 32 > (i + 31) / 32)4462 if ((type_info->param_count + func->locals_count + 31) / 32 > (i + 31) / 32)
4185 func->local_types = arena_realloc(func->local_types, sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));4463 func->local_types = realloc(func->local_types, sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
4186 for (; i < type_info->param_count + func->locals_count; i += 1)4464 for (; i < type_info->param_count + func->locals_count; i += 1)
4187 switch (local_type) {4465 switch (local_type) {
4188 case -1: case -3: bs_unset(func->local_types, i); break;4466 case -1: case -3: bs_unset(func->local_types, i); break;
...@@ -4191,26 +4469,11 @@ int main(int argc, char **argv) {...@@ -4191,26 +4469,11 @@ int main(int argc, char **argv) {
4191 }4469 }
4192 }4470 }
41934471
4472 //fprintf(stderr, "set up func %u with pc %u:%u\n", func->type_idx, pc.opcode, pc.operand);
4194 func->entry_pc = pc;4473 func->entry_pc = pc;
4195 vm_decodeCode(&vm, func, &code_i, &pc);4474 vm_decodeCode(&vm, func, &code_i, &pc);
4196 if (code_i != code_begin + size) panic("bad code size");4475 if (code_i != code_begin + size) panic("bad code size");
4197 }4476 }
4198
4199 uint64_t opcode_counts[0x100];
4200 memset(opcode_counts, 0, 0x100);
4201 uint64_t prefixed_opcode_counts[0x100];
4202 memset(prefixed_opcode_counts, 0, 0x100);
4203 bool is_prefixed = false;
4204 for (uint32_t opcode_i = 0; opcode_i < pc.opcode; opcode_i += 1) {
4205 uint8_t opcode = vm.opcodes[opcode_i];
4206 if (!is_prefixed) {
4207 opcode_counts[opcode] += 1;
4208 is_prefixed = opcode == WasmOp_prefixed;
4209 } else {
4210 prefixed_opcode_counts[opcode] += 1;
4211 is_prefixed = false;
4212 }
4213 }
4214 }4477 }
42154478
4216 vm_call(&vm, start_fn_idx);4479 vm_call(&vm, start_fn_idx);