This commit is contained in:
Svyatoslav Nikolsky
2017-06-19 12:04:16 +03:00
parent 8d7d39d80b
commit 7bd7c6df98
4 changed files with 91 additions and 229 deletions

View File

@ -108,14 +108,6 @@ impl ModuleInstanceInterface for EnvModuleInstance {
self.instance.export_entry(name, externals, required_type) self.instance.export_entry(name, externals, required_type)
} }
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error> {
self.instance.function_type(function_index, externals)
}
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error> {
self.instance.function_type_by_index(type_index)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> { fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
self.instance.table(index) self.instance.table(index)
} }
@ -128,6 +120,14 @@ impl ModuleInstanceInterface for EnvModuleInstance {
self.instance.global(index, variable_type) self.instance.global(index, variable_type)
} }
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error> {
self.instance.function_type(function_index, externals)
}
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error> {
self.instance.function_type_by_index(type_index)
}
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> { fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
self.instance.function_reference(index, externals) self.instance.function_reference(index, externals)
} }
@ -136,21 +136,11 @@ impl ModuleInstanceInterface for EnvModuleInstance {
self.instance.function_reference_indirect(table_idx, type_idx, func_idx, externals) self.instance.function_reference_indirect(table_idx, type_idx, func_idx, externals)
} }
fn function_body<'a>(&'a self, internal_index: u32, function_type: Option<&FunctionType>) -> Result<Option<InternalFunction<'a>>, Error> { fn function_body<'a>(&'a self, _internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error> {
Ok(None) Ok(None)
//self.instance.function_body(internal_index, function_type)
} }
/*fn call_function(&self, outer: CallerContext, index: ItemIndex, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> { fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
self.instance.call_function(outer, index, function_type)
}
fn call_function_indirect(&self, outer: CallerContext, table_index: ItemIndex, type_index: u32, func_index: u32) -> Result<Option<RuntimeValue>, Error> {
self.instance.call_function_indirect(outer, table_index, type_index, func_index)
}*/
fn call_internal_function(&self, outer: CallerContext, index: u32, _function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> {
// TODO: check function type
// to make interpreter independent of *SCRIPTEN runtime, just make abort/assert = interpreter Error // to make interpreter independent of *SCRIPTEN runtime, just make abort/assert = interpreter Error
match index { match index {
INDEX_FUNC_ABORT => self.global(ItemIndex::IndexSpace(INDEX_GLOBAL_ABORT), Some(VariableType::I32)) INDEX_FUNC_ABORT => self.global(ItemIndex::IndexSpace(INDEX_GLOBAL_ABORT), Some(VariableType::I32))

View File

@ -85,12 +85,24 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
self.env.export_entry(name, externals, required_type) self.env.export_entry(name, externals, required_type)
} }
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
self.env.table(index)
}
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
self.env.memory(index)
}
fn global(&self, index: ItemIndex, variable_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error> {
self.env.global(index, variable_type)
}
fn function_type<'b>(&self, function_index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<FunctionType, Error> { fn function_type<'b>(&self, function_index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<FunctionType, Error> {
let index = match function_index { let index = match function_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index, ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"), ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"),
}; };
println!("=== env_native.function_type({})", index);
if index < NATIVE_INDEX_FUNC_MIN { if index < NATIVE_INDEX_FUNC_MIN {
return self.env.function_type(function_index, externals); return self.env.function_type(function_index, externals);
} }
@ -105,18 +117,6 @@ println!("=== env_native.function_type({})", index);
self.function_type(ItemIndex::Internal(type_index), None) self.function_type(ItemIndex::Internal(type_index), None)
} }
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
self.env.table(index)
}
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
self.env.memory(index)
}
fn global(&self, index: ItemIndex, variable_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error> {
self.env.global(index, variable_type)
}
fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> { fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
self.env.function_reference(index, externals) self.env.function_reference(index, externals)
} }
@ -125,17 +125,15 @@ println!("=== env_native.function_type({})", index);
self.env.function_reference_indirect(table_idx, type_idx, func_idx, externals) self.env.function_reference_indirect(table_idx, type_idx, func_idx, externals)
} }
fn function_body<'b>(&'b self, internal_index: u32, function_type: Option<&FunctionType>) -> Result<Option<InternalFunction<'b>>, Error> { fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
Ok(None) Ok(None)
//self.env.function_body(internal_index, function_type)
} }
fn call_internal_function(&self, outer: CallerContext, index: u32, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> { fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
if index < NATIVE_INDEX_FUNC_MIN { if index < NATIVE_INDEX_FUNC_MIN {
return self.env.call_internal_function(outer, index, function_type); return self.env.call_internal_function(outer, index);
} }
println!("=== env_native.args({:?})", outer.value_stack);
// TODO: check type
self.functions self.functions
.get((index - NATIVE_INDEX_FUNC_MIN) as usize) .get((index - NATIVE_INDEX_FUNC_MIN) as usize)
.ok_or(Error::Native(format!("trying to call native function with index {}", index))) .ok_or(Error::Native(format!("trying to call native function with index {}", index)))

View File

@ -49,28 +49,24 @@ pub trait ModuleInstanceInterface {
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error>; fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error>;
/// Get export entry. /// Get export entry.
fn export_entry<'a>(&self, name: &str, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, required_type: &ExportEntryType) -> Result<Internal, Error>; fn export_entry<'a>(&self, name: &str, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, required_type: &ExportEntryType) -> Result<Internal, Error>;
/// Get function type for given function index.
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error>;
/// Get function type for given function index.
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error>;
/// Get table reference. /// Get table reference.
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error>; fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error>;
/// Get memory reference. /// Get memory reference.
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error>; fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error>;
/// Get global reference. /// Get global reference.
fn global(&self, index: ItemIndex, variable_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error>; fn global(&self, index: ItemIndex, variable_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error>;
/// Get function type for given function index.
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error>;
/// Get function type for given function index.
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error>;
/// Get function reference. /// Get function reference.
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>; fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>;
/// Get function indirect reference. /// Get function indirect reference.
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>; fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>;
/// Get internal function for interpretation. /// Get internal function for interpretation.
fn function_body<'a>(&'a self, internal_index: u32, function_type: Option<&FunctionType>) -> Result<Option<InternalFunction<'a>>, Error>; fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error>;
/// Call function with given index in functions index space. /// Call function with given internal index.
//fn call_function<'a>(&self, outer: CallerContext, index: ItemIndex, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error>; fn call_internal_function<'a>(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error>;
/// Call function with given index in the given table.
//fn call_function_indirect<'a>(&self, outer: CallerContext, table_index: ItemIndex, type_index: u32, func_index: u32) -> Result<Option<RuntimeValue>, Error>;
/// Call function with internal index.
fn call_internal_function<'a>(&self, outer: CallerContext, index: u32, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error>;
} }
/// Item index in items index space. /// Item index in items index space.
@ -129,8 +125,6 @@ impl<'a> fmt::Debug for InternalFunctionReference<'a> {
/// Internal function ready for interpretation. /// Internal function ready for interpretation.
pub struct InternalFunction<'a> { pub struct InternalFunction<'a> {
/// Function type.
pub func_type: &'a FunctionType,
/// Function locals. /// Function locals.
pub locals: &'a [Local], pub locals: &'a [Local],
/// Function body. /// Function body.
@ -233,6 +227,19 @@ impl ModuleInstance {
}), }),
} }
} }
fn check_function_type(&self, function_index: ItemIndex, required_function_type: Option<&FunctionType>, externals: Option<&HashMap<String, Arc<ModuleInstanceInterface>>>) -> Result<(), Error> {
if let Some(ref required_function_type) = required_function_type {
let actual_function_type = self.function_type(function_index, externals)?;
if **required_function_type != actual_function_type {
return Err(Error::Function(format!("expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(),
actual_function_type.params(), actual_function_type.return_type())));
}
}
Ok(())
}
} }
impl ModuleInstanceInterface for ModuleInstance { impl ModuleInstanceInterface for ModuleInstance {
@ -385,9 +392,8 @@ impl ModuleInstanceInterface for ModuleInstance {
let ExecutionParams { args, externals } = params; let ExecutionParams { args, externals } = params;
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT); let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let function_reference = self.function_reference(ItemIndex::IndexSpace(index), Some(&externals))?; let function_reference = self.function_reference(ItemIndex::IndexSpace(index), Some(&externals))?;
let function_type = self.function_type(ItemIndex::IndexSpace(index), Some(&externals))?;
let function_context = CallerContext::topmost(&mut args, &externals); let function_context = CallerContext::topmost(&mut args, &externals);
function_reference.module.call_internal_function(function_context, function_reference.internal_index, Some(&function_type)) function_reference.module.call_internal_function(function_context, function_reference.internal_index)
} }
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> { fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
@ -429,38 +435,6 @@ impl ModuleInstanceInterface for ModuleInstance {
.ok_or(Error::Program(format!("unresolved import {}", name)))) .ok_or(Error::Program(format!("unresolved import {}", name))))
} }
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error> {
println!("=== getting function_type({}, {:?})", self.name, function_index);
match self.imports.parse_function_index(function_index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.require_function(ItemIndex::Internal(index))
.and_then(|ft| self.function_type_by_index(ft)),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Function(format!("trying to access external function with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Function(format!("trying to access external function with index {} in module with {}-entries import section", index, s.entries().len()))))
.and_then(|e| {
let module = self.imports.module(externals, e.module())?;
let function_type = match e.external() {
&External::Function(type_index) => self.function_type_by_index(type_index)?,
_ => return Err(Error::Function(format!("exported function {} is not a function", index))),
};
let external_function_index = self.imports.function(externals, e, Some(&function_type))?;
module.function_type(ItemIndex::IndexSpace(external_function_index), externals)
}),
}
}
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error> {
self.module.type_section()
.ok_or(Error::Validation(format!("type reference {} exists in module without type section", type_index)))
.and_then(|s| match s.types().get(type_index as usize) {
Some(&Type::Function(ref function_type)) => Ok(function_type),
_ => Err(Error::Validation(format!("missing function type with index {}", type_index))),
})
.map(Clone::clone)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> { fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
match self.imports.parse_table_index(index) { match self.imports.parse_table_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"),
@ -500,6 +474,32 @@ println!("=== getting function_type({}, {:?})", self.name, function_index);
} }
} }
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error> {
match self.imports.parse_function_index(function_index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.require_function(ItemIndex::Internal(index))
.and_then(|ft| self.function_type_by_index(ft)),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Function(format!("trying to access external function with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Function(format!("trying to access external function with index {} in module with {}-entries import section", index, s.entries().len()))))
.and_then(|e| match e.external() {
&External::Function(type_index) => self.function_type_by_index(type_index),
_ => Err(Error::Function(format!("exported function {} is not a function", index))),
}),
}
}
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error> {
self.module.type_section()
.ok_or(Error::Validation(format!("type reference {} exists in module without type section", type_index)))
.and_then(|s| match s.types().get(type_index as usize) {
Some(&Type::Function(ref function_type)) => Ok(function_type),
_ => Err(Error::Validation(format!("missing function type with index {}", type_index))),
})
.map(Clone::clone)
}
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> { fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
match self.imports.parse_function_index(index) { match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
@ -508,8 +508,10 @@ println!("=== getting function_type({}, {:?})", self.name, function_index);
internal_index: index, internal_index: index,
}), }),
ItemIndex::External(index) => { ItemIndex::External(index) => {
let import_section = self.module.import_section().unwrap(); let import_entry = self.module.import_section()
let import_entry = import_section.entries().get(index as usize).unwrap(); .expect("parse_function_index has returned External(index); it is only returned when import section exists; qed")
.entries().get(index as usize)
.expect("parse_function_index has returned External(index); it is only returned when entry with index exists in import section exists; qed");
let required_function_type = self.function_type(ItemIndex::External(index), externals)?; let required_function_type = self.function_type(ItemIndex::External(index), externals)?;
let internal_function_index = self.imports.function(externals, import_entry, Some(&required_function_type))?; let internal_function_index = self.imports.function(externals, import_entry, Some(&required_function_type))?;
Ok(InternalFunctionReference { Ok(InternalFunctionReference {
@ -521,13 +523,6 @@ println!("=== getting function_type({}, {:?})", self.name, function_index);
} }
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> { fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
let function_type = match self.module.type_section()
.ok_or(Error::Function(format!("trying to indirect call function {} with non-existent function section", func_idx)))
.and_then(|s| s.types().get(type_idx as usize)
.ok_or(Error::Function(format!("trying to indirect call function {} with non-existent type index {}", func_idx, type_idx))))? {
&Type::Function(ref function_type) => function_type,
};
let table = self.table(ItemIndex::IndexSpace(table_idx))?; let table = self.table(ItemIndex::IndexSpace(table_idx))?;
let (module, index) = match table.get(func_idx)? { let (module, index) = match table.get(func_idx)? {
RuntimeValue::AnyFunc(module, index) => (module.clone(), index), RuntimeValue::AnyFunc(module, index) => (module.clone(), index),
@ -535,32 +530,18 @@ println!("=== getting function_type({}, {:?})", self.name, function_index);
}; };
let module = self.imports.module(externals, &module)?; let module = self.imports.module(externals, &module)?;
let required_function_type = self.function_type_by_index(type_idx)?;
let actual_function_type = module.function_type(ItemIndex::IndexSpace(index), externals)?;
if required_function_type != actual_function_type {
return Err(Error::Function(format!("expected indirect function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(),
actual_function_type.params(), actual_function_type.return_type())));
}
module.function_reference(ItemIndex::IndexSpace(index), externals) module.function_reference(ItemIndex::IndexSpace(index), externals)
} }
fn function_body<'a>(&'a self, internal_index: u32, function_type: Option<&FunctionType>) -> Result<Option<InternalFunction<'a>>, Error> { fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error> {
// internal index = index of function in functions section && index of code in code section
// get function type index
let function_type_index = self.module
.function_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without function section", internal_index)))
.and_then(|s| s.entries()
.get(internal_index as usize)
.ok_or(Error::Function(format!("trying to call function with index {} in module with {} functions", internal_index, s.entries().len()))))?
.type_ref();
// function type index = index of function type in types index
// get function type
let item_type = self.module
.type_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without types section", internal_index)))
.and_then(|s| s.types()
.get(function_type_index as usize)
.ok_or(Error::Function(format!("trying to call function with type index {} in module with {} types", function_type_index, s.types().len()))))?;
let actual_function_type = match item_type {
&Type::Function(ref function_type) => function_type,
};
// get function body
let function_body = self.module let function_body = self.module
.code_section() .code_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without code section", internal_index))) .ok_or(Error::Function(format!("trying to call function with index {} in module without code section", internal_index)))
@ -569,100 +550,14 @@ println!("=== getting function_type({}, {:?})", self.name, function_index);
.ok_or(Error::Function(format!("trying to call function with index {} in module with {} functions codes", internal_index, s.bodies().len()))))?; .ok_or(Error::Function(format!("trying to call function with index {} in module with {} functions codes", internal_index, s.bodies().len()))))?;
Ok(Some(InternalFunction { Ok(Some(InternalFunction {
func_type: actual_function_type,
locals: function_body.locals(), locals: function_body.locals(),
body: function_body.code().elements(), body: function_body.code().elements(),
})) }))
/*match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => {
// internal index = index of function in functions section && index of code in code section
// get function type index
let function_type_index = self.module
.function_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without function section", index)))
.and_then(|s| s.entries()
.get(index as usize)
.ok_or(Error::Function(format!("trying to call function with index {} in module with {} functions", index, s.entries().len()))))?
.type_ref();
// function type index = index of function type in types index
// get function type
let item_type = self.module
.type_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without types section", index)))
.and_then(|s| s.types()
.get(function_type_index as usize)
.ok_or(Error::Function(format!("trying to call function with type index {} in module with {} types", function_type_index, s.types().len()))))?;
let actual_function_type = match item_type {
&Type::Function(ref function_type) => function_type,
};
// get function body
let function_body = self.module
.code_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without code section", index)))
.and_then(|s| s.bodies()
.get(index as usize)
.ok_or(Error::Function(format!("trying to call function with index {} in module with {} functions codes", index, s.bodies().len()))))?;
Ok(Some(Function {
func_type: actual_function_type,
body: function_body.code().elements(),
}))
},
ItemIndex::External(index) => {
},
}*/
} }
/*fn call_function(&self, outer: CallerContext, index: ItemIndex, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> { fn call_internal_function(&self, mut outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
match self.imports.parse_function_index(index) { let function_type = self.function_type(ItemIndex::Internal(index), None)?;
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.call_internal_function(outer, index, function_type),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Function(format!("trying to access external function with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Function(format!("trying to access external function with index {} in module with {}-entries import section", index, s.entries().len()))))
.and_then(|e| Ok((self.imports.module(Some(outer.externals), e.module())?,
self.imports.function(Some(outer.externals), e, function_type)?)))
.and_then(|(m, index)| m.call_internal_function(outer, index, function_type)),
}
}
fn call_function_indirect(&self, outer: CallerContext, table_index: ItemIndex, type_index: u32, func_index: u32) -> Result<Option<RuntimeValue>, Error> {
let function_type = match self.module.type_section()
.ok_or(Error::Function(format!("trying to indirect call function {} with non-existent function section", func_index)))
.and_then(|s| s.types().get(type_index as usize)
.ok_or(Error::Function(format!("trying to indirect call function {} with non-existent type index {}", func_index, type_index))))? {
&Type::Function(ref function_type) => function_type,
};
let table = self.table(table_index)?;
let (module, index) = match table.get(func_index)? {
RuntimeValue::AnyFunc(module, index) => (module.clone(), index),
_ => return Err(Error::Function(format!("trying to indirect call function {} via non-anyfunc table {:?}", func_index, table_index))),
};
let module = self.imports.module(Some(outer.externals), &module)?;
module.call_function(outer, ItemIndex::IndexSpace(index), Some(function_type))
}*/
fn call_internal_function(&self, mut outer: CallerContext, index: u32, required_function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> {
println!("=== call_internal_function({})", index);
let function_type_index = self.require_function(ItemIndex::Internal(index))?;
let function_type = self.function_type_by_index(function_type_index)?;
let function_body = self.function_body(index, required_function_type)?;
if let Some(ref required_function_type) = required_function_type {
if **required_function_type != function_type {
return Err(Error::Function(format!("expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(), function_type.params(), function_type.return_type())));
}
}
let mut args = prepare_function_args(&function_type, outer.value_stack)?; let mut args = prepare_function_args(&function_type, outer.value_stack)?;
println!("=== call_internal_Function.function_type: {:?}", function_type);
println!("=== call_internal_Function.args: {:?}", args);
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index }; let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index };
let inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args); let inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args);
Interpreter::run_function(inner) Interpreter::run_function(inner)
@ -701,27 +596,6 @@ pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
Ok(()) Ok(())
} }
/*fn prepare_function_locals(function_type: &FunctionType, function_body: &FuncBody, outer: &mut CallerContext) -> Result<Vec<VariableInstance>, Error> {
// locals = function arguments + defined locals
function_type.params().iter().rev()
.map(|param_type| {
let param_value = outer.value_stack.pop()?;
let actual_type = param_value.variable_type();
let expected_type = (*param_type).into();
if actual_type != Some(expected_type) {
return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type)));
}
VariableInstance::new(true, expected_type, param_value)
})
.collect::<Vec<_>>().into_iter().rev()
.chain(function_body.locals()
.iter()
.flat_map(|l| repeat(l.value_type().into()).take(l.count() as usize))
.map(|vt| VariableInstance::new(true, vt, RuntimeValue::default(vt))))
.collect::<Result<Vec<_>, _>>()
}*/
fn get_initializer(expr: &InitExpr, module: &Module, imports: &ModuleImports, expected_type: VariableType) -> Result<RuntimeValue, Error> { fn get_initializer(expr: &InitExpr, module: &Module, imports: &ModuleImports, expected_type: VariableType) -> Result<RuntimeValue, Error> {
let first_opcode = match expr.code().len() { let first_opcode = match expr.code().len() {
1 => &expr.code()[0], 1 => &expr.code()[0],

View File

@ -100,7 +100,7 @@ impl Interpreter {
loop { loop {
let mut function_context = function_stack.pop_back().expect("on loop entry - not empty; on loop continue - checking for emptiness; qed"); let mut function_context = function_stack.pop_back().expect("on loop entry - not empty; on loop continue - checking for emptiness; qed");
let function_ref = function_context.function.clone(); let function_ref = function_context.function.clone();
let function_body = function_ref.module.function_body(function_ref.internal_index, None)?; let function_body = function_ref.module.function_body(function_ref.internal_index)?;
let function_return = match function_body { let function_return = match function_body {
Some(function_body) => { Some(function_body) => {
@ -120,7 +120,7 @@ impl Interpreter {
} }
let nested_context = CallerContext::nested(&mut function_context); let nested_context = CallerContext::nested(&mut function_context);
RunResult::Return(function_ref.module.call_internal_function(nested_context, function_ref.internal_index, None)?) RunResult::Return(function_ref.module.call_internal_function(nested_context, function_ref.internal_index)?)
}, },
}; };