WASI support for Windows (incomplete)

extensions
Volodymyr Shymanskyy 5 years ago
parent 30fbcf04b0
commit 6f317c814a

@ -77,7 +77,7 @@ include_directories("./source/")
#-fno-optimize-sibling-calls
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3AllocateLinearMemory=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI -Dd_m3AllocateLinearMemory=1")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG=1")
if(EMSCRIPTEN)
@ -103,7 +103,6 @@ elseif(WIN32)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oxs /Oy /GS- /Qvec -Clang -O3")
endif()
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wstrict-aliasing -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -O0")

@ -15,6 +15,12 @@
//#error <wasi/core.h> is only supported on WASI platforms.
//#endif
# if defined (M3_COMPILER_MSVC)
# define _Static_assert(...)
# define __attribute__(...)
# define _Noreturn
# endif
#if !defined(__x86_64__)
# define _Static_assert(...)
#endif

@ -14,32 +14,29 @@
#if defined(d_m3HasWASI)
typedef uint32_t __wasi_size_t;
#include "extra/wasi_core.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/random.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
# if defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
# include <unistd.h>
# elif defined(_WIN32)
/* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
# define SystemFunction036 NTAPI SystemFunction036
# include <NTSecAPI.h>
# undef SystemFunction036
# endif
//TODO
#define PREOPEN_CNT 5
#define NANOS_PER_SEC 1000000000
typedef uint32_t __wasi_size_t;
#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
# include <unistd.h>
# include <sys/uio.h>
# include <sys/random.h>
# include <fcntl.h>
# define HAS_IOVEC
#elif defined(_WIN32)
# include <Windows.h>
// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
# define SystemFunction036 NTAPI SystemFunction036
# include <NTSecAPI.h>
# undef SystemFunction036
# define ssize_t SSIZE_T
#endif
struct wasi_iovec
{
@ -47,6 +44,18 @@ struct wasi_iovec
__wasi_size_t iov_len;
};
static inline
uint32_t addr2offset(IM3Runtime m, void *addr) {
return (u8*)addr - m->memory.wasmPages;
}
static inline
void *offset2addr(IM3Runtime m, uint32_t offset) {
return m->memory.wasmPages + offset;
}
#define PREOPEN_CNT 5
typedef struct Preopen {
int fd;
char* path;
@ -96,20 +105,58 @@ __wasi_errno_t errno_to_wasi(int errnum) {
case EPIPE: return __WASI_EPIPE; break;
case EDOM: return __WASI_EDOM; break;
case ERANGE: return __WASI_ERANGE; break;
default: return errno;
default: return __WASI_EINVAL;
}
}
#if defined(_WIN32)
static inline
uint32_t addr2offset(IM3Runtime m, void *addr) {
return (u8*)addr - m->memory.wasmPages;
int clock_gettime(int clk_id, struct timespec *spec)
{
__int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime);
wintime -= 116444736000000000i64; //1jan1601 to 1jan1970
spec->tv_sec = wintime / 10000000i64; //seconds
spec->tv_nsec = wintime % 10000000i64 *100; //nano-seconds
return 0;
}
static inline
void *offset2addr(IM3Runtime m, uint32_t offset) {
return m->memory.wasmPages + offset;
int clock_getres(int clk_id, struct timespec *spec) {
return -1; // Defaults to 1000000
}
static inline
int convert_clockid(__wasi_clockid_t in) {
return 0;
}
#else // _WIN32
static inline
int convert_clockid(__wasi_clockid_t in) {
switch (in) {
case __WASI_CLOCK_MONOTONIC: return CLOCK_MONOTONIC;
case __WASI_CLOCK_PROCESS_CPUTIME_ID: return CLOCK_PROCESS_CPUTIME_ID;
case __WASI_CLOCK_REALTIME: return CLOCK_REALTIME;
case __WASI_CLOCK_THREAD_CPUTIME_ID: return CLOCK_THREAD_CPUTIME_ID;
default: return -1;
}
}
#endif // _WIN32
static inline
__wasi_timestamp_t convert_timespec(const struct timespec *ts) {
if (ts->tv_sec < 0)
return 0;
if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000)
return UINT64_MAX;
return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec;
}
#if defined(HAS_IOVEC)
static
void copy_iov_to_host(struct iovec* host_iov, IM3Runtime runtime, uint32_t iov_offset, int32_t iovs_len)
{
@ -121,6 +168,7 @@ void copy_iov_to_host(struct iovec* host_iov, IM3Runtime runtime, uint32_t iov_o
}
}
#endif
/*
* WASI API implementation
@ -223,6 +271,13 @@ m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get)
if (runtime == NULL || fdstat == NULL) { m3ApiReturn(__WASI_EINVAL); }
#ifdef _WIN32
fdstat->fs_filetype = 0;
fdstat->fs_flags = 0;
fdstat->fs_rights_base = (uint64_t)-1; // all rights
fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights
m3ApiReturn(__WASI_ESUCCESS);
#else
struct stat fd_stat;
int fl = fcntl(fd, F_GETFL);
if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); }
@ -242,6 +297,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get)
fdstat->fs_rights_base = (uint64_t)-1; // all rights
fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights
m3ApiReturn(__WASI_ESUCCESS);
#endif
}
m3ApiRawFunction(m3_wasi_unstable_fd_seek)
@ -286,6 +342,9 @@ m3ApiRawFunction(m3_wasi_unstable_path_open)
m3ApiReturn(__WASI_EINVAL);
}
#ifdef _WIN32
// TODO
#else
// copy path so we can ensure it is NULL terminated
char host_path [path_len+1];
@ -322,7 +381,7 @@ m3ApiRawFunction(m3_wasi_unstable_path_open)
* fd = host_fd;
m3ApiReturn(__WASI_ESUCCESS);
}
#endif
}
m3ApiRawFunction(m3_wasi_unstable_fd_read)
@ -335,6 +394,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_read)
if (runtime == NULL || nread == NULL) { m3ApiReturn(__WASI_EINVAL); }
#if defined(HAS_IOVEC)
struct iovec iovs[iovs_len];
copy_iov_to_host(iovs, runtime, iovs_offset, iovs_len);
@ -342,6 +402,24 @@ m3ApiRawFunction(m3_wasi_unstable_fd_read)
if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); }
*nread = ret;
m3ApiReturn(__WASI_ESUCCESS);
#else
ssize_t res = 0;
struct wasi_iovec *wasi_iov = offset2addr(runtime, iovs_offset);
for (int i = 0; i < iovs_len; i++) {
void* addr = offset2addr(runtime, wasi_iov[i].iov_base);
size_t len = wasi_iov[i].iov_len;
if (len == 0) continue;
fprintf(stderr, "R %d %d\n", i, len);
int ret = _read (fd, addr, len);
if (ret < 0) m3ApiReturn(errno_to_wasi(errno));
res += ret;
if (ret < len) break;
}
*nread = res;
m3ApiReturn(__WASI_ESUCCESS);
#endif
}
m3ApiRawFunction(m3_wasi_unstable_fd_write)
@ -354,6 +432,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_write)
if (runtime == NULL || nwritten == NULL) { m3ApiReturn(__WASI_EINVAL); }
#if defined(HAS_IOVEC)
struct iovec iovs[iovs_len];
copy_iov_to_host(iovs, runtime, iovs_offset, iovs_len);
@ -361,6 +440,24 @@ m3ApiRawFunction(m3_wasi_unstable_fd_write)
if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); }
*nwritten = ret;
m3ApiReturn(__WASI_ESUCCESS);
#else
ssize_t res = 0;
struct wasi_iovec *wasi_iov = offset2addr(runtime, iovs_offset);
for (int i = 0; i < iovs_len; i++) {
void* addr = offset2addr(runtime, wasi_iov[i].iov_base);
size_t len = wasi_iov[i].iov_len;
if (len == 0) continue;
fprintf(stderr, "W %d %d\n", i, len);
int ret = _write (fd, addr, len);
if (ret < 0) m3ApiReturn(errno_to_wasi(errno));
res += ret;
if (ret < len) break;
}
*nwritten = res;
m3ApiReturn(__WASI_ESUCCESS);
#endif
}
m3ApiRawFunction(m3_wasi_unstable_fd_close)
@ -377,39 +474,31 @@ m3ApiRawFunction(m3_wasi_unstable_fd_datasync)
m3ApiReturnType (uint32_t)
m3ApiGetArg (__wasi_fd_t, fd)
#if defined(_WIN32)
int ret = fflush(fd);
m3ApiReturn(ret == 0 ? __WASI_ESUCCESS : ret);
#else
int ret = fdatasync(fd);
m3ApiReturn(ret == 0 ? __WASI_ESUCCESS : ret);
#endif
}
m3ApiRawFunction(m3_wasi_unstable_random_get)
{
m3ApiReturnType (uint32_t)
m3ApiGetArgMem (void* , buf)
m3ApiGetArgMem (uint8_t* , buf)
m3ApiGetArg (__wasi_size_t , buflen)
while (1) {
ssize_t retlen = 0;
#if defined(__wasi__)
retlen = getentropy(buf, buflen);
if (retlen == 0) {
retlen = buflen;
}
#elif defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
size_t pos = 0;
for (; pos + 256 < buflen; pos += 256) {
if (getentropy((char *)buf + pos, 256)) {
m3ApiReturn(errno_to_wasi(errno));
}
}
if (getentropy((char *)buf + pos, buflen - pos)) {
m3ApiReturn(errno_to_wasi(errno));
#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
size_t reqlen = min(buflen, 256);
if (getentropy(buf, reqlen) < 0) {
retlen = -1;
} else {
retlen = reqlen;
}
m3ApiReturn(__WASI_ESUCCESS);
#elif defined(__NetBSD__)
// TODO
// sysctl(buf, buflen)
#elif defined(__FreeBSD__) || defined(__linux__)
retlen = getrandom(buf, buflen, 0);
#elif defined(_WIN32)
@ -417,50 +506,60 @@ m3ApiRawFunction(m3_wasi_unstable_random_get)
m3ApiReturn(__WASI_ESUCCESS);
}
#else
// use syscall ?
abort (); // unsupport
retlen = -1;
m3ApiReturn(__WASI_ENOSYS);
#endif
if (retlen < 0) {
if (errno == EINTR) { continue; }
if (errno == EINTR || errno == EAGAIN) {
continue;
}
m3ApiReturn(errno_to_wasi(errno));
} else if (retlen == buflen) {
m3ApiReturn(__WASI_ESUCCESS);
} else {
buf += retlen;
buflen -= retlen;
}
if (retlen == buflen) { m3ApiReturn(__WASI_ESUCCESS); }
buf = (void *)((uint8_t *)buf + retlen);
buflen -= retlen;
}
}
m3ApiRawFunction(m3_wasi_unstable_clock_res_get)
{
m3ApiReturnType (uint32_t)
m3ApiGetArg (__wasi_clockid_t , clock_id)
m3ApiGetArg (__wasi_clockid_t , wasi_clk_id)
m3ApiGetArgMem (__wasi_timestamp_t* , resolution)
if (runtime == NULL || resolution == NULL) { m3ApiReturn(__WASI_EINVAL); }
int clk = convert_clockid(wasi_clk_id);
if (clk < 0) m3ApiReturn(__WASI_EINVAL);
struct timespec tp;
if (clock_getres(clock_id, &tp) != 0)
if (clock_getres(clk, &tp) != 0)
*resolution = 1000000;
else
*resolution = (tp.tv_sec * NANOS_PER_SEC) + tp.tv_nsec;
*resolution = convert_timespec(&tp);
m3ApiReturn(__WASI_ESUCCESS);
}
m3ApiRawFunction(m3_wasi_unstable_clock_time_get)
{
m3ApiReturnType (uint32_t)
m3ApiGetArg (__wasi_clockid_t , clock_id)
m3ApiGetArg (__wasi_clockid_t , wasi_clk_id)
m3ApiGetArg (__wasi_timestamp_t , precision)
m3ApiGetArgMem (__wasi_timestamp_t* , time)
if (runtime == NULL || time == NULL) { m3ApiReturn(__WASI_EINVAL); }
int clk = convert_clockid(wasi_clk_id);
if (clk < 0) m3ApiReturn(__WASI_EINVAL);
struct timespec tp;
if (clock_gettime(clock_id, &tp) != 0) { m3ApiReturn(errno_to_wasi(errno)); }
if (clock_gettime(clk, &tp) != 0) {
m3ApiReturn(errno_to_wasi(errno));
}
//printf("=== time: %lu.%09u\n", tp.tv_sec, tp.tv_nsec);
*time = (uint64_t)tp.tv_sec * NANOS_PER_SEC + tp.tv_nsec;
*time = convert_timespec(&tp);
m3ApiReturn(__WASI_ESUCCESS);
}
@ -493,11 +592,14 @@ M3Result m3_LinkWASI (IM3Module module)
const char* namespace = "wasi_unstable";
#ifdef _WIN32
// TODO
#else
// Preopen dirs
for (int i = 3; i < PREOPEN_CNT; i++) {
preopen[i].fd = open(preopen[i].path, O_RDONLY);
}
#endif
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "args_sizes_get", &m3_wasi_unstable_args_sizes_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "environ_sizes_get", &m3_wasi_unstable_environ_sizes_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "args_get", &m3_wasi_unstable_args_get)));

Loading…
Cancel
Save