From 94837587eed2783dd1562c8ed97751980f76a94a Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 22 Jul 2021 18:08:36 -0300 Subject: [PATCH 1/8] feat: parses and builds enum with value ast --- crates/backend/src/ast.rs | 2 ++ crates/backend/src/codegen.rs | 18 +++++++++++++----- crates/macro-support/src/parser.rs | 6 +----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 4671bf4551a..26f52b5cacb 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -374,6 +374,8 @@ pub struct Enum { pub struct Variant { /// The name of this variant pub name: Ident, + /// The fields of this variant + pub fields: syn::Fields, /// The backing value of this variant pub value: u32, /// The doc comments on this variant, if any diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 348d10295ff..a28a01993b2 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1206,8 +1206,9 @@ impl ToTokens for ast::Enum { let hole = &self.hole; let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; + let variant_value = &variant.value; quote! { - if js == #enum_name::#variant_name as u32 { + if js == #variant_value { #enum_name::#variant_name } } @@ -1219,7 +1220,9 @@ impl ToTokens for ast::Enum { #[inline] fn into_abi(self) -> u32 { - self as u32 + use wasm_bindgen::__rt::std::boxed::Box; + use wasm_bindgen::__rt::WasmRefCell; + Box::into_raw(Box::new(WasmRefCell::new(self))) as u32 } } @@ -1229,9 +1232,14 @@ impl ToTokens for ast::Enum { #[inline] unsafe fn from_abi(js: u32) -> Self { - #(#cast_clauses else)* { - wasm_bindgen::throw_str("invalid enum value passed") - } + use wasm_bindgen::__rt::std::boxed::Box; + use wasm_bindgen::__rt::{assert_not_null, WasmRefCell}; + + let ptr = js as *mut WasmRefCell<#enum_name>; + assert_not_null(ptr); + let js = Box::from_raw(ptr); + (*js).borrow_mut(); // make sure no one's borrowing + js.into_inner() } } diff --git a/crates/macro-support/src/parser.rs b/crates/macro-support/src/parser.rs index ac0e835dfda..4b183ba47b2 100644 --- a/crates/macro-support/src/parser.rs +++ b/crates/macro-support/src/parser.rs @@ -1211,11 +1211,6 @@ impl<'a> MacroParse<(&'a mut TokenStream, BindgenAttrs)> for syn::ItemEnum { .iter() .enumerate() .map(|(i, v)| { - match v.fields { - syn::Fields::Unit => (), - _ => bail_span!(v.fields, "only C-Style enums allowed with #[wasm_bindgen]"), - } - // Require that everything either has a discriminant or doesn't. // We don't really want to get in the business of emulating how // rustc assigns values to enums. @@ -1255,6 +1250,7 @@ impl<'a> MacroParse<(&'a mut TokenStream, BindgenAttrs)> for syn::ItemEnum { name: v.ident.clone(), value, comments, + fields: v.fields.clone(), }) }) .collect::, Diagnostic>>()?; From 1173c7c4eaaafb7cf38cf9b5fe6a089cdc02ba57 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 17:46:06 -0300 Subject: [PATCH 2/8] temp: move to desktop --- crates/backend/src/codegen.rs | 44 +++++++++++++++++++++-------------- src/convert/slices.rs | 2 +- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index a28a01993b2..eff2034a228 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1207,52 +1207,60 @@ impl ToTokens for ast::Enum { let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; let variant_value = &variant.value; + let fields = &variant.fields.clone(); + let variant_fields_into_array = fields.iter().enumerate().map(|(index, field)| { + quote! { + #field::from_abi(variant[(#index + 1)]) + } + }); + quote! { - if js == #variant_value { - #enum_name::#variant_name + if variant[0] == #variant_value { + #enum_name::#variant_name(#(#variant_fields_into_array)*,) } } }); (quote! { + use wasm_bindgen::convert::{WasmAbi, traits::*}; + #[automatically_derived] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { - type Abi = u32; + type Abi = WasmSlice; #[inline] - fn into_abi(self) -> u32 { - use wasm_bindgen::__rt::std::boxed::Box; - use wasm_bindgen::__rt::WasmRefCell; - Box::into_raw(Box::new(WasmRefCell::new(self))) as u32 + fn into_abi(self) -> WasmSlice { + WasmSlice::null_slice() } } #[automatically_derived] impl wasm_bindgen::convert::FromWasmAbi for #enum_name { - type Abi = u32; + type Abi = WasmSlice; #[inline] - unsafe fn from_abi(js: u32) -> Self { - use wasm_bindgen::__rt::std::boxed::Box; - use wasm_bindgen::__rt::{assert_not_null, WasmRefCell}; + unsafe fn from_abi(js: WasmSlice) -> Self { + let ptr = <*mut u32>::from_abi(js.ptr); + let len = js.len as usize; + let variant = Vec::from_raw_parts(ptr, len, len).into_boxed_slice(); - let ptr = js as *mut WasmRefCell<#enum_name>; - assert_not_null(ptr); - let js = Box::from_raw(ptr); - (*js).borrow_mut(); // make sure no one's borrowing - js.into_inner() + #(#cast_clauses else)* { + wasm_bindgen::throw_str("invalid enum value passed") + } } } #[automatically_derived] impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name { #[inline] - fn is_none(val: &u32) -> bool { *val == #hole } + fn is_none(val: &WasmSlice) -> bool { + <*mut u32>::from_abi(val.ptr) == (#hole as u32) + } } #[automatically_derived] impl wasm_bindgen::convert::OptionIntoWasmAbi for #enum_name { #[inline] - fn none() -> Self::Abi { #hole } + fn none() -> Self::Abi { WasmSlice { ptr: 0, len: 0 } } } #[automatically_derived] diff --git a/src/convert/slices.rs b/src/convert/slices.rs index 9d0970f4e6a..67081ea31b3 100644 --- a/src/convert/slices.rs +++ b/src/convert/slices.rs @@ -23,7 +23,7 @@ pub struct WasmSlice { unsafe impl WasmAbi for WasmSlice {} #[inline] -fn null_slice() -> WasmSlice { +pub fn null_slice() -> WasmSlice { WasmSlice { ptr: 0, len: 0 } } From e5f71bf4e9e7241f198788682bb68cce029488be Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 19:54:03 -0300 Subject: [PATCH 3/8] feat: adds WASM ABI transformation for enums --- crates/backend/src/codegen.rs | 45 +++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index eff2034a228..8cbabd4c344 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1202,11 +1202,14 @@ impl<'a> ToTokens for DescribeImport<'a> { impl ToTokens for ast::Enum { fn to_tokens(&self, into: &mut TokenStream) { + use quote::format_ident; + let enum_name = &self.rust_name; let hole = &self.hole; let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; let variant_value = &variant.value; + let fields = &variant.fields.clone(); let variant_fields_into_array = fields.iter().enumerate().map(|(index, field)| { quote! { @@ -1216,20 +1219,52 @@ impl ToTokens for ast::Enum { quote! { if variant[0] == #variant_value { - #enum_name::#variant_name(#(#variant_fields_into_array)*,) + #enum_name::#variant_name(#(#variant_fields_into_array),*) } } }); + let into_clauses = self.variants.iter().map(|variant| { + let variant_name = &variant.name; + let variant_value = &variant.value; + + let fields = &variant.fields.clone(); + let variant_array_into_tuple = fields.iter().enumerate().map(|(index, _)| { + let varname = format_ident!("arg{}", index); + quote! { + #varname + } + }); + + let variant_types_into_vector = fields.iter().enumerate().map(|(index, field)| { + let varname = format_ident!("arg{}", index); + quote! { + #field::into_abi(#varname) + } + }); + + quote! { + #enum_name::#variant_name(#(#variant_array_into_tuple),*) => vec![#variant_value, #(#variant_types_into_vector),*] + } + }); (quote! { - use wasm_bindgen::convert::{WasmAbi, traits::*}; + use wasm_bindgen::convert::{WasmAbi, WasmSlice}; #[automatically_derived] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { type Abi = WasmSlice; - #[inline] fn into_abi(self) -> WasmSlice { - WasmSlice::null_slice() + let vector = match self { + #(#into_clauses),* + }; + + let ptr = vector.as_ptr(); + let len = vector.len(); + core::mem::forget(vector); + WasmSlice { + ptr: ptr.into_abi(), + len: len as u32, + } } } @@ -1253,7 +1288,7 @@ impl ToTokens for ast::Enum { impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name { #[inline] fn is_none(val: &WasmSlice) -> bool { - <*mut u32>::from_abi(val.ptr) == (#hole as u32) + val.ptr == (#hole as u32) } } From 19c0e25499fc7b774c4fe00527952cb1bd23f244 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 20:02:10 -0300 Subject: [PATCH 4/8] refactor: updates names in enum with value ABI transformation --- crates/backend/src/codegen.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 8cbabd4c344..19e606ab097 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1228,14 +1228,14 @@ impl ToTokens for ast::Enum { let variant_value = &variant.value; let fields = &variant.fields.clone(); - let variant_array_into_tuple = fields.iter().enumerate().map(|(index, _)| { + let field_vector_into_tuple = fields.iter().enumerate().map(|(index, _)| { let varname = format_ident!("arg{}", index); quote! { #varname } }); - let variant_types_into_vector = fields.iter().enumerate().map(|(index, field)| { + let fields_into_vector = fields.iter().enumerate().map(|(index, field)| { let varname = format_ident!("arg{}", index); quote! { #field::into_abi(#varname) @@ -1243,7 +1243,7 @@ impl ToTokens for ast::Enum { }); quote! { - #enum_name::#variant_name(#(#variant_array_into_tuple),*) => vec![#variant_value, #(#variant_types_into_vector),*] + #enum_name::#variant_name(#(#field_vector_into_tuple),*) => vec![#variant_value, #(#fields_into_vector),*] } }); (quote! { From 9e57d6e8cccc3e1e11e3c6fc806667201ba8eaf0 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 20:06:37 -0300 Subject: [PATCH 5/8] refactor: removes unnecessary mapping for enum ABI vector construction --- crates/backend/src/codegen.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 19e606ab097..65189f9e113 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1235,15 +1235,11 @@ impl ToTokens for ast::Enum { } }); - let fields_into_vector = fields.iter().enumerate().map(|(index, field)| { - let varname = format_ident!("arg{}", index); - quote! { - #field::into_abi(#varname) - } - }); + let field_names = field_vector_into_tuple.clone(); quote! { - #enum_name::#variant_name(#(#field_vector_into_tuple),*) => vec![#variant_value, #(#fields_into_vector),*] + #enum_name::#variant_name(#(#field_vector_into_tuple),*) + => vec![#variant_value, #((#field_names).into_abi()),*] } }); (quote! { From acf94b311cb4601e535a904f55d8407004aff1a5 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 30 Jul 2021 16:45:20 -0300 Subject: [PATCH 6/8] feat: encodes enum variants as u32 arrays --- crates/backend/src/codegen.rs | 26 +++++---- crates/cli-support/src/descriptor.rs | 30 ++++++++++- crates/cli-support/src/js/binding.rs | 1 + crates/cli-support/src/wit/incoming.rs | 24 +++++++-- crates/cli-support/src/wit/outgoing.rs | 31 ++++++++--- crates/cli-support/src/wit/standard.rs | 10 +++- src/convert/mod.rs | 2 +- src/convert/slices.rs | 73 ++++++++++++++++++++++++++ 8 files changed, 169 insertions(+), 28 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 65189f9e113..526015a28d0 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1211,14 +1211,14 @@ impl ToTokens for ast::Enum { let variant_value = &variant.value; let fields = &variant.fields.clone(); - let variant_fields_into_array = fields.iter().enumerate().map(|(index, field)| { + let variant_fields_into_array = fields.iter().map(|field| { quote! { - #field::from_abi(variant[(#index + 1)]) + #field::from_abi(<#field as FromWasmAbi>::Abi::pop_from_u32_vector(&mut vector)) } }); quote! { - if variant[0] == #variant_value { + if vector.pop().unwrap() == #variant_value { #enum_name::#variant_name(#(#variant_fields_into_array),*) } } @@ -1230,20 +1230,24 @@ impl ToTokens for ast::Enum { let fields = &variant.fields.clone(); let field_vector_into_tuple = fields.iter().enumerate().map(|(index, _)| { let varname = format_ident!("arg{}", index); - quote! { - #varname - } + quote! { + #varname + } }); let field_names = field_vector_into_tuple.clone(); quote! { #enum_name::#variant_name(#(#field_vector_into_tuple),*) - => vec![#variant_value, #((#field_names).into_abi()),*] + => { + let mut vector = vec![(#variant_value).into_abi()]; + #((#field_names).into_abi().push_into_u32_vector(&mut vector));*; + vector + } } }); (quote! { - use wasm_bindgen::convert::{WasmAbi, WasmSlice}; + use wasm_bindgen::convert::{WasmAbi, WasmSlice, FromWasmAbi, VectorEncoding}; #[automatically_derived] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { @@ -1272,10 +1276,11 @@ impl ToTokens for ast::Enum { unsafe fn from_abi(js: WasmSlice) -> Self { let ptr = <*mut u32>::from_abi(js.ptr); let len = js.len as usize; - let variant = Vec::from_raw_parts(ptr, len, len).into_boxed_slice(); + let mut vector = Vec::from_raw_parts(ptr, len, len); + let err = format!("{:?}", vector.len()).as_str(); #(#cast_clauses else)* { - wasm_bindgen::throw_str("invalid enum value passed") + wasm_bindgen::throw_str(err,) } } } @@ -1299,7 +1304,6 @@ impl ToTokens for ast::Enum { fn describe() { use wasm_bindgen::describe::*; inform(ENUM); - inform(#hole); } } }) diff --git a/crates/cli-support/src/descriptor.rs b/crates/cli-support/src/descriptor.rs index a3b73a2221a..165b91254dc 100644 --- a/crates/cli-support/src/descriptor.rs +++ b/crates/cli-support/src/descriptor.rs @@ -65,7 +65,7 @@ pub enum Descriptor { String, Externref, NamedExternref(String), - Enum { hole: u32 }, + Enum, RustStruct(String), Char, Option(Box), @@ -107,6 +107,12 @@ pub enum VectorKind { NamedExternref(String), } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct EnumVariant { + pub name: String, + pub fields: Vec +} + impl Descriptor { pub fn decode(mut data: &[u32]) -> Descriptor { let descriptor = Descriptor::_decode(&mut data, false); @@ -139,7 +145,7 @@ impl Descriptor { CACHED_STRING => Descriptor::CachedString, STRING => Descriptor::String, EXTERNREF => Descriptor::Externref, - ENUM => Descriptor::Enum { hole: get(data) }, + ENUM => Descriptor::Enum, RUST_STRUCT => { let name = get_string(data); Descriptor::RustStruct(name) @@ -216,6 +222,26 @@ fn get_string(data: &mut &[u32]) -> String { .collect() } +// fn get_enum(data: &mut &[u32]) -> Descriptor { +// let name = get_string(data); +// let hole = get(data); +// let variants = (0..get(data)).map(|_| { + +// let variant_name = get_string(data); +// let variant_fields = (0..get(data)).map(|_| { +// Descriptor::_decode(data, false) +// }).collect(); + +// EnumVariant { +// name: variant_name, +// fields: variant_fields +// } + +// }).collect(); + +// Descriptor::Enum {name, variants, hole} +// } + impl Closure { fn decode(data: &mut &[u32]) -> Closure { let shim_idx = get(data); diff --git a/crates/cli-support/src/js/binding.rs b/crates/cli-support/src/js/binding.rs index c29e808587e..c0665b41881 100644 --- a/crates/cli-support/src/js/binding.rs +++ b/crates/cli-support/src/js/binding.rs @@ -1353,5 +1353,6 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) { AdapterType::NamedExternref(name) => dst.push_str(name), AdapterType::Struct(name) => dst.push_str(name), AdapterType::Function => dst.push_str("any"), + AdapterType::Enum => dst.push_str("placeholder") } } diff --git a/crates/cli-support/src/wit/incoming.rs b/crates/cli-support/src/wit/incoming.rs index 1778516caad..eb5285c54df 100644 --- a/crates/cli-support/src/wit/incoming.rs +++ b/crates/cli-support/src/wit/incoming.rs @@ -99,7 +99,17 @@ impl InstructionBuilder<'_, '_> { self.get(AdapterType::F64); self.output.push(AdapterType::F64); } - Descriptor::Enum { .. } => self.number(WitVT::U32, WasmVT::I32), + Descriptor::Enum { .. } => { + let kind = crate::descriptor::VectorKind::U32; + + let malloc = self.cx.malloc()?; + let mem = self.cx.memory()?; + self.instruction( + &[AdapterType::Enum.option()], + Instruction::OptionVector { kind, malloc, mem }, + &[AdapterType::I32, AdapterType::I32], + ); + } Descriptor::Ref(d) => self.incoming_ref(false, d)?, Descriptor::RefMut(d) => self.incoming_ref(true, d)?, Descriptor::Option(d) => self.incoming_option(d)?, @@ -281,11 +291,15 @@ impl InstructionBuilder<'_, '_> { &[AdapterType::I32], ); } - Descriptor::Enum { hole } => { + Descriptor::Enum { .. } => { + let kind = crate::descriptor::VectorKind::U32; + + let malloc = self.cx.malloc()?; + let mem = self.cx.memory()?; self.instruction( - &[AdapterType::U32.option()], - Instruction::I32FromOptionEnum { hole: *hole }, - &[AdapterType::I32], + &[AdapterType::Enum.option()], + Instruction::OptionVector { kind, malloc, mem }, + &[AdapterType::I32, AdapterType::I32], ); } Descriptor::RustStruct(name) => { diff --git a/crates/cli-support/src/wit/outgoing.rs b/crates/cli-support/src/wit/outgoing.rs index e2598f7e920..f121f97495f 100644 --- a/crates/cli-support/src/wit/outgoing.rs +++ b/crates/cli-support/src/wit/outgoing.rs @@ -71,7 +71,6 @@ impl InstructionBuilder<'_, '_> { self.get(AdapterType::F64); self.output.push(AdapterType::F64); } - Descriptor::Enum { .. } => self.outgoing_i32(AdapterType::U32), Descriptor::Char => { self.instruction( @@ -167,6 +166,22 @@ impl InstructionBuilder<'_, '_> { arg ), + Descriptor::Enum { .. } => { + let kind = crate::descriptor::VectorKind::U32; + + let mem = self.cx.memory()?; + let free = self.cx.free()?; + self.instruction( + &[AdapterType::I32, AdapterType::I32], + Instruction::VectorLoad { + kind, + mem, + free, + }, + &[AdapterType::Enum], + ); + } + // nothing to do Descriptor::Unit => {} @@ -304,13 +319,13 @@ impl InstructionBuilder<'_, '_> { &[AdapterType::String.option()], ); } - Descriptor::Enum { hole } => { - self.instruction( - &[AdapterType::I32], - Instruction::OptionEnumFromI32 { hole: *hole }, - &[AdapterType::U32.option()], - ); - } + // Descriptor::Enum => { + // self.instruction( + // &[AdapterType::I32], + // Instruction::OptionEnumFromI32 { hole: *hole }, + // &[AdapterType::U32.option()], + // ); + // } Descriptor::RustStruct(name) => { self.instruction( &[AdapterType::I32], diff --git a/crates/cli-support/src/wit/standard.rs b/crates/cli-support/src/wit/standard.rs index 78df620d765..9e89c1ab70c 100644 --- a/crates/cli-support/src/wit/standard.rs +++ b/crates/cli-support/src/wit/standard.rs @@ -87,6 +87,13 @@ pub enum AdapterType { Struct(String), NamedExternref(String), Function, + Enum, +} + +#[derive(Debug, Clone)] +pub struct EnumVariantAdapter { + pub name: String, + pub fields: Vec } #[derive(Debug, Clone)] @@ -372,7 +379,8 @@ impl AdapterType { | AdapterType::Function | AdapterType::Struct(_) | AdapterType::Bool - | AdapterType::Vector(_) => return None, + | AdapterType::Vector(_) + | AdapterType::Enum => return None, }) } diff --git a/src/convert/mod.rs b/src/convert/mod.rs index ce2c0b2c847..6685f7b77ee 100644 --- a/src/convert/mod.rs +++ b/src/convert/mod.rs @@ -7,5 +7,5 @@ mod slices; mod traits; pub use self::impls::*; -pub use self::slices::WasmSlice; +pub use self::slices::{WasmSlice, VectorEncoding}; pub use self::traits::*; diff --git a/src/convert/slices.rs b/src/convert/slices.rs index 67081ea31b3..7b092881ff6 100644 --- a/src/convert/slices.rs +++ b/src/convert/slices.rs @@ -309,3 +309,76 @@ if_std! { fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 } } } + +pub trait VectorEncoding { + fn push_into_u32_vector(self, vector: &mut Vec); + + fn pop_from_u32_vector(vector: &mut Vec) -> Self; +} + +impl VectorEncoding for u32 { + fn push_into_u32_vector(self, vector: &mut Vec) { + vector.push(self) + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + vector.pop().unwrap() + } +} + +impl VectorEncoding for () { + fn push_into_u32_vector(self, vector: &mut Vec) { + vector.push(0) + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + vector.pop().unwrap(); + () + } +} + +impl VectorEncoding for f32 { + fn push_into_u32_vector(self, vector: &mut Vec) { + let as_u32 = self.to_bits(); + vector.push(as_u32); + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + f32::from_bits(vector.pop().unwrap()) + } +} + +impl VectorEncoding for f64 { + fn push_into_u32_vector(self, vector: &mut Vec) { + let as_u64 = self.to_bits(); + let hi = (as_u64 >> 32) as u32; + let lo = as_u64 as u32; + vector.push(hi); + vector.push(lo); + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + let hi = vector.pop().unwrap(); + let lo = vector.pop().unwrap(); + let as_u64 = (hi as u64) << 32 | (lo as u64); + f64::from_bits(as_u64) + } +} + +impl VectorEncoding for WasmSlice { + fn push_into_u32_vector(self, vector: &mut Vec) { + let WasmSlice { ptr, len } = self; + + vector.push(ptr); + vector.push(len); + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + let ptr = vector.pop().unwrap(); + let len = vector.pop().unwrap(); + WasmSlice { + ptr, + len + } + } +} From eaa6e7e4c8830ea3a833597a1161d73c454ce809 Mon Sep 17 00:00:00 2001 From: "xiang.zhao" Date: Fri, 1 Jul 2022 15:26:45 +0800 Subject: [PATCH 7/8] fix code format --- crates/cli-support/src/descriptor.rs | 2 +- crates/cli-support/src/js/binding.rs | 2 +- crates/cli-support/src/wit/outgoing.rs | 6 +----- crates/cli-support/src/wit/standard.rs | 2 +- src/convert/mod.rs | 2 +- src/convert/slices.rs | 5 +---- 6 files changed, 6 insertions(+), 13 deletions(-) diff --git a/crates/cli-support/src/descriptor.rs b/crates/cli-support/src/descriptor.rs index 165b91254dc..214d72048f1 100644 --- a/crates/cli-support/src/descriptor.rs +++ b/crates/cli-support/src/descriptor.rs @@ -110,7 +110,7 @@ pub enum VectorKind { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct EnumVariant { pub name: String, - pub fields: Vec + pub fields: Vec, } impl Descriptor { diff --git a/crates/cli-support/src/js/binding.rs b/crates/cli-support/src/js/binding.rs index c0665b41881..30cf31e14be 100644 --- a/crates/cli-support/src/js/binding.rs +++ b/crates/cli-support/src/js/binding.rs @@ -1353,6 +1353,6 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) { AdapterType::NamedExternref(name) => dst.push_str(name), AdapterType::Struct(name) => dst.push_str(name), AdapterType::Function => dst.push_str("any"), - AdapterType::Enum => dst.push_str("placeholder") + AdapterType::Enum => dst.push_str("placeholder"), } } diff --git a/crates/cli-support/src/wit/outgoing.rs b/crates/cli-support/src/wit/outgoing.rs index f121f97495f..55746a257ce 100644 --- a/crates/cli-support/src/wit/outgoing.rs +++ b/crates/cli-support/src/wit/outgoing.rs @@ -173,11 +173,7 @@ impl InstructionBuilder<'_, '_> { let free = self.cx.free()?; self.instruction( &[AdapterType::I32, AdapterType::I32], - Instruction::VectorLoad { - kind, - mem, - free, - }, + Instruction::VectorLoad { kind, mem, free }, &[AdapterType::Enum], ); } diff --git a/crates/cli-support/src/wit/standard.rs b/crates/cli-support/src/wit/standard.rs index 9e89c1ab70c..a1b99f84b49 100644 --- a/crates/cli-support/src/wit/standard.rs +++ b/crates/cli-support/src/wit/standard.rs @@ -93,7 +93,7 @@ pub enum AdapterType { #[derive(Debug, Clone)] pub struct EnumVariantAdapter { pub name: String, - pub fields: Vec + pub fields: Vec, } #[derive(Debug, Clone)] diff --git a/src/convert/mod.rs b/src/convert/mod.rs index 6685f7b77ee..3891d61a1f5 100644 --- a/src/convert/mod.rs +++ b/src/convert/mod.rs @@ -7,5 +7,5 @@ mod slices; mod traits; pub use self::impls::*; -pub use self::slices::{WasmSlice, VectorEncoding}; +pub use self::slices::{VectorEncoding, WasmSlice}; pub use self::traits::*; diff --git a/src/convert/slices.rs b/src/convert/slices.rs index 7b092881ff6..5fbd0fcb118 100644 --- a/src/convert/slices.rs +++ b/src/convert/slices.rs @@ -376,9 +376,6 @@ impl VectorEncoding for WasmSlice { fn pop_from_u32_vector(vector: &mut Vec) -> Self { let ptr = vector.pop().unwrap(); let len = vector.pop().unwrap(); - WasmSlice { - ptr, - len - } + WasmSlice { ptr, len } } } From 2ff77617aee42dd3e86f28c4b5933456e6678cd5 Mon Sep 17 00:00:00 2001 From: "xiang.zhao" Date: Fri, 1 Jul 2022 20:49:27 +0800 Subject: [PATCH 8/8] fix --- .gitignore | 1 + crates/backend/src/codegen.rs | 41 +++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 8cdf73b9e4f..319ffaa37af 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ yarn.lock /publish.exe .vscode webdriver.json +crates/foo \ No newline at end of file diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 526015a28d0..e936abc242d 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1213,16 +1213,23 @@ impl ToTokens for ast::Enum { let fields = &variant.fields.clone(); let variant_fields_into_array = fields.iter().map(|field| { quote! { - #field::from_abi(<#field as FromWasmAbi>::Abi::pop_from_u32_vector(&mut vector)) + #field::from_abi(<<#field as wasm_bindgen::convert::FromWasmAbi>::Abi as wasm_bindgen::convert::VectorEncoding>::pop_from_u32_vector(&mut vector)) } }); + let variant_field_names = if let syn::Fields::Unit = fields { + quote! {} + } else { + quote! {(#(#variant_fields_into_array),*)} + }; + quote! { if vector.pop().unwrap() == #variant_value { - #enum_name::#variant_name(#(#variant_fields_into_array),*) + #enum_name::#variant_name #variant_field_names } } }); + let into_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; let variant_value = &variant.value; @@ -1237,23 +1244,30 @@ impl ToTokens for ast::Enum { let field_names = field_vector_into_tuple.clone(); + let variant_field_names = if let syn::Fields::Unit = fields { + quote! {} + } else { + quote! {(#(#field_vector_into_tuple),*)} + }; + quote! { - #enum_name::#variant_name(#(#field_vector_into_tuple),*) + #enum_name::#variant_name #variant_field_names => { + #[allow(unused_mut)] let mut vector = vec![(#variant_value).into_abi()]; + #[allow(unused_imports)] + use wasm_bindgen::convert::VectorEncoding; #((#field_names).into_abi().push_into_u32_vector(&mut vector));*; vector } } }); (quote! { - use wasm_bindgen::convert::{WasmAbi, WasmSlice, FromWasmAbi, VectorEncoding}; - #[automatically_derived] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { - type Abi = WasmSlice; + type Abi = wasm_bindgen::convert::WasmSlice; - fn into_abi(self) -> WasmSlice { + fn into_abi(self) -> wasm_bindgen::convert::WasmSlice { let vector = match self { #(#into_clauses),* }; @@ -1261,7 +1275,7 @@ impl ToTokens for ast::Enum { let ptr = vector.as_ptr(); let len = vector.len(); core::mem::forget(vector); - WasmSlice { + wasm_bindgen::convert::WasmSlice { ptr: ptr.into_abi(), len: len as u32, } @@ -1270,17 +1284,16 @@ impl ToTokens for ast::Enum { #[automatically_derived] impl wasm_bindgen::convert::FromWasmAbi for #enum_name { - type Abi = WasmSlice; + type Abi = wasm_bindgen::convert::WasmSlice; #[inline] - unsafe fn from_abi(js: WasmSlice) -> Self { + unsafe fn from_abi(js: wasm_bindgen::convert::WasmSlice) -> Self { let ptr = <*mut u32>::from_abi(js.ptr); let len = js.len as usize; let mut vector = Vec::from_raw_parts(ptr, len, len); - let err = format!("{:?}", vector.len()).as_str(); #(#cast_clauses else)* { - wasm_bindgen::throw_str(err,) + wasm_bindgen::throw_str(format!("{:?}", vector.len()).as_str()) } } } @@ -1288,7 +1301,7 @@ impl ToTokens for ast::Enum { #[automatically_derived] impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name { #[inline] - fn is_none(val: &WasmSlice) -> bool { + fn is_none(val: &wasm_bindgen::convert::WasmSlice) -> bool { val.ptr == (#hole as u32) } } @@ -1296,7 +1309,7 @@ impl ToTokens for ast::Enum { #[automatically_derived] impl wasm_bindgen::convert::OptionIntoWasmAbi for #enum_name { #[inline] - fn none() -> Self::Abi { WasmSlice { ptr: 0, len: 0 } } + fn none() -> Self::Abi { wasm_bindgen::convert::WasmSlice { ptr: 0, len: 0 } } } #[automatically_derived]