diff --git a/crates/api/src/externals.rs b/crates/api/src/externals.rs index 56aca24ad5..c5a6325be5 100644 --- a/crates/api/src/externals.rs +++ b/crates/api/src/externals.rs @@ -255,7 +255,7 @@ impl Global { } else { panic!("wasmtime export is not memory") }; - let ty = GlobalType::from_cranelift_global(global.clone()); + let ty = GlobalType::from_cranelift_global(&global); Global { _store: store.clone(), r#type: ty, @@ -395,7 +395,7 @@ impl Table { } else { panic!("wasmtime export is not table") }; - let ty = TableType::from_cranelift_table(table.table.clone()); + let ty = TableType::from_cranelift_table(&table.table); Table { store: store.clone(), r#type: ty, @@ -479,7 +479,7 @@ impl Memory { } else { panic!("wasmtime export is not memory") }; - let ty = MemoryType::from_cranelift_memory(memory.memory.clone()); + let ty = MemoryType::from_cranelift_memory(&memory.memory); Memory { _store: store.clone(), r#type: ty, diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 24be6a614b..767b7d22ea 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -3,9 +3,10 @@ use crate::externals::Extern; use crate::module::Module; use crate::r#ref::HostRef; use crate::runtime::Store; +use crate::types::{ExportType, ExternType, Name}; use crate::{HashMap, HashSet}; use alloc::string::{String, ToString}; -use alloc::{borrow::ToOwned, boxed::Box, rc::Rc, vec::Vec}; +use alloc::{boxed::Box, rc::Rc, vec::Vec}; use anyhow::Result; use core::cell::RefCell; use wasmtime_jit::{instantiate, Resolver}; @@ -49,6 +50,8 @@ pub fn instantiate_in_context( pub struct Instance { instance_handle: InstanceHandle, + module: HostRef, + // We need to keep CodeMemory alive. contexts: HashSet, @@ -70,8 +73,12 @@ impl Instance { .zip(externs.iter()) .map(|(i, e)| (i.module().to_string(), i.name().to_string(), e.clone())) .collect::>(); - let (mut instance_handle, contexts) = - instantiate_in_context(module.borrow().binary(), imports, context, exports)?; + let (mut instance_handle, contexts) = instantiate_in_context( + module.borrow().binary().expect("binary"), + imports, + context, + exports, + )?; let exports = { let module = module.borrow(); @@ -89,6 +96,7 @@ impl Instance { }; Ok(Instance { instance_handle, + module: module.clone(), contexts, exports, }) @@ -98,14 +106,25 @@ impl Instance { &self.exports } + pub fn find_export_by_name(&self, name: &str) -> Option<&Extern> { + let (i, _) = self + .module + .borrow() + .exports() + .iter() + .enumerate() + .find(|(_, e)| e.name().as_str() == name)?; + Some(&self.exports()[i]) + } + pub fn from_handle( store: &HostRef, instance_handle: InstanceHandle, - ) -> Result<(Instance, HashMap)> { + ) -> Result { let contexts = HashSet::new(); let mut exports = Vec::new(); - let mut export_names_map = HashMap::new(); + let mut exports_types = Vec::new(); let mut mutable = instance_handle.clone(); for (name, _) in instance_handle.clone().exports() { let export = mutable.lookup(name).expect("export"); @@ -115,7 +134,8 @@ impl Instance { // imported into this store using the from_handle() method. let _ = store.borrow_mut().register_cranelift_signature(signature); } - export_names_map.insert(name.to_owned(), exports.len()); + let extern_type = ExternType::from_wasmtime_export(&export); + exports_types.push(ExportType::new(Name::new(name), extern_type)); exports.push(Extern::from_wasmtime_export( store, instance_handle.clone(), @@ -123,14 +143,17 @@ impl Instance { )); } - Ok(( - Instance { - instance_handle, - contexts, - exports: exports.into_boxed_slice(), - }, - export_names_map, - )) + let module = HostRef::new(Module::from_exports( + store, + exports_types.into_boxed_slice(), + )); + + Ok(Instance { + instance_handle, + module, + contexts, + exports: exports.into_boxed_slice(), + }) } pub fn handle(&self) -> &InstanceHandle { diff --git a/crates/api/src/module.rs b/crates/api/src/module.rs index 5499fed94d..26efc9e74d 100644 --- a/crates/api/src/module.rs +++ b/crates/api/src/module.rs @@ -170,10 +170,16 @@ fn read_imports_and_exports(binary: &[u8]) -> Result<(Box<[ImportType]>, Box<[Ex Ok((imports.into_boxed_slice(), exports.into_boxed_slice())) } +#[derive(Clone)] +pub(crate) enum ModuleCodeSource { + Binary(Box<[u8]>), + Unknown, +} + #[derive(Clone)] pub struct Module { store: HostRef, - binary: Box<[u8]>, + source: ModuleCodeSource, imports: Box<[ImportType]>, exports: Box<[ExportType]>, } @@ -183,13 +189,16 @@ impl Module { let (imports, exports) = read_imports_and_exports(binary)?; Ok(Module { store: store.clone(), - binary: binary.into(), + source: ModuleCodeSource::Binary(binary.into()), imports, exports, }) } - pub(crate) fn binary(&self) -> &[u8] { - &self.binary + pub(crate) fn binary(&self) -> Option<&[u8]> { + match &self.source { + ModuleCodeSource::Binary(b) => Some(b), + _ => None, + } } pub fn validate(_store: &Store, binary: &[u8]) -> bool { validate(binary, None).is_ok() @@ -200,4 +209,12 @@ impl Module { pub fn exports(&self) -> &[ExportType] { &self.exports } + pub fn from_exports(store: &HostRef, exports: Box<[ExportType]>) -> Self { + Module { + store: store.clone(), + source: ModuleCodeSource::Unknown, + imports: Box::new([]), + exports, + } + } } diff --git a/crates/api/src/runtime.rs b/crates/api/src/runtime.rs index 801de8dd52..e79050516b 100644 --- a/crates/api/src/runtime.rs +++ b/crates/api/src/runtime.rs @@ -1,7 +1,7 @@ -use crate::context::{create_compiler, Context}; +use crate::context::Context; use crate::r#ref::HostRef; use crate::HashMap; -use alloc::{boxed::Box, rc::Rc, string::String}; +use alloc::{rc::Rc, string::String}; use core::cell::RefCell; use cranelift_codegen::{ir, settings}; use wasmtime_jit::{CompilationStrategy, Features}; @@ -81,11 +81,6 @@ impl Engine { pub(crate) fn config(&self) -> &Config { &self.config } - - pub fn create_wasmtime_context(&self) -> wasmtime_jit::Context { - let flags = self.config.flags().clone(); - wasmtime_jit::Context::new(Box::new(create_compiler(flags, self.config.strategy()))) - } } // Store diff --git a/crates/api/src/types.rs b/crates/api/src/types.rs index 1c51e00013..0f32b27953 100644 --- a/crates/api/src/types.rs +++ b/crates/api/src/types.rs @@ -127,6 +127,22 @@ impl ExternType { _ => panic!("ExternType::ExternMemory expected"), } } + pub(crate) fn from_wasmtime_export(export: &wasmtime_runtime::Export) -> Self { + match export { + wasmtime_runtime::Export::Function { signature, .. } => { + ExternType::ExternFunc(FuncType::from_cranelift_signature(signature.clone())) + } + wasmtime_runtime::Export::Memory { memory, .. } => { + ExternType::ExternMemory(MemoryType::from_cranelift_memory(&memory.memory)) + } + wasmtime_runtime::Export::Global { global, .. } => { + ExternType::ExternGlobal(GlobalType::from_cranelift_global(&global)) + } + wasmtime_runtime::Export::Table { table, .. } => { + ExternType::ExternTable(TableType::from_cranelift_table(&table.table)) + } + } + } } // Function Types @@ -224,7 +240,7 @@ impl GlobalType { self.mutability } - pub(crate) fn from_cranelift_global(global: cranelift_wasm::Global) -> GlobalType { + pub(crate) fn from_cranelift_global(global: &cranelift_wasm::Global) -> GlobalType { let ty = ValType::from_cranelift_type(global.ty); let mutability = if global.mutability { Mutability::Var @@ -254,7 +270,7 @@ impl TableType { &self.limits } - pub(crate) fn from_cranelift_table(table: cranelift_wasm::Table) -> TableType { + pub(crate) fn from_cranelift_table(table: &cranelift_wasm::Table) -> TableType { assert!(if let cranelift_wasm::TableElementType::Func = table.ty { true } else { @@ -281,7 +297,7 @@ impl MemoryType { &self.limits } - pub(crate) fn from_cranelift_memory(memory: cranelift_wasm::Memory) -> MemoryType { + pub(crate) fn from_cranelift_memory(memory: &cranelift_wasm::Memory) -> MemoryType { MemoryType::new(Limits::new( memory.minimum, memory.maximum.unwrap_or(::core::u32::MAX), @@ -294,6 +310,16 @@ impl MemoryType { #[derive(Debug, Clone)] pub struct Name(String); +impl Name { + pub fn new(value: &str) -> Self { + Name(value.to_owned()) + } + + pub fn as_str(&self) -> &str { + self.0.as_str() + } +} + impl From for Name { fn from(s: String) -> Name { Name(s) diff --git a/crates/api/src/values.rs b/crates/api/src/values.rs index ba3584f28e..42163b119d 100644 --- a/crates/api/src/values.rs +++ b/crates/api/src/values.rs @@ -180,6 +180,34 @@ impl Into for Val { } } +impl From for Val { + fn from(rv: RuntimeValue) -> Self { + match rv { + RuntimeValue::I32(i) => Val::I32(i), + RuntimeValue::I64(i) => Val::I64(i), + RuntimeValue::F32(u) => Val::F32(u), + RuntimeValue::F64(u) => Val::F64(u), + x => { + panic!("unsupported {:?}", x); + } + } + } +} + +impl Into for Val { + fn into(self) -> RuntimeValue { + match self { + Val::I32(i) => RuntimeValue::I32(i), + Val::I64(i) => RuntimeValue::I64(i), + Val::F32(u) => RuntimeValue::F32(u), + Val::F64(u) => RuntimeValue::F64(u), + x => { + panic!("unsupported {:?}", x); + } + } + } +} + pub(crate) fn into_checked_anyfunc( val: Val, store: &HostRef, diff --git a/crates/interface-types/Cargo.toml b/crates/interface-types/Cargo.toml index 7b6fd02a55..b37e883e3a 100644 --- a/crates/interface-types/Cargo.toml +++ b/crates/interface-types/Cargo.toml @@ -16,6 +16,7 @@ cranelift-codegen = { version = "0.50.0", default-features = false } walrus = "0.13" wasmparser = { version = "0.39.2", default-features = false } wasm-webidl-bindings = "0.6" +wasmtime = { path = '../api' } wasmtime-jit = { path = '../jit', default-features = false } wasmtime-runtime = { path = '../runtime', default-features = false } wasmtime-wasi = { path = '../wasi' } diff --git a/crates/interface-types/src/lib.rs b/crates/interface-types/src/lib.rs index 27f2973748..e4aa84910c 100644 --- a/crates/interface-types/src/lib.rs +++ b/crates/interface-types/src/lib.rs @@ -18,6 +18,7 @@ use core::slice; use core::str; use cranelift_codegen::ir; use wasm_webidl_bindings::ast; +use wasmtime_api as api; use wasmtime_jit::{ActionOutcome, Context, RuntimeValue}; use wasmtime_runtime::{Export, InstanceHandle}; @@ -141,12 +142,55 @@ impl ModuleData { let incoming = binding.param_bindings()?; let outgoing = binding.result_bindings()?; - let wasm_args = translate_incoming(cx, handle, &incoming, args)?; + let wasm_args = + translate_incoming(&mut RawTranslateContext::new(cx, handle), &incoming, args)?; let wasm_results = match cx.invoke(handle, export, &wasm_args)? { ActionOutcome::Returned { values } => values, ActionOutcome::Trapped { message } => bail!("trapped: {}", message), }; - translate_outgoing(cx, handle, &outgoing, &wasm_results) + translate_outgoing( + &mut RawTranslateContext::new(cx, handle), + &outgoing, + &wasm_results, + ) + } + + /// Invokes wasmtime function with a `&[Value]` list. `Value` the set of + /// wasm interface types. + pub fn invoke_export( + &self, + instance: &api::HostRef, + export: &str, + args: &[Value], + ) -> Result> { + let mut handle = instance.borrow().handle().clone(); + + let binding = self.binding_for_export(&mut handle, export)?; + let incoming = binding.param_bindings()?; + let outgoing = binding.result_bindings()?; + + let f = instance + .borrow() + .find_export_by_name(export) + .ok_or_else(|| format_err!("failed to find export `{}`", export))? + .func() + .ok_or_else(|| format_err!("`{}` is not a function", export))? + .clone(); + + let mut cx = InstanceTranslateContext(instance.clone()); + let wasm_args = translate_incoming(&mut cx, &incoming, args)? + .into_iter() + .map(|rv| rv.into()) + .collect::>(); + let wasm_results = match f.borrow().call(&wasm_args) { + Ok(values) => values + .to_vec() + .into_iter() + .map(|v: api::Val| v.into()) + .collect::>(), + Err(trap) => bail!("trapped: {:?}", trap), + }; + translate_outgoing(&mut cx, &outgoing, &wasm_results) } /// Returns an appropriate binding for the `name` export in this module @@ -300,9 +344,95 @@ fn abi2ast(param: &ir::AbiParam) -> Result { }) } +trait TranslateContext { + fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result; + unsafe fn get_memory(&mut self) -> Result<&mut [u8]>; +} + +struct RawTranslateContext<'a> { + cx: &'a mut Context, + handle: &'a mut InstanceHandle, +} + +impl<'a> RawTranslateContext<'a> { + fn new(cx: &'a mut Context, handle: &'a mut InstanceHandle) -> Self { + RawTranslateContext { cx, handle } + } +} + +impl TranslateContext for RawTranslateContext<'_> { + fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result { + let alloc_args = vec![RuntimeValue::I32(len)]; + let results = match self.cx.invoke(self.handle, alloc_func_name, &alloc_args)? { + ActionOutcome::Returned { values } => values, + ActionOutcome::Trapped { message } => bail!("trapped: {}", message), + }; + if results.len() != 1 { + bail!("allocator function wrong number of results"); + } + Ok(match results[0] { + RuntimeValue::I32(i) => i, + _ => bail!("allocator function bad return type"), + }) + } + unsafe fn get_memory(&mut self) -> Result<&mut [u8]> { + let memory = self + .handle + .lookup("memory") + .ok_or_else(|| format_err!("no exported `memory`"))?; + let definition = match memory { + wasmtime_runtime::Export::Memory { definition, .. } => definition, + _ => bail!("export `memory` wasn't a `Memory`"), + }; + Ok(slice::from_raw_parts_mut( + (*definition).base, + (*definition).current_length, + )) + } +} + +struct InstanceTranslateContext(pub api::HostRef); + +impl TranslateContext for InstanceTranslateContext { + fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result { + let alloc = self + .0 + .borrow() + .find_export_by_name(alloc_func_name) + .ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))? + .func() + .ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))? + .clone(); + let alloc_args = vec![api::Val::I32(len)]; + let results = match alloc.borrow().call(&alloc_args) { + Ok(values) => values, + Err(trap) => bail!("trapped: {:?}", trap), + }; + if results.len() != 1 { + bail!("allocator function wrong number of results"); + } + Ok(match results[0] { + api::Val::I32(i) => i, + _ => bail!("allocator function bad return type"), + }) + } + unsafe fn get_memory(&mut self) -> Result<&mut [u8]> { + let memory = self + .0 + .borrow() + .find_export_by_name("memory") + .ok_or_else(|| format_err!("failed to find `memory` export"))? + .memory() + .ok_or_else(|| format_err!("`memory` is not a memory"))? + .clone(); + let ptr = memory.borrow().data_ptr(); + let len = memory.borrow().data_size(); + Ok(std::slice::from_raw_parts_mut(ptr, len)) + } +} + fn translate_incoming( - cx: &mut Context, - handle: &mut InstanceHandle, + cx: &mut dyn TranslateContext, bindings: &[ast::IncomingBindingExpression], args: &[Value], ) -> Result> { @@ -313,29 +443,11 @@ fn translate_incoming( _ => bail!("unsupported incoming binding expr {:?}", expr), }; - let mut copy = |alloc_func_name: &str, bytes: &[u8]| { + let mut copy = |alloc_func_name: &str, bytes: &[u8]| -> Result<(i32, i32)> { let len = i32::try_from(bytes.len()).map_err(|_| format_err!("length overflow"))?; - let alloc_args = vec![RuntimeValue::I32(len)]; - let results = match cx.invoke(handle, alloc_func_name, &alloc_args)? { - ActionOutcome::Returned { values } => values, - ActionOutcome::Trapped { message } => bail!("trapped: {}", message), - }; - if results.len() != 1 { - bail!("allocator function wrong number of results"); - } - let ptr = match results[0] { - RuntimeValue::I32(i) => i, - _ => bail!("allocator function bad return type"), - }; - let memory = handle - .lookup("memory") - .ok_or_else(|| format_err!("no exported `memory`"))?; - let definition = match memory { - wasmtime_runtime::Export::Memory { definition, .. } => definition, - _ => bail!("export `memory` wasn't a `Memory`"), - }; + let ptr = cx.invoke_alloc(alloc_func_name, len)?; unsafe { - let raw = slice::from_raw_parts_mut((*definition).base, (*definition).current_length); + let raw = cx.get_memory()?; raw[ptr as usize..][..bytes.len()].copy_from_slice(bytes) } @@ -392,27 +504,12 @@ fn translate_incoming( } fn translate_outgoing( - cx: &mut Context, - handle: &mut InstanceHandle, + cx: &mut dyn TranslateContext, bindings: &[ast::OutgoingBindingExpression], args: &[RuntimeValue], ) -> Result> { let mut values = Vec::new(); - let raw_memory = || unsafe { - let memory = handle - .lookup_immutable("memory") - .ok_or_else(|| format_err!("no exported `memory`"))?; - let definition = match memory { - wasmtime_runtime::Export::Memory { definition, .. } => definition, - _ => bail!("export `memory` wasn't a `Memory`"), - }; - Ok(slice::from_raw_parts_mut( - (*definition).base, - (*definition).current_length, - )) - }; - let get = |idx: u32| { args.get(idx as usize) .cloned() @@ -468,11 +565,11 @@ fn translate_outgoing( RuntimeValue::I32(a) => a, _ => bail!("length must be an i32"), }; - let bytes = &raw_memory()?[offset as usize..][..length as usize]; + let bytes = unsafe { &cx.get_memory()?[offset as usize..][..length as usize] }; values.push(Value::String(str::from_utf8(bytes).unwrap().to_string())); } _ => { - drop((cx, handle)); + drop(cx); bail!("unsupported outgoing binding expr {:?}", expr); } } diff --git a/crates/misc/rust/Cargo.toml b/crates/misc/rust/Cargo.toml index 451c224a8e..7de0e1707e 100644 --- a/crates/misc/rust/Cargo.toml +++ b/crates/misc/rust/Cargo.toml @@ -21,6 +21,7 @@ wasmtime-interface-types = { path = "../../interface-types" } wasmtime-jit = { path = "../../jit" } wasmtime-rust-macro = { path = "./macro" } wasmtime-wasi = { path = "../../wasi" } +wasmtime = { path = "../../api" } anyhow = "1.0.19" [badges] diff --git a/crates/misc/rust/macro/src/lib.rs b/crates/misc/rust/macro/src/lib.rs index 902960fca3..ad1584ff35 100644 --- a/crates/misc/rust/macro/src/lib.rs +++ b/crates/misc/rust/macro/src/lib.rs @@ -34,8 +34,7 @@ fn generate_struct(item: &syn::ItemTrait) -> syn::Result { let root = root(); Ok(quote! { #vis struct #name { - cx: #root::wasmtime_jit::Context, - handle: #root::wasmtime_jit::InstanceHandle, + instance: #root::wasmtime_api::HostRef<#root::wasmtime_api::Instance>, data: #root::wasmtime_interface_types::ModuleData, } }) @@ -49,34 +48,53 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result { #vis fn load_file(path: impl AsRef) -> #root::anyhow::Result<#name> { let bytes = std::fs::read(path)?; - let isa = { - let isa_builder = #root::cranelift_native::builder() - .map_err(|s| #root::anyhow::format_err!("{}", s))?; - let flag_builder = #root::cranelift_codegen::settings::builder(); - isa_builder.finish(#root::cranelift_codegen::settings::Flags::new(flag_builder)) - }; + use #root::wasmtime_api::{HostRef, Config, Extern, Engine, Store, Instance, Module}; + use #root::anyhow::{bail, format_err}; + + let config = { + let flag_builder = #root::cranelift_codegen::settings::builder(); + let flags = #root::cranelift_codegen::settings::Flags::new(flag_builder); + let features = #root::wasmtime_jit::Features { + multi_value: true, + ..Default::default() + }; + let strategy = #root::wasmtime_jit::CompilationStrategy::Auto; + Config::new(flags, features, false, strategy) + }; + let engine = HostRef::new(Engine::new(config)); + let store = HostRef::new(Store::new(&engine)); + let global_exports = store.borrow().global_exports().clone(); - let mut cx = #root::wasmtime_jit::Context::with_isa( - isa, - #root::wasmtime_jit::CompilationStrategy::Auto - ).with_features(#root::wasmtime_jit::Features { - multi_value: true, - ..Default::default() - }); let data = #root::wasmtime_interface_types::ModuleData::new(&bytes)?; + + let module = HostRef::new(Module::new(&store, &bytes)?); + + let mut imports: Vec = Vec::new(); if let Some(module_name) = data.find_wasi_module_name() { let wasi_handle = wasmtime_wasi::instantiate_wasi( "", - cx.get_global_exports(), + global_exports, &[], &[], &[], )?; - cx.name_instance(module_name, wasi_handle); + let wasi_instance = Instance::from_handle(&store, wasi_handle)?; + for i in module.borrow().imports().iter() { + if i.module().as_str() != module_name { + bail!("unknown import module {}", i.module().as_str()); + } + if let Some(export) = wasi_instance.find_export_by_name(i.name().as_str()) { + imports.push(export.clone()); + } else { + bail!("unknown import {}:{}", i.module().as_str(), i.name().as_str()) + } + } } - let handle = cx.instantiate_module(None, &bytes)?; + let instance = HostRef::new( + Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))? + ); - Ok(#name { cx, handle, data }) + Ok(#name { instance, data }) } }) } @@ -156,9 +174,8 @@ fn generate_methods(item: &syn::ItemTrait) -> syn::Result { let args = [ #(#args),* ]; - let results = self.data.invoke( - &mut self.cx, - &mut self.handle, + let results = self.data.invoke_export( + &self.instance, stringify!(#name), &args, ).expect("wasm execution failed"); diff --git a/crates/misc/rust/src/lib.rs b/crates/misc/rust/src/lib.rs index 9fde663b10..9e03dd8954 100644 --- a/crates/misc/rust/src/lib.rs +++ b/crates/misc/rust/src/lib.rs @@ -6,6 +6,7 @@ pub mod __rt { pub use anyhow; pub use cranelift_codegen; pub use cranelift_native; + pub use wasmtime_api; pub use wasmtime_interface_types; pub use wasmtime_jit; diff --git a/crates/wasi-common/tests/wasm_tests/runtime.rs b/crates/wasi-common/tests/wasm_tests/runtime.rs index fc0dd617fe..215fbb8a3e 100644 --- a/crates/wasi-common/tests/wasm_tests/runtime.rs +++ b/crates/wasi-common/tests/wasm_tests/runtime.rs @@ -73,11 +73,11 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any .imports() .iter() .map(|i| { - let module_name = i.module().to_string(); - if let Some((instance, map)) = module_registry.get(&module_name) { - let field_name = i.name().to_string(); - if let Some(export_index) = map.get(&field_name) { - Ok(instance.exports()[*export_index].clone()) + let module_name = i.module().as_str(); + if let Some(instance) = module_registry.get(module_name) { + let field_name = i.name().as_str(); + if let Some(export) = instance.find_export_by_name(field_name) { + Ok(export.clone()) } else { bail!( "import {} was not found in module {}", diff --git a/src/bin/wasmtime.rs b/src/bin/wasmtime.rs index f6826975fa..77b7eb204d 100644 --- a/src/bin/wasmtime.rs +++ b/src/bin/wasmtime.rs @@ -328,7 +328,7 @@ fn main() -> Result<()> { fn instantiate_module( store: &HostRef, - module_registry: &HashMap)>, + module_registry: &HashMap, path: &Path, ) -> Result<(HostRef, HostRef, Vec)> { // Read the wasm module binary either as `*.wat` or a raw binary @@ -342,11 +342,11 @@ fn instantiate_module( .imports() .iter() .map(|i| { - let module_name = i.module().to_string(); - if let Some((instance, map)) = module_registry.get(&module_name) { - let field_name = i.name().to_string(); - if let Some(export_index) = map.get(&field_name) { - Ok(instance.exports()[*export_index].clone()) + let module_name = i.module().as_str(); + if let Some(instance) = module_registry.get(module_name) { + let field_name = i.name().as_str(); + if let Some(export) = instance.find_export_by_name(field_name) { + Ok(export.clone()) } else { bail!( "Import {} was not found in module {}", @@ -367,7 +367,7 @@ fn instantiate_module( fn handle_module( store: &HostRef, - module_registry: &HashMap)>, + module_registry: &HashMap, args: &Args, path: &Path, ) -> Result<()> { @@ -376,14 +376,13 @@ fn handle_module( // If a function to invoke was given, invoke it. if let Some(f) = &args.flag_invoke { let data = ModuleData::new(&data)?; - invoke_export(store, instance, &data, f, args)?; + invoke_export(instance, &data, f, args)?; } Ok(()) } fn invoke_export( - store: &HostRef, instance: HostRef, data: &ModuleData, name: &str, @@ -434,9 +433,8 @@ fn invoke_export( // Invoke the function and then afterwards print all the results that came // out, if there are any. - let mut context = store.borrow().engine().borrow().create_wasmtime_context(); let results = data - .invoke(&mut context, &mut handle, name, &values) + .invoke_export(&instance, name, &values) .with_context(|| format!("failed to invoke `{}`", name))?; if results.len() > 0 { eprintln!(