diff --git a/crates/wasi-common/src/fs/dir.rs b/crates/wasi-common/src/fs/dir.rs index f50fcfc06b..29739a2449 100644 --- a/crates/wasi-common/src/fs/dir.rs +++ b/crates/wasi-common/src/fs/dir.rs @@ -199,7 +199,7 @@ impl<'ctx> Drop for Dir<'ctx> { // the file descriptor was closed or not, and if we retried (for // something like EINTR), we might close another valid file descriptor // opened after we closed ours. - let _ = unsafe { hostcalls::fd_close(self.ctx, self.fd) }; + let _ = unsafe { hostcalls::fd_close(self.ctx, &mut [], self.fd) }; } } diff --git a/crates/wasi-common/src/fs/file.rs b/crates/wasi-common/src/fs/file.rs index 86090b2c3a..c837b30124 100644 --- a/crates/wasi-common/src/fs/file.rs +++ b/crates/wasi-common/src/fs/file.rs @@ -35,7 +35,7 @@ impl<'ctx> File<'ctx> { /// /// [`std::fs::File::sync_all`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_all pub fn sync_all(&self) -> io::Result<()> { - wasi_errno_to_io_error(unsafe { hostcalls::fd_sync(self.ctx, self.fd) }) + wasi_errno_to_io_error(unsafe { hostcalls::fd_sync(self.ctx, &mut [], self.fd) }) } /// This function is similar to `sync_all`, except that it may not synchronize @@ -45,7 +45,7 @@ impl<'ctx> File<'ctx> { /// /// [`std::fs::File::sync_data`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_data pub fn sync_data(&self) -> io::Result<()> { - wasi_errno_to_io_error(unsafe { hostcalls::fd_datasync(self.ctx, self.fd) }) + wasi_errno_to_io_error(unsafe { hostcalls::fd_datasync(self.ctx, &mut [], self.fd) }) } /// Truncates or extends the underlying file, updating the size of this file @@ -55,7 +55,9 @@ impl<'ctx> File<'ctx> { /// /// [`std::fs::File::set_len`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.set_len pub fn set_len(&self, size: u64) -> io::Result<()> { - wasi_errno_to_io_error(unsafe { hostcalls::fd_filestat_set_size(self.ctx, self.fd, size) }) + wasi_errno_to_io_error(unsafe { + hostcalls::fd_filestat_set_size(self.ctx, &mut [], self.fd, size) + }) } /// Queries metadata about the underlying file. @@ -75,7 +77,7 @@ impl<'ctx> Drop for File<'ctx> { // the file descriptor was closed or not, and if we retried (for // something like EINTR), we might close another valid file descriptor // opened after we closed ours. - let _ = unsafe { hostcalls::fd_close(self.ctx, self.fd) }; + let _ = unsafe { hostcalls::fd_close(self.ctx, &mut [], self.fd) }; } } diff --git a/crates/wasi-common/src/hostcalls/fs.rs b/crates/wasi-common/src/hostcalls/fs.rs index dd83a2c12a..f9a140869c 100644 --- a/crates/wasi-common/src/hostcalls/fs.rs +++ b/crates/wasi-common/src/hostcalls/fs.rs @@ -3,9 +3,9 @@ use crate::ctx::WasiCtx; use crate::{hostcalls_impl, wasi, wasi32}; hostcalls! { - pub unsafe fn fd_close(wasi_ctx: &mut WasiCtx, fd: wasi::__wasi_fd_t,) -> wasi::__wasi_errno_t; + pub unsafe fn fd_close(wasi_ctx: &mut WasiCtx, memory: &mut [u8], fd: wasi::__wasi_fd_t,) -> wasi::__wasi_errno_t; - pub unsafe fn fd_datasync(wasi_ctx: &WasiCtx, fd: wasi::__wasi_fd_t,) -> wasi::__wasi_errno_t; + pub unsafe fn fd_datasync(wasi_ctx: &WasiCtx, memory: &mut [u8], fd: wasi::__wasi_fd_t,) -> wasi::__wasi_errno_t; pub unsafe fn fd_pread( wasi_ctx: &WasiCtx, @@ -38,6 +38,7 @@ hostcalls! { pub unsafe fn fd_renumber( wasi_ctx: &mut WasiCtx, + memory: &mut [u8], from: wasi::__wasi_fd_t, to: wasi::__wasi_fd_t, ) -> wasi::__wasi_errno_t; @@ -67,18 +68,20 @@ hostcalls! { pub unsafe fn fd_fdstat_set_flags( wasi_ctx: &WasiCtx, + memory: &mut [u8], fd: wasi::__wasi_fd_t, fdflags: wasi::__wasi_fdflags_t, ) -> wasi::__wasi_errno_t; pub unsafe fn fd_fdstat_set_rights( wasi_ctx: &mut WasiCtx, + memory: &mut [u8], fd: wasi::__wasi_fd_t, fs_rights_base: wasi::__wasi_rights_t, fs_rights_inheriting: wasi::__wasi_rights_t, ) -> wasi::__wasi_errno_t; - pub unsafe fn fd_sync(wasi_ctx: &WasiCtx, fd: wasi::__wasi_fd_t,) -> wasi::__wasi_errno_t; + pub unsafe fn fd_sync(wasi_ctx: &WasiCtx, memory: &mut [u8], fd: wasi::__wasi_fd_t,) -> wasi::__wasi_errno_t; pub unsafe fn fd_write( wasi_ctx: &mut WasiCtx, @@ -91,6 +94,7 @@ hostcalls! { pub unsafe fn fd_advise( wasi_ctx: &WasiCtx, + memory: &mut [u8], fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, @@ -99,6 +103,7 @@ hostcalls! { pub unsafe fn fd_allocate( wasi_ctx: &WasiCtx, + memory: &mut [u8], fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, @@ -179,6 +184,7 @@ hostcalls! { pub unsafe fn fd_filestat_set_times( wasi_ctx: &WasiCtx, + memory: &mut [u8], fd: wasi::__wasi_fd_t, st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, @@ -187,6 +193,7 @@ hostcalls! { pub unsafe fn fd_filestat_set_size( wasi_ctx: &WasiCtx, + memory: &mut [u8], fd: wasi::__wasi_fd_t, st_size: wasi::__wasi_filesize_t, ) -> wasi::__wasi_errno_t; diff --git a/crates/wasi-common/src/hostcalls/misc.rs b/crates/wasi-common/src/hostcalls/misc.rs index 592942d58e..883b5a54ac 100644 --- a/crates/wasi-common/src/hostcalls/misc.rs +++ b/crates/wasi-common/src/hostcalls/misc.rs @@ -5,7 +5,7 @@ use log::trace; use wasi_common_cbindgen::wasi_common_cbindgen; #[wasi_common_cbindgen] -pub unsafe fn proc_exit(rval: wasi::__wasi_exitcode_t) { +pub unsafe fn proc_exit(_wasi_ctx: &WasiCtx, _memory: &mut [u8], rval: wasi::__wasi_exitcode_t) { trace!("proc_exit(rval={:?})", rval); // TODO: Rather than call std::process::exit here, we should trigger a // stack unwind similar to a trap. @@ -51,18 +51,21 @@ hostcalls! { ) -> wasi::__wasi_errno_t; pub unsafe fn random_get( + wasi_ctx: &WasiCtx, memory: &mut [u8], buf_ptr: wasi32::uintptr_t, buf_len: wasi32::size_t, ) -> wasi::__wasi_errno_t; pub unsafe fn clock_res_get( + wasi_ctx: &WasiCtx, memory: &mut [u8], clock_id: wasi::__wasi_clockid_t, resolution_ptr: wasi32::uintptr_t, ) -> wasi::__wasi_errno_t; pub unsafe fn clock_time_get( + wasi_ctx: &WasiCtx, memory: &mut [u8], clock_id: wasi::__wasi_clockid_t, precision: wasi::__wasi_timestamp_t, @@ -78,5 +81,8 @@ hostcalls! { nevents: wasi32::uintptr_t, ) -> wasi::__wasi_errno_t; - pub unsafe fn sched_yield() -> wasi::__wasi_errno_t; + pub unsafe fn sched_yield( + wasi_ctx: &WasiCtx, + memory: &mut [u8], + ) -> wasi::__wasi_errno_t; } diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index 71d84f52ca..7cfd6ff427 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs.rs @@ -14,7 +14,11 @@ use std::fs::File; use std::io::{self, Read, Seek, SeekFrom, Write}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; -pub(crate) unsafe fn fd_close(wasi_ctx: &mut WasiCtx, fd: wasi::__wasi_fd_t) -> Result<()> { +pub(crate) unsafe fn fd_close( + wasi_ctx: &mut WasiCtx, + _memory: &mut [u8], + fd: wasi::__wasi_fd_t, +) -> Result<()> { trace!("fd_close(fd={:?})", fd); if let Ok(fe) = wasi_ctx.get_fd_entry(fd) { @@ -28,7 +32,11 @@ pub(crate) unsafe fn fd_close(wasi_ctx: &mut WasiCtx, fd: wasi::__wasi_fd_t) -> Ok(()) } -pub(crate) unsafe fn fd_datasync(wasi_ctx: &WasiCtx, fd: wasi::__wasi_fd_t) -> Result<()> { +pub(crate) unsafe fn fd_datasync( + wasi_ctx: &WasiCtx, + _memory: &mut [u8], + fd: wasi::__wasi_fd_t, +) -> Result<()> { trace!("fd_datasync(fd={:?})", fd); let fd = wasi_ctx @@ -173,6 +181,7 @@ pub(crate) unsafe fn fd_read( pub(crate) unsafe fn fd_renumber( wasi_ctx: &mut WasiCtx, + _memory: &mut [u8], from: wasi::__wasi_fd_t, to: wasi::__wasi_fd_t, ) -> Result<()> { @@ -289,6 +298,7 @@ pub(crate) unsafe fn fd_fdstat_get( pub(crate) unsafe fn fd_fdstat_set_flags( wasi_ctx: &WasiCtx, + _memory: &mut [u8], fd: wasi::__wasi_fd_t, fdflags: wasi::__wasi_fdflags_t, ) -> Result<()> { @@ -304,6 +314,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags( pub(crate) unsafe fn fd_fdstat_set_rights( wasi_ctx: &mut WasiCtx, + _memory: &mut [u8], fd: wasi::__wasi_fd_t, fs_rights_base: wasi::__wasi_rights_t, fs_rights_inheriting: wasi::__wasi_rights_t, @@ -327,7 +338,11 @@ pub(crate) unsafe fn fd_fdstat_set_rights( Ok(()) } -pub(crate) unsafe fn fd_sync(wasi_ctx: &WasiCtx, fd: wasi::__wasi_fd_t) -> Result<()> { +pub(crate) unsafe fn fd_sync( + wasi_ctx: &WasiCtx, + _memory: &mut [u8], + fd: wasi::__wasi_fd_t, +) -> Result<()> { trace!("fd_sync(fd={:?})", fd); let fd = wasi_ctx @@ -381,6 +396,7 @@ pub(crate) unsafe fn fd_write( pub(crate) unsafe fn fd_advise( wasi_ctx: &WasiCtx, + _memory: &mut [u8], fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, @@ -404,6 +420,7 @@ pub(crate) unsafe fn fd_advise( pub(crate) unsafe fn fd_allocate( wasi_ctx: &WasiCtx, + _memory: &mut [u8], fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, @@ -687,6 +704,7 @@ pub(crate) unsafe fn fd_filestat_get( pub(crate) unsafe fn fd_filestat_set_times( wasi_ctx: &WasiCtx, + _memory: &mut [u8], fd: wasi::__wasi_fd_t, st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, @@ -746,6 +764,7 @@ pub(crate) fn fd_filestat_set_times_impl( pub(crate) unsafe fn fd_filestat_set_size( wasi_ctx: &WasiCtx, + _memory: &mut [u8], fd: wasi::__wasi_fd_t, st_size: wasi::__wasi_filesize_t, ) -> Result<()> { diff --git a/crates/wasi-common/src/hostcalls_impl/misc.rs b/crates/wasi-common/src/hostcalls_impl/misc.rs index 3123621ada..696eb1b7ba 100644 --- a/crates/wasi-common/src/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/hostcalls_impl/misc.rs @@ -128,6 +128,7 @@ pub(crate) fn environ_sizes_get( } pub(crate) fn random_get( + _wasi_ctx: &WasiCtx, memory: &mut [u8], buf_ptr: wasi32::uintptr_t, buf_len: wasi32::size_t, @@ -143,6 +144,7 @@ pub(crate) fn random_get( } pub(crate) fn clock_res_get( + _wasi_ctx: &WasiCtx, memory: &mut [u8], clock_id: wasi::__wasi_clockid_t, resolution_ptr: wasi32::uintptr_t, @@ -161,6 +163,7 @@ pub(crate) fn clock_res_get( } pub(crate) fn clock_time_get( + _wasi_ctx: &WasiCtx, memory: &mut [u8], clock_id: wasi::__wasi_clockid_t, precision: wasi::__wasi_timestamp_t, @@ -180,7 +183,7 @@ pub(crate) fn clock_time_get( enc_timestamp_byref(memory, time_ptr, time) } -pub(crate) fn sched_yield() -> Result<()> { +pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> Result<()> { trace!("sched_yield()"); std::thread::yield_now(); diff --git a/crates/wasi-common/wig/src/lib.rs b/crates/wasi-common/wig/src/lib.rs index 44fc0ff43a..2ebb52582a 100644 --- a/crates/wasi-common/wig/src/lib.rs +++ b/crates/wasi-common/wig/src/lib.rs @@ -2,6 +2,7 @@ extern crate proc_macro; mod raw_types; mod utils; +mod wasi; use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; @@ -29,3 +30,9 @@ pub fn witx_wasi32_types(args: TokenStream) -> TokenStream { raw_types::Mode::Wasi32, )) } + +/// A single-use macro in the `wasmtime-wasi` crate. +#[proc_macro] +pub fn define_add_wrappers_to_module(args: TokenStream) -> TokenStream { + wasi::add_wrappers_to_module(args.into()).into() +} diff --git a/crates/wasi-common/wig/src/utils.rs b/crates/wasi-common/wig/src/utils.rs index 283cbd2d1a..74d71e5eb4 100644 --- a/crates/wasi-common/wig/src/utils.rs +++ b/crates/wasi-common/wig/src/utils.rs @@ -1,4 +1,5 @@ use proc_macro2::{Literal, TokenStream, TokenTree}; + /// Given the input tokens to a macro invocation, return the path to the /// witx file to process. pub(crate) fn witx_path_from_args(args: TokenStream) -> (String, String) { @@ -26,8 +27,8 @@ pub(crate) fn witx_path_from_args(args: TokenStream) -> (String, String) { } fn witx_path(phase: &str, id: &str) -> String { - let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into()); - format!("{}/WASI/phases/{}/witx/{}.witx", root, phase, id) + let root = env!("CARGO_MANIFEST_DIR"); + format!("{}/../WASI/phases/{}/witx/{}.witx", root, phase, id) } // Convert a `Literal` holding a string literal into the `String`. diff --git a/crates/wasi-common/wig/src/wasi.rs b/crates/wasi-common/wig/src/wasi.rs new file mode 100644 index 0000000000..fe4d4141b4 --- /dev/null +++ b/crates/wasi-common/wig/src/wasi.rs @@ -0,0 +1,231 @@ +use crate::utils; +use proc_macro2::{Ident, Span, TokenStream}; +use quote::{format_ident, quote}; + +enum Abi { + I32, + I64, + F32, + F64, +} + +/// This is a single-use macro intended to be used in the `wasmtime-wasi` crate. +/// +/// This macro will generate a function, `add_wrappers_to_module`, which will +/// use the input arguments to register all wasi functions inside of a `Module` +/// instance. This will automatically assign the wasm underlying types and +/// perform conversions from the wasm type to the underlying wasi type (often +/// unsigned or of a smaller width). +/// +/// The generated shim functions here will also `trace!` their arguments for +/// logging purposes. Otherwise this is hopefully somewhat straightforward! +/// +/// I'd recommend using `cargo +nightly expand` to explore the output of this +/// macro some more. +pub fn add_wrappers_to_module(args: TokenStream) -> TokenStream { + let (path, _phase) = utils::witx_path_from_args(args); + let doc = match witx::load(&[&path]) { + Ok(doc) => doc, + Err(e) => { + panic!("error opening file {}: {}", path, e); + } + }; + + let mut add = Vec::new(); + + for module in doc.modules() { + for func in module.funcs() { + let name = func.name.as_str(); + let name_ident = Ident::new(func.name.as_str(), Span::call_site()); + + let mut shim_arg_decls = Vec::new(); + let mut params = Vec::new(); + let mut formats = Vec::new(); + let mut format_args = Vec::new(); + let mut hostcall_args = Vec::new(); + + for param in func.params.iter() { + let name = format_ident!( + "{}", + match param.name.as_str() { + "in" | "type" => format!("r#{}", param.name.as_str()), + s => s.to_string(), + } + ); + + // Registers a new parameter to the shim we're making with the + // given `name`, the `abi_ty` wasm type and `hex` defines + // whether it's debug-printed in a hex format or not. + // + // This will register a whole bunch of things: + // + // * The cranelift type for the parameter + // * Syntax to specify the actual function parameter + // * How to log the parameter value in a call to `trace!` + // * How to actually pass this argument to the host + // implementation, converting as necessary. + let mut add_param = |name: &Ident, abi_ty: Abi, hex: bool| { + match abi_ty { + Abi::I32 => { + params.push(quote! { types::I32 }); + shim_arg_decls.push(quote! { #name: i32 }); + } + Abi::I64 => { + params.push(quote! { types::I64 }); + shim_arg_decls.push(quote! { #name: i64 }); + } + Abi::F32 => { + params.push(quote! { types::F32 }); + shim_arg_decls.push(quote! { #name: f32 }); + } + Abi::F64 => { + params.push(quote! { types::F64 }); + shim_arg_decls.push(quote! { #name: f64 }); + } + } + formats.push(format!("{}={}", name, if hex { "{:#x}" } else { "{}" },)); + format_args.push(name.clone()); + hostcall_args.push(quote! { #name as _ }); + }; + + match &*param.tref.type_() { + witx::Type::Enum(e) => match e.repr { + witx::IntRepr::U64 => add_param(&name, Abi::I64, false), + _ => add_param(&name, Abi::I32, false), + }, + + witx::Type::Flags(f) => match f.repr { + witx::IntRepr::U64 => add_param(&name, Abi::I64, true), + _ => add_param(&name, Abi::I32, true), + }, + + witx::Type::Builtin(witx::BuiltinType::S8) + | witx::Type::Builtin(witx::BuiltinType::U8) + | witx::Type::Builtin(witx::BuiltinType::S16) + | witx::Type::Builtin(witx::BuiltinType::U16) + | witx::Type::Builtin(witx::BuiltinType::S32) + | witx::Type::Builtin(witx::BuiltinType::U32) => { + add_param(&name, Abi::I32, false); + } + + witx::Type::Builtin(witx::BuiltinType::S64) + | witx::Type::Builtin(witx::BuiltinType::U64) => { + add_param(&name, Abi::I64, false); + } + + witx::Type::Builtin(witx::BuiltinType::F32) => { + add_param(&name, Abi::F32, false); + } + + witx::Type::Builtin(witx::BuiltinType::F64) => { + add_param(&name, Abi::F64, false); + } + + // strings/arrays have an extra ABI parameter for the length + // of the array passed. + witx::Type::Builtin(witx::BuiltinType::String) | witx::Type::Array(_) => { + add_param(&name, Abi::I32, true); + let len = format_ident!("{}_len", name); + add_param(&len, Abi::I32, false); + } + + witx::Type::ConstPointer(_) + | witx::Type::Handle(_) + | witx::Type::Pointer(_) => { + add_param(&name, Abi::I32, true); + } + + witx::Type::Struct(_) | witx::Type::Union(_) => { + panic!("unsupported argument type") + } + } + } + + let mut results = func.results.iter(); + let mut ret_ty = quote! { () }; + let mut cvt_ret = quote! {}; + let mut returns = Vec::new(); + let mut handle_early_error = quote! { panic!("error: {:?}", e) }; + + // The first result is returned bare right now... + if let Some(ret) = results.next() { + handle_early_error = quote! { return e.into() }; + match &*ret.tref.type_() { + // Eventually we'll want to add support for more returned + // types, but for now let's just conform to what `*.witx` + // definitions currently use. + witx::Type::Enum(e) => match e.repr { + witx::IntRepr::U16 => { + returns.push(quote! { types::I32 }); + ret_ty = quote! { i32 }; + cvt_ret = quote! { .into() } + } + other => panic!("unsupported ret enum repr {:?}", other), + }, + other => panic!("unsupported first return {:?}", other), + } + } + + // ... and all remaining results are returned via out-poiners + for result in results { + let name = format_ident!("{}", result.name.as_str()); + params.push(quote! { types::I32 }); + shim_arg_decls.push(quote! { #name: i32 }); + formats.push(format!("{}={{:#x}}", name)); + format_args.push(name.clone()); + hostcall_args.push(quote! { #name as u32 }); + } + + let format_str = format!("{}({})", name, formats.join(", ")); + add.push(quote! { + let sig = module.signatures.push(translate_signature( + ir::Signature { + params: vec![#(cranelift_codegen::ir::AbiParam::new(#params)),*], + returns: vec![#(cranelift_codegen::ir::AbiParam::new(#returns)),*], + call_conv, + }, + pointer_type, + )); + let func = module.functions.push(sig); + module + .exports + .insert(#name.to_owned(), Export::Function(func)); + + unsafe extern "C" fn #name_ident( + ctx: *mut wasmtime_runtime::VMContext, + #(#shim_arg_decls),* + ) -> #ret_ty { + log::trace!( + #format_str, + #(#format_args),* + ); + let wasi_ctx = match get_wasi_ctx(&mut *ctx) { + Ok(e) => e, + Err(e) => #handle_early_error, + }; + let memory = match get_memory(&mut *ctx) { + Ok(e) => e, + Err(e) => #handle_early_error, + }; + wasi_common::hostcalls::#name_ident( + wasi_ctx, + memory, + #(#hostcall_args),* + ) #cvt_ret + } + finished_functions.push(#name_ident as *const _); + }); + } + } + + quote! { + pub fn add_wrappers_to_module( + module: &mut Module, + finished_functions: &mut PrimaryMap, + call_conv: isa::CallConv, + pointer_type: types::Type, + ) { + #(#add)* + } + } +} diff --git a/crates/wasi/Cargo.toml b/crates/wasi/Cargo.toml index d35b6994ac..5dd272911d 100644 --- a/crates/wasi/Cargo.toml +++ b/crates/wasi/Cargo.toml @@ -21,6 +21,7 @@ cranelift-entity = { version = "0.50.0", features = ["enable-serde"] } cranelift-wasm = { version = "0.50.0", features = ["enable-serde"] } target-lexicon = "0.9.0" log = { version = "0.4.8", default-features = false } +wig = { path = "../wasi-common/wig" } [badges] maintenance = { status = "actively-developed" } diff --git a/crates/wasi/src/instantiate.rs b/crates/wasi/src/instantiate.rs index 15a6d54377..79d103953f 100644 --- a/crates/wasi/src/instantiate.rs +++ b/crates/wasi/src/instantiate.rs @@ -1,4 +1,3 @@ -use super::syscalls; use cranelift_codegen::ir::types; use cranelift_codegen::{ir, isa}; use cranelift_entity::PrimaryMap; @@ -8,9 +7,10 @@ use std::collections::HashMap; use std::fs::File; use std::rc::Rc; use target_lexicon::HOST; +use wasi_common::wasi; use wasi_common::{WasiCtx, WasiCtxBuilder}; use wasmtime_environ::{translate_signature, Export, Module}; -use wasmtime_runtime::{Imports, InstanceHandle, InstantiationError, VMFunctionBody}; +use wasmtime_runtime::{Imports, InstanceHandle, InstantiationError, VMContext}; /// Creates `wasmtime::Instance` object implementing the "wasi" interface. pub fn create_wasi_instance( @@ -64,79 +64,19 @@ pub fn instantiate_wasi_with_context( ) -> Result { let pointer_type = types::Type::triple_pointer_type(&HOST); let mut module = Module::new(); - let mut finished_functions: PrimaryMap = - PrimaryMap::new(); + let mut finished_functions = PrimaryMap::new(); let call_conv = isa::CallConv::triple_default(&HOST); - macro_rules! signature { - ($name:ident) => {{ - let sig = module.signatures.push(translate_signature( - ir::Signature { - params: syscalls::$name::params() - .into_iter() - .map(ir::AbiParam::new) - .collect(), - returns: syscalls::$name::results() - .into_iter() - .map(ir::AbiParam::new) - .collect(), - call_conv, - }, - pointer_type, - )); - let func = module.functions.push(sig); - module - .exports - .insert(stringify!($name).to_owned(), Export::Function(func)); - finished_functions.push(syscalls::$name::SHIM as *const VMFunctionBody); - }}; - } - - signature!(args_get); - signature!(args_sizes_get); - signature!(clock_res_get); - signature!(clock_time_get); - signature!(environ_get); - signature!(environ_sizes_get); - signature!(fd_prestat_get); - signature!(fd_prestat_dir_name); - signature!(fd_close); - signature!(fd_datasync); - signature!(fd_pread); - signature!(fd_pwrite); - signature!(fd_read); - signature!(fd_renumber); - signature!(fd_seek); - signature!(fd_tell); - signature!(fd_fdstat_get); - signature!(fd_fdstat_set_flags); - signature!(fd_fdstat_set_rights); - signature!(fd_sync); - signature!(fd_write); - signature!(fd_advise); - signature!(fd_allocate); - signature!(path_create_directory); - signature!(path_link); - signature!(path_open); - signature!(fd_readdir); - signature!(path_readlink); - signature!(path_rename); - signature!(fd_filestat_get); - signature!(fd_filestat_set_times); - signature!(fd_filestat_set_size); - signature!(path_filestat_get); - signature!(path_filestat_set_times); - signature!(path_symlink); - signature!(path_unlink_file); - signature!(path_remove_directory); - signature!(poll_oneoff); - signature!(proc_exit); - signature!(proc_raise); - signature!(random_get); - signature!(sched_yield); - signature!(sock_recv); - signature!(sock_send); - signature!(sock_shutdown); + // This function is defined in the macro invocation of + // `define_add_wrappers_to_module` below. For more information about how + // this works it'd recommended to read the source in + // `crates/wasi-common/wig/src/wasi.rs`. + add_wrappers_to_module( + &mut module, + &mut finished_functions, + call_conv, + pointer_type, + ); let imports = Imports::none(); let data_initializers = Vec::new(); @@ -153,3 +93,40 @@ pub fn instantiate_wasi_with_context( Box::new(wasi_ctx), ) } + +wig::define_add_wrappers_to_module!( + "snapshot" "wasi_snapshot_preview1" +); + +// Used by `add_wrappers_to_module` defined in the macro above +fn get_wasi_ctx(vmctx: &mut VMContext) -> Result<&mut WasiCtx, wasi::__wasi_errno_t> { + unsafe { + vmctx + .host_state() + .downcast_mut::() + .ok_or_else(|| panic!("no host state named WasiCtx available")) + } +} + +// Used by `add_wrappers_to_module` defined in the macro above +fn get_memory(vmctx: &mut VMContext) -> Result<&mut [u8], wasi::__wasi_errno_t> { + unsafe { + match vmctx.lookup_global_export("memory") { + Some(wasmtime_runtime::Export::Memory { + definition, + vmctx: _, + memory: _, + }) => Ok(std::slice::from_raw_parts_mut( + (*definition).base, + (*definition).current_length, + )), + x => { + log::error!( + "no export named \"memory\", or the export isn't a mem: {:?}", + x + ); + Err(wasi::__WASI_ERRNO_INVAL) + } + } + } +} diff --git a/crates/wasi/src/lib.rs b/crates/wasi/src/lib.rs index b8452d3b64..c152b34132 100644 --- a/crates/wasi/src/lib.rs +++ b/crates/wasi/src/lib.rs @@ -2,7 +2,6 @@ mod instantiate; pub mod old; -mod syscalls; pub use instantiate::{create_wasi_instance, instantiate_wasi, instantiate_wasi_with_context}; diff --git a/crates/wasi/src/syscalls.rs b/crates/wasi/src/syscalls.rs deleted file mode 100644 index e8f80be244..0000000000 --- a/crates/wasi/src/syscalls.rs +++ /dev/null @@ -1,977 +0,0 @@ -use cranelift_codegen::ir::types::{Type, I32, I64}; -use log::{error, trace}; -use wasi_common::{hostcalls, wasi, wasi32, WasiCtx}; -use wasmtime_runtime::{Export, VMContext}; - -pub trait AbiRet { - type Abi; - fn convert(self) -> Self::Abi; - fn codegen_tys() -> Vec; -} - -pub trait AbiParam { - type Abi; - fn convert(arg: Self::Abi) -> Self; - fn codegen_ty() -> Type; -} - -macro_rules! cast32 { - ($($i:ident)*) => ($( - impl AbiRet for $i { - type Abi = i32; - - fn convert(self) -> Self::Abi { - self as i32 - } - - fn codegen_tys() -> Vec { vec![I32] } - } - - impl AbiParam for $i { - type Abi = i32; - - fn convert(param: i32) -> Self { - param as $i - } - - fn codegen_ty() -> Type { I32 } - } - )*) -} - -macro_rules! cast64 { - ($($i:ident)*) => ($( - impl AbiRet for $i { - type Abi = i64; - - fn convert(self) -> Self::Abi { - self as i64 - } - - fn codegen_tys() -> Vec { vec![I64] } - } - - impl AbiParam for $i { - type Abi = i64; - - fn convert(param: i64) -> Self { - param as $i - } - - fn codegen_ty() -> Type { I64 } - } - )*) -} - -cast32!(i8 i16 i32 u8 u16 u32); -cast64!(i64 u64); - -impl AbiRet for () { - type Abi = (); - fn convert(self) {} - fn codegen_tys() -> Vec { - Vec::new() - } -} - -fn get_wasi_ctx(vmctx: &mut VMContext) -> Result<&mut WasiCtx, wasi::__wasi_errno_t> { - unsafe { - vmctx - .host_state() - .downcast_mut::() - .ok_or_else(|| panic!("no host state named WasiCtx available")) - } -} - -fn get_memory(vmctx: &mut VMContext) -> Result<&mut [u8], wasi::__wasi_errno_t> { - unsafe { - match vmctx.lookup_global_export("memory") { - Some(Export::Memory { - definition, - vmctx: _, - memory: _, - }) => Ok(std::slice::from_raw_parts_mut( - (*definition).base, - (*definition).current_length, - )), - x => { - error!( - "no export named \"memory\", or the export isn't a mem: {:?}", - x - ); - Err(wasi::__WASI_ERRNO_INVAL) - } - } - } -} - -macro_rules! ok_or_errno { - ($expr:expr) => { - match $expr { - Ok(v) => v, - Err(e) => { - trace!(" -> errno={}", wasi::strerror(e)); - return e; - } - } - }; -} - -macro_rules! syscalls { - ($(pub unsafe extern "C" fn $name:ident($ctx:ident: *mut VMContext $(, $arg:ident: $ty:ty)*,) -> $ret:ty { - $($body:tt)* - })*) => ($( - pub mod $name { - use super::*; - - /// Returns the codegen types of all the parameters to the shim - /// generated - pub fn params() -> Vec { - vec![$(<$ty as AbiParam>::codegen_ty()),*] - } - - /// Returns the codegen types of all the results of the shim - /// generated - pub fn results() -> Vec { - <$ret as AbiRet>::codegen_tys() - } - - /// The actual function pointer to the shim for a syscall. - /// - /// NB: ideally we'd expose `shim` below, but it seems like there's - /// a compiler bug which prvents that from being cast to a `usize`. - pub static SHIM: unsafe extern "C" fn( - *mut VMContext, - $(<$ty as AbiParam>::Abi),* - ) -> <$ret as AbiRet>::Abi = shim; - - unsafe extern "C" fn shim( - $ctx: *mut VMContext, - $($arg: <$ty as AbiParam>::Abi,)* - ) -> <$ret as AbiRet>::Abi { - let r = super::$name($ctx, $(<$ty as AbiParam>::convert($arg),)*); - <$ret as AbiRet>::convert(r) - } - } - - pub unsafe extern "C" fn $name($ctx: *mut VMContext, $($arg: $ty,)*) -> $ret { - $($body)* - } - )*) -} - -syscalls! { - pub unsafe extern "C" fn args_get( - vmctx: *mut VMContext, - argv: wasi32::uintptr_t, - argv_buf: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "args_get(argv={:#x?}, argv_buf={:#x?})", - argv, - argv_buf, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::args_get(wasi_ctx, memory, argv, argv_buf) - } - - pub unsafe extern "C" fn args_sizes_get( - vmctx: *mut VMContext, - argc: wasi32::uintptr_t, - argv_buf_size: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "args_sizes_get(argc={:#x?}, argv_buf_size={:#x?})", - argc, - argv_buf_size, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::args_sizes_get(wasi_ctx, memory, argc, argv_buf_size) - } - - pub unsafe extern "C" fn clock_res_get( - vmctx: *mut VMContext, - clock_id: wasi::__wasi_clockid_t, - resolution: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "clock_res_get(clock_id={:?}, resolution={:#x?})", - clock_id, - resolution, - ); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::clock_res_get(memory, clock_id, resolution) - } - - pub unsafe extern "C" fn clock_time_get( - vmctx: *mut VMContext, - clock_id: wasi::__wasi_clockid_t, - precision: wasi::__wasi_timestamp_t, - time: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "clock_time_get(clock_id={:?}, precision={:?}, time={:#x?})", - clock_id, - precision, - time, - ); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::clock_time_get(memory, clock_id, precision, time) - } - - pub unsafe extern "C" fn environ_get( - vmctx: *mut VMContext, - environ: wasi32::uintptr_t, - environ_buf: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "environ_get(environ={:#x?}, environ_buf={:#x?})", - environ, - environ_buf, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::environ_get(wasi_ctx, memory, environ, environ_buf) - } - - pub unsafe extern "C" fn environ_sizes_get( - vmctx: *mut VMContext, - environ_count: wasi32::uintptr_t, - environ_buf_size: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "environ_sizes_get(environ_count={:#x?}, environ_buf_size={:#x?})", - environ_count, - environ_buf_size, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::environ_sizes_get(wasi_ctx, memory, environ_count, environ_buf_size) - } - - pub unsafe extern "C" fn fd_prestat_get( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - buf: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_prestat_get(fd={:?}, buf={:#x?})", fd, buf); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_prestat_get(wasi_ctx, memory, fd, buf) - } - - pub unsafe extern "C" fn fd_prestat_dir_name( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_prestat_dir_name(fd={:?}, path={:#x?}, path_len={})", fd, path, path_len); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_prestat_dir_name(wasi_ctx, memory, fd, path, path_len) - } - - pub unsafe extern "C" fn fd_close( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_close(fd={:?})", fd); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_close(wasi_ctx, fd) - } - - pub unsafe extern "C" fn fd_datasync( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_datasync(fd={:?})", fd); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_datasync(wasi_ctx, fd) - } - - pub unsafe extern "C" fn fd_pread( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - iovs: wasi32::uintptr_t, - iovs_len: wasi32::size_t, - offset: wasi::__wasi_filesize_t, - nread: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_pread(fd={:?}, iovs={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})", - fd, - iovs, - iovs_len, - offset, - nread - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_pread( - wasi_ctx, - memory, - fd, - iovs, - iovs_len, - offset, - nread - ) - } - - pub unsafe extern "C" fn fd_pwrite( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - iovs: wasi32::uintptr_t, - iovs_len: wasi32::size_t, - offset: wasi::__wasi_filesize_t, - nwritten: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_pwrite(fd={:?}, iovs={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})", - fd, - iovs, - iovs_len, - offset, - nwritten - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_pwrite( - wasi_ctx, - memory, - fd, - iovs, - iovs_len, - offset, - nwritten - ) - } - - pub unsafe extern "C" fn fd_read( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - iovs: wasi32::uintptr_t, - iovs_len: wasi32::size_t, - nread: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_read(fd={:?}, iovs={:#x?}, iovs_len={:?}, nread={:#x?})", - fd, - iovs, - iovs_len, - nread - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_read(wasi_ctx, memory, fd, iovs, iovs_len, nread) - } - - pub unsafe extern "C" fn fd_renumber( - vmctx: *mut VMContext, - from: wasi::__wasi_fd_t, - to: wasi::__wasi_fd_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_renumber(from={:?}, to={:?})", from, to); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_renumber(wasi_ctx, from, to) - } - - pub unsafe extern "C" fn fd_seek( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - offset: wasi::__wasi_filedelta_t, - whence: wasi::__wasi_whence_t, - newoffset: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})", - fd, - offset, - wasi::whence_to_str(whence), - newoffset - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_seek(wasi_ctx, memory, fd, offset, whence, newoffset) - } - - pub unsafe extern "C" fn fd_tell( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - newoffset: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_tell(wasi_ctx, memory, fd, newoffset) - } - - pub unsafe extern "C" fn fd_fdstat_get( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - buf: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_fdstat_get(fd={:?}, buf={:#x?})", fd, buf); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_fdstat_get(wasi_ctx, memory, fd, buf) - } - - pub unsafe extern "C" fn fd_fdstat_set_flags( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - flags: wasi::__wasi_fdflags_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_fdstat_set_flags(fd={:?}, flags={:#x?})", - fd, - flags - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_fdstat_set_flags(wasi_ctx, fd, flags) - } - - pub unsafe extern "C" fn fd_fdstat_set_rights( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - fs_rights_base: wasi::__wasi_rights_t, - fs_rights_inheriting: wasi::__wasi_rights_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})", - fd, - fs_rights_base, - fs_rights_inheriting - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_fdstat_set_rights( - wasi_ctx, - fd, - fs_rights_base, - fs_rights_inheriting - ) - } - - pub unsafe extern "C" fn fd_sync( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_sync(fd={:?})", fd); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_sync(wasi_ctx, fd) - } - - pub unsafe extern "C" fn fd_write( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - iovs: wasi32::uintptr_t, - iovs_len: wasi32::size_t, - nwritten: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_write(fd={:?}, iovs={:#x?}, iovs_len={:?}, nwritten={:#x?})", - fd, - iovs, - iovs_len, - nwritten - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_write(wasi_ctx, memory, fd, iovs, iovs_len, nwritten) - } - - pub unsafe extern "C" fn fd_advise( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - offset: wasi::__wasi_filesize_t, - len: wasi::__wasi_filesize_t, - advice: wasi::__wasi_advice_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_advise(fd={:?}, offset={}, len={}, advice={:?})", - fd, - offset, - len, - advice - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_advise(wasi_ctx, fd, offset, len, advice) - } - - pub unsafe extern "C" fn fd_allocate( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - offset: wasi::__wasi_filesize_t, - len: wasi::__wasi_filesize_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_allocate(wasi_ctx, fd, offset, len) - } - - pub unsafe extern "C" fn path_create_directory( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_create_directory(fd={:?}, path={:#x?}, path_len={})", - fd, - path, - path_len, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_create_directory(wasi_ctx, memory, fd, path, path_len) - } - - pub unsafe extern "C" fn path_link( - vmctx: *mut VMContext, - fd0: wasi::__wasi_fd_t, - flags0: wasi::__wasi_lookupflags_t, - path0: wasi32::uintptr_t, - path_len0: wasi32::size_t, - fd1: wasi::__wasi_fd_t, - path1: wasi32::uintptr_t, - path_len1: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_link(fd0={:?}, flags0={:?}, path0={:#x?}, path_len0={}, fd1={:?}, path1={:#x?}, path_len1={})", - fd0, - flags0, - path0, - path_len0, - fd1, - path1, - path_len1 - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_link( - wasi_ctx, - memory, - fd0, - flags0, - path0, - path_len0, - fd1, - path1, - path_len1 - ) - } - - // TODO: When multi-value happens, switch to that instead of passing - // the `fd` by reference? - pub unsafe extern "C" fn path_open( - vmctx: *mut VMContext, - dirfd: wasi::__wasi_fd_t, - dirflags: wasi::__wasi_lookupflags_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - oflags: wasi::__wasi_oflags_t, - fs_rights_base: wasi::__wasi_rights_t, - fs_rights_inheriting: wasi::__wasi_rights_t, - fs_flags: wasi::__wasi_fdflags_t, - fd: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_open(dirfd={:?}, dirflags={:?}, path={:#x?}, path_len={:?}, oflags={:#x?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?}, fs_flags={:#x?}, fd={:#x?})", - dirfd, - dirflags, - path, - path_len, - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - fd - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_open( - wasi_ctx, - memory, - dirfd, - dirflags, - path, - path_len, - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - fd - ) - } - - pub unsafe extern "C" fn fd_readdir( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - buf: wasi32::uintptr_t, - buf_len: wasi32::size_t, - cookie: wasi::__wasi_dircookie_t, - buf_used: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})", - fd, - buf, - buf_len, - cookie, - buf_used, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_readdir( - wasi_ctx, - memory, - fd, - buf, - buf_len, - cookie, - buf_used - ) - } - - pub unsafe extern "C" fn path_readlink( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - buf: wasi32::uintptr_t, - buf_len: wasi32::size_t, - buf_used: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_readlink(fd={:?}, path={:#x?}, path_len={:?}, buf={:#x?}, buf_len={}, buf_used={:#x?})", - fd, - path, - path_len, - buf, - buf_len, - buf_used, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_readlink( - wasi_ctx, - memory, - fd, - path, - path_len, - buf, - buf_len, - buf_used - ) - } - - pub unsafe extern "C" fn path_rename( - vmctx: *mut VMContext, - fd0: wasi::__wasi_fd_t, - path0: wasi32::uintptr_t, - path_len0: wasi32::size_t, - fd1: wasi::__wasi_fd_t, - path1: wasi32::uintptr_t, - path_len1: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_rename(fd0={:?}, path0={:#x?}, path_len0={:?}, fd1={:?}, path1={:#x?}, path_len1={:?})", - fd0, - path0, - path_len0, - fd1, - path1, - path_len1, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_rename( - wasi_ctx, - memory, - fd0, - path0, - path_len0, - fd1, - path1, - path_len1 - ) - } - - pub unsafe extern "C" fn fd_filestat_get( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - buf: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!("fd_filestat_get(fd={:?}, buf={:#x?})", fd, buf); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::fd_filestat_get(wasi_ctx, memory, fd, buf) - } - - pub unsafe extern "C" fn fd_filestat_set_times( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - st_atim: wasi::__wasi_timestamp_t, - st_mtim: wasi::__wasi_timestamp_t, - fstflags: wasi::__wasi_fstflags_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fstflags={:#x?})", - fd, - st_atim, st_mtim, - fstflags - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_filestat_set_times(wasi_ctx, fd, st_atim, st_mtim, fstflags) - } - - pub unsafe extern "C" fn fd_filestat_set_size( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - size: wasi::__wasi_filesize_t, - ) -> wasi::__wasi_errno_t { - trace!( - "fd_filestat_set_size(fd={:?}, size={})", - fd, - size - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - hostcalls::fd_filestat_set_size(wasi_ctx, fd, size) - } - - pub unsafe extern "C" fn path_filestat_get( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - flags: wasi::__wasi_lookupflags_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - buf: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_filestat_get(fd={:?}, flags={:?}, path={:#x?}, path_len={}, buf={:#x?})", - fd, - flags, - path, - path_len, - buf - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_filestat_get(wasi_ctx, memory, fd, flags, path, path_len, buf) - } - - pub unsafe extern "C" fn path_filestat_set_times( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - flags: wasi::__wasi_lookupflags_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - st_atim: wasi::__wasi_timestamp_t, - st_mtim: wasi::__wasi_timestamp_t, - fstflags: wasi::__wasi_fstflags_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_filestat_set_times(fd={:?}, flags={:?}, path={:#x?}, path_len={}, st_atim={}, st_mtim={}, fstflags={:#x?})", - fd, - flags, - path, - path_len, - st_atim, st_mtim, - fstflags - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_filestat_set_times( - wasi_ctx, - memory, - fd, - flags, - path, - path_len, - st_atim, - st_mtim, - fstflags - ) - } - - pub unsafe extern "C" fn path_symlink( - vmctx: *mut VMContext, - path0: wasi32::uintptr_t, - path_len0: wasi32::size_t, - fd: wasi::__wasi_fd_t, - path1: wasi32::uintptr_t, - path_len1: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_symlink(path0={:#x?}, path_len0={}, fd={:?}, path1={:#x?}, path_len1={})", - path0, - path_len0, - fd, - path1, - path_len1 - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_symlink( - wasi_ctx, - memory, - path0, - path_len0, - fd, - path1, - path_len1 - ) - } - - pub unsafe extern "C" fn path_unlink_file( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_unlink_file(fd={:?}, path={:#x?}, path_len={})", - fd, - path, - path_len - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_unlink_file(wasi_ctx, memory, fd, path, path_len) - } - - pub unsafe extern "C" fn path_remove_directory( - vmctx: *mut VMContext, - fd: wasi::__wasi_fd_t, - path: wasi32::uintptr_t, - path_len: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!( - "path_remove_directory(fd={:?}, path={:#x?}, path_len={})", - fd, - path, - path_len - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::path_remove_directory(wasi_ctx, memory, fd, path, path_len) - } - - pub unsafe extern "C" fn poll_oneoff( - vmctx: *mut VMContext, - in_: wasi32::uintptr_t, - out: wasi32::uintptr_t, - nsubscriptions: wasi32::size_t, - nevents: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "poll_oneoff(in={:#x?}, out={:#x?}, nsubscriptions={}, nevents={:#x?})", - in_, - out, - nsubscriptions, - nevents, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::poll_oneoff(wasi_ctx, memory, in_, out, nsubscriptions, nevents) - } - - pub unsafe extern "C" fn proc_exit(_vmctx: *mut VMContext, rval: u32,) -> () { - trace!("proc_exit(rval={:?})", rval); - hostcalls::proc_exit(rval) - } - - pub unsafe extern "C" fn proc_raise( - vmctx: *mut VMContext, - sig: wasi::__wasi_signal_t, - ) -> wasi::__wasi_errno_t { - trace!("proc_raise(sig={:?})", sig); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::proc_raise(wasi_ctx, memory, sig) - } - - pub unsafe extern "C" fn random_get( - vmctx: *mut VMContext, - buf: wasi32::uintptr_t, - buf_len: wasi32::size_t, - ) -> wasi::__wasi_errno_t { - trace!("random_get(buf={:#x?}, buf_len={:?})", buf, buf_len); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::random_get(memory, buf, buf_len) - } - - pub unsafe extern "C" fn sched_yield(_vmctx: *mut VMContext,) -> wasi::__wasi_errno_t { - trace!("sched_yield(void)"); - hostcalls::sched_yield() - } - - pub unsafe extern "C" fn sock_recv( - vmctx: *mut VMContext, - sock: wasi::__wasi_fd_t, - ri_data: wasi32::uintptr_t, - ri_data_len: wasi32::size_t, - ri_flags: wasi::__wasi_riflags_t, - ro_datalen: wasi32::uintptr_t, - ro_flags: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "sock_recv(sock={:?}, ri_data={:#x?}, ri_data_len={}, ri_flags={:#x?}, ro_datalen={:#x?}, ro_flags={:#x?})", - sock, - ri_data, ri_data_len, ri_flags, - ro_datalen, ro_flags - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::sock_recv( - wasi_ctx, - memory, - sock, - ri_data, - ri_data_len, - ri_flags, - ro_datalen, - ro_flags - ) - } - - pub unsafe extern "C" fn sock_send( - vmctx: *mut VMContext, - sock: wasi::__wasi_fd_t, - si_data: wasi32::uintptr_t, - si_data_len: wasi32::size_t, - si_flags: wasi::__wasi_siflags_t, - so_datalen: wasi32::uintptr_t, - ) -> wasi::__wasi_errno_t { - trace!( - "sock_send(sock={:?}, si_data={:#x?}, si_data_len={}, si_flags={:#x?}, so_datalen={:#x?})", - sock, - si_data, si_data_len, si_flags, so_datalen, - ); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::sock_send( - wasi_ctx, - memory, - sock, - si_data, - si_data_len, - si_flags, - so_datalen - ) - } - - pub unsafe extern "C" fn sock_shutdown( - vmctx: *mut VMContext, - sock: wasi::__wasi_fd_t, - how: wasi::__wasi_sdflags_t, - ) -> wasi::__wasi_errno_t { - trace!("sock_shutdown(sock={:?}, how={:?})", sock, how); - let wasi_ctx = ok_or_errno!(get_wasi_ctx(&mut *vmctx)); - let memory = ok_or_errno!(get_memory(&mut *vmctx)); - hostcalls::sock_shutdown(wasi_ctx, memory, sock, how) - } -}