diff --git a/Cargo.lock b/Cargo.lock index f402f5aef9c2..5675a0971b60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3496,18 +3496,18 @@ dependencies = [ [[package]] name = "wast" -version = "22.0.0" +version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe1220ed7f824992b426a76125a3403d048eaf0f627918e97ade0d9b9d510d20" +checksum = "c24a3ee360d01d60ed0a0f960ab76a6acce64348cdb0bf8699c2a866fad57c7c" dependencies = [ "leb128", ] [[package]] name = "wast" -version = "32.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c24a3ee360d01d60ed0a0f960ab76a6acce64348cdb0bf8699c2a866fad57c7c" +checksum = "1d04fe175c7f78214971293e7d8875673804e736092206a3a4544dbc12811c1b" dependencies = [ "leb128", ] @@ -3631,15 +3631,16 @@ dependencies = [ [[package]] name = "witx" -version = "0.8.8" +version = "0.9.0" dependencies = [ "anyhow", "diff", "log", "pretty_env_logger", + "rayon", "structopt", "thiserror", - "wast 22.0.0", + "wast 33.0.0", ] [[package]] diff --git a/crates/wasi-common/WASI b/crates/wasi-common/WASI index 8deb71ddd095..ef8c1a53feb2 160000 --- a/crates/wasi-common/WASI +++ b/crates/wasi-common/WASI @@ -1 +1 @@ -Subproject commit 8deb71ddd0955101cb69333b08284e7b01775928 +Subproject commit ef8c1a53feb2dfb763d4ea5c7d9e0a0126b45579 diff --git a/crates/wasi-crypto/spec b/crates/wasi-crypto/spec index 6d7821dec301..1f3078088bd0 160000 --- a/crates/wasi-crypto/spec +++ b/crates/wasi-crypto/spec @@ -1 +1 @@ -Subproject commit 6d7821dec301a11dcf3c0d50e5a51af5169eaee3 +Subproject commit 1f3078088bd0de36a0bc96859a1724e7d338a832 diff --git a/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs b/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs index ea94966b3316..79cef9d68cb9 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs @@ -1,7 +1,9 @@ use super::{guest_types, WasiCryptoCtx}; use std::convert::TryInto; -use wasi_crypto::{ensure, CryptoError, KeyPairEncoding, PublicKeyEncoding, SecretKeyEncoding}; +use wasi_crypto::{ + ensure, CryptoError, KeyPairEncoding, PublicKeyEncoding, SecretKeyEncoding, Version, +}; impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetricCommon for WasiCryptoCtx @@ -57,7 +59,7 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr kp_old_handle.into(), kp_new_handle.into(), )? - .into()) + .0) } fn keypair_from_id( @@ -69,7 +71,7 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr ) -> Result { let kp_id = &*kp_id_ptr.as_array(kp_id_len).as_slice()?; Ok(self - .keypair_from_id(secrets_manager_handle.into(), kp_id, kp_version.into())? + .keypair_from_id(secrets_manager_handle.into(), kp_id, Version(kp_version))? .into()) } @@ -116,7 +118,7 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr let (kp_id, version) = self.keypair_id(kp_handle.into())?; ensure!(kp_id.len() <= kp_id_buf.len(), CryptoError::Overflow.into()); kp_id_buf.copy_from_slice(&kp_id); - Ok((kp_id.len().try_into()?, version.into())) + Ok((kp_id.len().try_into()?, version.0)) } fn keypair_export( diff --git a/crates/wasi-crypto/src/wiggle_interfaces/common.rs b/crates/wasi-crypto/src/wiggle_interfaces/common.rs index 25969df1c9e1..be7b49b30a54 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/common.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/common.rs @@ -111,7 +111,7 @@ impl super::wasi_ephemeral_crypto_common::WasiEphemeralCryptoCommon for WasiCryp Ok(self.secrets_manager_invalidate( secrets_manager_handle.into(), key_id, - key_version.into(), + Version(key_version), )?) } } @@ -125,15 +125,3 @@ impl From for AlgorithmType { } } } - -impl From for Version { - fn from(version: guest_types::Version) -> Self { - Version(version.into()) - } -} - -impl From for guest_types::Version { - fn from(version: Version) -> Self { - version.into() - } -} diff --git a/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs b/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs index b14abc34b3ec..89d33ce8ec67 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs @@ -1,7 +1,7 @@ use super::{guest_types, WasiCryptoCtx}; use std::convert::TryInto; -use wasi_crypto::{ensure, CryptoError}; +use wasi_crypto::{ensure, CryptoError, Version}; impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for WasiCryptoCtx { // --- secrets_manager @@ -55,7 +55,7 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa symmetric_key_old_handle.into(), symmetric_key_new_handle.into(), )? - .into()) + .0) } fn symmetric_key_from_id( @@ -72,7 +72,7 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa .symmetric_key_from_id( secrets_manager_handle.into(), symmetric_key_id, - symmetric_key_version.into(), + Version(symmetric_key_version), )? .into()) } @@ -129,7 +129,7 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa CryptoError::Overflow.into() ); key_id_buf.copy_from_slice(&key_id); - Ok((key_id.len().try_into()?, version.into())) + Ok((key_id.len().try_into()?, version.0)) } fn symmetric_key_close( diff --git a/crates/wasi-nn/spec b/crates/wasi-nn/spec index 793d4cd888ab..8adc5b9b3bb8 160000 --- a/crates/wasi-nn/spec +++ b/crates/wasi-nn/spec @@ -1 +1 @@ -Subproject commit 793d4cd888ab74e3b7bf018bcc6ab2a2426a1004 +Subproject commit 8adc5b9b3bb8f885d44f55b464718e24af892c94 diff --git a/crates/wasi-nn/src/impl.rs b/crates/wasi-nn/src/impl.rs index fb8e781dd183..e18caafdc2d6 100644 --- a/crates/wasi-nn/src/impl.rs +++ b/crates/wasi-nn/src/impl.rs @@ -12,7 +12,7 @@ use wiggle::GuestPtr; #[derive(Debug, Error)] pub enum UsageError { - #[error("Only OpenVINO's IR is currently supported, passed encoding: {0}")] + #[error("Only OpenVINO's IR is currently supported, passed encoding: {0:?}")] InvalidEncoding(GraphEncoding), #[error("OpenVINO expects only two buffers (i.e. [ir, weights]), passed: {0}")] InvalidNumberOfBuilders(u32), diff --git a/crates/wasi-nn/src/lib.rs b/crates/wasi-nn/src/lib.rs index 2e2c08b0376b..68999d9310d3 100644 --- a/crates/wasi-nn/src/lib.rs +++ b/crates/wasi-nn/src/lib.rs @@ -18,7 +18,6 @@ wasmtime_wiggle::wasmtime_integration!({ wasi_ephemeral_nn => { name: WasiNn, docs: "An instantiated instance of the wasi-nn exports.", - function_override: {} } }, }); diff --git a/crates/wasi-nn/src/witx.rs b/crates/wasi-nn/src/witx.rs index b686fcd0913e..011c173ad85f 100644 --- a/crates/wasi-nn/src/witx.rs +++ b/crates/wasi-nn/src/witx.rs @@ -6,23 +6,23 @@ use crate::ctx::WasiNnError; wiggle::from_witx!({ witx: ["$WASI_ROOT/phases/ephemeral/witx/wasi_ephemeral_nn.witx"], ctx: WasiNnCtx, - errors: { errno => WasiNnError } + errors: { nn_errno => WasiNnError } }); -use types::Errno; +use types::NnErrno; /// Wiggle generates code that performs some input validation on the arguments passed in by users of /// wasi-nn. Here we convert the validation error into one (or more, eventually) of the error /// variants defined in the witx. impl types::GuestErrorConversion for WasiNnCtx { - fn into_errno(&self, e: wiggle::GuestError) -> Errno { + fn into_nn_errno(&self, e: wiggle::GuestError) -> NnErrno { eprintln!("Guest error: {:?}", e); - Errno::InvalidArgument + NnErrno::InvalidArgument } } impl<'a> types::UserErrorConversion for WasiNnCtx { - fn errno_from_wasi_nn_error(&self, e: WasiNnError) -> Result { + fn nn_errno_from_wasi_nn_error(&self, e: WasiNnError) -> Result { eprintln!("Host error: {:?}", e); match e { WasiNnError::OpenvinoError(_) => unimplemented!(), @@ -33,7 +33,7 @@ impl<'a> types::UserErrorConversion for WasiNnCtx { } /// Additionally, we must let Wiggle know which of our error codes represents a successful operation. -impl wiggle::GuestErrorType for Errno { +impl wiggle::GuestErrorType for NnErrno { fn success() -> Self { Self::Success } diff --git a/crates/wiggle/Cargo.toml b/crates/wiggle/Cargo.toml index d7bba56082e3..88c8315bdce0 100644 --- a/crates/wiggle/Cargo.toml +++ b/crates/wiggle/Cargo.toml @@ -12,7 +12,7 @@ include = ["src/**/*", "LICENSE"] [dependencies] thiserror = "1" -witx = { path = "../wasi-common/WASI/tools/witx", version = "0.8.7", optional = true } +witx = { path = "../wasi-common/WASI/tools/witx", version = "0.9", optional = true } wiggle-macro = { path = "macro", version = "0.23.0" } tracing = "0.1.15" bitflags = "1.2" diff --git a/crates/wiggle/generate/Cargo.toml b/crates/wiggle/generate/Cargo.toml index 54cb70d20d9c..1a7459a519a5 100644 --- a/crates/wiggle/generate/Cargo.toml +++ b/crates/wiggle/generate/Cargo.toml @@ -14,7 +14,7 @@ include = ["src/**/*", "LICENSE"] [lib] [dependencies] -witx = { version = "0.8.7", path = "../../wasi-common/WASI/tools/witx" } +witx = { version = "0.9", path = "../../wasi-common/WASI/tools/witx" } quote = "1.0" proc-macro2 = "1.0" heck = "0.3" diff --git a/crates/wiggle/generate/src/error_transform.rs b/crates/wiggle/generate/src/error_transform.rs index 3598e221de3f..56fa10eaf0ad 100644 --- a/crates/wiggle/generate/src/error_transform.rs +++ b/crates/wiggle/generate/src/error_transform.rs @@ -49,10 +49,14 @@ impl ErrorTransform { pub fn for_abi_error(&self, tref: &TypeRef) -> Option<&UserErrorType> { match tref { - TypeRef::Name(nt) => self.m.iter().find(|u| u.abi_type.name == nt.name), + TypeRef::Name(nt) => self.for_name(nt), TypeRef::Value { .. } => None, } } + + pub fn for_name(&self, nt: &NamedType) -> Option<&UserErrorType> { + self.m.iter().find(|u| u.abi_type.name == nt.name) + } } pub struct UserErrorType { diff --git a/crates/wiggle/generate/src/funcs.rs b/crates/wiggle/generate/src/funcs.rs index 50f5eec64044..187178e8b6f7 100644 --- a/crates/wiggle/generate/src/funcs.rs +++ b/crates/wiggle/generate/src/funcs.rs @@ -1,11 +1,12 @@ -use proc_macro2::TokenStream; -use quote::quote; - use crate::error_transform::ErrorTransform; use crate::lifetimes::anon_lifetime; use crate::module_trait::passed_by_reference; use crate::names::Names; use crate::types::WiggleType; +use proc_macro2::{Ident, Span, TokenStream}; +use quote::quote; +use std::mem; +use witx::Instruction; pub fn define_func( names: &Names, @@ -13,178 +14,55 @@ pub fn define_func( func: &witx::InterfaceFunc, errxform: &ErrorTransform, ) -> TokenStream { - let funcname = func.name.as_str(); - - let ident = names.func(&func.name); let rt = names.runtime_mod(); + let ident = names.func(&func.name); let ctx_type = names.ctx_type(); - let coretype = func.core_type(); - let params = coretype.args.iter().map(|arg| { - let name = names.func_core_arg(arg); - let atom = names.atom_type(arg.repr()); - quote!(#name : #atom) + let (wasm_params, wasm_results) = func.wasm_signature(); + let param_names = (0..wasm_params.len()) + .map(|i| Ident::new(&format!("arg{}", i), Span::call_site())) + .collect::>(); + let abi_params = wasm_params.iter().zip(¶m_names).map(|(arg, name)| { + let wasm = names.wasm_type(*arg); + quote!(#name : #wasm) }); - let abi_args = quote!( - ctx: &#ctx_type, - memory: &dyn #rt::GuestMemory, - #(#params),* - ); - let abi_ret = if let Some(ret) = &coretype.ret { - match ret.signifies { - witx::CoreParamSignifies::Value(atom) => names.atom_type(atom), - _ => unreachable!("ret should always be passed by value"), + let abi_ret = match wasm_results.len() { + 0 => quote!(()), + 1 => { + let ty = names.wasm_type(wasm_results[0]); + quote!(#ty) } - } else { - quote!(()) + _ => unimplemented!(), }; - let err_type = coretype.ret.clone().map(|ret| ret.param.tref); - let ret_err = coretype - .ret - .map(|ret| { - let name = names.func_param(&ret.param.name); - let conversion = if let Some(user_err) = errxform.for_abi_error(&ret.param.tref) { - let method = names.user_error_conversion_method(&user_err); - quote!(UserErrorConversion::#method(ctx, e)) - } else { - quote!(Ok(e)) - }; - quote! { - let e = #conversion; - #rt::tracing::event!( - #rt::tracing::Level::TRACE, - #name = #rt::tracing::field::debug(&e), - ); - match e { - Ok(e) => { return Ok(#abi_ret::from(e)); }, - Err(e) => { return Err(e); }, - } - } - }) - .unwrap_or_else(|| quote!(())); - - let error_handling = |location: &str| -> TokenStream { - if let Some(tref) = &err_type { - let abi_ret = match tref.type_().passed_by() { - witx::TypePassedBy::Value(atom) => names.atom_type(atom), - _ => unreachable!("err should always be passed by value"), - }; - let err_typename = names.type_ref(&tref, anon_lifetime()); - let err_method = names.guest_error_conversion_method(&tref); - quote! { - let e = #rt::GuestError::InFunc { funcname: #funcname, location: #location, err: Box::new(e.into()) }; - let err: #err_typename = GuestErrorConversion::#err_method(ctx, e); - return Ok(#abi_ret::from(err)); - } - } else { - quote! { - panic!("error: {:?}", e) - } - } - }; - - let marshal_args = func - .params - .iter() - .map(|p| marshal_arg(names, p, error_handling(p.name.as_str()))); - let trait_args = func.params.iter().map(|param| { - let name = names.func_param(¶m.name); - if passed_by_reference(&*param.tref.type_()) { - quote!(&#name) - } else { - quote!(#name) - } - }); - - let log_marshalled_args = if func.params.len() > 0 { - let rt = names.runtime_mod(); - let args = func.params.iter().map(|param| { - let name = names.func_param(¶m.name); - if param.impls_display() { - quote!( #name = #rt::tracing::field::display(&#name) ) - } else { - quote!( #name = #rt::tracing::field::debug(&#name) ) - } - }); - quote! { - #rt::tracing::event!(#rt::tracing::Level::TRACE, #(#args),*); - } - } else { - quote!() - }; - - let (trait_rets, trait_bindings) = if func.results.len() < 2 { - (quote!({}), quote!(_)) - } else { - let trait_rets: Vec<_> = func - .results - .iter() - .skip(1) - .map(|result| names.func_param(&result.name)) - .collect(); - let bindings = quote!((#(#trait_rets),*)); - let trace_rets = func.results.iter().skip(1).map(|result| { - let name = names.func_param(&result.name); - if result.tref.impls_display() { - quote!(#name = #rt::tracing::field::display(&#name)) - } else { - quote!(#name = #rt::tracing::field::debug(&#name)) - } - }); - let rets = quote! { - #rt::tracing::event!(#rt::tracing::Level::TRACE, #(#trace_rets),*); - (#(#trait_rets),*) - }; - (rets, bindings) - }; - - // Return value pointers need to be validated before the api call, then - // assigned to afterwards. marshal_result returns these two statements as a pair. - let marshal_rets = func - .results - .iter() - .skip(1) - .map(|result| marshal_result(names, result, &error_handling)); - let marshal_rets_pre = marshal_rets.clone().map(|(pre, _post)| pre); - let marshal_rets_post = marshal_rets.map(|(_pre, post)| post); - - let success = if let Some(ref err_type) = err_type { - let err_typename = names.type_ref(&err_type, anon_lifetime()); - quote! { - let success:#err_typename = #rt::GuestErrorType::success(); - #rt::tracing::event!( - #rt::tracing::Level::TRACE, - success=#rt::tracing::field::display(&success) - ); - Ok(#abi_ret::from(success)) - } - } else { - quote!(Ok(())) - }; + let mut body = TokenStream::new(); + func.call_interface( + &module.name, + &mut Rust { + src: &mut body, + params: ¶m_names, + block_storage: Vec::new(), + blocks: Vec::new(), + rt: &rt, + names, + module, + funcname: func.name.as_str(), + errxform, + }, + ); - let trait_name = names.trait_name(&module.name); let mod_name = &module.name.as_str(); let func_name = &func.name.as_str(); + quote! { + #[allow(unreachable_code)] // deals with warnings in noreturn functions + pub fn #ident( + ctx: &#ctx_type, + memory: &dyn #rt::GuestMemory, + #(#abi_params),* + ) -> Result<#abi_ret, #rt::Trap> { + use std::convert::TryFrom as _; - if func.noreturn { - quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, #rt::Trap> { - let _span = #rt::tracing::span!( - #rt::tracing::Level::TRACE, - "wiggle abi", - module = #mod_name, - function = #func_name - ); - let _enter = _span.enter(); - - #(#marshal_args)* - #log_marshalled_args - let trap = #trait_name::#ident(ctx, #(#trait_args),*); - Err(trap) - }) - } else { - quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, #rt::Trap> { let _span = #rt::tracing::span!( #rt::tracing::Level::TRACE, "wiggle abi", @@ -193,161 +71,272 @@ pub fn define_func( ); let _enter = _span.enter(); - #(#marshal_args)* - #(#marshal_rets_pre)* - #log_marshalled_args - let #trait_bindings = match #trait_name::#ident(ctx, #(#trait_args),*) { - Ok(#trait_bindings) => { #trait_rets }, - Err(e) => { #ret_err }, - }; - #(#marshal_rets_post)* - #success - }) + #body + } } } -fn marshal_arg( - names: &Names, - param: &witx::InterfaceFuncParam, - error_handling: TokenStream, -) -> TokenStream { - let rt = names.runtime_mod(); - let tref = ¶m.tref; - let interface_typename = names.type_ref(&tref, anon_lifetime()); - - let try_into_conversion = { - let name = names.func_param(¶m.name); - quote! { - let #name: #interface_typename = { - use ::std::convert::TryInto; - match #name.try_into() { - Ok(a) => a, - Err(e) => { - #error_handling - } +struct Rust<'a> { + src: &'a mut TokenStream, + params: &'a [Ident], + block_storage: Vec, + blocks: Vec, + rt: &'a TokenStream, + names: &'a Names, + module: &'a witx::Module, + funcname: &'a str, + errxform: &'a ErrorTransform, +} + +impl witx::Bindgen for Rust<'_> { + type Operand = TokenStream; + + fn push_block(&mut self) { + let prev = mem::replace(self.src, TokenStream::new()); + self.block_storage.push(prev); + } + + fn finish_block(&mut self, operand: Option) { + let to_restore = self.block_storage.pop().unwrap(); + let src = mem::replace(self.src, to_restore); + match operand { + None => self.blocks.push(src), + Some(s) => { + if src.is_empty() { + self.blocks.push(s); + } else { + self.blocks.push(quote!({ #src; #s })); } - }; + } } - }; + } + + // This is only used for `call_wasm` at this time. + fn allocate_space(&mut self, _: usize, _: &witx::NamedType) { + unimplemented!() + } - let read_conversion = { - let pointee_type = names.type_ref(tref, anon_lifetime()); - let arg_name = names.func_ptr_binding(¶m.name); - let name = names.func_param(¶m.name); - quote! { - let #name = match #rt::GuestPtr::<#pointee_type>::new(memory, #arg_name as u32).read() { - Ok(r) => r, - Err(e) => { - #error_handling + fn emit( + &mut self, + inst: &Instruction<'_>, + operands: &mut Vec, + results: &mut Vec, + ) { + let rt = self.rt; + let wrap_err = |location: &str| { + let funcname = self.funcname; + quote! { + |e| { + #rt::GuestError::InFunc { + funcname: #funcname, + location: #location, + err: Box::new(#rt::GuestError::from(e)), + } } - }; - } - }; + } + }; + + let mut try_from = |ty: TokenStream| { + let val = operands.pop().unwrap(); + let wrap_err = wrap_err(&format!("convert {}", ty)); + results.push(quote!(#ty::try_from(#val).map_err(#wrap_err)?)); + }; - match &*tref.type_() { - witx::Type::Enum(_e) => try_into_conversion, - witx::Type::Flags(_f) => try_into_conversion, - witx::Type::Int(_i) => try_into_conversion, - witx::Type::Builtin(b) => match b { - witx::BuiltinType::U8 | witx::BuiltinType::U16 | witx::BuiltinType::Char8 => { - try_into_conversion + match inst { + Instruction::GetArg { nth } => { + let param = &self.params[*nth]; + results.push(quote!(#param)); } - witx::BuiltinType::S8 | witx::BuiltinType::S16 => { - let name = names.func_param(¶m.name); - quote! { - let #name: #interface_typename = match (#name as i32).try_into() { - Ok(a) => a, - Err(e) => { - #error_handling - } + + Instruction::PointerFromI32 { ty } | Instruction::ConstPointerFromI32 { ty } => { + let val = operands.pop().unwrap(); + let pointee_type = self.names.type_ref(ty, anon_lifetime()); + results.push(quote! { + #rt::GuestPtr::<#pointee_type>::new(memory, #val as u32) + }); + } + + Instruction::ListFromPointerLength { ty } => { + let ptr = &operands[0]; + let len = &operands[1]; + let ty = match &**ty.type_() { + witx::Type::Builtin(witx::BuiltinType::Char) => quote!(str), + _ => { + let ty = self.names.type_ref(ty, anon_lifetime()); + quote!([#ty]) } - } + }; + results.push(quote! { + #rt::GuestPtr::<#ty>::new(memory, (#ptr as u32, #len as u32)); + }) } - witx::BuiltinType::U32 - | witx::BuiltinType::S32 - | witx::BuiltinType::U64 - | witx::BuiltinType::S64 - | witx::BuiltinType::USize - | witx::BuiltinType::F32 - | witx::BuiltinType::F64 => { - let name = names.func_param(¶m.name); - quote! { - let #name = #name as #interface_typename; + + Instruction::CallInterface { func, .. } => { + // Use the `tracing` crate to log all arguments that are going + // out, and afterwards we call the function with those bindings. + let mut args = Vec::new(); + for (i, param) in func.params.iter().enumerate() { + let name = self.names.func_param(¶m.name); + let val = &operands[i]; + self.src.extend(quote!(let #name = #val;)); + if passed_by_reference(param.tref.type_()) { + args.push(quote!(&#name)); + } else { + args.push(quote!(#name)); + } } - } - witx::BuiltinType::String => { - let lifetime = anon_lifetime(); - let ptr_name = names.func_ptr_binding(¶m.name); - let len_name = names.func_len_binding(¶m.name); - let name = names.func_param(¶m.name); - quote! { - let #name = #rt::GuestPtr::<#lifetime, str>::new(memory, (#ptr_name as u32, #len_name as u32)); + if func.params.len() > 0 { + let args = func + .params + .iter() + .map(|param| { + let name = self.names.func_param(¶m.name); + if param.impls_display() { + quote!( #name = #rt::tracing::field::display(&#name) ) + } else { + quote!( #name = #rt::tracing::field::debug(&#name) ) + } + }) + .collect::>(); + self.src.extend(quote! { + #rt::tracing::event!(#rt::tracing::Level::TRACE, #(#args),*); + }); + } + + let trait_name = self.names.trait_name(&self.module.name); + let ident = self.names.func(&func.name); + self.src.extend(quote! { + let ret = #trait_name::#ident(ctx, #(#args),*); + #rt::tracing::event!( + #rt::tracing::Level::TRACE, + result = #rt::tracing::field::debug(&ret), + ); + }); + + if func.results.len() > 0 { + results.push(quote!(ret)); + } else if func.noreturn { + self.src.extend(quote!(return Err(ret);)); } } - }, - witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => { - let pointee_type = names.type_ref(pointee, anon_lifetime()); - let name = names.func_param(¶m.name); - quote! { - let #name = #rt::GuestPtr::<#pointee_type>::new(memory, #name as u32); + + // Lowering an enum is typically simple but if we have an error + // transformation registered for this enum then what we're actually + // doing is lowering from a user-defined error type to the error + // enum, and *then* we lower to an i32. + Instruction::EnumLower { ty } => { + let val = operands.pop().unwrap(); + let val = match self.errxform.for_name(ty) { + Some(custom) => { + let method = self.names.user_error_conversion_method(&custom); + quote!(UserErrorConversion::#method(ctx, #val)?) + } + None => val, + }; + results.push(quote!(#val as i32)); } - } - witx::Type::Struct(_) => read_conversion, - witx::Type::Array(arr) => { - let pointee_type = names.type_ref(arr, anon_lifetime()); - let ptr_name = names.func_ptr_binding(¶m.name); - let len_name = names.func_len_binding(¶m.name); - let name = names.func_param(¶m.name); - quote! { - let #name = #rt::GuestPtr::<[#pointee_type]>::new(memory, (#ptr_name as u32, #len_name as u32)); + + Instruction::ResultLower { err: err_ty, .. } => { + let err = self.blocks.pop().unwrap(); + let ok = self.blocks.pop().unwrap(); + let val = operands.pop().unwrap(); + let err_typename = self.names.type_ref(err_ty.unwrap(), anon_lifetime()); + results.push(quote! { + match #val { + Ok(e) => { #ok; <#err_typename as #rt::GuestErrorType>::success() as i32 } + Err(e) => { #err } + } + }); } - } - witx::Type::Union(_u) => read_conversion, - witx::Type::Handle(_h) => { - let name = names.func_param(¶m.name); - let handle_type = names.type_ref(tref, anon_lifetime()); - quote!( let #name = #handle_type::from(#name); ) - } - } -} -fn marshal_result( - names: &Names, - result: &witx::InterfaceFuncParam, - error_handling: F, -) -> (TokenStream, TokenStream) -where - F: Fn(&str) -> TokenStream, -{ - let rt = names.runtime_mod(); - let tref = &result.tref; - - let write_val_to_ptr = { - let pointee_type = names.type_ref(tref, anon_lifetime()); - // core type is given func_ptr_binding name. - let ptr_name = names.func_ptr_binding(&result.name); - let ptr_err_handling = error_handling(&format!("{}:result_ptr_mut", result.name.as_str())); - let pre = quote! { - let #ptr_name = #rt::GuestPtr::<#pointee_type>::new(memory, #ptr_name as u32); - }; - // trait binding returns func_param name. - let val_name = names.func_param(&result.name); - let post = quote! { - if let Err(e) = #ptr_name.write(#val_name) { - #ptr_err_handling + Instruction::VariantPayload => results.push(quote!(e)), + + Instruction::Return { amt: 0 } => { + self.src.extend(quote!(return Ok(()))); } - }; - (pre, post) - }; + Instruction::Return { amt: 1 } => { + let val = operands.pop().unwrap(); + self.src.extend(quote!(return Ok(#val))); + } + Instruction::Return { .. } => unimplemented!(), - match &*tref.type_() { - witx::Type::Builtin(b) => match b { - witx::BuiltinType::String => unimplemented!("string result types"), - _ => write_val_to_ptr, - }, - witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } | witx::Type::Array { .. } => { - unimplemented!("pointer/array result types") + Instruction::TupleLower { amt } => { + let names = (0..*amt) + .map(|i| Ident::new(&format!("t{}", i), Span::call_site())) + .collect::>(); + let val = operands.pop().unwrap(); + self.src.extend(quote!( let (#(#names,)*) = #val;)); + results.extend(names.iter().map(|i| quote!(#i))); + } + + Instruction::Store { ty } => { + let ptr = operands.pop().unwrap(); + let val = operands.pop().unwrap(); + let wrap_err = wrap_err(&format!("write {}", ty.name.as_str())); + let pointee_type = self.names.type_(&ty.name); + self.src.extend(quote! { + #rt::GuestPtr::<#pointee_type>::new(memory, #ptr as u32) + .write(#val) + .map_err(#wrap_err)?; + }); + } + + Instruction::Load { ty } => { + let ptr = operands.pop().unwrap(); + let wrap_err = wrap_err(&format!("read {}", ty.name.as_str())); + let pointee_type = self.names.type_(&ty.name); + results.push(quote! { + #rt::GuestPtr::<#pointee_type>::new(memory, #ptr as u32) + .read() + .map_err(#wrap_err)? + }); + } + + Instruction::HandleFromI32 { ty } => { + let val = operands.pop().unwrap(); + let ty = self.names.type_(&ty.name); + results.push(quote!(#ty::from(#val))); + } + + // Smaller-than-32 numerical conversions are done with `TryFrom` to + // ensure we're not losing bits. + Instruction::U8FromI32 => try_from(quote!(u8)), + Instruction::S8FromI32 => try_from(quote!(i8)), + Instruction::Char8FromI32 => try_from(quote!(u8)), + Instruction::U16FromI32 => try_from(quote!(u16)), + Instruction::S16FromI32 => try_from(quote!(i16)), + + // Conversions with matching bit-widths but different signededness + // use `as` since we're basically just reinterpreting the bits. + Instruction::U32FromI32 | Instruction::UsizeFromI32 => { + let val = operands.pop().unwrap(); + results.push(quote!(#val as u32)); + } + Instruction::U64FromI64 => { + let val = operands.pop().unwrap(); + results.push(quote!(#val as u64)); + } + + // Conversions to enums/bitflags use `TryFrom` to ensure that the + // values are valid coming in. + Instruction::EnumLift { ty } + | Instruction::BitflagsFromI64 { ty } + | Instruction::BitflagsFromI32 { ty } => { + let ty = self.names.type_(&ty.name); + try_from(quote!(#ty)) + } + + // No conversions necessary for these, the native wasm type matches + // our own representation. + Instruction::If32FromF32 + | Instruction::If64FromF64 + | Instruction::S32FromI32 + | Instruction::S64FromI64 => results.push(operands.pop().unwrap()), + + // There's a number of other instructions we could implement but + // they're not exercised by WASI at this time. As necessary we can + // add code to implement them. + other => panic!("no implementation for {:?}", other), } - _ => write_val_to_ptr, } } diff --git a/crates/wiggle/generate/src/lib.rs b/crates/wiggle/generate/src/lib.rs index b9a07f93ce26..2e172633dfaf 100644 --- a/crates/wiggle/generate/src/lib.rs +++ b/crates/wiggle/generate/src/lib.rs @@ -6,10 +6,10 @@ mod module_trait; mod names; mod types; -use proc_macro2::TokenStream; -use quote::quote; - +use heck::ShoutySnakeCase; use lifetimes::anon_lifetime; +use proc_macro2::{Literal, TokenStream}; +use quote::quote; pub use config::Config; pub use error_transform::{ErrorTransform, UserErrorType}; @@ -25,6 +25,19 @@ pub fn generate(doc: &witx::Document, names: &Names, errs: &ErrorTransform) -> T let types = doc.typenames().map(|t| define_datatype(&names, &t)); + let constants = doc.constants().map(|c| { + let name = quote::format_ident!( + "{}_{}", + c.ty.as_str().to_shouty_snake_case(), + c.name.as_str().to_shouty_snake_case() + ); + let ty = names.type_(&c.ty); + let value = Literal::u64_unsuffixed(c.value); + quote! { + pub const #name: #ty = #value; + } + }); + let guest_error_methods = doc.error_types().map(|t| { let typename = names.type_ref(&t, anon_lifetime()); let err_method = names.guest_error_conversion_method(&t); @@ -67,7 +80,10 @@ pub fn generate(doc: &witx::Document, names: &Names, errs: &ErrorTransform) -> T quote!( pub mod types { + use std::convert::TryFrom; + #(#types)* + #(#constants)* #guest_error_conversion #user_error_conversion } diff --git a/crates/wiggle/generate/src/lifetimes.rs b/crates/wiggle/generate/src/lifetimes.rs index 75b102209c02..87b1aad9a479 100644 --- a/crates/wiggle/generate/src/lifetimes.rs +++ b/crates/wiggle/generate/src/lifetimes.rs @@ -19,46 +19,37 @@ impl LifetimeExt for witx::Type { fn is_transparent(&self) -> bool { match self { witx::Type::Builtin(b) => b.is_transparent(), - witx::Type::Struct(s) => s.is_transparent(), - witx::Type::Enum { .. } - | witx::Type::Flags { .. } - | witx::Type::Int { .. } - | witx::Type::Handle { .. } => true, - witx::Type::Union { .. } + witx::Type::Record(s) => s.is_transparent(), + witx::Type::Handle { .. } => true, + witx::Type::Variant { .. } | witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } - | witx::Type::Array { .. } => false, + | witx::Type::List { .. } => false, } } fn needs_lifetime(&self) -> bool { match self { witx::Type::Builtin(b) => b.needs_lifetime(), - witx::Type::Struct(s) => s.needs_lifetime(), - witx::Type::Union(u) => u.needs_lifetime(), - witx::Type::Enum { .. } - | witx::Type::Flags { .. } - | witx::Type::Int { .. } - | witx::Type::Handle { .. } => false, + witx::Type::Record(s) => s.needs_lifetime(), + witx::Type::Variant(u) => u.needs_lifetime(), + witx::Type::Handle { .. } => false, witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } - | witx::Type::Array { .. } => true, + | witx::Type::List { .. } => true, } } } impl LifetimeExt for witx::BuiltinType { fn is_transparent(&self) -> bool { - !self.needs_lifetime() + true } fn needs_lifetime(&self) -> bool { - match self { - witx::BuiltinType::String => true, - _ => false, - } + false } } -impl LifetimeExt for witx::StructDatatype { +impl LifetimeExt for witx::RecordDatatype { fn is_transparent(&self) -> bool { self.members.iter().all(|m| m.tref.is_transparent()) } @@ -67,12 +58,12 @@ impl LifetimeExt for witx::StructDatatype { } } -impl LifetimeExt for witx::UnionDatatype { +impl LifetimeExt for witx::Variant { fn is_transparent(&self) -> bool { false } fn needs_lifetime(&self) -> bool { - self.variants + self.cases .iter() .any(|m| m.tref.as_ref().map(|t| t.needs_lifetime()).unwrap_or(false)) } diff --git a/crates/wiggle/generate/src/module_trait.rs b/crates/wiggle/generate/src/module_trait.rs index a7a7289d09ee..30dae0007668 100644 --- a/crates/wiggle/generate/src/module_trait.rs +++ b/crates/wiggle/generate/src/module_trait.rs @@ -7,17 +7,11 @@ use crate::names::Names; use witx::Module; pub fn passed_by_reference(ty: &witx::Type) -> bool { - let passed_by = match ty.passed_by() { - witx::TypePassedBy::Value { .. } => false, - witx::TypePassedBy::Pointer { .. } | witx::TypePassedBy::PointerLengthPair { .. } => true, - }; match ty { - witx::Type::Builtin(b) => match &*b { - witx::BuiltinType::String => true, - _ => passed_by, - }, - witx::Type::Pointer(_) | witx::Type::ConstPointer(_) | witx::Type::Array(_) => true, - _ => passed_by, + witx::Type::Pointer(_) | witx::Type::ConstPointer(_) | witx::Type::List(_) => true, + witx::Type::Record(r) => r.bitflags_repr().is_none(), + witx::Type::Variant(v) => !v.is_enum(), + _ => false, } } @@ -49,28 +43,36 @@ pub fn define_module_trait(names: &Names, m: &Module, errxform: &ErrorTransform) quote!(#arg_name: #arg_type) }); - let result = if !f.noreturn { - let rets = f - .results - .iter() - .skip(1) - .map(|ret| names.type_ref(&ret.tref, lifetime.clone())); - let err = f - .results - .get(0) - .map(|err_result| { - if let Some(custom_err) = errxform.for_abi_error(&err_result.tref) { - let tn = custom_err.typename(); - quote!(super::#tn) - } else { - names.type_ref(&err_result.tref, lifetime.clone()) - } - }) - .unwrap_or(quote!(())); - quote!( Result<(#(#rets),*), #err> ) - } else { - let rt = names.runtime_mod(); - quote!(#rt::Trap) + let rt = names.runtime_mod(); + let result = match f.results.len() { + 0 if f.noreturn => quote!(#rt::Trap), + 0 => quote!(()), + 1 => { + let (ok, err) = match &**f.results[0].tref.type_() { + witx::Type::Variant(v) => match v.as_expected() { + Some(p) => p, + None => unimplemented!("anonymous variant ref {:?}", v), + }, + _ => unimplemented!(), + }; + + let ok = match ok { + Some(ty) => names.type_ref(ty, lifetime.clone()), + None => quote!(()), + }; + let err = match err { + Some(ty) => match errxform.for_abi_error(ty) { + Some(custom) => { + let tn = custom.typename(); + quote!(super::#tn) + } + None => names.type_ref(ty, lifetime.clone()), + }, + None => quote!(()), + }; + quote!(Result<#ok, #err>) + } + _ => unimplemented!(), }; if is_anonymous { diff --git a/crates/wiggle/generate/src/names.rs b/crates/wiggle/generate/src/names.rs index f6266ec41f97..b9eb9e47528f 100644 --- a/crates/wiggle/generate/src/names.rs +++ b/crates/wiggle/generate/src/names.rs @@ -2,7 +2,7 @@ use escaping::{escape_id, handle_2big_enum_variant, NamingConvention}; use heck::{ShoutySnakeCase, SnakeCase}; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; -use witx::{AtomType, BuiltinType, Id, Type, TypeRef}; +use witx::{BuiltinType, Id, Type, TypeRef, WasmType}; use crate::{lifetimes::LifetimeExt, UserErrorType}; @@ -32,15 +32,11 @@ impl Names { quote!(#ident) } - pub fn builtin_type(&self, b: BuiltinType, lifetime: TokenStream) -> TokenStream { + pub fn builtin_type(&self, b: BuiltinType) -> TokenStream { match b { - BuiltinType::String => { - let rt = self.runtime_mod(); - quote!(#rt::GuestPtr<#lifetime, str>) - } - BuiltinType::U8 => quote!(u8), + BuiltinType::U8 { .. } => quote!(u8), BuiltinType::U16 => quote!(u16), - BuiltinType::U32 => quote!(u32), + BuiltinType::U32 { .. } => quote!(u32), BuiltinType::U64 => quote!(u64), BuiltinType::S8 => quote!(i8), BuiltinType::S16 => quote!(i16), @@ -48,16 +44,16 @@ impl Names { BuiltinType::S64 => quote!(i64), BuiltinType::F32 => quote!(f32), BuiltinType::F64 => quote!(f64), - BuiltinType::Char8 => quote!(u8), - BuiltinType::USize => quote!(u32), + BuiltinType::Char => quote!(char), } } - pub fn atom_type(&self, atom: AtomType) -> TokenStream { - match atom { - AtomType::I32 => quote!(i32), - AtomType::I64 => quote!(i64), - AtomType::F32 => quote!(f32), - AtomType::F64 => quote!(f64), + + pub fn wasm_type(&self, ty: WasmType) -> TokenStream { + match ty { + WasmType::I32 => quote!(i32), + WasmType::I64 => quote!(i64), + WasmType::F32 => quote!(f32), + WasmType::F64 => quote!(f64), } } @@ -72,16 +68,44 @@ impl Names { } } TypeRef::Value(ty) => match &**ty { - Type::Builtin(builtin) => self.builtin_type(*builtin, lifetime.clone()), + Type::Builtin(builtin) => self.builtin_type(*builtin), Type::Pointer(pointee) | Type::ConstPointer(pointee) => { let rt = self.runtime_mod(); let pointee_type = self.type_ref(&pointee, lifetime.clone()); quote!(#rt::GuestPtr<#lifetime, #pointee_type>) } - Type::Array(pointee) => { - let rt = self.runtime_mod(); - let pointee_type = self.type_ref(&pointee, lifetime.clone()); - quote!(#rt::GuestPtr<#lifetime, [#pointee_type]>) + Type::List(pointee) => match &**pointee.type_() { + Type::Builtin(BuiltinType::Char) => { + let rt = self.runtime_mod(); + quote!(#rt::GuestPtr<#lifetime, str>) + } + _ => { + let rt = self.runtime_mod(); + let pointee_type = self.type_ref(&pointee, lifetime.clone()); + quote!(#rt::GuestPtr<#lifetime, [#pointee_type]>) + } + }, + Type::Variant(v) => match v.as_expected() { + Some((ok, err)) => { + let ok = match ok { + Some(ty) => self.type_ref(ty, lifetime.clone()), + None => quote!(()), + }; + let err = match err { + Some(ty) => self.type_ref(ty, lifetime.clone()), + None => quote!(()), + }; + quote!(Result<#ok, #err>) + } + None => unimplemented!("anonymous variant ref {:?}", tref), + }, + Type::Record(r) if r.is_tuple() => { + let types = r + .members + .iter() + .map(|m| self.type_ref(&m.tref, lifetime.clone())) + .collect::>(); + quote!((#(#types,)*)) } _ => unimplemented!("anonymous type ref {:?}", tref), }, @@ -144,14 +168,6 @@ impl Names { escape_id(id, NamingConvention::SnakeCase) } - pub fn func_core_arg(&self, arg: &witx::CoreParamType) -> Ident { - match arg.signifies { - witx::CoreParamSignifies::Value { .. } => self.func_param(&arg.param.name), - witx::CoreParamSignifies::PointerTo => self.func_ptr_binding(&arg.param.name), - witx::CoreParamSignifies::LengthOf => self.func_len_binding(&arg.param.name), - } - } - /// For when you need a {name}_ptr binding for passing a value by reference: pub fn func_ptr_binding(&self, id: &Id) -> Ident { format_ident!("{}_ptr", id.as_str().to_snake_case()) @@ -164,10 +180,9 @@ impl Names { fn builtin_name(b: &BuiltinType) -> &'static str { match b { - BuiltinType::String => "string", - BuiltinType::U8 => "u8", + BuiltinType::U8 { .. } => "u8", BuiltinType::U16 => "u16", - BuiltinType::U32 => "u32", + BuiltinType::U32 { .. } => "u32", BuiltinType::U64 => "u64", BuiltinType::S8 => "i8", BuiltinType::S16 => "i16", @@ -175,8 +190,7 @@ impl Names { BuiltinType::S64 => "i64", BuiltinType::F32 => "f32", BuiltinType::F64 => "f64", - BuiltinType::Char8 => "char8", - BuiltinType::USize => "usize", + BuiltinType::Char => "char", } } diff --git a/crates/wiggle/generate/src/types/enum.rs b/crates/wiggle/generate/src/types/enum.rs deleted file mode 100644 index cef56065effb..000000000000 --- a/crates/wiggle/generate/src/types/enum.rs +++ /dev/null @@ -1,120 +0,0 @@ -use super::{atom_token, int_repr_tokens}; -use crate::names::Names; - -use proc_macro2::TokenStream; -use quote::quote; - -pub(super) fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream { - let ident = names.type_(&name); - let rt = names.runtime_mod(); - - let repr = int_repr_tokens(e.repr); - let abi_repr = atom_token(match e.repr { - witx::IntRepr::U8 | witx::IntRepr::U16 | witx::IntRepr::U32 => witx::AtomType::I32, - witx::IntRepr::U64 => witx::AtomType::I64, - }); - - let mut variant_names = vec![]; - let mut tryfrom_repr_cases = vec![]; - let mut to_repr_cases = vec![]; - let mut to_display = vec![]; - - for (n, variant) in e.variants.iter().enumerate() { - let variant_name = names.enum_variant(&variant.name); - let docs = variant.docs.trim(); - let ident_str = ident.to_string(); - let variant_str = variant_name.to_string(); - tryfrom_repr_cases.push(quote!(#n => Ok(#ident::#variant_name))); - to_repr_cases.push(quote!(#ident::#variant_name => #n as #repr)); - to_display.push(quote!(#ident::#variant_name => format!("{} ({}::{}({}))", #docs, #ident_str, #variant_str, #repr::from(*self)))); - variant_names.push(variant_name); - } - - quote! { - #[repr(#repr)] - #[derive(Copy, Clone, Debug, ::std::hash::Hash, Eq, PartialEq)] - pub enum #ident { - #(#variant_names),* - } - - impl ::std::fmt::Display for #ident { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - let to_str = match self { - #(#to_display,)* - }; - write!(f, "{}", to_str) - } - } - - impl ::std::convert::TryFrom<#repr> for #ident { - type Error = #rt::GuestError; - fn try_from(value: #repr) -> Result<#ident, #rt::GuestError> { - match value as usize { - #(#tryfrom_repr_cases),*, - _ => Err( #rt::GuestError::InvalidEnumValue(stringify!(#ident))), - } - } - } - - impl ::std::convert::TryFrom<#abi_repr> for #ident { - type Error = #rt::GuestError; - fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> { - #ident::try_from(value as #repr) - } - } - - impl From<#ident> for #repr { - fn from(e: #ident) -> #repr { - match e { - #(#to_repr_cases),* - } - } - } - - impl From<#ident> for #abi_repr { - fn from(e: #ident) -> #abi_repr { - #repr::from(e) as #abi_repr - } - } - - impl<'a> #rt::GuestType<'a> for #ident { - fn guest_size() -> u32 { - #repr::guest_size() - } - - fn guest_align() -> usize { - #repr::guest_align() - } - - fn read(location: & #rt::GuestPtr<#ident>) -> Result<#ident, #rt::GuestError> { - use std::convert::TryFrom; - let reprval = #repr::read(&location.cast())?; - let value = #ident::try_from(reprval)?; - Ok(value) - } - - fn write(location: & #rt::GuestPtr<'_, #ident>, val: Self) - -> Result<(), #rt::GuestError> - { - #repr::write(&location.cast(), #repr::from(val)) - } - } - - unsafe impl <'a> #rt::GuestTypeTransparent<'a> for #ident { - #[inline] - fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> { - use std::convert::TryFrom; - // Validate value in memory using #ident::try_from(reprval) - let reprval = unsafe { (location as *mut #repr).read() }; - let _val = #ident::try_from(reprval)?; - Ok(()) - } - } - } -} - -impl super::WiggleType for witx::EnumDatatype { - fn impls_display(&self) -> bool { - true - } -} diff --git a/crates/wiggle/generate/src/types/flags.rs b/crates/wiggle/generate/src/types/flags.rs index cda13a2bfa1e..6082ed5f7384 100644 --- a/crates/wiggle/generate/src/types/flags.rs +++ b/crates/wiggle/generate/src/types/flags.rs @@ -1,27 +1,24 @@ -use super::{atom_token, int_repr_tokens}; use crate::names::Names; use proc_macro2::{Literal, TokenStream}; use quote::quote; -use std::convert::TryFrom; -pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> TokenStream { +pub(super) fn define_flags( + names: &Names, + name: &witx::Id, + repr: witx::IntRepr, + record: &witx::RecordDatatype, +) -> TokenStream { let rt = names.runtime_mod(); let ident = names.type_(&name); - let repr = int_repr_tokens(f.repr); - let abi_repr = atom_token(match f.repr { - witx::IntRepr::U8 | witx::IntRepr::U16 | witx::IntRepr::U32 => witx::AtomType::I32, - witx::IntRepr::U64 => witx::AtomType::I64, - }); + let abi_repr = names.wasm_type(repr.into()); + let repr = super::int_repr_tokens(repr); let mut names_ = vec![]; let mut values_ = vec![]; - for (i, f) in f.flags.iter().enumerate() { - let name = names.flag_member(&f.name); - let value = 1u128 - .checked_shl(u32::try_from(i).expect("flag value overflow")) - .expect("flag value overflow"); - let value_token = Literal::u128_unsuffixed(value); + for (i, member) in record.members.iter().enumerate() { + let name = names.flag_member(&member.name); + let value_token = Literal::usize_unsuffixed(1 << i); names_.push(name); values_.push(value_token); } @@ -45,7 +42,7 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty } } - impl ::std::convert::TryFrom<#repr> for #ident { + impl TryFrom<#repr> for #ident { type Error = #rt::GuestError; fn try_from(value: #repr) -> Result { if #repr::from(!#ident::all()) & value != 0 { @@ -56,10 +53,10 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty } } - impl ::std::convert::TryFrom<#abi_repr> for #ident { + impl TryFrom<#abi_repr> for #ident { type Error = #rt::GuestError; - fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> { - #ident::try_from(value as #repr) + fn try_from(value: #abi_repr) -> Result { + #ident::try_from(#repr::try_from(value)?) } } @@ -69,12 +66,6 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty } } - impl From<#ident> for #abi_repr { - fn from(e: #ident) -> #abi_repr { - #repr::from(e) as #abi_repr - } - } - impl<'a> #rt::GuestType<'a> for #ident { fn guest_size() -> u32 { #repr::guest_size() @@ -106,12 +97,5 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty Ok(()) } } - - } -} - -impl super::WiggleType for witx::FlagsDatatype { - fn impls_display(&self) -> bool { - true } } diff --git a/crates/wiggle/generate/src/types/handle.rs b/crates/wiggle/generate/src/types/handle.rs index 310c9e7d6e8b..0f23419b0d9c 100644 --- a/crates/wiggle/generate/src/types/handle.rs +++ b/crates/wiggle/generate/src/types/handle.rs @@ -78,8 +78,6 @@ pub(super) fn define_handle( Ok(()) } } - - } } diff --git a/crates/wiggle/generate/src/types/int.rs b/crates/wiggle/generate/src/types/int.rs deleted file mode 100644 index d916b65b7064..000000000000 --- a/crates/wiggle/generate/src/types/int.rs +++ /dev/null @@ -1,100 +0,0 @@ -use super::{atom_token, int_repr_tokens}; -use crate::names::Names; - -use proc_macro2::TokenStream; -use quote::quote; - -pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStream { - let rt = names.runtime_mod(); - let ident = names.type_(&name); - let repr = int_repr_tokens(i.repr); - let abi_repr = atom_token(match i.repr { - witx::IntRepr::U8 | witx::IntRepr::U16 | witx::IntRepr::U32 => witx::AtomType::I32, - witx::IntRepr::U64 => witx::AtomType::I64, - }); - let consts = i - .consts - .iter() - .map(|r#const| { - let const_ident = names.int_member(&r#const.name); - let value = r#const.value; - quote!(pub const #const_ident: #ident = #ident(#value)) - }) - .collect::>(); - - quote! { - #[repr(transparent)] - #[derive(Copy, Clone, Debug, ::std::hash::Hash, Eq, PartialEq)] - pub struct #ident(#repr); - - impl #ident { - #(#consts;)* - } - - impl ::std::fmt::Display for #ident { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write!(f, "{:?}", self) - } - } - - impl ::std::convert::TryFrom<#repr> for #ident { - type Error = #rt::GuestError; - fn try_from(value: #repr) -> Result { - Ok(#ident(value)) - } - } - - impl ::std::convert::TryFrom<#abi_repr> for #ident { - type Error = #rt::GuestError; - fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> { - #ident::try_from(value as #repr) - } - } - - impl From<#ident> for #repr { - fn from(e: #ident) -> #repr { - e.0 - } - } - - impl From<#ident> for #abi_repr { - fn from(e: #ident) -> #abi_repr { - #repr::from(e) as #abi_repr - } - } - - impl<'a> #rt::GuestType<'a> for #ident { - fn guest_size() -> u32 { - #repr::guest_size() - } - - fn guest_align() -> usize { - #repr::guest_align() - } - - fn read(location: &#rt::GuestPtr<'a, #ident>) -> Result<#ident, #rt::GuestError> { - Ok(#ident(#repr::read(&location.cast())?)) - - } - - fn write(location: &#rt::GuestPtr<'_, #ident>, val: Self) -> Result<(), #rt::GuestError> { - #repr::write(&location.cast(), val.0) - } - } - - unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident { - #[inline] - fn validate(_location: *mut #ident) -> Result<(), #rt::GuestError> { - // All bit patterns accepted - Ok(()) - } - } - - } -} - -impl super::WiggleType for witx::IntDatatype { - fn impls_display(&self) -> bool { - true - } -} diff --git a/crates/wiggle/generate/src/types/mod.rs b/crates/wiggle/generate/src/types/mod.rs index 6ed29af94b8c..255c2ce7b223 100644 --- a/crates/wiggle/generate/src/types/mod.rs +++ b/crates/wiggle/generate/src/types/mod.rs @@ -1,9 +1,8 @@ -mod r#enum; +// mod r#enum; mod flags; mod handle; -mod int; -mod r#struct; -mod union; +mod record; +mod variant; use crate::lifetimes::LifetimeExt; use crate::names::Names; @@ -15,11 +14,11 @@ pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStrea match &namedtype.tref { witx::TypeRef::Name(alias_to) => define_alias(names, &namedtype.name, &alias_to), witx::TypeRef::Value(v) => match &**v { - witx::Type::Enum(e) => r#enum::define_enum(names, &namedtype.name, &e), - witx::Type::Int(i) => int::define_int(names, &namedtype.name, &i), - witx::Type::Flags(f) => flags::define_flags(names, &namedtype.name, &f), - witx::Type::Struct(s) => r#struct::define_struct(names, &namedtype.name, &s), - witx::Type::Union(u) => union::define_union(names, &namedtype.name, &u), + witx::Type::Record(r) => match r.bitflags_repr() { + Some(repr) => flags::define_flags(names, &namedtype.name, repr, &r), + None => record::define_struct(names, &namedtype.name, &r), + }, + witx::Type::Variant(v) => variant::define_variant(names, &namedtype.name, &v), witx::Type::Handle(h) => handle::define_handle(names, &namedtype.name, &h), witx::Type::Builtin(b) => define_builtin(names, &namedtype.name, *b), witx::Type::Pointer(p) => { @@ -30,7 +29,7 @@ pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStrea let rt = names.runtime_mod(); define_witx_pointer(names, &namedtype.name, quote!(#rt::GuestPtr), p) } - witx::Type::Array(arr) => define_witx_array(names, &namedtype.name, &arr), + witx::Type::List(arr) => define_witx_list(names, &namedtype.name, &arr), }, } } @@ -47,12 +46,8 @@ fn define_alias(names: &Names, name: &witx::Id, to: &witx::NamedType) -> TokenSt fn define_builtin(names: &Names, name: &witx::Id, builtin: witx::BuiltinType) -> TokenStream { let ident = names.type_(name); - let built = names.builtin_type(builtin, quote!('a)); - if builtin.needs_lifetime() { - quote!(pub type #ident<'a> = #built;) - } else { - quote!(pub type #ident = #built;) - } + let built = names.builtin_type(builtin); + quote!(pub type #ident = #built;) } fn define_witx_pointer( @@ -67,14 +62,14 @@ fn define_witx_pointer( quote!(pub type #ident<'a> = #pointer_type<'a, #pointee_type>;) } -fn define_witx_array(names: &Names, name: &witx::Id, arr_raw: &witx::TypeRef) -> TokenStream { +fn define_witx_list(names: &Names, name: &witx::Id, arr_raw: &witx::TypeRef) -> TokenStream { let ident = names.type_(name); let rt = names.runtime_mod(); let pointee_type = names.type_ref(arr_raw, quote!('a)); quote!(pub type #ident<'a> = #rt::GuestPtr<'a, [#pointee_type]>;) } -fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream { +pub fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream { match int_repr { witx::IntRepr::U8 => quote!(u8), witx::IntRepr::U16 => quote!(u16), @@ -83,15 +78,6 @@ fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream { } } -fn atom_token(atom: witx::AtomType) -> TokenStream { - match atom { - witx::AtomType::I32 => quote!(i32), - witx::AtomType::I64 => quote!(i64), - witx::AtomType::F32 => quote!(f32), - witx::AtomType::F64 => quote!(f64), - } -} - pub trait WiggleType { fn impls_display(&self) -> bool; } @@ -114,16 +100,13 @@ impl WiggleType for witx::NamedType { impl WiggleType for witx::Type { fn impls_display(&self) -> bool { match self { - witx::Type::Enum(x) => x.impls_display(), - witx::Type::Int(x) => x.impls_display(), - witx::Type::Flags(x) => x.impls_display(), - witx::Type::Struct(x) => x.impls_display(), - witx::Type::Union(x) => x.impls_display(), + witx::Type::Record(x) => x.impls_display(), + witx::Type::Variant(x) => x.impls_display(), witx::Type::Handle(x) => x.impls_display(), witx::Type::Builtin(x) => x.impls_display(), witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } - | witx::Type::Array { .. } => false, + | witx::Type::List { .. } => false, } } } @@ -136,11 +119,6 @@ impl WiggleType for witx::BuiltinType { impl WiggleType for witx::InterfaceFuncParam { fn impls_display(&self) -> bool { - match &*self.tref.type_() { - witx::Type::Struct { .. } - | witx::Type::Union { .. } - | witx::Type::Builtin(witx::BuiltinType::String { .. }) => false, - _ => self.tref.impls_display(), - } + self.tref.impls_display() } } diff --git a/crates/wiggle/generate/src/types/struct.rs b/crates/wiggle/generate/src/types/record.rs similarity index 94% rename from crates/wiggle/generate/src/types/struct.rs rename to crates/wiggle/generate/src/types/record.rs index 2a79a6e9accb..eaabcc6426ad 100644 --- a/crates/wiggle/generate/src/types/struct.rs +++ b/crates/wiggle/generate/src/types/record.rs @@ -8,7 +8,7 @@ use witx::Layout; pub(super) fn define_struct( names: &Names, name: &witx::Id, - s: &witx::StructDatatype, + s: &witx::RecordDatatype, ) -> TokenStream { let rt = names.runtime_mod(); let ident = names.type_(name); @@ -28,7 +28,7 @@ pub(super) fn define_struct( } } witx::TypeRef::Value(ty) => match &**ty { - witx::Type::Builtin(builtin) => names.builtin_type(*builtin, quote!('a)), + witx::Type::Builtin(builtin) => names.builtin_type(*builtin), witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => { let pointee_type = names.type_ref(&pointee, quote!('a)); quote!(#rt::GuestPtr<'a, #pointee_type>) @@ -52,9 +52,9 @@ pub(super) fn define_struct( } witx::TypeRef::Value(ty) => match &**ty { witx::Type::Builtin(builtin) => { - let type_ = names.builtin_type(*builtin, anon_lifetime()); + let type_ = names.builtin_type(*builtin); quote! { - let #name = <#type_ as #rt::GuestType>::read(&#location)?; + let #name = <#type_ as #rt::GuestType>::read(&#location)?; } } witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => { @@ -141,7 +141,7 @@ pub(super) fn define_struct( } } -impl super::WiggleType for witx::StructDatatype { +impl super::WiggleType for witx::RecordDatatype { fn impls_display(&self) -> bool { false } diff --git a/crates/wiggle/generate/src/types/union.rs b/crates/wiggle/generate/src/types/union.rs deleted file mode 100644 index ecc3253f3c52..000000000000 --- a/crates/wiggle/generate/src/types/union.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::lifetimes::LifetimeExt; -use crate::names::Names; - -use proc_macro2::TokenStream; -use quote::quote; -use witx::Layout; - -pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> TokenStream { - let rt = names.runtime_mod(); - let ident = names.type_(name); - let size = u.mem_size_align().size as u32; - let align = u.mem_size_align().align as usize; - let ulayout = u.union_layout(); - let contents_offset = ulayout.contents_offset as u32; - - let lifetime = quote!('a); - - let variants = u.variants.iter().map(|v| { - let var_name = names.enum_variant(&v.name); - if let Some(tref) = &v.tref { - let var_type = names.type_ref(&tref, lifetime.clone()); - quote!(#var_name(#var_type)) - } else { - quote!(#var_name) - } - }); - - let tagname = names.type_(&u.tag.name); - - let read_variant = u.variants.iter().map(|v| { - let variantname = names.enum_variant(&v.name); - if let Some(tref) = &v.tref { - let varianttype = names.type_ref(tref, lifetime.clone()); - quote! { - #tagname::#variantname => { - let variant_ptr = location.cast::().add(#contents_offset)?; - let variant_val = <#varianttype as #rt::GuestType>::read(&variant_ptr.cast())?; - Ok(#ident::#variantname(variant_val)) - } - } - } else { - quote! { #tagname::#variantname => Ok(#ident::#variantname), } - } - }); - - let write_variant = u.variants.iter().map(|v| { - let variantname = names.enum_variant(&v.name); - let write_tag = quote! { - location.cast().write(#tagname::#variantname)?; - }; - if let Some(tref) = &v.tref { - let varianttype = names.type_ref(tref, lifetime.clone()); - quote! { - #ident::#variantname(contents) => { - #write_tag - let variant_ptr = location.cast::().add(#contents_offset)?; - <#varianttype as #rt::GuestType>::write(&variant_ptr.cast(), contents)?; - } - } - } else { - quote! { - #ident::#variantname => { - #write_tag - } - } - } - }); - - let (enum_lifetime, extra_derive) = if u.needs_lifetime() { - (quote!(<'a>), quote!()) - } else { - (quote!(), quote!(, PartialEq)) - }; - - quote! { - #[derive(Clone, Debug #extra_derive)] - pub enum #ident #enum_lifetime { - #(#variants),* - } - - impl<'a> #rt::GuestType<'a> for #ident #enum_lifetime { - fn guest_size() -> u32 { - #size - } - - fn guest_align() -> usize { - #align - } - - fn read(location: &#rt::GuestPtr<'a, Self>) - -> Result - { - let tag = location.cast().read()?; - match tag { - #(#read_variant)* - } - - } - - fn write(location: &#rt::GuestPtr<'_, Self>, val: Self) - -> Result<(), #rt::GuestError> - { - match val { - #(#write_variant)* - } - Ok(()) - } - } - } -} - -impl super::WiggleType for witx::UnionDatatype { - fn impls_display(&self) -> bool { - false - } -} diff --git a/crates/wiggle/generate/src/types/variant.rs b/crates/wiggle/generate/src/types/variant.rs new file mode 100644 index 000000000000..93df4edb1d78 --- /dev/null +++ b/crates/wiggle/generate/src/types/variant.rs @@ -0,0 +1,149 @@ +use crate::lifetimes::LifetimeExt; +use crate::names::Names; + +use proc_macro2::{Literal, TokenStream}; +use quote::quote; +use witx::Layout; + +pub(super) fn define_variant(names: &Names, name: &witx::Id, v: &witx::Variant) -> TokenStream { + let rt = names.runtime_mod(); + let ident = names.type_(name); + let size = v.mem_size_align().size as u32; + let align = v.mem_size_align().align as usize; + let contents_offset = v.payload_offset() as u32; + + let lifetime = quote!('a); + let tag_ty = super::int_repr_tokens(v.tag_repr); + + let variants = v.cases.iter().map(|c| { + let var_name = names.enum_variant(&c.name); + if let Some(tref) = &c.tref { + let var_type = names.type_ref(&tref, lifetime.clone()); + quote!(#var_name(#var_type)) + } else { + quote!(#var_name) + } + }); + + let read_variant = v.cases.iter().enumerate().map(|(i, c)| { + let i = Literal::usize_unsuffixed(i); + let variantname = names.enum_variant(&c.name); + if let Some(tref) = &c.tref { + let varianttype = names.type_ref(tref, lifetime.clone()); + quote! { + #i => { + let variant_ptr = location.cast::().add(#contents_offset)?; + let variant_val = <#varianttype as #rt::GuestType>::read(&variant_ptr.cast())?; + Ok(#ident::#variantname(variant_val)) + } + } + } else { + quote! { #i => Ok(#ident::#variantname), } + } + }); + + let write_variant = v.cases.iter().enumerate().map(|(i, c)| { + let variantname = names.enum_variant(&c.name); + let write_tag = quote! { + location.cast().write(#i as #tag_ty)?; + }; + if let Some(tref) = &c.tref { + let varianttype = names.type_ref(tref, lifetime.clone()); + quote! { + #ident::#variantname(contents) => { + #write_tag + let variant_ptr = location.cast::().add(#contents_offset)?; + <#varianttype as #rt::GuestType>::write(&variant_ptr.cast(), contents)?; + } + } + } else { + quote! { + #ident::#variantname => { + #write_tag + } + } + } + }); + + let mut extra_derive = quote!(); + let enum_try_from = if v.cases.iter().all(|c| c.tref.is_none()) { + let tryfrom_repr_cases = v.cases.iter().enumerate().map(|(i, c)| { + let variant_name = names.enum_variant(&c.name); + let n = Literal::usize_unsuffixed(i); + quote!(#n => Ok(#ident::#variant_name)) + }); + let abi_ty = names.wasm_type(v.tag_repr.into()); + extra_derive = quote!(, Copy); + quote! { + impl TryFrom<#tag_ty> for #ident { + type Error = #rt::GuestError; + fn try_from(value: #tag_ty) -> Result<#ident, #rt::GuestError> { + match value { + #(#tryfrom_repr_cases),*, + _ => Err( #rt::GuestError::InvalidEnumValue(stringify!(#ident))), + } + } + } + + impl TryFrom<#abi_ty> for #ident { + type Error = #rt::GuestError; + fn try_from(value: #abi_ty) -> Result<#ident, #rt::GuestError> { + #ident::try_from(#tag_ty::try_from(value)?) + } + } + } + } else { + quote!() + }; + + let (enum_lifetime, extra_derive) = if v.needs_lifetime() { + (quote!(<'a>), quote!()) + } else { + (quote!(), quote!(, PartialEq #extra_derive)) + }; + + quote! { + #[derive(Clone, Debug #extra_derive)] + pub enum #ident #enum_lifetime { + #(#variants),* + } + + #enum_try_from + + impl<'a> #rt::GuestType<'a> for #ident #enum_lifetime { + fn guest_size() -> u32 { + #size + } + + fn guest_align() -> usize { + #align + } + + fn read(location: &#rt::GuestPtr<'a, Self>) + -> Result + { + let tag = location.cast::<#tag_ty>().read()?; + match tag { + #(#read_variant)* + _ => Err(#rt::GuestError::InvalidEnumValue(stringify!(#ident))), + } + + } + + fn write(location: &#rt::GuestPtr<'_, Self>, val: Self) + -> Result<(), #rt::GuestError> + { + match val { + #(#write_variant)* + } + Ok(()) + } + } + } +} + +impl super::WiggleType for witx::Variant { + fn impls_display(&self) -> bool { + false + } +} diff --git a/crates/wiggle/macro/Cargo.toml b/crates/wiggle/macro/Cargo.toml index c18c3dee745f..baee8ce1647c 100644 --- a/crates/wiggle/macro/Cargo.toml +++ b/crates/wiggle/macro/Cargo.toml @@ -22,7 +22,7 @@ doctest = false [dependencies] wiggle-generate = { path = "../generate", version = "0.23.0" } -witx = { path = "../../wasi-common/WASI/tools/witx", version = "0.8.7" } +witx = { version = "0.9", path = "../../wasi-common/WASI/tools/witx" } quote = "1.0" syn = { version = "1.0", features = ["full"] } diff --git a/crates/wiggle/src/lib.rs b/crates/wiggle/src/lib.rs index 4ecbf27da543..24a4ca7c4077 100644 --- a/crates/wiggle/src/lib.rs +++ b/crates/wiggle/src/lib.rs @@ -942,3 +942,9 @@ pub enum Trap { /// Any other Trap is just an unstructured String, for reporting and debugging. String(String), } + +impl From for Trap { + fn from(err: GuestError) -> Trap { + Trap::String(err.to_string()) + } +} diff --git a/crates/wiggle/test-helpers/examples/tracing.rs b/crates/wiggle/test-helpers/examples/tracing.rs index 0f06e1850905..fe2dd51d8e7e 100644 --- a/crates/wiggle/test-helpers/examples/tracing.rs +++ b/crates/wiggle/test-helpers/examples/tracing.rs @@ -15,15 +15,14 @@ pub enum RichError { // trivial function. wiggle::from_witx!({ witx_literal: " -(typename $errno (enum u8 $ok $invalid_arg $picket_line)) -(typename $s (struct (field $f1 (@witx usize)) (field $f2 (@witx pointer u8)))) -(typename $t (struct (field $f1 u32) (field $f2 f32))) +(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line)) +(typename $s (record (field $f1 (@witx usize)) (field $f2 (@witx pointer u8)))) +(typename $t (record (field $f1 u32) (field $f2 f32))) (module $one_error_conversion (@interface func (export \"foo\") (param $strike u32) (param $s $s) - (result $err $errno) - (result $t $t))) + (result $err (expected $t (error $errno))))) ", ctx: WasiCtx, errors: { errno => RichError }, @@ -90,7 +89,7 @@ fn main() { let r0 = one_error_conversion::foo(&ctx, &host_memory, 0, 0, 8); assert_eq!( r0, - Ok(i32::from(types::Errno::Ok)), + Ok(types::Errno::Ok as i32), "Expected return value for strike=0" ); assert!(ctx.log.borrow().is_empty(), "No error log for strike=0"); @@ -99,7 +98,7 @@ fn main() { let r1 = one_error_conversion::foo(&ctx, &host_memory, 1, 0, 8); assert_eq!( r1, - Ok(i32::from(types::Errno::PicketLine)), + Ok(types::Errno::PicketLine as i32), "Expected return value for strike=1" ); assert_eq!( @@ -112,7 +111,7 @@ fn main() { let r2 = one_error_conversion::foo(&ctx, &host_memory, 2, 0, 8); assert_eq!( r2, - Ok(i32::from(types::Errno::InvalidArg)), + Ok(types::Errno::InvalidArg as i32), "Expected return value for strike=2" ); assert_eq!( diff --git a/crates/wiggle/tests/arrays.rs b/crates/wiggle/tests/arrays.rs index b796a212d799..f5e577ba2940 100644 --- a/crates/wiggle/tests/arrays.rs +++ b/crates/wiggle/tests/arrays.rs @@ -105,7 +105,7 @@ impl ReduceExcusesExcercise { self.return_ptr_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "reduce excuses errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "reduce excuses errno"); let expected = *self .excuse_values @@ -183,7 +183,7 @@ impl PopulateExcusesExcercise { self.array_ptr_loc.ptr as i32, self.elements.len() as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "populate excuses errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "populate excuses errno"); let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> = host_memory.ptr((self.array_ptr_loc.ptr, self.elements.len() as u32)); @@ -309,7 +309,7 @@ impl SumElementsExercise { self.start_ix as i32, self.return_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "sum_of_element errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "sum_of_element errno"); let result_ptr = host_memory.ptr::(self.return_loc.ptr); let result = result_ptr.read().expect("read result"); @@ -330,7 +330,7 @@ impl SumElementsExercise { ); assert_eq!( res, - Ok(types::Errno::InvalidArg.into()), + Ok(types::Errno::InvalidArg as i32), "out of bounds sum_of_element errno" ); @@ -346,7 +346,7 @@ impl SumElementsExercise { if self.start_ix <= self.end_ix { assert_eq!( res, - Ok(types::Errno::Ok.into()), + Ok(types::Errno::Ok as i32), "expected ok sum_of_elements errno" ); let result_ptr = host_memory.ptr::(self.return_loc.ptr); @@ -367,7 +367,7 @@ impl SumElementsExercise { } else { assert_eq!( res, - Ok(types::Errno::InvalidArg.into()), + Ok(types::Errno::InvalidArg as i32), "expected error out-of-bounds sum_of_elements" ); } @@ -384,7 +384,7 @@ impl SumElementsExercise { ); assert_eq!( res, - Ok(types::Errno::InvalidArg.into()), + Ok(types::Errno::InvalidArg as i32), "out of bounds sum_of_elements errno" ); } diff --git a/crates/wiggle/tests/arrays.witx b/crates/wiggle/tests/arrays.witx index 4b6a1f14c56c..3522fc40961b 100644 --- a/crates/wiggle/tests/arrays.witx +++ b/crates/wiggle/tests/arrays.witx @@ -1,36 +1,36 @@ (use "errno.witx") (use "excuse.witx") -(typename $const_excuse_array (array (@witx const_pointer $excuse))) -(typename $excuse_array (array (@witx pointer $excuse))) +(typename $const_excuse_array (list (@witx const_pointer $excuse))) +(typename $excuse_array (list (@witx pointer $excuse))) (module $arrays (@interface func (export "reduce_excuses") (param $excuses $const_excuse_array) - (result $error $errno) - (result $reduced $excuse) + (result $error (expected $excuse (error $errno))) ) (@interface func (export "populate_excuses") (param $excuses $excuse_array) - (result $error $errno) + (result $error (expected (error $errno))) ) ) (typename $pair_ints - (struct + (record (field $first s32) (field $second s32))) +(typename $s32 s32) + (module $array_traversal (@interface func (export "sum_of_element") - (param $elements (array $pair_ints)) + (param $elements (list $pair_ints)) (param $index (@witx usize)) - (result $error $errno) - (result $sum s32)) + (result $error (expected $s32 (error $errno)))) (@interface func (export "sum_of_elements") - (param $elements (array $pair_ints)) + (param $elements (list $pair_ints)) (param $start (@witx usize)) (param $end (@witx usize)) - (result $error $errno) - (result $sum s32))) + (result $error (expected $s32 (error $errno)))) +) diff --git a/crates/wiggle/tests/atoms.rs b/crates/wiggle/tests/atoms.rs index f2da4827a80b..b39bec5b1559 100644 --- a/crates/wiggle/tests/atoms.rs +++ b/crates/wiggle/tests/atoms.rs @@ -34,7 +34,7 @@ impl IntFloatExercise { let e = atoms::int_float_args(&ctx, &host_memory, self.an_int as i32, self.an_float); - assert_eq!(e, Ok(types::Errno::Ok.into()), "int_float_args error"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "int_float_args error"); } pub fn strat() -> BoxedStrategy { @@ -72,7 +72,7 @@ impl DoubleIntExercise { .ptr::(self.return_loc.ptr) .read() .expect("failed to read return"); - assert_eq!(e, Ok(types::Errno::Ok.into()), "errno"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "errno"); assert_eq!(return_val, (self.input as f32) * 2.0, "return val"); } diff --git a/crates/wiggle/tests/atoms.witx b/crates/wiggle/tests/atoms.witx index 932d7c9ffdf2..87144fc3eeac 100644 --- a/crates/wiggle/tests/atoms.witx +++ b/crates/wiggle/tests/atoms.witx @@ -6,9 +6,8 @@ (@interface func (export "int_float_args") (param $an_int u32) (param $an_float f32) - (result $error $errno)) + (result $error (expected (error $errno)))) (@interface func (export "double_int_return_float") (param $an_int u32) - (result $error $errno) - (result $doubled_it $alias_to_float)) + (result $error (expected $alias_to_float (error $errno)))) ) diff --git a/crates/wiggle/tests/errno.witx b/crates/wiggle/tests/errno.witx index 36ee67622eec..845e2389ed7a 100644 --- a/crates/wiggle/tests/errno.witx +++ b/crates/wiggle/tests/errno.witx @@ -1,5 +1,5 @@ (typename $errno - (enum u32 + (enum (@witx tag u32) ;;; Success $ok ;;; Invalid argument diff --git a/crates/wiggle/tests/errors.rs b/crates/wiggle/tests/errors.rs index 425296246967..53d39a233d97 100644 --- a/crates/wiggle/tests/errors.rs +++ b/crates/wiggle/tests/errors.rs @@ -17,11 +17,11 @@ mod convert_just_errno { // trivial function. wiggle::from_witx!({ witx_literal: " -(typename $errno (enum u8 $ok $invalid_arg $picket_line)) +(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line)) (module $one_error_conversion (@interface func (export \"foo\") (param $strike u32) - (result $err $errno))) + (result $err (expected (error $errno))))) ", ctx: WasiCtx, errors: { errno => RichError }, @@ -68,7 +68,7 @@ mod convert_just_errno { let r0 = one_error_conversion::foo(&ctx, &host_memory, 0); assert_eq!( r0, - Ok(i32::from(types::Errno::Ok)), + Ok(types::Errno::Ok as i32), "Expected return value for strike=0" ); assert!(ctx.log.borrow().is_empty(), "No error log for strike=0"); @@ -77,7 +77,7 @@ mod convert_just_errno { let r1 = one_error_conversion::foo(&ctx, &host_memory, 1); assert_eq!( r1, - Ok(i32::from(types::Errno::PicketLine)), + Ok(types::Errno::PicketLine as i32), "Expected return value for strike=1" ); assert_eq!( @@ -90,7 +90,7 @@ mod convert_just_errno { let r2 = one_error_conversion::foo(&ctx, &host_memory, 2); assert_eq!( r2, - Ok(i32::from(types::Errno::InvalidArg)), + Ok(types::Errno::InvalidArg as i32), "Expected return value for strike=2" ); assert_eq!( @@ -120,15 +120,15 @@ mod convert_multiple_error_types { // Additionally, test that the function "baz" marked noreturn always returns a wiggle::Trap. wiggle::from_witx!({ witx_literal: " -(typename $errno (enum u8 $ok $invalid_arg $picket_line)) -(typename $errno2 (enum u8 $ok $too_much_coffee)) +(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line)) +(typename $errno2 (enum (@witx tag u8) $ok $too_much_coffee)) (module $two_error_conversions (@interface func (export \"foo\") (param $strike u32) - (result $err $errno)) + (result $err (expected (error $errno)))) (@interface func (export \"bar\") (param $drink u32) - (result $err $errno2)) + (result $err (expected (error $errno2)))) (@interface func (export \"baz\") (param $drink u32) (@witx noreturn))) diff --git a/crates/wiggle/tests/excuse.witx b/crates/wiggle/tests/excuse.witx index 14a927164eb6..1aacc92709f4 100644 --- a/crates/wiggle/tests/excuse.witx +++ b/crates/wiggle/tests/excuse.witx @@ -1,5 +1,5 @@ (typename $excuse - (enum u8 + (enum (@witx tag u8) $dog_ate $traffic $sleeping)) diff --git a/crates/wiggle/tests/flags.rs b/crates/wiggle/tests/flags.rs index 1a2bb0019fdb..b97285a94a71 100644 --- a/crates/wiggle/tests/flags.rs +++ b/crates/wiggle/tests/flags.rs @@ -75,11 +75,11 @@ impl ConfigureCarExercise { let res = flags::configure_car( &ctx, &host_memory, - self.old_config.into(), + self.old_config.bits() as i32, self.other_config_by_ptr.ptr as i32, self.return_ptr_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "configure car errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "configure car errno"); let res_config = host_memory .ptr::(self.return_ptr_loc.ptr) diff --git a/crates/wiggle/tests/flags.witx b/crates/wiggle/tests/flags.witx index b46f73d5b5b2..98dbf911e9d7 100644 --- a/crates/wiggle/tests/flags.witx +++ b/crates/wiggle/tests/flags.witx @@ -1,7 +1,7 @@ (use "errno.witx") (typename $car_config - (flags u8 + (flags (@witx repr u8) $automatic $awd $suv)) @@ -10,7 +10,6 @@ (@interface func (export "configure_car") (param $old_config $car_config) (param $old_config_by_ptr (@witx const_pointer $car_config)) - (result $error $errno) - (result $new_config $car_config) + (result $error (expected $car_config (error $errno))) ) ) diff --git a/crates/wiggle/tests/handles.rs b/crates/wiggle/tests/handles.rs index 4ad9085a42da..d562e0bb14f6 100644 --- a/crates/wiggle/tests/handles.rs +++ b/crates/wiggle/tests/handles.rs @@ -37,7 +37,7 @@ impl HandleExercise { let e = handle_examples::fd_create(&ctx, &host_memory, self.return_loc.ptr as i32); - assert_eq!(e, Ok(types::Errno::Ok.into()), "fd_create error"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "fd_create error"); let h_got: u32 = host_memory .ptr(self.return_loc.ptr) @@ -48,13 +48,13 @@ impl HandleExercise { let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32); - assert_eq!(e, Ok(types::Errno::Ok.into()), "fd_consume error"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "fd_consume error"); let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32 + 1); assert_eq!( e, - Ok(types::Errno::InvalidArg.into()), + Ok(types::Errno::InvalidArg as i32), "fd_consume invalid error" ); } diff --git a/crates/wiggle/tests/handles.witx b/crates/wiggle/tests/handles.witx index 69c1b0546ea1..6991d9dc2223 100644 --- a/crates/wiggle/tests/handles.witx +++ b/crates/wiggle/tests/handles.witx @@ -4,9 +4,8 @@ (module $handle_examples (@interface func (export "fd_create") - (result $error $errno) - (result $fd $fd)) + (result $error (expected $fd (error $errno)))) (@interface func (export "fd_consume") (param $fd $fd) - (result $error $errno)) + (result $error (expected (error $errno)))) ) diff --git a/crates/wiggle/tests/ints.rs b/crates/wiggle/tests/ints.rs index 82d04a4a00db..d09615cca697 100644 --- a/crates/wiggle/tests/ints.rs +++ b/crates/wiggle/tests/ints.rs @@ -12,7 +12,7 @@ impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> ints::Ints for WasiCtx<'a> { fn cookie_cutter(&self, init_cookie: types::Cookie) -> Result { - let res = if init_cookie == types::Cookie::START { + let res = if init_cookie == types::COOKIE_START { types::Bool::True } else { types::Bool::False @@ -50,10 +50,10 @@ impl CookieCutterExercise { let res = ints::cookie_cutter( &ctx, &host_memory, - self.cookie.into(), + self.cookie as i64, self.return_ptr_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "cookie cutter errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "cookie cutter errno"); let is_cookie_start = host_memory .ptr::(self.return_ptr_loc.ptr) @@ -66,7 +66,7 @@ impl CookieCutterExercise { } else { false }, - self.cookie == types::Cookie::START, + self.cookie == types::COOKIE_START, "returned Bool should test if input was Cookie::START", ); } diff --git a/crates/wiggle/tests/ints.witx b/crates/wiggle/tests/ints.witx index 09dc62f5ec97..2ad73600a206 100644 --- a/crates/wiggle/tests/ints.witx +++ b/crates/wiggle/tests/ints.witx @@ -1,18 +1,13 @@ (use "errno.witx") -(typename $cookie - (int u64 - (const $start 0))) +(typename $cookie u64) +(@witx const $cookie $start 0) -(typename $bool - (enum u8 - $false - $true)) +(typename $bool bool) (module $ints (@interface func (export "cookie_cutter") (param $init_cookie $cookie) - (result $error $errno) - (result $is_start $bool) + (result $error (expected $bool (error $errno))) ) ) diff --git a/crates/wiggle/tests/keywords.rs b/crates/wiggle/tests/keywords.rs index bc1ee4edce04..1aa84e188ae6 100644 --- a/crates/wiggle/tests/keywords.rs +++ b/crates/wiggle/tests/keywords.rs @@ -8,7 +8,7 @@ mod enum_test { wiggle::from_witx!({ witx_literal: "(typename $self - (enum u8 + (enum (@witx tag u8) $self $2big ) @@ -35,7 +35,7 @@ mod module_trait_fn_and_arg_test { }); impl<'a> self_::Self_ for WasiCtx<'a> { #[allow(unused_variables)] - fn fn_(&self, use_: u32, virtual_: u32) -> Result<(), ()> { + fn fn_(&self, use_: u32, virtual_: u32) { unimplemented!(); } } @@ -46,7 +46,7 @@ mod struct_test { wiggle::from_witx!({ witx_literal: "(typename $self - (struct + (record (field $become s32) (field $mut s32) ) diff --git a/crates/wiggle/tests/keywords_union.witx b/crates/wiggle/tests/keywords_union.witx index 14d29b70ddef..7e3dcf99bfe9 100644 --- a/crates/wiggle/tests/keywords_union.witx +++ b/crates/wiggle/tests/keywords_union.witx @@ -1,15 +1,15 @@ (typename $union - (enum u8 + (enum (@witx tag u8) $self $power ) ) (typename $self - (union $union + (variant (@witx tag $union) ;; A union variant that will expand to a strict keyword `Self`. - (field $self (@witx pointer f32)) + (case $self (@witx pointer f32)) ;; Oh it's true, that there's power in a union! - (field $power (@witx pointer f32)) + (case $power (@witx pointer f32)) ) ) diff --git a/crates/wiggle/tests/pointers.rs b/crates/wiggle/tests/pointers.rs index 5bc271948036..ebae550fc3f1 100644 --- a/crates/wiggle/tests/pointers.rs +++ b/crates/wiggle/tests/pointers.rs @@ -152,12 +152,12 @@ impl PointersAndEnumsExercise { let e = pointers::pointers_and_enums( &ctx, &host_memory, - self.input1.into(), + self.input1 as i32, self.input2_loc.ptr as i32, self.input3_loc.ptr as i32, self.input4_ptr_loc.ptr as i32, ); - assert_eq!(e, Ok(types::Errno::Ok.into()), "errno"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "errno"); // Implementation of pointers_and_enums writes input3 to the input2_loc: let written_to_input2_loc: i32 = host_memory @@ -166,8 +166,7 @@ impl PointersAndEnumsExercise { .expect("input2 ref"); assert_eq!( - written_to_input2_loc, - self.input3.into(), + written_to_input2_loc, self.input3 as i32, "pointers_and_enums written to input2" ); diff --git a/crates/wiggle/tests/pointers.witx b/crates/wiggle/tests/pointers.witx index 9a73a3752054..f5243b667eaa 100644 --- a/crates/wiggle/tests/pointers.witx +++ b/crates/wiggle/tests/pointers.witx @@ -7,5 +7,5 @@ (param $an_excuse_by_reference (@witx pointer $excuse)) (param $a_lamer_excuse (@witx const_pointer $excuse)) (param $two_layers_of_excuses (@witx pointer (@witx const_pointer $excuse))) - (result $error $errno)) + (result $error (expected (error $errno)))) ) diff --git a/crates/wiggle/tests/strings.rs b/crates/wiggle/tests/strings.rs index a55917e4dff7..0caeb73782d4 100644 --- a/crates/wiggle/tests/strings.rs +++ b/crates/wiggle/tests/strings.rs @@ -88,7 +88,7 @@ impl HelloStringExercise { self.test_word.len() as i32, self.return_ptr_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "hello string errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "hello string errno"); let given = host_memory .ptr::(self.return_ptr_loc.ptr) @@ -209,7 +209,7 @@ impl MultiStringExercise { self.c.len() as i32, self.return_ptr_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "multi string errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "multi string errno"); let given = host_memory .ptr::(self.return_ptr_loc.ptr) @@ -287,7 +287,7 @@ impl OverlappingStringExercise { a_len - self.offset_c as i32, self.return_ptr_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "multi string errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "multi string errno"); let given = host_memory .ptr::(self.return_ptr_loc.ptr) diff --git a/crates/wiggle/tests/strings.witx b/crates/wiggle/tests/strings.witx index b3531e87bb21..918c1b327a27 100644 --- a/crates/wiggle/tests/strings.witx +++ b/crates/wiggle/tests/strings.witx @@ -1,16 +1,17 @@ (use "errno.witx") + +(typename $ret u32) + (module $strings (@interface func (export "hello_string") (param $a_string string) - (result $error $errno) - (result $total_bytes u32) + (result $error (expected $ret (error $errno))) ) (@interface func (export "multi_string") (param $a string) (param $b string) (param $c string) - (result $error $errno) - (result $total_bytes u32) + (result $error (expected $ret (error $errno))) ) ) diff --git a/crates/wiggle/tests/structs.rs b/crates/wiggle/tests/structs.rs index 9e92f1b86e3c..537ac0afb56d 100644 --- a/crates/wiggle/tests/structs.rs +++ b/crates/wiggle/tests/structs.rs @@ -118,7 +118,7 @@ impl SumOfPairExercise { self.return_loc.ptr as i32, ); - assert_eq!(sum_err, Ok(types::Errno::Ok.into()), "sum errno"); + assert_eq!(sum_err, Ok(types::Errno::Ok as i32), "sum errno"); let return_val: i64 = host_memory .ptr(self.return_loc.ptr) @@ -218,7 +218,7 @@ impl SumPairPtrsExercise { assert_eq!( res, - Ok(types::Errno::Ok.into()), + Ok(types::Errno::Ok as i32), "sum of pair of ptrs errno" ); @@ -299,7 +299,7 @@ impl SumIntAndPtrExercise { self.return_loc.ptr as i32, ); - assert_eq!(res, Ok(types::Errno::Ok.into()), "sum of int and ptr errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "sum of int and ptr errno"); let doubled: i64 = host_memory .ptr(self.return_loc.ptr) @@ -338,7 +338,7 @@ impl ReturnPairInts { let err = structs::return_pair_ints(&ctx, &host_memory, self.return_loc.ptr as i32); - assert_eq!(err, Ok(types::Errno::Ok.into()), "return struct errno"); + assert_eq!(err, Ok(types::Errno::Ok as i32), "return struct errno"); let return_struct: types::PairInts = host_memory .ptr(self.return_loc.ptr) @@ -420,7 +420,7 @@ impl ReturnPairPtrsExercise { assert_eq!( res, - Ok(types::Errno::Ok.into()), + Ok(types::Errno::Ok as i32), "return pair of ptrs errno" ); @@ -530,7 +530,7 @@ impl SumArrayExercise { ); // should be no error - if hostcall did a GuestError it should eprintln it. - assert_eq!(res, Ok(types::Errno::Ok.into()), "reduce excuses errno"); + assert_eq!(res, Ok(types::Errno::Ok as i32), "reduce excuses errno"); // Sum is inputs upcasted to u16 let expected: u16 = self.inputs.iter().map(|v| *v as u16).sum(); diff --git a/crates/wiggle/tests/structs.witx b/crates/wiggle/tests/structs.witx index 2a64b125f943..16f5ced8ec84 100644 --- a/crates/wiggle/tests/structs.witx +++ b/crates/wiggle/tests/structs.witx @@ -2,49 +2,46 @@ (use "errno.witx") (typename $pair_ints - (struct + (record (field $first s32) (field $second s32))) (typename $pair_int_ptrs - (struct + (record (field $first (@witx const_pointer s32)) (field $second (@witx const_pointer s32)))) (typename $pair_int_and_ptr - (struct + (record (field $first (@witx const_pointer s32)) (field $second s32))) -(typename $some_bytes (array u8)) +(typename $some_bytes (list u8)) (typename $struct_of_array - (struct + (record (field $arr $some_bytes))) +(typename $s64 s64) +(typename $u16 u16) + (module $structs (@interface func (export "sum_of_pair") (param $an_pair $pair_ints) - (result $error $errno) - (result $doubled s64)) + (result $error (expected $s64 (error $errno)))) (@interface func (export "sum_of_pair_of_ptrs") (param $an_pair $pair_int_ptrs) - (result $error $errno) - (result $doubled s64)) + (result $error (expected $s64 (error $errno)))) (@interface func (export "sum_of_int_and_ptr") (param $an_pair $pair_int_and_ptr) - (result $error $errno) - (result $double s64)) + (result $error (expected $s64 (error $errno)))) (@interface func (export "return_pair_ints") - (result $error $errno) - (result $an_pair $pair_ints)) + (result $error (expected $pair_ints (error $errno)))) (@interface func (export "return_pair_of_ptrs") (param $first (@witx const_pointer s32)) (param $second (@witx const_pointer s32)) - (result $error $errno) - (result $an_pair $pair_int_ptrs)) + (result $error (expected $pair_int_ptrs (error $errno)))) (@interface func (export "sum_array") (param $an_arr $struct_of_array) - (result $error $errno) - (result $doubled u16)) + (result $error (expected $u16 (error $errno)))) ) diff --git a/crates/wiggle/tests/typenames.witx b/crates/wiggle/tests/typenames.witx index 1351fc4e13ce..df60c5c34e17 100644 --- a/crates/wiggle/tests/typenames.witx +++ b/crates/wiggle/tests/typenames.witx @@ -15,7 +15,7 @@ ;;; Identifiers for clocks. (typename $clockid - (enum u32 + (enum (@witx tag u32) ;;; The clock measuring real time. Time value zero corresponds with ;;; 1970-01-01T00:00:00Z. $realtime @@ -36,7 +36,7 @@ ;;; API; some are used in higher-level library layers, and others are provided ;;; merely for alignment with POSIX. (typename $errno - (enum u16 + (enum (@witx tag u16) ;;; No error occurred. System call completed successfully. $success ;;; Argument list too long. @@ -196,7 +196,7 @@ ;;; File descriptor rights, determining which actions may be performed. (typename $rights - (flags u64 + (flags (@witx repr u64) ;;; The right to invoke `fd_datasync`. ;; ;;; If `path_open` is set, includes the right to invoke @@ -278,7 +278,7 @@ ;;; A region of memory for scatter/gather reads. (typename $iovec - (struct + (record ;;; The address of the buffer to be filled. (field $buf (@witx pointer u8)) ;;; The length of the buffer to be filled. @@ -288,7 +288,7 @@ ;;; A region of memory for scatter/gather writes. (typename $ciovec - (struct + (record ;;; The address of the buffer to be written. (field $buf (@witx const_pointer u8)) ;;; The length of the buffer to be written. @@ -296,15 +296,15 @@ ) ) -(typename $iovec_array (array $iovec)) -(typename $ciovec_array (array $ciovec)) +(typename $iovec_array (list $iovec)) +(typename $ciovec_array (list $ciovec)) ;;; Relative offset within a file. (typename $filedelta s64) ;;; The position relative to which to set the offset of the file descriptor. (typename $whence - (enum u8 + (enum (@witx tag u8) ;;; Seek relative to start-of-file. $set ;;; Seek relative to current position. @@ -327,7 +327,7 @@ ;;; The type of a file descriptor or file. (typename $filetype - (enum u8 + (enum (@witx tag u8) ;;; The type of the file descriptor or file is unknown or is different from any of the other types specified. $unknown ;;; The file descriptor or file refers to a block device inode. @@ -349,7 +349,7 @@ ;;; A directory entry. (typename $dirent - (struct + (record ;;; The offset of the next directory entry stored in this directory. (field $d_next $dircookie) ;;; The serial number of the file referred to by this directory entry. @@ -363,7 +363,7 @@ ;;; File or memory access pattern advisory information. (typename $advice - (enum u8 + (enum (@witx tag u8) ;;; The application has no advice to give on its behavior with respect to the specified data. $normal ;;; The application expects to access the specified data sequentially from lower offsets to higher offsets. @@ -381,7 +381,7 @@ ;;; File descriptor flags. (typename $fdflags - (flags u16 + (flags (@witx repr u16) ;;; Append mode: Data written to the file is always appended to the file's end. $append ;;; Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. @@ -399,7 +399,7 @@ ;;; File descriptor attributes. (typename $fdstat - (struct + (record ;;; File type. (field $fs_filetype $filetype) ;;; File descriptor flags. @@ -418,7 +418,7 @@ ;;; Which file time attributes to adjust. (typename $fstflags - (flags u16 + (flags (@witx repr u16) ;;; Adjust the last data access timestamp to the value stored in `filestat::atim`. $atim ;;; Adjust the last data access timestamp to the time of clock `clockid::realtime`. @@ -432,7 +432,7 @@ ;;; Flags determining the method of how paths are resolved. (typename $lookupflags - (flags u32 + (flags (@witx repr u32) ;;; As long as the resolved path corresponds to a symbolic link, it is expanded. $symlink_follow ) @@ -440,7 +440,7 @@ ;;; Open flags used by `path_open`. (typename $oflags - (flags u16 + (flags (@witx repr u16) ;;; Create file if it does not exist. $creat ;;; Fail if not a directory. @@ -457,7 +457,7 @@ ;;; File attributes. (typename $filestat - (struct + (record ;;; Device ID of device containing the file. (field $dev $device) ;;; File serial number. @@ -483,7 +483,7 @@ ;;; Type of a subscription to an event or its occurrence. (typename $eventtype - (enum u8 + (enum (@witx tag u8) ;;; The time value of clock `subscription_clock::id` has ;;; reached timestamp `subscription_clock::timeout`. $clock @@ -499,7 +499,7 @@ ;;; The state of the file descriptor subscribed to with ;;; `eventtype::fd_read` or `eventtype::fd_write`. (typename $eventrwflags - (flags u16 + (flags (@witx repr u16) ;;; The peer of this socket has closed or disconnected. $fd_readwrite_hangup ) @@ -508,7 +508,7 @@ ;;; The contents of an $event when type is `eventtype::fd_read` or ;;; `eventtype::fd_write`. (typename $event_fd_readwrite - (struct + (record ;;; The number of bytes available for reading or writing. (field $nbytes $filesize) ;;; The state of the file descriptor. @@ -518,7 +518,7 @@ ;;; An event that occurred. (typename $event - (struct + (record ;;; User-provided value that got attached to `subscription::userdata`. (field $userdata $userdata) ;;; If non-zero, an error that occurred while processing the subscription request. @@ -534,7 +534,7 @@ ;;; Flags determining how to interpret the timestamp provided in ;;; `subscription_clock::timeout`. (typename $subclockflags - (flags u16 + (flags (@witx repr u16) ;;; If set, treat the timestamp provided in ;;; `subscription_clock::timeout` as an absolute timestamp of clock ;;; `subscription_clock::id`. If clear, treat the timestamp @@ -546,7 +546,7 @@ ;;; The contents of a `subscription` when type is `eventtype::clock`. (typename $subscription_clock - (struct + (record ;;; The clock against which to compare the timestamp. (field $id $clockid) ;;; The absolute or relative timestamp. @@ -562,7 +562,7 @@ ;;; The contents of a `subscription` when type is type is ;;; `eventtype::fd_read` or `eventtype::fd_write`. (typename $subscription_fd_readwrite - (struct + (record ;;; The file descriptor on which to wait for it to become ready for reading or writing. (field $file_descriptor $fd) ) @@ -570,16 +570,16 @@ ;;; The contents of a `subscription`. (typename $subscription_u - (union $eventtype - (field $clock $subscription_clock) - (field $fd_read $subscription_fd_readwrite) - (field $fd_write $subscription_fd_readwrite) + (union (@witx tag $eventtype) + $subscription_clock + $subscription_fd_readwrite + $subscription_fd_readwrite ) ) ;;; Subscription to an event. (typename $subscription - (struct + (record ;;; User-provided value that is attached to the subscription in the ;;; implementation and returned through `event::userdata`. (field $userdata $userdata) @@ -593,7 +593,7 @@ ;;; Signal condition. (typename $signal - (enum u8 + (enum (@witx tag u8) ;;; No signal. Note that POSIX has special semantics for `kill(pid, 0)`, ;;; so this value is reserved. $none @@ -606,7 +606,7 @@ ;;; Terminal quit signal. ;;; Action: Terminates the process. $quit - ;;; Illegal instruction. + ;;; Illegal inrecordion. ;;; Action: Terminates the process. $ill ;;; Trace/breakpoint trap. @@ -692,7 +692,7 @@ ;;; Flags provided to `sock_recv`. (typename $riflags - (flags u16 + (flags (@witx repr u16) ;;; Returns the message without removing it from the socket's receive queue. $recv_peek ;;; On byte-stream sockets, block until the full amount of data can be returned. @@ -702,7 +702,7 @@ ;;; Flags returned by `sock_recv`. (typename $roflags - (flags u16 + (flags (@witx repr u16) ;;; Returned by `sock_recv`: Message data has been truncated. $recv_data_truncated ) @@ -714,7 +714,7 @@ ;;; Which channels on a socket to shut down. (typename $sdflags - (flags u8 + (flags (@witx repr u8) ;;; Disables further receive operations. $rd ;;; Disables further send operations. @@ -724,7 +724,7 @@ ;;; Identifiers for preopened capabilities. (typename $preopentype - (enum u8 + (enum (@witx tag u8) ;;; A pre-opened directory. $dir ) @@ -732,7 +732,7 @@ ;;; The contents of a $prestat when type is `preopentype::dir`. (typename $prestat_dir - (struct + (record ;;; The length of the directory name for use with `fd_prestat_dir_name`. (field $pr_name_len $size) ) @@ -740,7 +740,7 @@ ;;; Information about a pre-opened capability. (typename $prestat - (union $preopentype - (field $dir $prestat_dir) + (union (@witx tag $preopentype) + $prestat_dir ) ) diff --git a/crates/wiggle/tests/union.rs b/crates/wiggle/tests/union.rs index 22a9f967ec1c..04a1f4cce06b 100644 --- a/crates/wiggle/tests/union.rs +++ b/crates/wiggle/tests/union.rs @@ -108,7 +108,7 @@ impl GetTagExercise { let ctx = WasiCtx::new(); let host_memory = HostMemory::new(); - let discriminant: u8 = reason_tag(&self.input).into(); + let discriminant = reason_tag(&self.input) as u8; host_memory .ptr(self.input_loc.ptr) .write(discriminant) @@ -133,7 +133,7 @@ impl GetTagExercise { self.return_loc.ptr as i32, ); - assert_eq!(e, Ok(types::Errno::Ok.into()), "get_tag errno"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "get_tag errno"); let return_val: types::Excuse = host_memory .ptr(self.return_loc.ptr) @@ -185,7 +185,7 @@ impl ReasonMultExercise { let ctx = WasiCtx::new(); let host_memory = HostMemory::new(); - let discriminant: u8 = reason_tag(&self.input).into(); + let discriminant = reason_tag(&self.input) as u8; host_memory .ptr(self.input_loc.ptr) .write(discriminant) @@ -217,7 +217,7 @@ impl ReasonMultExercise { self.multiply_by as i32, ); - assert_eq!(e, Ok(types::Errno::Ok.into()), "reason_mult errno"); + assert_eq!(e, Ok(types::Errno::Ok as i32), "reason_mult errno"); match self.input { types::Reason::DogAte(f) => { diff --git a/crates/wiggle/tests/union.witx b/crates/wiggle/tests/union.witx index d76f150ddda0..0559666b8aed 100644 --- a/crates/wiggle/tests/union.witx +++ b/crates/wiggle/tests/union.witx @@ -5,27 +5,26 @@ ;; Fight for the full product of your labor! (typename $reason - (union $excuse - (field $dog_ate f32) - (field $traffic s32) - (empty $sleeping))) + (variant (@witx tag $excuse) + (case $dog_ate f32) + (case $traffic s32) + (case $sleeping))) (typename $reason_mut - (union $excuse - (field $dog_ate (@witx pointer f32)) - (field $traffic (@witx pointer s32)) - (empty $sleeping))) + (variant (@witx tag $excuse) + (case $dog_ate (@witx pointer f32)) + (case $traffic (@witx pointer s32)) + (case $sleeping))) (module $union_example (@interface func (export "get_tag") (param $r $reason) - (result $error $errno) - (result $t $excuse) + (result $error (expected $excuse (error $errno))) ) (@interface func (export "reason_mult") (param $r $reason_mut) (param $multiply_by u32) - (result $error $errno) + (result $error (expected (error $errno))) ) ) diff --git a/crates/wiggle/tests/wasi.rs b/crates/wiggle/tests/wasi.rs index 07b56db62ae5..95c146152680 100644 --- a/crates/wiggle/tests/wasi.rs +++ b/crates/wiggle/tests/wasi.rs @@ -322,7 +322,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> { unimplemented!("poll_oneoff") } - fn proc_exit(&self, _rval: types::Exitcode) -> std::result::Result<(), ()> { + fn proc_exit(&self, _rval: types::Exitcode) -> wiggle::Trap { unimplemented!("proc_exit") } diff --git a/crates/wiggle/tests/wasi.witx b/crates/wiggle/tests/wasi.witx index 98cd94787843..df3c670f3eee 100644 --- a/crates/wiggle/tests/wasi.witx +++ b/crates/wiggle/tests/wasi.witx @@ -17,15 +17,13 @@ (@interface func (export "args_get") (param $argv (@witx pointer (@witx pointer u8))) (param $argv_buf (@witx pointer u8)) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Return command-line argument data sizes. (@interface func (export "args_sizes_get") - (result $error $errno) - ;;; The number of arguments. - (result $argc $size) - ;;; The size of the argument string data. - (result $argv_buf_size $size) + ;;; Returns the number of arguments and the size of the argument string + ;;; data, or an error. + (result $error (expected (tuple $size $size) (error $errno))) ) ;;; Read environment variable data. @@ -33,15 +31,13 @@ (@interface func (export "environ_get") (param $environ (@witx pointer (@witx pointer u8))) (param $environ_buf (@witx pointer u8)) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Return environment variable data sizes. (@interface func (export "environ_sizes_get") - (result $error $errno) - ;;; The number of environment variable arguments. - (result $environc $size) - ;;; The size of the environment variable data. - (result $environ_buf_size $size) + ;;; Returns the number of environment variable arguments and the size of the + ;;; environment variable data. + (result $error (expected (tuple $size $size) (error $errno))) ) ;;; Return the resolution of a clock. @@ -51,9 +47,8 @@ (@interface func (export "clock_res_get") ;;; The clock for which to return the resolution. (param $id $clockid) - (result $error $errno) - ;;; The resolution of the clock. - (result $resolution $timestamp) + ;;; The resolution of the clock, or an error if one happened. + (result $error (expected $timestamp (error $errno))) ) ;;; Return the time value of a clock. ;;; Note: This is similar to `clock_gettime` in POSIX. @@ -62,9 +57,8 @@ (param $id $clockid) ;;; The maximum lag (exclusive) that the returned time value may have, compared to its actual value. (param $precision $timestamp) - (result $error $errno) ;;; The time value of the clock. - (result $time $timestamp) + (result $error (expected $timestamp (error $errno))) ) ;;; Provide file advisory information on a file descriptor. @@ -77,7 +71,7 @@ (param $len $filesize) ;;; The advice. (param $advice $advice) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Force the allocation of space in a file. @@ -88,30 +82,29 @@ (param $offset $filesize) ;;; The length of the area that is allocated. (param $len $filesize) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Close a file descriptor. ;;; Note: This is similar to `close` in POSIX. (@interface func (export "fd_close") (param $fd $fd) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Synchronize the data of a file to disk. ;;; Note: This is similar to `fdatasync` in POSIX. (@interface func (export "fd_datasync") (param $fd $fd) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Get the attributes of a file descriptor. ;;; Note: This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. (@interface func (export "fd_fdstat_get") (param $fd $fd) - (result $error $errno) ;;; The buffer where the file descriptor's attributes are stored. - (result $stat $fdstat) + (result $error (expected $fdstat (error $errno))) ) ;;; Adjust the flags associated with a file descriptor. @@ -120,7 +113,7 @@ (param $fd $fd) ;;; The desired values of the file descriptor flags. (param $flags $fdflags) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Adjust the rights associated with a file descriptor. @@ -130,15 +123,14 @@ ;;; The desired rights of the file descriptor. (param $fs_rights_base $rights) (param $fs_rights_inheriting $rights) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Return the attributes of an open file. (@interface func (export "fd_filestat_get") (param $fd $fd) - (result $error $errno) ;;; The buffer where the file's attributes are stored. - (result $buf $filestat) + (result $error (expected $filestat (error $errno))) ) ;;; Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. @@ -147,7 +139,7 @@ (param $fd $fd) ;;; The desired file size. (param $size $filesize) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Adjust the timestamps of an open file or directory. @@ -160,7 +152,7 @@ (param $mtim $timestamp) ;;; A bitmask indicating which timestamps to adjust. (param $fst_flags $fstflags) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Read from a file descriptor, without using and updating the file descriptor's offset. @@ -171,17 +163,15 @@ (param $iovs $iovec_array) ;;; The offset within the file at which to read. (param $offset $filesize) - (result $error $errno) ;;; The number of bytes read. - (result $nread $size) + (result $error (expected $size (error $errno))) ) ;;; Return a description of the given preopened file descriptor. (@interface func (export "fd_prestat_get") (param $fd $fd) - (result $error $errno) ;;; The buffer where the description is stored. - (result $buf $prestat) + (result $error (expected $prestat (error $errno))) ) ;;; Return a description of the given preopened file descriptor. @@ -190,7 +180,7 @@ ;;; A buffer into which to write the preopened directory name. (param $path (@witx pointer u8)) (param $path_len $size) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Write to a file descriptor, without using and updating the file descriptor's offset. @@ -201,9 +191,8 @@ (param $iovs $ciovec_array) ;;; The offset within the file at which to write. (param $offset $filesize) - (result $error $errno) ;;; The number of bytes written. - (result $nwritten $size) + (result $error (expected $size (error $errno))) ) ;;; Read from a file descriptor. @@ -212,15 +201,14 @@ (param $fd $fd) ;;; List of scatter/gather vectors to which to store data. (param $iovs $iovec_array) - (result $error $errno) ;;; The number of bytes read. - (result $nread $size) + (result $error (expected $size (error $errno))) ) ;;; Read directory entries from a directory. ;;; When successful, the contents of the output buffer consist of a sequence of - ;;; directory entries. Each directory entry consists of a dirent_t object, - ;;; followed by dirent_t::d_namlen bytes holding the name of the directory + ;;; directory entries. Each directory entry consists of a `dirent` object, + ;;; followed by `dirent::d_namlen` bytes holding the name of the directory ;;; entry. ;; ;;; This function fills the output buffer as much as possible, potentially @@ -234,9 +222,8 @@ (param $buf_len $size) ;;; The location within the directory to start reading (param $cookie $dircookie) - (result $error $errno) ;;; The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. - (result $bufused $size) + (result $error (expected $size (error $errno))) ) ;;; Atomically replace a file descriptor by renumbering another file descriptor. @@ -253,7 +240,7 @@ (param $fd $fd) ;;; The file descriptor to overwrite. (param $to $fd) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Move the offset of a file descriptor. @@ -264,25 +251,23 @@ (param $offset $filedelta) ;;; The base from which the offset is relative. (param $whence $whence) - (result $error $errno) ;;; The new offset of the file descriptor, relative to the start of the file. - (result $newoffset $filesize) + (result $error (expected $filesize (error $errno))) ) ;;; Synchronize the data and metadata of a file to disk. ;;; Note: This is similar to `fsync` in POSIX. (@interface func (export "fd_sync") (param $fd $fd) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Return the current offset of a file descriptor. ;;; Note: This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX. (@interface func (export "fd_tell") (param $fd $fd) - (result $error $errno) ;;; The current offset of the file descriptor, relative to the start of the file. - (result $offset $filesize) + (result $error (expected $filesize (error $errno))) ) ;;; Write to a file descriptor. @@ -291,9 +276,7 @@ (param $fd $fd) ;;; List of scatter/gather vectors from which to retrieve data. (param $iovs $ciovec_array) - (result $error $errno) - ;;; The number of bytes written. - (result $nwritten $size) + (result $error (expected $size (error $errno))) ) ;;; Create a directory. @@ -302,7 +285,7 @@ (param $fd $fd) ;;; The path at which to create the directory. (param $path string) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Return the attributes of a file or directory. @@ -313,9 +296,8 @@ (param $flags $lookupflags) ;;; The path of the file or directory to inspect. (param $path string) - (result $error $errno) ;;; The buffer where the file's attributes are stored. - (result $buf $filestat) + (result $error (expected $filestat (error $errno))) ) ;;; Adjust the timestamps of a file or directory. @@ -332,7 +314,7 @@ (param $mtim $timestamp) ;;; A bitmask indicating which timestamps to adjust. (param $fst_flags $fstflags) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Create a hard link. @@ -347,7 +329,7 @@ (param $new_fd $fd) ;;; The destination path at which to create the hard link. (param $new_path string) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Open a file or directory. @@ -377,11 +359,10 @@ ;;; descriptor itself, while the *inheriting* rights are rights that apply to ;;; file descriptors derived from it. (param $fs_rights_base $rights) - (param $fs_rights_inherting $rights) + (param $fs_rights_inheriting $rights) (param $fdflags $fdflags) - (result $error $errno) ;;; The file descriptor of the file that has been opened. - (result $opened_fd $fd) + (result $error (expected $fd (error $errno))) ) ;;; Read the contents of a symbolic link. @@ -393,9 +374,8 @@ ;;; The buffer to which to write the contents of the symbolic link. (param $buf (@witx pointer u8)) (param $buf_len $size) - (result $error $errno) ;;; The number of bytes placed in the buffer. - (result $bufused $size) + (result $error (expected $size (error $errno))) ) ;;; Remove a directory. @@ -405,7 +385,7 @@ (param $fd $fd) ;;; The path to a directory to remove. (param $path string) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Rename a file or directory. @@ -418,7 +398,7 @@ (param $new_fd $fd) ;;; The destination path to which to rename the file or directory. (param $new_path string) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Create a symbolic link. @@ -429,7 +409,7 @@ (param $fd $fd) ;;; The destination path at which to create the symbolic link. (param $new_path string) - (result $error $errno) + (result $error (expected (error $errno))) ) @@ -440,7 +420,7 @@ (param $fd $fd) ;;; The path to a file to unlink. (param $path string) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Concurrently poll for the occurrence of a set of events. @@ -451,9 +431,8 @@ (param $out (@witx pointer $event)) ;;; Both the number of subscriptions and events. (param $nsubscriptions $size) - (result $error $errno) ;;; The number of events stored. - (result $nevents $size) + (result $error (expected $size (error $errno))) ) ;;; Terminate the process normally. An exit code of 0 indicates successful @@ -462,6 +441,7 @@ (@interface func (export "proc_exit") ;;; The exit code returned by the process. (param $rval $exitcode) + (@witx noreturn) ) ;;; Send a signal to the process of the calling thread. @@ -469,13 +449,13 @@ (@interface func (export "proc_raise") ;;; The signal condition to trigger. (param $sig $signal) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Temporarily yield execution of the calling thread. ;;; Note: This is similar to `sched_yield` in POSIX. (@interface func (export "sched_yield") - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Write high-quality random data into a buffer. @@ -488,7 +468,7 @@ ;;; The buffer to fill with random data. (param $buf (@witx pointer u8)) (param $buf_len $size) - (result $error $errno) + (result $error (expected (error $errno))) ) ;;; Receive a message from a socket. @@ -500,11 +480,8 @@ (param $ri_data $iovec_array) ;;; Message flags. (param $ri_flags $riflags) - (result $error $errno) - ;;; Number of bytes stored in ri_data. - (result $ro_datalen $size) - ;;; Message flags. - (result $ro_flags $roflags) + ;;; Number of bytes stored in ri_data and message flags. + (result $error (expected (tuple $size $roflags) (error $errno))) ) ;;; Send a message on a socket. @@ -516,9 +493,8 @@ (param $si_data $ciovec_array) ;;; Message flags. (param $si_flags $siflags) - (result $error $errno) ;;; Number of bytes transmitted. - (result $so_datalen $size) + (result $error (expected $size (error $errno))) ) ;;; Shut down socket send and receive channels. @@ -527,6 +503,6 @@ (param $fd $fd) ;;; Which channels on the socket to shut down. (param $how $sdflags) - (result $error $errno) + (result $error (expected (error $errno))) ) ) diff --git a/crates/wiggle/wasmtime/Cargo.toml b/crates/wiggle/wasmtime/Cargo.toml index 97ca34ebc77b..31f45eeaf3e5 100644 --- a/crates/wiggle/wasmtime/Cargo.toml +++ b/crates/wiggle/wasmtime/Cargo.toml @@ -13,7 +13,7 @@ include = ["src/**/*", "LICENSE"] [dependencies] wasmtime = { path = "../../wasmtime", version = "0.23.0", default-features = false } wasmtime-wiggle-macro = { path = "./macro", version = "0.23.0" } -witx = { path = "../../wasi-common/WASI/tools/witx", version = "0.8.7", optional = true } +witx = { version = "0.9", path = "../../wasi-common/WASI/tools/witx", optional = true } wiggle = { path = "..", version = "0.23.0" } wiggle-borrow = { path = "../borrow", version = "0.23.0" } diff --git a/crates/wiggle/wasmtime/macro/Cargo.toml b/crates/wiggle/wasmtime/macro/Cargo.toml index 2ac0b1465dbd..fd4b365f0d2e 100644 --- a/crates/wiggle/wasmtime/macro/Cargo.toml +++ b/crates/wiggle/wasmtime/macro/Cargo.toml @@ -15,7 +15,7 @@ proc-macro = true test = false [dependencies] -witx = { path = "../../../wasi-common/WASI/tools/witx", version = "0.8.7" } +witx = { version = "0.9", path = "../../../wasi-common/WASI/tools/witx" } wiggle-generate = { path = "../../generate", version = "0.23.0" } quote = "1.0" syn = { version = "1.0", features = ["full", "extra-traits"] } diff --git a/crates/wiggle/wasmtime/macro/src/config.rs b/crates/wiggle/wasmtime/macro/src/config.rs index 6359ed0ec483..5e95bad957fb 100644 --- a/crates/wiggle/wasmtime/macro/src/config.rs +++ b/crates/wiggle/wasmtime/macro/src/config.rs @@ -144,7 +144,6 @@ impl Parse for TargetConf { enum ModuleConfField { Name(Ident), Docs(String), - FunctionOverride(FunctionOverrideConf), } impl Parse for ModuleConfField { @@ -159,10 +158,6 @@ impl Parse for ModuleConfField { input.parse::()?; let docs: syn::LitStr = input.parse()?; Ok(ModuleConfField::Docs(docs.value())) - } else if lookahead.peek(kw::function_override) { - input.parse::()?; - input.parse::()?; - Ok(ModuleConfField::FunctionOverride(input.parse()?)) } else { Err(lookahead.error()) } @@ -173,14 +168,12 @@ impl Parse for ModuleConfField { pub struct ModuleConf { pub name: Ident, pub docs: Option, - pub function_override: FunctionOverrideConf, } impl ModuleConf { fn build(fields: impl Iterator, err_loc: Span) -> Result { let mut name = None; let mut docs = None; - let mut function_override = None; for f in fields { match f { ModuleConfField::Name(c) => { @@ -195,18 +188,11 @@ impl ModuleConf { } docs = Some(c); } - ModuleConfField::FunctionOverride(c) => { - if function_override.is_some() { - return Err(Error::new(err_loc, "duplicate `function_override` field")); - } - function_override = Some(c); - } } } Ok(ModuleConf { name: name.ok_or_else(|| Error::new(err_loc, "`name` field required"))?, docs, - function_override: function_override.unwrap_or_default(), }) } } @@ -248,42 +234,3 @@ impl Parse for ModulesConf { }) } } - -#[derive(Debug, Clone, Default)] -pub struct FunctionOverrideConf { - pub funcs: Vec, -} -impl FunctionOverrideConf { - pub fn find(&self, name: &str) -> Option<&Ident> { - self.funcs - .iter() - .find(|f| f.name == name) - .map(|f| &f.replacement) - } -} - -impl Parse for FunctionOverrideConf { - fn parse(input: ParseStream) -> Result { - let contents; - let _lbrace = braced!(contents in input); - let fields: Punctuated = - contents.parse_terminated(FunctionOverrideField::parse)?; - Ok(FunctionOverrideConf { - funcs: fields.into_iter().collect(), - }) - } -} - -#[derive(Debug, Clone)] -pub struct FunctionOverrideField { - pub name: String, - pub replacement: Ident, -} -impl Parse for FunctionOverrideField { - fn parse(input: ParseStream) -> Result { - let name = input.parse::()?.to_string(); - input.parse::]>()?; - let replacement = input.parse::()?; - Ok(FunctionOverrideField { name, replacement }) - } -} diff --git a/crates/wiggle/wasmtime/macro/src/lib.rs b/crates/wiggle/wasmtime/macro/src/lib.rs index 7f13308f167b..a2d05f729d39 100644 --- a/crates/wiggle/wasmtime/macro/src/lib.rs +++ b/crates/wiggle/wasmtime/macro/src/lib.rs @@ -1,5 +1,5 @@ use proc_macro::TokenStream; -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::quote; use syn::parse_macro_input; use wiggle_generate::Names; @@ -88,14 +88,9 @@ fn generate_module( let module_id = names.module(&module.name); let target_module = quote! { #target_path::#module_id }; - let ctor_externs = module.funcs().map(|f| { - if let Some(func_override) = module_conf.function_override.find(&f.name.as_str()) { - let name_ident = names.func(&f.name); - quote! { let #name_ident = wasmtime::Func::wrap(store, #func_override); } - } else { - generate_func(&f, names, &target_module) - } - }); + let ctor_externs = module + .funcs() + .map(|f| generate_func(&f, names, &target_module)); let type_name = module_conf.name.clone(); let type_docs = module_conf @@ -158,23 +153,21 @@ fn generate_func( ) -> TokenStream2 { let name_ident = names.func(&func.name); - let coretype = func.core_type(); + let (params, results) = func.wasm_signature(); - let arg_decls = coretype.args.iter().map(|arg| { - let name = names.func_core_arg(arg); - let atom = names.atom_type(arg.repr()); - quote! { #name: #atom } + let arg_names = (0..params.len()) + .map(|i| Ident::new(&format!("arg{}", i), Span::call_site())) + .collect::>(); + let arg_decls = params.iter().enumerate().map(|(i, ty)| { + let name = &arg_names[i]; + let wasm = names.wasm_type(*ty); + quote! { #name: #wasm } }); - let arg_names = coretype.args.iter().map(|arg| names.func_core_arg(arg)); - - let ret_ty = if let Some(ret) = &coretype.ret { - let ret_ty = match ret.signifies { - witx::CoreParamSignifies::Value(atom) => names.atom_type(atom), - _ => unreachable!("coretype ret should always be passed by value"), - }; - quote! { #ret_ty } - } else { - quote! {()} + + let ret_ty = match results.len() { + 0 => quote!(()), + 1 => names.wasm_type(results[0]), + _ => unimplemented!(), }; let runtime = names.runtime_mod();