// // m3_api_meta_wasi.c // // Created by Volodymyr Shymanskyy on 01/08/20. // Copyright © 2020 Volodymyr Shymanskyy. All rights reserved. // #include "m3_api_wasi.h" #include "m3_api_defs.h" #include "m3_env.h" #include "m3_exception.h" #if defined(d_m3HasMetaWASI) // NOTE: MetaWASI mostly redirects WASI calls to the host WASI environment #if !defined(__wasi__) # error "MetaWASI is only supported on WASI target" #endif #if __has_include("wasi/api.h") # include #elif __has_include("wasi/core.h") # warning "Using legacy WASI headers" # include # define __WASI_ERRNO_SUCCESS __WASI_ESUCCESS # define __WASI_ERRNO_INVAL __WASI_EINVAL #else # error "Missing WASI headers" #endif typedef size_t __wasi_size_t; static inline void copy_iov_to_host(void* _mem, __wasi_iovec_t* host_iov, __wasi_iovec_t* wasi_iov, int32_t iovs_len) { // Convert wasi memory offsets to host addresses for (int i = 0; i < iovs_len; i++) { host_iov[i].buf = m3ApiOffsetToPtr(wasi_iov[i].buf); host_iov[i].buf_len = wasi_iov[i].buf_len; } } /* * WASI API implementation */ m3ApiRawFunction(m3_wasi_unstable_args_get) { m3ApiReturnType (uint32_t) m3ApiGetArgMem (uint32_t * , argv) m3ApiGetArgMem (char * , argv_buf) if (runtime == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } for (u32 i = 0; i < runtime->argc; ++i) { argv[i] = m3ApiPtrToOffset (argv_buf); size_t len = strlen (runtime->argv[i]); memcpy (argv_buf, runtime->argv[i], len); argv_buf += len; * argv_buf++ = 0; } m3ApiReturn(__WASI_ERRNO_SUCCESS); } m3ApiRawFunction(m3_wasi_unstable_args_sizes_get) { m3ApiReturnType (uint32_t) m3ApiGetArgMem (__wasi_size_t * , argc) m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) if (runtime == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } *argc = runtime->argc; *argv_buf_size = 0; for (u32 i = 0; i < runtime->argc; ++i) { * argv_buf_size += strlen (runtime->argv[i]) + 1; } m3ApiReturn(__WASI_ERRNO_SUCCESS); } m3ApiRawFunction(m3_wasi_unstable_environ_get) { m3ApiReturnType (uint32_t) m3ApiGetArgMem (uint32_t * , env) m3ApiGetArgMem (char * , env_buf) __wasi_errno_t ret; __wasi_size_t env_count, env_buf_size; ret = __wasi_environ_sizes_get(&env_count, &env_buf_size); if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret); ret = __wasi_environ_get(env, env_buf); if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret); for (u32 i = 0; i < env_count; ++i) { env[i] = m3ApiPtrToOffset (env[i]); } m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_environ_sizes_get) { m3ApiReturnType (uint32_t) m3ApiGetArgMem (__wasi_size_t * , env_count) m3ApiGetArgMem (__wasi_size_t * , env_buf_size) __wasi_errno_t ret = __wasi_environ_sizes_get(env_count, env_buf_size); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_prestat_dir_name) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArgMem (char * , path) m3ApiGetArg (__wasi_size_t , path_len) __wasi_errno_t ret = __wasi_fd_prestat_dir_name(fd, path, path_len); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_prestat_get) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArgMem (__wasi_prestat_t * , buf) __wasi_errno_t ret = __wasi_fd_prestat_get(fd, buf); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) __wasi_errno_t ret = __wasi_fd_fdstat_get(fd, fdstat); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_set_flags) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArg (__wasi_fdflags_t , flags) __wasi_errno_t ret = __wasi_fd_fdstat_set_flags(fd, flags); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_seek) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArg (__wasi_filedelta_t , offset) m3ApiGetArg (__wasi_whence_t , whence) m3ApiGetArgMem (__wasi_filesize_t * , result) __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_path_open) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , dirfd) m3ApiGetArg (__wasi_lookupflags_t , dirflags) m3ApiGetArgMem (const char * , path) m3ApiGetArg (__wasi_size_t , path_len) m3ApiGetArg (__wasi_oflags_t , oflags) m3ApiGetArg (__wasi_rights_t , fs_rights_base) m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) m3ApiGetArg (__wasi_fdflags_t , fs_flags) m3ApiGetArgMem (__wasi_fd_t * , fd) __wasi_errno_t ret = __wasi_path_open(dirfd, dirflags, path, path_len, oflags, fs_rights_base, fs_rights_inheriting, fs_flags, fd); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_path_filestat_get) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArg (__wasi_lookupflags_t , flags) m3ApiGetArgMem (const char * , path) m3ApiGetArg (uint32_t , path_len) m3ApiGetArgMem (__wasi_filestat_t * , buf) __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, buf); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_read) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) m3ApiGetArg (__wasi_size_t , iovs_len) m3ApiGetArgMem (__wasi_size_t * , nread) __wasi_iovec_t iovs[iovs_len]; copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); __wasi_errno_t ret = __wasi_fd_read(fd, iovs, iovs_len, nread); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_write) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) m3ApiGetArg (__wasi_size_t , iovs_len) m3ApiGetArgMem (__wasi_size_t * , nwritten) __wasi_iovec_t iovs[iovs_len]; copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); __wasi_errno_t ret = __wasi_fd_write(fd, (__wasi_ciovec_t*)iovs, iovs_len, nwritten); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_readdir) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t , fd) m3ApiGetArgMem (void * , buf) m3ApiGetArg (__wasi_size_t , buf_len) m3ApiGetArg (__wasi_dircookie_t , cookie) m3ApiGetArgMem (__wasi_size_t * , bufused) __wasi_errno_t ret = __wasi_fd_readdir(fd, buf, buf_len, cookie, bufused); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_close) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t, fd) __wasi_errno_t ret = __wasi_fd_close(fd); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_fd_datasync) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_fd_t, fd) __wasi_errno_t ret = __wasi_fd_datasync(fd); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_random_get) { m3ApiReturnType (uint32_t) m3ApiGetArgMem (uint8_t * , buf) m3ApiGetArg (__wasi_size_t , buflen) __wasi_errno_t ret = __wasi_random_get(buf, buflen); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_clock_res_get) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) m3ApiGetArgMem (__wasi_timestamp_t * , resolution) __wasi_errno_t ret = __wasi_clock_res_get(wasi_clk_id, resolution); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_clock_time_get) { m3ApiReturnType (uint32_t) m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) m3ApiGetArg (__wasi_timestamp_t , precision) m3ApiGetArgMem (__wasi_timestamp_t * , time) __wasi_errno_t ret = __wasi_clock_time_get(wasi_clk_id, precision, time); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_poll_oneoff) { m3ApiReturnType (uint32_t) m3ApiGetArgMem (const __wasi_subscription_t * , in) m3ApiGetArgMem (__wasi_event_t * , out) m3ApiGetArg (__wasi_size_t , nsubscriptions) m3ApiGetArgMem (__wasi_size_t * , nevents) __wasi_errno_t ret = __wasi_poll_oneoff(in, out, nsubscriptions, nevents); m3ApiReturn(ret); } m3ApiRawFunction(m3_wasi_unstable_proc_exit) { m3ApiGetArg (uint32_t, code) runtime->exit_code = code; m3ApiTrap(m3Err_trapExit); } static M3Result SuppressLookupFailure(M3Result i_result) { if (i_result == m3Err_functionLookupFailed) return m3Err_none; else return i_result; } M3Result m3_LinkWASI (IM3Module module) { M3Result result = m3Err_none; static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; for (int i=0; i<2; i++) { const char* wasi = namespaces[i]; _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_unstable_clock_res_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_unstable_clock_time_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_unstable_environ_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_unstable_environ_sizes_get))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_unstable_fd_close))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_unstable_fd_datasync))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_unstable_fd_fdstat_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_unstable_fd_fdstat_set_flags))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_get", "i(i*)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_unstable_fd_prestat_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_unstable_fd_prestat_dir_name))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_unstable_fd_read))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",&m3_wasi_unstable_fd_readdir))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_unstable_fd_write))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_unstable_path_open))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_unstable_poll_oneoff))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_exit", "v(i)", &m3_wasi_unstable_proc_exit))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_unstable_random_get))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); } _catch: return result; } #endif // d_m3HasMetaWASI