mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-12 06:21:40 +00:00
call && call_indirect are working
This commit is contained in:
@ -7,7 +7,7 @@ use interpreter::Error;
|
||||
use interpreter::imports::ModuleImports;
|
||||
use interpreter::memory::MemoryInstance;
|
||||
use interpreter::program::ProgramInstanceEssence;
|
||||
use interpreter::runner::{Interpreter, FunctionContext};
|
||||
use interpreter::runner::{Interpreter, FunctionContext, prepare_function_args};
|
||||
use interpreter::stack::StackWithLimit;
|
||||
use interpreter::table::TableInstance;
|
||||
use interpreter::validator::{Validator, FunctionValidationContext};
|
||||
@ -49,8 +49,10 @@ pub trait ModuleInstanceInterface {
|
||||
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error>;
|
||||
/// Get export entry.
|
||||
fn export_entry<'a>(&self, name: &str, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, required_type: &ExportEntryType) -> Result<Internal, Error>;
|
||||
/// Get function type.
|
||||
/// 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.
|
||||
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error>;
|
||||
/// Get memory reference.
|
||||
@ -62,7 +64,7 @@ pub trait ModuleInstanceInterface {
|
||||
/// 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>;
|
||||
/// Get internal function for interpretation.
|
||||
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error>;
|
||||
fn function_body<'a>(&'a self, internal_index: u32, function_type: Option<&FunctionType>) -> Result<Option<InternalFunction<'a>>, Error>;
|
||||
/// Call function with given index in functions index space.
|
||||
//fn call_function<'a>(&self, outer: CallerContext, index: ItemIndex, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error>;
|
||||
/// Call function with given index in the given table.
|
||||
@ -117,8 +119,6 @@ pub struct InternalFunctionReference<'a> {
|
||||
pub module: Arc<ModuleInstanceInterface + 'a>,
|
||||
/// Internal function index.
|
||||
pub internal_index: u32,
|
||||
// Internal function type.
|
||||
//pub function_type: &'a FunctionType,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for InternalFunctionReference<'a> {
|
||||
@ -233,15 +233,6 @@ impl ModuleInstance {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn require_function_type(&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))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleInstanceInterface for ModuleInstance {
|
||||
@ -250,7 +241,7 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
if let Some(start_function) = self.module.start_section() {
|
||||
let func_type_index = self.require_function(ItemIndex::IndexSpace(start_function))?;
|
||||
if is_user_module { // tests use non-empty main functions
|
||||
let func_type = self.require_function_type(func_type_index)?;
|
||||
let func_type = self.function_type_by_index(func_type_index)?;
|
||||
if func_type.return_type() != None || func_type.params().len() != 0 {
|
||||
return Err(Error::Validation("start function expected to have type [] -> []".into()));
|
||||
}
|
||||
@ -287,7 +278,7 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
// for functions we need to check if function type matches in both modules
|
||||
&External::Function(ref function_type_index) => {
|
||||
// External::Function points to function type in type section in this module
|
||||
let import_function_type = self.require_function_type(*function_type_index)?;
|
||||
let import_function_type = self.function_type_by_index(*function_type_index)?;
|
||||
|
||||
// get export entry in external module
|
||||
let external_module = self.imports.module(externals, import.module())?;
|
||||
@ -300,7 +291,7 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
_ => return Err(Error::Validation(format!("Export with name {} from module {} is not a function", import.field(), import.module()))),
|
||||
};
|
||||
|
||||
if import_function_type != &export_function_type {
|
||||
if import_function_type != export_function_type {
|
||||
return Err(Error::Validation(format!("Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
|
||||
function_type_index, import_function_type.params(), import_function_type.return_type(),
|
||||
export_function_type.params(), export_function_type.return_type())));
|
||||
@ -346,7 +337,7 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
let code_section = self.module.code_section().expect("function_section_len != 0; function_section_len == code_section_len; qed");
|
||||
// check every function body
|
||||
for (index, function) in function_section.entries().iter().enumerate() {
|
||||
let function_type = self.require_function_type(function.type_ref())?;
|
||||
let function_type = self.function_type_by_index(function.type_ref())?;
|
||||
let function_body = code_section.bodies().get(index as usize).ok_or(Error::Validation(format!("Missing body for function {}", index)))?;
|
||||
let mut locals = function_type.params().to_vec();
|
||||
locals.extend(function_body.locals().iter().flat_map(|l| repeat(l.value_type()).take(l.count() as usize)));
|
||||
@ -439,19 +430,37 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
}
|
||||
|
||||
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.require_function_type(ft).map(Clone::clone)),
|
||||
.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| self.imports.module(externals, e.module()))
|
||||
.and_then(|m| m.function_type(ItemIndex::IndexSpace(index), externals)),
|
||||
.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> {
|
||||
match self.imports.parse_table_index(index) {
|
||||
ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"),
|
||||
@ -501,9 +510,11 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
ItemIndex::External(index) => {
|
||||
let import_section = self.module.import_section().unwrap();
|
||||
let import_entry = import_section.entries().get(index as usize).unwrap();
|
||||
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))?;
|
||||
Ok(InternalFunctionReference {
|
||||
module: self.imports.module(externals, import_entry.module())?,
|
||||
internal_index: index
|
||||
internal_index: internal_function_index,
|
||||
})
|
||||
},
|
||||
}
|
||||
@ -527,7 +538,7 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
module.function_reference(ItemIndex::IndexSpace(index), externals)
|
||||
}
|
||||
|
||||
fn function_body<'a>(&'a self, internal_index: u32/*, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>*/) -> Result<Option<InternalFunction<'a>>, Error> {
|
||||
fn function_body<'a>(&'a self, internal_index: u32, function_type: Option<&FunctionType>) -> 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
|
||||
@ -637,30 +648,21 @@ impl ModuleInstanceInterface for ModuleInstance {
|
||||
}*/
|
||||
|
||||
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.require_function_type(function_type_index)?;
|
||||
let function_body = self.function_body(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 {
|
||||
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 args = function_type.params().iter()
|
||||
.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::<Result<Vec<_>, _>>()?;
|
||||
|
||||
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 inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args);
|
||||
Interpreter::run_function(inner)
|
||||
@ -699,7 +701,7 @@ pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_function_locals(function_type: &FunctionType, function_body: &FuncBody, outer: &mut CallerContext) -> Result<Vec<VariableInstance>, Error> {
|
||||
/*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| {
|
||||
@ -718,7 +720,7 @@ fn prepare_function_locals(function_type: &FunctionType, function_body: &FuncBod
|
||||
.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> {
|
||||
let first_opcode = match expr.code().len() {
|
||||
|
Reference in New Issue
Block a user