diff --git a/src/interpreter/imports.rs b/src/interpreter/imports.rs new file mode 100644 index 0000000..7d6f2a1 --- /dev/null +++ b/src/interpreter/imports.rs @@ -0,0 +1,36 @@ +use std::rc::Rc; +use elements::{FunctionType, GlobalType, MemoryType, TableType}; +use interpreter::store::{FuncInstance, GlobalInstance}; +use interpreter::memory::MemoryInstance; +use interpreter::table::TableInstance; +use interpreter::Error; + +pub trait ImportResolver { + fn resolve_func( + &self, + module_name: &str, + field_name: &str, + func_type: &FunctionType, + ) -> Result, Error>; + + fn resolve_global( + &self, + module_name: &str, + field_name: &str, + global_type: &GlobalType, + ) -> Result, Error>; + + fn resolve_memory( + &self, + module_name: &str, + field_name: &str, + memory_type: &MemoryType, + ) -> Result, Error>; + + fn resolve_table( + &self, + module_name: &str, + field_name: &str, + table_type: &TableType, + ) -> Result, Error>; +} diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 62015e7..512ca4c 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -140,6 +140,7 @@ mod value; mod variable; mod store; mod host; +mod imports; #[cfg(test)] mod tests; diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index fe69b21..ece9f3b 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -26,10 +26,10 @@ impl ProgramInstance { module: Module, state: &mut St, ) -> Result, Error> { - let mut extern_vals = Vec::new(); + let mut externvals = Vec::new(); for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) { let module = self.modules.get(import_entry.module()).ok_or_else(|| Error::Program(format!("Module {} not found", import_entry.module())))?; - let extern_val = module + let externval = module .export_by_name(import_entry.field()) .ok_or_else(|| { Error::Program(format!( @@ -38,10 +38,10 @@ impl ProgramInstance { import_entry.field() )) })?; - extern_vals.push(extern_val); + externvals.push(externval); } - let module_instance = ModuleInstance::instantiate(&module, &extern_vals, state)?; + let module_instance = ModuleInstance::instantiate_with_externvals(&module, &externvals, state)?; self.modules.insert(name.to_owned(), Rc::clone(&module_instance)); Ok(module_instance) diff --git a/src/interpreter/store.rs b/src/interpreter/store.rs index 3da9a42..9bba1bc 100644 --- a/src/interpreter/store.rs +++ b/src/interpreter/store.rs @@ -9,6 +9,7 @@ use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance}; use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter}; use interpreter::host::AnyFunc; +use interpreter::imports::ImportResolver; use validation::validate_module; use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, DEFAULT_VALUE_STACK_LIMIT}; @@ -190,7 +191,6 @@ impl ModuleInstance { } } - pub fn memory_by_index(&self, idx: u32) -> Option> { self .memories @@ -417,7 +417,7 @@ impl ModuleInstance { Ok(()) } - pub fn instantiate( + pub fn instantiate_with_externvals( module: &Module, extern_vals: &[ExternVal], state: &mut St, @@ -471,6 +471,44 @@ impl ModuleInstance { Ok(instance) } + pub fn instantiate( + module: &Module, + resolver: &I, + state: &mut St, + ) -> Result, Error> { + let mut extern_vals = Vec::new(); + for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) { + let module_name = import_entry.module(); + let field_name = import_entry.field(); + let extern_val = match *import_entry.external() { + External::Function(fn_ty_idx) => { + // Module is not yet validated so we have to check type indexes. + let types = module.type_section().map(|s| s.types()).unwrap_or(&[]); + let &Type::Function(ref func_type) = types.get(fn_ty_idx as usize) + .ok_or_else(|| Error::Validation(format!("Function type {} not found", fn_ty_idx)))?; + + let func = resolver.resolve_func(module_name, field_name, func_type)?; + ExternVal::Func(func) + }, + External::Table(ref table_type) => { + let table = resolver.resolve_table(module_name, field_name, table_type)?; + ExternVal::Table(table) + }, + External::Memory(ref memory_type) => { + let memory = resolver.resolve_memory(module_name, field_name, memory_type)?; + ExternVal::Memory(memory) + }, + External::Global(ref global_type) => { + let global = resolver.resolve_global(module_name, field_name, global_type)?; + ExternVal::Global(global) + } + }; + extern_vals.push(extern_val); + } + + Self::instantiate_with_externvals(module, &extern_vals, state) + } + pub fn invoke_index( &self, func_idx: u32,