Add import resolver

This commit is contained in:
Sergey Pepyakin
2017-12-13 16:57:28 +01:00
parent 1bbfd4219f
commit 6089807d78
4 changed files with 81 additions and 6 deletions

View File

@ -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<Rc<FuncInstance>, Error>;
fn resolve_global(
&self,
module_name: &str,
field_name: &str,
global_type: &GlobalType,
) -> Result<Rc<GlobalInstance>, Error>;
fn resolve_memory(
&self,
module_name: &str,
field_name: &str,
memory_type: &MemoryType,
) -> Result<Rc<MemoryInstance>, Error>;
fn resolve_table(
&self,
module_name: &str,
field_name: &str,
table_type: &TableType,
) -> Result<Rc<TableInstance>, Error>;
}

View File

@ -140,6 +140,7 @@ mod value;
mod variable; mod variable;
mod store; mod store;
mod host; mod host;
mod imports;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View File

@ -26,10 +26,10 @@ impl ProgramInstance {
module: Module, module: Module,
state: &mut St, state: &mut St,
) -> Result<Rc<ModuleInstance>, Error> { ) -> Result<Rc<ModuleInstance>, 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(&[]) { 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 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()) .export_by_name(import_entry.field())
.ok_or_else(|| { .ok_or_else(|| {
Error::Program(format!( Error::Program(format!(
@ -38,10 +38,10 @@ impl ProgramInstance {
import_entry.field() 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)); self.modules.insert(name.to_owned(), Rc::clone(&module_instance));
Ok(module_instance) Ok(module_instance)

View File

@ -9,6 +9,7 @@ use interpreter::{Error, MemoryInstance,
RuntimeValue, TableInstance}; RuntimeValue, TableInstance};
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter}; use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
use interpreter::host::AnyFunc; use interpreter::host::AnyFunc;
use interpreter::imports::ImportResolver;
use validation::validate_module; use validation::validate_module;
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX,
DEFAULT_VALUE_STACK_LIMIT}; DEFAULT_VALUE_STACK_LIMIT};
@ -190,7 +191,6 @@ impl ModuleInstance {
} }
} }
pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> { pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> {
self self
.memories .memories
@ -417,7 +417,7 @@ impl ModuleInstance {
Ok(()) Ok(())
} }
pub fn instantiate<St: 'static>( pub fn instantiate_with_externvals<St: 'static>(
module: &Module, module: &Module,
extern_vals: &[ExternVal], extern_vals: &[ExternVal],
state: &mut St, state: &mut St,
@ -471,6 +471,44 @@ impl ModuleInstance {
Ok(instance) Ok(instance)
} }
pub fn instantiate<St: 'static, I: ImportResolver>(
module: &Module,
resolver: &I,
state: &mut St,
) -> Result<Rc<ModuleInstance>, 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<St: 'static>( pub fn invoke_index<St: 'static>(
&self, &self,
func_idx: u32, func_idx: u32,