diff --git a/Cargo.lock b/Cargo.lock index a981255b6e68..cbfcb184faee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1008,6 +1008,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe" dependencies = [ "autocfg 1.0.0", + "serde", ] [[package]] diff --git a/cranelift/codegen/src/ir/extfunc.rs b/cranelift/codegen/src/ir/extfunc.rs index 9bb089fd5606..6390f28a4353 100644 --- a/cranelift/codegen/src/ir/extfunc.rs +++ b/cranelift/codegen/src/ir/extfunc.rs @@ -11,6 +11,8 @@ use crate::machinst::RelocDistance; use alloc::vec::Vec; use core::fmt; use core::str::FromStr; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; /// Function signature. /// @@ -20,6 +22,7 @@ use core::str::FromStr; /// A signature can optionally include ISA-specific ABI information which specifies exactly how /// arguments and return values are passed. #[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Signature { /// The arguments passed to the function. pub params: Vec, @@ -145,6 +148,7 @@ impl fmt::Display for Signature { /// This describes the value type being passed to or from a function along with flags that affect /// how the argument is passed. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct AbiParam { /// Type of the argument value. pub value_type: Type, @@ -255,6 +259,7 @@ impl fmt::Display for AbiParam { /// On some architectures, small integer function arguments are extended to the width of a /// general-purpose register. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum ArgumentExtension { /// No extension, high bits are indeterminate. None, @@ -272,6 +277,7 @@ pub enum ArgumentExtension { /// /// The argument purpose is used to indicate any special meaning of an argument or return value. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum ArgumentPurpose { /// A normal user program value passed to or from a function. Normal, diff --git a/cranelift/codegen/src/ir/immediates.rs b/cranelift/codegen/src/ir/immediates.rs index f6f485e4d103..27746315d68b 100644 --- a/cranelift/codegen/src/ir/immediates.rs +++ b/cranelift/codegen/src/ir/immediates.rs @@ -8,6 +8,8 @@ use alloc::vec::Vec; use core::fmt::{self, Display, Formatter}; use core::str::FromStr; use core::{i32, u32}; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; /// Convert a type into a vector of bytes; all implementors in this file must use little-endian /// orderings of bytes to match WebAssembly's little-endianness. @@ -325,6 +327,7 @@ impl FromStr for Uimm32 { /// /// This is used as an immediate value in SIMD instructions. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct V128Imm(pub [u8; 16]); impl V128Imm { diff --git a/cranelift/codegen/src/ir/types.rs b/cranelift/codegen/src/ir/types.rs index 060c087747b3..319f3ae66f69 100644 --- a/cranelift/codegen/src/ir/types.rs +++ b/cranelift/codegen/src/ir/types.rs @@ -3,6 +3,8 @@ use core::default::Default; use core::fmt::{self, Debug, Display, Formatter}; use cranelift_codegen_shared::constants; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; use target_lexicon::{PointerWidth, Triple}; /// The type of an SSA value. @@ -21,6 +23,7 @@ use target_lexicon::{PointerWidth, Triple}; /// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type. /// #[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Type(u8); /// Not a valid type. Can't be loaded or stored. Can't be part of a SIMD vector. diff --git a/cranelift/codegen/src/ir/valueloc.rs b/cranelift/codegen/src/ir/valueloc.rs index 6fbe7e0195a1..d0b924886a19 100644 --- a/cranelift/codegen/src/ir/valueloc.rs +++ b/cranelift/codegen/src/ir/valueloc.rs @@ -98,6 +98,7 @@ impl<'a> fmt::Display for DisplayValueLoc<'a> { /// - For register arguments, there is usually no difference, but if we ever add support for a /// register-window ISA like SPARC, register arguments would also need to be translated. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum ArgumentLoc { /// This argument has not been assigned to a location yet. Unassigned, diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index a0496677f0c5..800a793aab3f 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -30,6 +30,7 @@ use crate::translation_utils::{ }; use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex}; use crate::wasm_unsupported; +use core::convert::TryInto; use core::{i32, u32}; use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; use cranelift_codegen::ir::immediates::Offset32; @@ -1039,7 +1040,9 @@ pub fn translate_operator( Operator::F32Le | Operator::F64Le => { translate_fcmp(FloatCC::LessThanOrEqual, builder, state) } - Operator::RefNull { ty } => state.push1(environ.translate_ref_null(builder.cursor(), *ty)?), + Operator::RefNull { ty } => { + state.push1(environ.translate_ref_null(builder.cursor(), (*ty).try_into()?)?) + } Operator::RefIsNull { ty: _ } => { let value = state.pop1(); state.push1(environ.translate_ref_is_null(builder.cursor(), value)?); diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index 25f5c3a5929e..9047df05d27e 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -547,7 +547,7 @@ impl TargetEnvironment for DummyEnvironment { } impl<'data> ModuleEnvironment<'data> for DummyEnvironment { - fn declare_signature(&mut self, _wasm: &WasmFuncType, sig: ir::Signature) -> WasmResult<()> { + fn declare_signature(&mut self, _wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> { self.info.signatures.push(sig); Ok(()) } diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index eacc90233f33..9a3498b05eab 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -12,22 +12,89 @@ use crate::translation_utils::{ Table, TableIndex, }; use core::convert::From; +use core::convert::TryFrom; use cranelift_codegen::cursor::FuncCursor; use cranelift_codegen::ir::immediates::Offset32; use cranelift_codegen::ir::{self, InstBuilder}; use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_frontend::FunctionBuilder; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; use std::boxed::Box; +use std::string::ToString; use thiserror::Error; use wasmparser::BinaryReaderError; use wasmparser::Operator; -// Re-export `wasmparser`'s function and value types so that consumers can -// associate this the original Wasm signature with each compiled function. This -// is often necessary because while each Wasm signature gets compiled down into -// a single native signature, multiple Wasm signatures might compile down into -// the same native signature. -pub use wasmparser::{FuncType as WasmFuncType, Type as WasmType}; +/// WebAssembly value type -- equivalent of `wasmparser`'s Type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +pub enum WasmType { + /// I32 type + I32, + /// I64 type + I64, + /// F32 type + F32, + /// F64 type + F64, + /// V128 type + V128, + /// FuncRef type + FuncRef, + /// ExternRef type + ExternRef, +} + +impl TryFrom for WasmType { + type Error = WasmError; + fn try_from(ty: wasmparser::Type) -> Result { + use wasmparser::Type::*; + match ty { + I32 => Ok(WasmType::I32), + I64 => Ok(WasmType::I64), + F32 => Ok(WasmType::F32), + F64 => Ok(WasmType::F64), + V128 => Ok(WasmType::V128), + FuncRef => Ok(WasmType::FuncRef), + ExternRef => Ok(WasmType::ExternRef), + EmptyBlockType | Func => Err(WasmError::InvalidWebAssembly { + message: "unexpected value type".to_string(), + offset: 0, + }), + } + } +} + +/// WebAssembly function type -- equivalent of `wasmparser`'s FuncType. +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +pub struct WasmFuncType { + /// Function params types. + pub params: Box<[WasmType]>, + /// Returns params types. + pub returns: Box<[WasmType]>, +} + +impl TryFrom for WasmFuncType { + type Error = WasmError; + fn try_from(ty: wasmparser::FuncType) -> Result { + Ok(Self { + params: ty + .params + .into_vec() + .into_iter() + .map(WasmType::try_from) + .collect::>()?, + returns: ty + .returns + .into_vec() + .into_iter() + .map(WasmType::try_from) + .collect::>()?, + }) + } +} /// The value of a WebAssembly global variable. #[derive(Clone, Copy)] @@ -524,7 +591,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment { /// Declares a function signature to the environment. fn declare_signature( &mut self, - wasm_func_type: &WasmFuncType, + wasm_func_type: WasmFuncType, sig: ir::Signature, ) -> WasmResult<()>; diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index 601996d6df11..11ec5b6ca72b 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -9,6 +9,7 @@ use crate::environ::{FuncEnvironment, ReturnMode, WasmResult}; use crate::state::{FuncTranslationState, ModuleTranslationState}; use crate::translation_utils::get_vmctx_value_label; use crate::wasm_unsupported; +use core::convert::TryInto; use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::{self, Block, InstBuilder, ValueLabel}; use cranelift_codegen::timing; @@ -196,7 +197,9 @@ fn declare_locals( let constant_handle = builder.func.dfg.constants.insert([0; 16].to_vec().into()); builder.ins().vconst(ir::types::I8X16, constant_handle) } - ExternRef | FuncRef => environ.translate_ref_null(builder.cursor(), wasm_type)?, + ExternRef | FuncRef => { + environ.translate_ref_null(builder.cursor(), wasm_type.try_into()?)? + } ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)), }; diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index 7075fbc19bf8..36f93cda13ee 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -15,6 +15,7 @@ use crate::translation_utils::{ }; use crate::{wasm_unsupported, HashMap}; use core::convert::TryFrom; +use core::convert::TryInto; use cranelift_codegen::ir::immediates::V128Imm; use cranelift_codegen::ir::{self, AbiParam, Signature}; use cranelift_entity::packed_option::ReservedValue; @@ -53,7 +54,7 @@ pub fn parse_type_section( .expect("only numeric types are supported in function signatures"); AbiParam::new(cret_arg) })); - environ.declare_signature(&wasm_func_ty, sig)?; + environ.declare_signature(wasm_func_ty.clone().try_into()?, sig)?; module_translation_state .wasm_types .push((wasm_func_ty.params, wasm_func_ty.returns)); @@ -104,7 +105,7 @@ pub fn parse_import_section<'data>( ImportSectionEntryType::Global(ref ty) => { environ.declare_global_import( Global { - wasm_ty: ty.content_type, + wasm_ty: ty.content_type.try_into()?, ty: type_to_type(ty.content_type, environ).unwrap(), mutability: ty.mutable, initializer: GlobalInit::Import, @@ -116,7 +117,7 @@ pub fn parse_import_section<'data>( ImportSectionEntryType::Table(ref tab) => { environ.declare_table_import( Table { - wasm_ty: tab.element_type, + wasm_ty: tab.element_type.try_into()?, ty: match tabletype_to_type(tab.element_type, environ)? { Some(t) => TableElementType::Val(t), None => TableElementType::Func, @@ -166,7 +167,7 @@ pub fn parse_table_section( for entry in tables { let table = entry?; environ.declare_table(Table { - wasm_ty: table.element_type, + wasm_ty: table.element_type.try_into()?, ty: match tabletype_to_type(table.element_type, environ)? { Some(t) => TableElementType::Val(t), None => TableElementType::Func, @@ -237,7 +238,7 @@ pub fn parse_global_section( } }; let global = Global { - wasm_ty: content_type, + wasm_ty: content_type.try_into()?, ty: type_to_type(content_type, environ).unwrap(), mutability: mutable, initializer, diff --git a/cranelift/wasm/src/translation_utils.rs b/cranelift/wasm/src/translation_utils.rs index 4bbab4e75ab4..2975584f7346 100644 --- a/cranelift/wasm/src/translation_utils.rs +++ b/cranelift/wasm/src/translation_utils.rs @@ -2,6 +2,7 @@ use crate::environ::{TargetEnvironment, WasmResult, WasmType}; use crate::state::ModuleTranslationState; use crate::wasm_unsupported; +use core::convert::TryInto; use core::u32; use cranelift_codegen::entity::entity_impl; use cranelift_codegen::ir; @@ -39,31 +40,37 @@ entity_impl!(DefinedGlobalIndex); /// Index type of a table (imported or defined) inside the WebAssembly module. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct TableIndex(u32); entity_impl!(TableIndex); /// Index type of a global variable (imported or defined) inside the WebAssembly module. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct GlobalIndex(u32); entity_impl!(GlobalIndex); /// Index type of a linear memory (imported or defined) inside the WebAssembly module. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct MemoryIndex(u32); entity_impl!(MemoryIndex); /// Index type of a signature (imported or defined) inside the WebAssembly module. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct SignatureIndex(u32); entity_impl!(SignatureIndex); /// Index type of a passive data segment inside the WebAssembly module. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct DataIndex(u32); entity_impl!(DataIndex); /// Index type of a passive element segment inside the WebAssembly module. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct ElemIndex(u32); entity_impl!(ElemIndex); @@ -75,6 +82,7 @@ entity_impl!(ElemIndex); /// Wasm `i64` and a `funcref` might be represented with a Cranelift `i64` on /// 64-bit architectures, and when GC is not required for func refs. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Global { /// The Wasm type of the value stored in the global. pub wasm_ty: crate::WasmType, @@ -88,6 +96,7 @@ pub struct Global { /// Globals are initialized via the `const` operators or by referring to another import. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum GlobalInit { /// An `i32.const`. I32Const(i32), @@ -111,6 +120,7 @@ pub enum GlobalInit { /// WebAssembly table. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Table { /// The table elements' Wasm type. pub wasm_ty: WasmType, @@ -124,6 +134,7 @@ pub struct Table { /// WebAssembly table element. Can be a function or a scalar type. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum TableElementType { /// A scalar type. Val(ir::Type), @@ -133,6 +144,7 @@ pub enum TableElementType { /// WebAssembly linear memory. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Memory { /// The minimum number of pages in the memory. pub minimum: u32, @@ -153,7 +165,9 @@ pub fn type_to_type( wasmparser::Type::F32 => Ok(ir::types::F32), wasmparser::Type::F64 => Ok(ir::types::F64), wasmparser::Type::V128 => Ok(ir::types::I8X16), - wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => Ok(environ.reference_type(ty)), + wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => { + Ok(environ.reference_type(ty.try_into()?)) + } ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)), } } @@ -170,7 +184,7 @@ pub fn tabletype_to_type( wasmparser::Type::F32 => Ok(Some(ir::types::F32)), wasmparser::Type::F64 => Ok(Some(ir::types::F64)), wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)), - wasmparser::Type::ExternRef => Ok(Some(environ.reference_type(ty))), + wasmparser::Type::ExternRef => Ok(Some(environ.reference_type(ty.try_into()?))), wasmparser::Type::FuncRef => Ok(None), ty => Err(wasm_unsupported!( "tabletype_to_type: table wasm type {:?}", @@ -226,7 +240,7 @@ pub fn block_with_params( builder.append_block_param(block, ir::types::F64); } wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => { - builder.append_block_param(block, environ.reference_type(*ty)); + builder.append_block_param(block, environ.reference_type((*ty).try_into()?)); } wasmparser::Type::V128 => { builder.append_block_param(block, ir::types::I8X16); diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index 1ab3dd6d07d0..73ddf7a2aef1 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -19,7 +19,7 @@ cranelift-frontend = { path = "../../cranelift/frontend", version = "0.65.0" } cranelift-wasm = { path = "../../cranelift/wasm", version = "0.65.0", features = ["enable-serde"] } wasmparser = "0.58.0" lightbeam = { path = "../lightbeam", optional = true, version = "0.18.0" } -indexmap = "1.0.2" +indexmap = { version = "1.0.2", features = ["serde-1"] } rayon = { version = "1.2.1", optional = true } thiserror = "1.0.4" directories = "2.0.1" diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs index 280210cfa4f0..2f9348fe40fe 100644 --- a/crates/environ/src/module.rs +++ b/crates/environ/src/module.rs @@ -11,6 +11,7 @@ use cranelift_wasm::{ }; use indexmap::IndexMap; use more_asserts::assert_ge; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, @@ -18,7 +19,7 @@ use std::sync::{ }; /// A WebAssembly table initializer. -#[derive(Clone, Debug, Hash)] +#[derive(Clone, Debug, Hash, Serialize, Deserialize)] pub struct TableElements { /// The index of a table to initialize. pub table_index: TableIndex, @@ -31,7 +32,7 @@ pub struct TableElements { } /// An index of an entity. -#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum EntityIndex { /// Function index. Function(FuncIndex), @@ -44,7 +45,7 @@ pub enum EntityIndex { } /// Implemenation styles for WebAssembly linear memory. -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] pub enum MemoryStyle { /// The actual memory can be resized and moved. Dynamic, @@ -80,7 +81,7 @@ impl MemoryStyle { /// A WebAssembly linear memory description along with our chosen style for /// implementing it. -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] pub struct MemoryPlan { /// The WebAssembly linear memory description. pub memory: Memory, @@ -103,7 +104,7 @@ impl MemoryPlan { } /// Implemenation styles for WebAssembly tables. -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] pub enum TableStyle { /// Signatures are stored in the table and checked in the caller. CallerChecksSignature, @@ -118,7 +119,7 @@ impl TableStyle { /// A WebAssembly table description along with our chosen style for /// implementing it. -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] pub struct TablePlan { /// The WebAssembly table description. pub table: cranelift_wasm::Table, @@ -136,9 +137,10 @@ impl TablePlan { /// A translated WebAssembly module, excluding the function bodies and /// memory initializers. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct Module { /// A unique identifier (within this process) for this module. + #[serde(skip_serializing, default = "Module::next_id")] pub id: usize, /// The name of this wasm module, often found in the wasm file. @@ -166,6 +168,7 @@ pub struct Module { pub passive_elements: HashMap>, /// WebAssembly passive data segments. + #[serde(with = "passive_data_serde")] pub passive_data: HashMap>, /// WebAssembly table initializers. @@ -178,7 +181,7 @@ pub struct Module { /// This is stored within a `Module` and it implements `Hash`, unlike `Module`, /// and is used as part of the cache key when we load compiled modules from the /// global cache. -#[derive(Debug, Hash)] +#[derive(Debug, Hash, Serialize, Deserialize)] pub struct ModuleLocal { /// Unprocessed signatures exactly as provided by `declare_signature()`. pub signatures: PrimaryMap, @@ -211,10 +214,8 @@ pub struct ModuleLocal { impl Module { /// Allocates the module data structures. pub fn new() -> Self { - static NEXT_ID: AtomicUsize = AtomicUsize::new(0); - Self { - id: NEXT_ID.fetch_add(1, SeqCst), + id: Self::next_id(), name: None, imports: Vec::new(), exports: IndexMap::new(), @@ -241,6 +242,11 @@ impl Module { pub fn get_passive_element(&self, index: ElemIndex) -> Option<&[FuncIndex]> { self.passive_elements.get(&index).map(|es| &**es) } + + fn next_id() -> usize { + static NEXT_ID: AtomicUsize = AtomicUsize::new(0); + NEXT_ID.fetch_add(1, SeqCst) + } } impl ModuleLocal { @@ -344,3 +350,49 @@ impl ModuleLocal { &self.signatures[self.functions[func_index]].0 } } + +mod passive_data_serde { + use super::{Arc, DataIndex, HashMap}; + use serde::{de::MapAccess, de::Visitor, ser::SerializeMap, Deserializer, Serializer}; + use std::fmt; + + pub(super) fn serialize( + data: &HashMap>, + ser: S, + ) -> Result + where + S: Serializer, + { + let mut map = ser.serialize_map(Some(data.len()))?; + for (k, v) in data { + map.serialize_entry(k, v.as_ref())?; + } + map.end() + } + + struct PassiveDataVisitor; + impl<'de> Visitor<'de> for PassiveDataVisitor { + type Value = HashMap>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a passive_data map") + } + fn visit_map(self, mut access: M) -> Result + where + M: MapAccess<'de>, + { + let mut map = HashMap::with_capacity(access.size_hint().unwrap_or(0)); + while let Some((key, value)) = access.next_entry::<_, Vec>()? { + map.insert(key, value.into()); + } + Ok(map) + } + } + + pub(super) fn deserialize<'de, D>(de: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + de.deserialize_map(PassiveDataVisitor) + } +} diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs index 8d6cd7997f78..1c363dcff49a 100644 --- a/crates/environ/src/module_environ.rs +++ b/crates/environ/src/module_environ.rs @@ -110,14 +110,10 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data Ok(()) } - fn declare_signature(&mut self, wasm: &WasmFuncType, sig: ir::Signature) -> WasmResult<()> { + fn declare_signature(&mut self, wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> { let sig = translate_signature(sig, self.pointer_type()); // TODO: Deduplicate signatures. - self.result - .module - .local - .signatures - .push((wasm.clone(), sig)); + self.result.module.local.signatures.push((wasm, sig)); Ok(()) } diff --git a/crates/wasmtime/src/externals.rs b/crates/wasmtime/src/externals.rs index 3beec44cf90f..ad25a6370d5b 100644 --- a/crates/wasmtime/src/externals.rs +++ b/crates/wasmtime/src/externals.rs @@ -202,13 +202,11 @@ impl Global { // The original export is coming from wasmtime_runtime itself we should // support all the types coming out of it, so assert such here. GlobalType::from_wasmtime_global(&self.wasmtime_export.global) - .expect("core wasm global type should be supported") } /// Returns the value type of this `global`. pub fn val_type(&self) -> ValType { ValType::from_wasm_type(&self.wasmtime_export.global.wasm_ty) - .expect("core wasm type should be supported") } /// Returns the underlying mutability of this `global`. diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index 660a9e84a233..749f632c09f2 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -545,7 +545,7 @@ impl Func { // This is only called with `Export::Function`, and since it's coming // from wasmtime_runtime itself we should support all the types coming // out of it, so assert such here. - FuncType::from_wasm_func_type(&wft).expect("core wasm signature should be supported") + FuncType::from_wasm_func_type(&wft) } /// Returns the number of parameters that this function takes. diff --git a/crates/wasmtime/src/types.rs b/crates/wasmtime/src/types.rs index 3baf77d5cbec..877562e1f995 100644 --- a/crates/wasmtime/src/types.rs +++ b/crates/wasmtime/src/types.rs @@ -123,16 +123,15 @@ impl ValType { } } - pub(crate) fn from_wasm_type(ty: &wasm::WasmType) -> Option { + pub(crate) fn from_wasm_type(ty: &wasm::WasmType) -> Self { match ty { - wasm::WasmType::I32 => Some(Self::I32), - wasm::WasmType::I64 => Some(Self::I64), - wasm::WasmType::F32 => Some(Self::F32), - wasm::WasmType::F64 => Some(Self::F64), - wasm::WasmType::V128 => Some(Self::V128), - wasm::WasmType::FuncRef => Some(Self::FuncRef), - wasm::WasmType::ExternRef => Some(Self::ExternRef), - wasm::WasmType::Func | wasm::WasmType::EmptyBlockType => None, + wasm::WasmType::I32 => Self::I32, + wasm::WasmType::I64 => Self::I64, + wasm::WasmType::F32 => Self::F32, + wasm::WasmType::F64 => Self::F64, + wasm::WasmType::V128 => Self::V128, + wasm::WasmType::FuncRef => Self::FuncRef, + wasm::WasmType::ExternRef => Self::ExternRef, } } } @@ -279,21 +278,21 @@ impl FuncType { /// Returns `None` if any types in the signature can't be converted to the /// types in this crate, but that should very rarely happen and largely only /// indicate a bug in our cranelift integration. - pub(crate) fn from_wasm_func_type(signature: &wasm::WasmFuncType) -> Option { + pub(crate) fn from_wasm_func_type(signature: &wasm::WasmFuncType) -> FuncType { let params = signature .params .iter() .map(|p| ValType::from_wasm_type(p)) - .collect::>>()?; + .collect::>(); let results = signature .returns .iter() .map(|r| ValType::from_wasm_type(r)) - .collect::>>()?; - Some(FuncType { + .collect::>(); + FuncType { params: params.into_boxed_slice(), results: results.into_boxed_slice(), - }) + } } } @@ -332,14 +331,14 @@ impl GlobalType { /// Returns `None` if the wasmtime global has a type that we can't /// represent, but that should only very rarely happen and indicate a bug. - pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> Option { - let ty = ValType::from_wasm_type(&global.wasm_ty)?; + pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> GlobalType { + let ty = ValType::from_wasm_type(&global.wasm_ty); let mutability = if global.mutability { Mutability::Var } else { Mutability::Const }; - Some(GlobalType::new(ty, mutability)) + GlobalType::new(ty, mutability) } } @@ -451,14 +450,10 @@ impl<'module> EntityType<'module> { /// Convert this `EntityType` to an `ExternType`. pub(crate) fn extern_type(&self) -> ExternType { match self { - EntityType::Function(sig) => FuncType::from_wasm_func_type(sig) - .expect("core wasm function type should be supported") - .into(), + EntityType::Function(sig) => FuncType::from_wasm_func_type(sig).into(), EntityType::Table(table) => TableType::from_wasmtime_table(table).into(), EntityType::Memory(memory) => MemoryType::from_wasmtime_memory(memory).into(), - EntityType::Global(global) => GlobalType::from_wasmtime_global(global) - .expect("core wasm global type should be supported") - .into(), + EntityType::Global(global) => GlobalType::from_wasmtime_global(global).into(), } } }