use crate::{ backend::{Backend, RunnableModule}, cache::{Artifact, Error as CacheError}, error, import::ImportObject, structures::{Map, TypedIndex}, types::{ FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, TableIndex, }, Instance, }; use crate::backend::CacheGen; use hashbrown::HashMap; use indexmap::IndexMap; use std::sync::Arc; /// This is used to instantiate a new WebAssembly module. #[doc(hidden)] pub struct ModuleInner { pub runnable_module: Box, pub cache_gen: Box, pub info: ModuleInfo, } #[derive(Clone, Serialize, Deserialize)] pub struct ModuleInfo { // This are strictly local and the typsystem ensures that. pub memories: Map, pub globals: Map, pub tables: Map, // These are strictly imported and the typesystem ensures that. pub imported_functions: Map, pub imported_memories: Map, pub imported_tables: Map, pub imported_globals: Map, pub exports: HashMap, pub data_initializers: Vec, pub elem_initializers: Vec, pub start_func: Option, pub func_assoc: Map, pub signatures: Map, pub backend: Backend, pub namespace_table: StringTable, pub name_table: StringTable, /// Symbol information from emscripten pub em_symbol_map: Option>, pub custom_sections: HashMap>, } impl ModuleInfo { pub fn import_custom_sections(&mut self, wasm: &[u8]) -> crate::error::ParseResult<()> { let mut parser = wasmparser::ModuleReader::new(wasm)?; while !parser.eof() { let section = parser.read()?; if let wasmparser::SectionCode::Custom { name, kind: _ } = section.code { let mut reader = section.get_binary_reader(); let len = reader.bytes_remaining(); let bytes = reader.read_bytes(len)?; let data = bytes.to_vec(); let name = name.to_string(); self.custom_sections.insert(name, data); } } Ok(()) } } /// A compiled WebAssembly module. /// /// `Module` is returned by the [`compile`] and /// [`compile_with`] functions. /// /// [`compile`]: fn.compile.html /// [`compile_with`]: fn.compile_with.html pub struct Module { inner: Arc, } impl Module { pub(crate) fn new(inner: Arc) -> Self { Module { inner } } /// Instantiate a WebAssembly module with the provided [`ImportObject`]. /// /// [`ImportObject`]: struct.ImportObject.html /// /// # Note: /// Instantiating a `Module` will also call the function designated as `start` /// in the WebAssembly module, if there is one. /// /// # Usage: /// ``` /// # use wasmer_runtime_core::error::Result; /// # use wasmer_runtime_core::Module; /// # use wasmer_runtime_core::imports; /// # fn instantiate(module: &Module) -> Result<()> { /// let import_object = imports! { /// // ... /// }; /// let instance = module.instantiate(&import_object)?; /// // ... /// # Ok(()) /// # } /// ``` pub fn instantiate(&self, import_object: &ImportObject) -> error::Result { Instance::new(Arc::clone(&self.inner), import_object) } pub fn cache(&self) -> Result { let (backend_metadata, code) = self.inner.cache_gen.generate_cache()?; Ok(Artifact::from_parts( Box::new(self.inner.info.clone()), backend_metadata, code, )) } pub fn info(&self) -> &ModuleInfo { &self.inner.info } } impl Clone for Module { fn clone(&self) -> Self { Self { inner: Arc::clone(&self.inner), } } } impl ModuleInner {} #[doc(hidden)] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ImportName { pub namespace_index: NamespaceIndex, pub name_index: NameIndex, } #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub enum ExportIndex { Func(FuncIndex), Memory(MemoryIndex), Global(GlobalIndex), Table(TableIndex), } /// A data initializer for linear memory. #[derive(Serialize, Deserialize, Debug, Clone)] pub struct DataInitializer { /// The index of the memory to initialize. pub memory_index: MemoryIndex, /// Either a constant offset or a `get_global` pub base: Initializer, /// The initialization data. #[cfg_attr(feature = "cache", serde(with = "serde_bytes"))] pub data: Vec, } /// A WebAssembly table initializer. #[derive(Serialize, Deserialize, Debug, Clone)] pub struct TableInitializer { /// The index of a table to initialize. pub table_index: TableIndex, /// Either a constant offset or a `get_global` pub base: Initializer, /// The values to write into the table elements. pub elements: Vec, } pub struct StringTableBuilder { map: IndexMap, buffer: String, count: u32, } impl StringTableBuilder { pub fn new() -> Self { Self { map: IndexMap::new(), buffer: String::new(), count: 0, } } pub fn register(&mut self, s: S) -> K where S: Into + AsRef, { let s_str = s.as_ref(); if self.map.contains_key(s_str) { self.map[s_str].0 } else { let offset = self.buffer.len(); let length = s_str.len(); let index = TypedIndex::new(self.count as _); self.buffer.push_str(s_str); self.map .insert(s.into(), (index, offset as u32, length as u32)); self.count += 1; index } } pub fn finish(self) -> StringTable { let table = self .map .values() .map(|(_, offset, length)| (*offset, *length)) .collect(); StringTable { table, buffer: self.buffer, } } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct StringTable { table: Map, buffer: String, } impl StringTable { pub fn new() -> Self { Self { table: Map::new(), buffer: String::new(), } } pub fn get(&self, index: K) -> &str { let (offset, length) = self.table[index]; let offset = offset as usize; let length = length as usize; &self.buffer[offset..offset + length] } } #[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NamespaceIndex(u32); impl TypedIndex for NamespaceIndex { #[doc(hidden)] fn new(index: usize) -> Self { NamespaceIndex(index as _) } #[doc(hidden)] fn index(&self) -> usize { self.0 as usize } } #[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NameIndex(u32); impl TypedIndex for NameIndex { #[doc(hidden)] fn new(index: usize) -> Self { NameIndex(index as _) } #[doc(hidden)] fn index(&self) -> usize { self.0 as usize } }