From c34e9807b103fcb56bbb0080ecd63a353e9c7a89 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 21 Apr 2020 00:34:15 +0300 Subject: [PATCH] WASI support for Big-Endian systems (#125) --- .github/workflows/tests.yml | 6 ++-- source/m3_api_defs.h | 16 +++++++++++ source/m3_api_wasi.c | 57 +++++++++++++++++++------------------ source/m3_compile.c | 30 ++++++++++++++----- 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ca7f836..493a6d5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -204,12 +204,12 @@ jobs: - {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static } - {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static } - {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static } - - {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static } - - {target: sparc64, toolchain: gcc-sparc64-linux-gnu, cc: sparc64-linux-gnu-gcc, qemu: qemu-sparc64-static } - {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static } - {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static } - {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static } - {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static } + - {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static } + - {target: sparc64, toolchain: gcc-sparc64-linux-gnu, cc: sparc64-linux-gnu-gcc, qemu: qemu-sparc64-static, skip_wasi: true } steps: - uses: actions/checkout@v2 @@ -236,7 +236,7 @@ jobs: cd test python3 run-spec-test.py --exec "${{ matrix.config.qemu }} ../build/wasm3 --repl" - name: Test WASI apps - continue-on-error: true # TODO + if: ${{ !matrix.config.skip_wasi }} run: | cd test python3 run-wasi-test.py --fast --exec "${{ matrix.config.qemu }} ../build/wasm3" diff --git a/source/m3_api_defs.h b/source/m3_api_defs.h index ec2635b..a0fc478 100644 --- a/source/m3_api_defs.h +++ b/source/m3_api_defs.h @@ -23,4 +23,20 @@ #define m3ApiTrap(VALUE) { return VALUE; } #define m3ApiSuccess() { return m3Err_none; } +# if defined(M3_BIG_ENDIAN) +# define m3ApiReadMem16(ptr) __builtin_bswap16((* (u16 *)(ptr))) +# define m3ApiReadMem32(ptr) __builtin_bswap32((* (u32 *)(ptr))) +# define m3ApiReadMem64(ptr) __builtin_bswap64((* (u64 *)(ptr))) +# define m3ApiWriteMem16(ptr, val) { * (u16 *)(ptr) = __builtin_bswap16((val)); } +# define m3ApiWriteMem32(ptr, val) { * (u32 *)(ptr) = __builtin_bswap32((val)); } +# define m3ApiWriteMem64(ptr, val) { * (u64 *)(ptr) = __builtin_bswap64((val)); } +# else +# define m3ApiReadMem16(ptr) (* (u16 *)(ptr)) +# define m3ApiReadMem32(ptr) (* (u32 *)(ptr)) +# define m3ApiReadMem64(ptr) (* (u64 *)(ptr)) +# define m3ApiWriteMem16(ptr, val) { * (u16 *)(ptr) = (val); } +# define m3ApiWriteMem32(ptr, val) { * (u32 *)(ptr) = (val); } +# define m3ApiWriteMem64(ptr, val) { * (u64 *)(ptr) = (val); } +# endif + #endif // m3_api_defs_h diff --git a/source/m3_api_wasi.c b/source/m3_api_wasi.c index deb9ba0..912da66 100644 --- a/source/m3_api_wasi.c +++ b/source/m3_api_wasi.c @@ -167,8 +167,8 @@ void copy_iov_to_host(void* _mem, struct iovec* host_iov, wasi_iovec_t* wasi_iov { // Convert wasi memory offsets to host addresses for (int i = 0; i < iovs_len; i++) { - host_iov[i].iov_base = m3ApiOffsetToPtr(wasi_iov[i].buf); - host_iov[i].iov_len = wasi_iov[i].buf_len; + host_iov[i].iov_base = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iov[i].buf)); + host_iov[i].iov_len = m3ApiReadMem32(&wasi_iov[i].buf_len); } } @@ -188,7 +188,7 @@ m3ApiRawFunction(m3_wasi_unstable_args_get) for (u32 i = 0; i < runtime->argc; ++i) { - argv[i] = m3ApiPtrToOffset (argv_buf); + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); size_t len = strlen (runtime->argv [i]); memcpy (argv_buf, runtime->argv [i], len); @@ -207,12 +207,15 @@ m3ApiRawFunction(m3_wasi_unstable_args_sizes_get) if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } - *argc = runtime->argc; - *argv_buf_size = 0; + __wasi_size_t buflen = 0; for (u32 i = 0; i < runtime->argc; ++i) { - * argv_buf_size += strlen (runtime->argv [i]) + 1; + buflen += strlen (runtime->argv [i]) + 1; } + + m3ApiWriteMem32(argc, runtime->argc); + m3ApiWriteMem32(argv_buf_size, buflen); + m3ApiReturn(__WASI_ESUCCESS); } @@ -262,8 +265,8 @@ m3ApiRawFunction(m3_wasi_unstable_fd_prestat_get) if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_EBADF); } - * (buf) = __WASI_PREOPENTYPE_DIR; - * (buf+1) = strlen(preopen[fd].path); + m3ApiWriteMem32(buf, __WASI_PREOPENTYPE_DIR); + m3ApiWriteMem32(buf+1, strlen(preopen[fd].path)); m3ApiReturn(__WASI_ESUCCESS); } @@ -300,11 +303,12 @@ m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get) (S_ISREG(mode) ? __WASI_FILETYPE_REGULAR_FILE : 0) | //(S_ISSOCK(mode) ? __WASI_FILETYPE_SOCKET_STREAM : 0) | (S_ISLNK(mode) ? __WASI_FILETYPE_SYMBOLIC_LINK : 0); - fdstat->fs_flags = ((fl & O_APPEND) ? __WASI_FDFLAG_APPEND : 0) | + m3ApiWriteMem16(&fdstat->fs_flags, + ((fl & O_APPEND) ? __WASI_FDFLAG_APPEND : 0) | ((fl & O_DSYNC) ? __WASI_FDFLAG_DSYNC : 0) | ((fl & O_NONBLOCK) ? __WASI_FDFLAG_NONBLOCK : 0) | //((fl & O_RSYNC) ? __WASI_FDFLAG_RSYNC : 0) | - ((fl & O_SYNC) ? __WASI_FDFLAG_SYNC : 0); + ((fl & O_SYNC) ? __WASI_FDFLAG_SYNC : 0)); fdstat->fs_rights_base = (uint64_t)-1; // all rights fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights m3ApiReturn(__WASI_ESUCCESS); @@ -341,7 +345,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_seek) ret = lseek(fd, offset, wasi_whence); #endif if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } - *result = ret; + m3ApiWriteMem64(result, ret); m3ApiReturn(__WASI_ESUCCESS); } @@ -371,8 +375,6 @@ m3ApiRawFunction(m3_wasi_unstable_path_open) memcpy (host_path, path, path_len); host_path [path_len] = '\0'; // NULL terminator - //printf ("== path_open: %s\n", host_path); - #if defined(_WIN32) // TODO: This all needs a proper implementation @@ -430,7 +432,7 @@ m3ApiRawFunction(m3_wasi_unstable_path_open) } else { - * fd = host_fd; + m3ApiWriteMem32(fd, host_fd); m3ApiReturn(__WASI_ESUCCESS); } #endif @@ -452,13 +454,13 @@ m3ApiRawFunction(m3_wasi_unstable_fd_read) ssize_t ret = readv(fd, iovs, iovs_len); if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } - *nread = ret; + m3ApiWriteMem32(nread, ret); m3ApiReturn(__WASI_ESUCCESS); #else ssize_t res = 0; for (__wasi_size_t i = 0; i < iovs_len; i++) { - void* addr = m3ApiOffsetToPtr(wasi_iovs[i].buf); - size_t len = wasi_iovs[i].buf_len; + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); if (len == 0) continue; int ret = read (fd, addr, len); @@ -466,7 +468,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_read) res += ret; if ((size_t)ret < len) break; } - *nread = res; + m3ApiWriteMem32(nread, res); m3ApiReturn(__WASI_ESUCCESS); #endif } @@ -487,13 +489,13 @@ m3ApiRawFunction(m3_wasi_unstable_fd_write) ssize_t ret = writev(fd, iovs, iovs_len); if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } - *nwritten = ret; + m3ApiWriteMem32(nwritten, ret); m3ApiReturn(__WASI_ESUCCESS); #else ssize_t res = 0; for (__wasi_size_t i = 0; i < iovs_len; i++) { - void* addr = m3ApiOffsetToPtr(wasi_iovs[i].buf); - size_t len = wasi_iovs[i].buf_len; + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); if (len == 0) continue; int ret = write (fd, addr, len); @@ -501,7 +503,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_write) res += ret; if ((size_t)ret < len) break; } - *nwritten = res; + m3ApiWriteMem32(nwritten, res); m3ApiReturn(__WASI_ESUCCESS); #endif } @@ -583,10 +585,11 @@ m3ApiRawFunction(m3_wasi_unstable_clock_res_get) if (clk < 0) m3ApiReturn(__WASI_EINVAL); struct timespec tp; - if (clock_getres(clk, &tp) != 0) - *resolution = 1000000; - else - *resolution = convert_timespec(&tp); + if (clock_getres(clk, &tp) != 0) { + m3ApiWriteMem64(resolution, 1000000); + } else { + m3ApiWriteMem64(resolution, convert_timespec(&tp)); + } m3ApiReturn(__WASI_ESUCCESS); } @@ -608,7 +611,7 @@ m3ApiRawFunction(m3_wasi_unstable_clock_time_get) m3ApiReturn(errno_to_wasi(errno)); } - *time = convert_timespec(&tp); + m3ApiWriteMem64(time, convert_timespec(&tp)); m3ApiReturn(__WASI_ESUCCESS); } diff --git a/source/m3_compile.c b/source/m3_compile.c index cde268b..3a34b18 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -526,6 +526,7 @@ M3Result PushConst (IM3Compilation o, u64 i_word, u8 i_type) if (!o->page) return result; bool matchFound = false; + bool is64BitType = Is64BitType(i_type); u32 numUsedConstSlots = o->maxConstSlotIndex - o->firstConstSlotIndex; u16 numRequiredSlots = GetTypeNumSlots (i_type); @@ -540,9 +541,14 @@ M3Result PushConst (IM3Compilation o, u64 i_word, u8 i_type) { if (IsSlotAllocated (o, slot) and IsSlotAllocated (o, slot + 1)) { - u64 * constant = (u64 *) & o->constants [slot - o->firstConstSlotIndex]; + u64 constant; + if (is64BitType) { + constant = * (u64 *) & o->constants [slot - o->firstConstSlotIndex]; + } else { + constant = * (u32 *) & o->constants [slot - o->firstConstSlotIndex]; + } - if (* constant == i_word) + if (constant == i_word) { matchFound = true; _ (Push (o, i_type, slot)); @@ -559,7 +565,13 @@ _ (Push (o, i_type, slot)); if (IsSlotAllocated (o, slot)) { - if (o->constants [i] == i_word) + u64 constant; + if (is64BitType) { + constant = * (u64 *) & o->constants [i]; + } else { + constant = * (u32 *) & o->constants [i]; + } + if (constant == i_word) { matchFound = true; _ (Push (o, i_type, slot)); @@ -592,12 +604,16 @@ _ (PushAllocatedSlotAndEmit (o, i_type)); { u16 constTableIndex = slot - o->firstConstSlotIndex; - if (Is64BitType (i_type)) + if (is64BitType) + { + u64 * constant = (u64 *) & o->constants [constTableIndex]; + * constant = i_word; + } + else { - u64 * constant64 = (u64 *) & o->constants [constTableIndex]; - * constant64 = i_word; + u32 * constant = (u32 *) & o->constants [constTableIndex]; + * constant = i_word; } - else o->constants [constTableIndex] = (u32) i_word; _ (Push (o, i_type, slot));