diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index a2444e32..062ad54e 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -87,19 +87,6 @@ pub enum Type { ByValue(syn::Type), } -pub enum VectorType { - String, - I8, - U8, - I16, - U16, - I32, - U32, - F32, - F64, - JsValue, -} - impl Program { pub fn push_item(&mut self, item: syn::Item, opts: Option, tokens: &mut Tokens) { match item { @@ -771,67 +758,3 @@ fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult< } syn::parse_error() } - -fn ungroup(input: &syn::Type) -> &syn::Type { - match *input { - syn::Type::Group(ref t) => &t.elem, - _ => input, - } -} - -impl VectorType { - fn from(ty: &syn::Type) -> Option { - let path = match *ungroup(ty) { - syn::Type::Path(syn::TypePath { - qself: None, - ref path, - }) => path, - _ => return None, - }; - match extract_path_ident(path)?.as_ref() { - "i8" => Some(VectorType::I8), - "u8" => Some(VectorType::U8), - "i16" => Some(VectorType::I16), - "u16" => Some(VectorType::U16), - "i32" => Some(VectorType::I32), - "u32" => Some(VectorType::U32), - "f32" => Some(VectorType::F32), - "f64" => Some(VectorType::F64), - "JsValue" => Some(VectorType::JsValue), - _ => None, - } - } - - pub fn abi_element(&self) -> syn::Ident { - match *self { - VectorType::String => syn::Ident::from("u8"), - VectorType::I8 => syn::Ident::from("i8"), - VectorType::U8 => syn::Ident::from("u8"), - VectorType::I16 => syn::Ident::from("i16"), - VectorType::U16 => syn::Ident::from("u16"), - VectorType::I32 => syn::Ident::from("i32"), - VectorType::U32 => syn::Ident::from("u32"), - VectorType::F32 => syn::Ident::from("f32"), - VectorType::F64 => syn::Ident::from("f64"), - VectorType::JsValue => syn::Ident::from("JsValue"), - } - } -} - -impl ToTokens for VectorType { - fn to_tokens(&self, tokens: &mut Tokens) { - let me = match *self { - VectorType::String => my_quote! { String }, - VectorType::I8 => my_quote! { Vec }, - VectorType::U8 => my_quote! { Vec }, - VectorType::I16 => my_quote! { Vec }, - VectorType::U16 => my_quote! { Vec }, - VectorType::I32 => my_quote! { Vec }, - VectorType::U32 => my_quote! { Vec }, - VectorType::F32 => my_quote! { Vec }, - VectorType::F64 => my_quote! { Vec }, - VectorType::JsValue => my_quote! { Vec }, - }; - me.to_tokens(tokens); - } -} diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 44c7fadd..15240d45 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -277,11 +277,13 @@ impl ToTokens for ast::Export { #[allow(non_snake_case)] pub extern fn #generated_name(#(#args),*) #ret_ty { ::wasm_bindgen::__rt::link_this_library(); - let mut __stack = unsafe { - ::wasm_bindgen::convert::GlobalStack::new() + let #ret = { + let mut __stack = unsafe { + ::wasm_bindgen::convert::GlobalStack::new() + }; + #(#arg_conversions)* + #receiver(#(#converted_arguments),*) }; - #(#arg_conversions)* - let #ret = #receiver(#(#converted_arguments),*); #convert_ret } }; @@ -398,22 +400,6 @@ impl ToTokens for ast::ImportFunction { for (i, (ty, name)) in self.function.arguments.iter().zip(names).enumerate() { match *ty { - // ast::Type::Vector(ref ty, owned) => { - // let ptr = syn::Ident::from(format!("{}_ptr", name)); - // let len = syn::Ident::from(format!("{}_len", name)); - // abi_argument_names.push(ptr); - // abi_argument_names.push(len); - // let abi_ty = ty.abi_element(); - // abi_arguments.push(my_quote! { #ptr: *const #abi_ty }); - // abi_arguments.push(my_quote! { #len: usize }); - // arg_conversions.push(my_quote! { - // let #ptr = #name.as_ptr(); - // let #len = #name.len(); - // }); - // if owned { - // arg_conversions.push(my_quote! { ::std::mem::forget(#name); }); - // } - // } ast::Type::ByValue(ref t) => { abi_argument_names.push(name); abi_arguments.push(my_quote! { @@ -422,12 +408,12 @@ impl ToTokens for ast::ImportFunction { if i == 0 && is_method { arg_conversions.push(my_quote! { let #name = <#t as ::wasm_bindgen::convert::WasmBoundary> - ::into_abi(self); + ::into_abi(self, &mut __stack); }); } else { arg_conversions.push(my_quote! { let #name = <#t as ::wasm_bindgen::convert::WasmBoundary> - ::into_abi(#name); + ::into_abi(#name, &mut __stack); }); } } @@ -438,12 +424,12 @@ impl ToTokens for ast::ImportFunction { if i == 0 && is_method { arg_conversions.push(my_quote! { let #name = <#t as ::wasm_bindgen::convert::ToRefWasmBoundary> - ::to_abi_ref(self); + ::to_abi_ref(self, &mut __stack); }); } else { arg_conversions.push(my_quote! { let #name = <#t as ::wasm_bindgen::convert::ToRefWasmBoundary> - ::to_abi_ref(#name); + ::to_abi_ref(#name, &mut __stack); }); } } @@ -457,33 +443,13 @@ impl ToTokens for ast::ImportFunction { <#t as ::wasm_bindgen::convert::WasmBoundary>::Abi }; convert_ret = my_quote! { - <#t as ::wasm_bindgen::convert::WasmBoundary>::from_abi(#ret_ident) + <#t as ::wasm_bindgen::convert::WasmBoundary> + ::from_abi( + #ret_ident, + &mut ::wasm_bindgen::convert::GlobalStack::new(), + ) }; } - - // Some(ast::Type::Vector(ref ty, true)) => { - // let name = syn::Ident::from("__ret_len"); - // let name_ptr = syn::Ident::from("__ret_len_ptr"); - // abi_argument_names.push(name_ptr); - // abi_arguments.push(my_quote! { #name_ptr: *mut usize }); - // arg_conversions.push(my_quote! { - // let mut #name = 0; - // let mut #name_ptr = &mut #name as *mut usize; - // }); - // let abi_ty = ty.abi_element(); - // abi_ret = my_quote! { *mut #abi_ty }; - // if let ast::VectorType::String = *ty { - // convert_ret = my_quote! { - // String::from_utf8_unchecked( - // Vec::from_raw_parts(#ret_ident, #name, #name) - // ) - // }; - // } else { - // convert_ret = my_quote! { - // Vec::from_raw_parts(#ret_ident, #name, #name) - // }; - // } - // } Some(ast::Type::ByRef(_)) | Some(ast::Type::ByMutRef(_)) => panic!("can't return a borrowed ref"), None => { @@ -493,23 +459,28 @@ impl ToTokens for ast::ImportFunction { } let mut exceptional_ret = my_quote!{}; - if self.function.opts.catch() { + let exn_data = if self.function.opts.catch() { let exn_data = syn::Ident::from("exn_data"); let exn_data_ptr = syn::Ident::from("exn_data_ptr"); abi_argument_names.push(exn_data_ptr); abi_arguments.push(my_quote! { #exn_data_ptr: *mut u32 }); - arg_conversions.push(my_quote! { - let mut #exn_data = [0; 2]; - let #exn_data_ptr = #exn_data.as_mut_ptr(); - }); convert_ret = my_quote! { Ok(#convert_ret) }; exceptional_ret = my_quote! { if #exn_data[0] == 1 { - return Err(<::wasm_bindgen::JsValue as - ::wasm_bindgen::convert::WasmBoundary>::from_abi(#exn_data[1])) + return Err( + < + ::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary + >::from_abi(#exn_data[1], &mut ::wasm_bindgen::convert::GlobalStack::new()), + ) } }; - } + my_quote! { + let mut #exn_data = [0; 2]; + let #exn_data_ptr = #exn_data.as_mut_ptr(); + } + } else { + quote! {} + }; let rust_name = self.rust_name; let import_name = self.shim; @@ -538,8 +509,12 @@ impl ToTokens for ast::ImportFunction { fn #import_name(#(#abi_arguments),*) -> #abi_ret; } unsafe { - #(#arg_conversions)* - let #ret_ident = #import_name(#(#abi_argument_names),*); + #exn_data + let #ret_ident = { + let mut __stack = ::wasm_bindgen::convert::GlobalStack::new(); + #(#arg_conversions)* + #import_name(#(#abi_argument_names),*) + }; #exceptional_ret #convert_ret } @@ -609,10 +584,13 @@ impl ToTokens for ast::ImportStatic { fn init() -> #ty { #[wasm_import_module = "__wbindgen_placeholder__"] extern { - fn #shim_name() -> u32; + fn #shim_name() -> <#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi; } unsafe { - ::wasm_bindgen::convert::WasmBoundary::from_abi(#shim_name()) + ::wasm_bindgen::convert::WasmBoundary::from_abi( + #shim_name(), + &mut ::wasm_bindgen::convert::GlobalStack::new(), + ) } } ::wasm_bindgen::JsStatic { diff --git a/crates/cli-support/src/js.rs b/crates/cli-support/src/js.rs index 537368a8..bf3edeb0 100644 --- a/crates/cli-support/src/js.rs +++ b/crates/cli-support/src/js.rs @@ -1,4 +1,3 @@ -use std::char; use std::collections::{HashSet, HashMap}; use std::fmt::Write; use std::mem; @@ -1375,75 +1374,58 @@ impl<'a, 'b> SubContext<'a, 'b> { let mut extra = String::new(); + let mut needs_next_global = false; for (i, arg) in import.function.arguments.iter().enumerate() { - match *arg { - shared::TYPE_NUMBER => { - invoc_args.push(format!("arg{}", i)); - abi_args.push(format!("arg{}", i)); - } - shared::TYPE_BOOLEAN => { - invoc_args.push(format!("arg{} !== 0", i)); - abi_args.push(format!("arg{}", i)); - } - // shared::TYPE_BORROWED_STR | - // shared::TYPE_STRING | - // shared::TYPE_VECTOR_U8 | - // shared::TYPE_VECTOR_I8 | - // shared::TYPE_SLICE_U8 | - // shared::TYPE_SLICE_I8 | - // shared::TYPE_VECTOR_U16 | - // shared::TYPE_VECTOR_I16 | - // shared::TYPE_SLICE_U16 | - // shared::TYPE_SLICE_I16 | - // shared::TYPE_VECTOR_U32 | - // shared::TYPE_VECTOR_I32 | - // shared::TYPE_SLICE_U32 | - // shared::TYPE_SLICE_I32 | - // shared::TYPE_VECTOR_F32 | - // shared::TYPE_VECTOR_F64 | - // shared::TYPE_SLICE_F32 | - // shared::TYPE_SLICE_F64 => { - // let ty = VectorType::from(*arg); - // let f = self.cx.expose_get_vector_from_wasm(&ty); - // abi_args.push(format!("ptr{}", i)); - // abi_args.push(format!("len{}", i)); - // extra.push_str(&format!(" - // let arg{0} = {func}(ptr{0}, len{0}); - // ", i, func = f)); - // invoc_args.push(format!("arg{}", i)); - // - // if ty.owned { - // extra.push_str(&format!(" - // wasm.__wbindgen_free(ptr{0}, len{0}); - // ", i)); - // self.cx.required_internal_exports.insert("__wbindgen_free"); - // } - // } + abi_args.push(format!("arg{}", i)); + let invoc_arg = match *arg { + shared::TYPE_NUMBER => format!("arg{}", i), + shared::TYPE_BOOLEAN => format!("arg{} !== 0", i), shared::TYPE_JS_OWNED => { self.cx.expose_take_object(); - invoc_args.push(format!("takeObject(arg{})", i)); - abi_args.push(format!("arg{}", i)); + format!("takeObject(arg{})", i) } shared::TYPE_JS_REF => { self.cx.expose_get_object(); - invoc_args.push(format!("getObject(arg{})", i)); - abi_args.push(format!("arg{}", i)); + format!("getObject(arg{})", i) } - custom if custom & shared::TYPE_CUSTOM_REF_FLAG == 0 => { - let s = self.cx.custom_type_name(custom).to_string(); - abi_args.push(format!("ptr{}", i)); - let assign = if self.cx.config.debug { - format!("let arg{0} = new {class}(ptr{0}, token);", i, class = s) - } else { - format!("let arg{0} = new {class}(ptr{0});", i, class = s) - }; - extra.push_str(&assign); - invoc_args.push(format!("arg{}", i)); + other => { + match VectorType::from(other) { + Some(ty) => { + let f = self.cx.expose_get_vector_from_wasm(&ty); + needs_next_global = true; + self.cx.expose_get_global_argument(); + extra.push_str(&format!(" + let len{0} = getGlobalArgument(next_global++); + let v{0} = {func}(arg{0}, len{0}); + ", i, func = f)); + + if ty.owned { + extra.push_str(&format!(" + wasm.__wbindgen_free(arg{0}, len{0} * {size}); + ", i, size = ty.size())); + self.cx.required_internal_exports.insert( + "__wbindgen_free" + ); + } + format!("v{}", i) + } + None => { + if other & shared::TYPE_CUSTOM_REF_FLAG != 0 { + panic!("cannot import custom ref types yet") + } + let s = self.cx.custom_type_name(other).to_string(); + let assign = if self.cx.config.debug { + format!("let c{0} = new {class}(arg{0}, token);", i, class = s) + } else { + format!("let c{0} = new {class}(arg{0});", i, class = s) + }; + extra.push_str(&assign); + format!("c{}", i) + } + } } - _ => { - panic!("unsupported type in import"); - } - } + }; + invoc_args.push(invoc_arg); } let nargs = invoc_args.len(); @@ -1533,27 +1515,26 @@ impl<'a, 'b> SubContext<'a, 'b> { self.cx.expose_add_heap_object(); format!("return addHeapObject({});", invoc) } - // Some(shared::TYPE_STRING) | - // Some(shared::TYPE_VECTOR_U8) | - // Some(shared::TYPE_VECTOR_I8) | - // Some(shared::TYPE_VECTOR_U16) | - // Some(shared::TYPE_VECTOR_I16) | - // Some(shared::TYPE_VECTOR_U32) | - // Some(shared::TYPE_VECTOR_I32) | - // Some(shared::TYPE_VECTOR_F32) | - // Some(shared::TYPE_VECTOR_F64) => { - // let ty = VectorType::from(import.function.ret.unwrap()); - // let f = self.cx.pass_to_wasm_function(&ty); - // self.cx.expose_uint32_memory(); - // abi_args.push("wasmretptr".to_string()); - // format!(" - // const [retptr, retlen] = {}({}); - // getUint32Memory()[wasmretptr / 4] = retlen; - // return retptr; - // ", f, invoc) - // } + Some(other) => { + match VectorType::from(other) { + Some(ty) => { + if !ty.owned { + panic!("cannot return borrowed slices in imports"); + } + let f = self.cx.pass_to_wasm_function(&ty); + self.cx.expose_uint32_memory(); + self.cx.expose_push_global_argument(); + format!(" + GLOBAL_ARGUMENT_CNT = 0; + const [retptr, retlen] = {}({}); + pushGlobalArgument(retlen); + return retptr; + ", f, invoc) + } + None => panic!("unimplemented return type in import"), + } + } None => invoc, - _ => unimplemented!(), }; let invoc = if import.catch { @@ -1575,6 +1556,9 @@ impl<'a, 'b> SubContext<'a, 'b> { dst.push_str(&abi_args.join(", ")); dst.push_str(") {\n"); + if needs_next_global { + dst.push_str("let next_global = 0;\n"); + } dst.push_str(&extra); dst.push_str(&format!("{}\n}}", invoc)); diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index a3693309..ad0e3b62 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -3,12 +3,10 @@ extern crate wasm_bindgen_shared as shared; extern crate serde_json; extern crate wasm_gc; -use std::char; use std::collections::BTreeSet; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; -use std::slice; use parity_wasm::elements::*;