Adapt runner

This commit is contained in:
Sergey Pepyakin 2017-12-11 13:59:54 +01:00
parent 17d3748ea2
commit b50a5a1a1e
4 changed files with 259 additions and 174 deletions

View File

@ -8,12 +8,13 @@ use interpreter::native::UserFunctionDescriptor;
use interpreter::imports::ModuleImports; use interpreter::imports::ModuleImports;
use interpreter::memory::MemoryInstance; use interpreter::memory::MemoryInstance;
use interpreter::program::ProgramInstanceEssence; use interpreter::program::ProgramInstanceEssence;
use interpreter::runner::{Interpreter, FunctionContext, prepare_function_args}; use interpreter::runner::{FunctionContext, prepare_function_args};
use interpreter::table::TableInstance; use interpreter::table::TableInstance;
use interpreter::validator::{Validator, FunctionValidationContext}; use interpreter::validator::{Validator, FunctionValidationContext};
use interpreter::value::{RuntimeValue, TryInto}; use interpreter::value::{RuntimeValue, TryInto};
use interpreter::variable::{VariableInstance, VariableType}; use interpreter::variable::{VariableInstance, VariableType};
use common::stack::StackWithLimit; use common::stack::StackWithLimit;
use interpreter::store::FuncId;
/// Maximum number of entries in value stack. /// Maximum number of entries in value stack.
const DEFAULT_VALUE_STACK_LIMIT: usize = 16384; const DEFAULT_VALUE_STACK_LIMIT: usize = 16384;
@ -120,21 +121,6 @@ pub struct CallerContext<'a> {
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
} }
/// Internal function reference.
#[derive(Clone)]
pub struct InternalFunctionReference<'a> {
/// Module reference.
pub module: Arc<ModuleInstanceInterface + 'a>,
/// Internal function index.
pub internal_index: u32,
}
impl<'a> fmt::Debug for InternalFunctionReference<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "InternalFunctionReference")
}
}
/// Internal function ready for interpretation. /// Internal function ready for interpretation.
pub struct InternalFunction<'a> { pub struct InternalFunction<'a> {
/// Function locals. /// Function locals.
@ -640,11 +626,13 @@ impl ModuleInstanceInterface for ModuleInstance {
} }
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> { fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
let function_type = self.function_type(ItemIndex::Internal(index))?; // TODO:
let args = prepare_function_args(&function_type, outer.value_stack)?; panic!()
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index }; // let function_type = self.function_type(ItemIndex::Internal(index))?;
let inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args); // let args = prepare_function_args(&function_type, outer.value_stack)?;
Interpreter::run_function(inner) // 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)
} }
} }

View File

@ -6,7 +6,7 @@ use parking_lot::RwLock;
use elements::{Internal, ValueType}; use elements::{Internal, ValueType};
use interpreter::Error; use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex, use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature}; CallerContext, ExportEntryType, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance; use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance; use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;

View File

@ -7,7 +7,8 @@ use std::iter::repeat;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use elements::{Opcode, BlockType, Local}; use elements::{Opcode, BlockType, Local};
use interpreter::Error; use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, InternalFunctionReference, FunctionSignature}; use interpreter::store::{Store, FuncId, ModuleId, FuncInstance};
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, FunctionSignature};
use interpreter::value::{ use interpreter::value::{
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto,
@ -17,14 +18,17 @@ use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, BlockFrame, BlockFrameTy
use common::stack::StackWithLimit; use common::stack::StackWithLimit;
/// Function interpreter. /// Function interpreter.
pub struct Interpreter; pub struct Interpreter<'store> {
store: &'store mut Store,
}
/// Function execution context. /// Function execution context.
pub struct FunctionContext<'a> { pub struct FunctionContext<'a> {
/// Is context initialized. /// Is context initialized.
pub is_initialized: bool, pub is_initialized: bool,
/// Internal function reference. /// Internal function reference.
pub function: InternalFunctionReference<'a>, pub function: FuncId,
pub module: ModuleId,
/// Execution-local external modules. /// Execution-local external modules.
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
/// Function return type. /// Function return type.
@ -41,13 +45,13 @@ pub struct FunctionContext<'a> {
/// Interpreter action to execute after executing instruction. /// Interpreter action to execute after executing instruction.
#[derive(Debug)] #[derive(Debug)]
pub enum InstructionOutcome<'a> { pub enum InstructionOutcome {
/// Continue with next instruction. /// Continue with next instruction.
RunNextInstruction, RunNextInstruction,
/// Branch to given frame. /// Branch to given frame.
Branch(usize), Branch(usize),
/// Execute function call. /// Execute function call.
ExecuteCall(InternalFunctionReference<'a>), ExecuteCall(FuncId),
/// End current frame. /// End current frame.
End, End,
/// Return from current function block. /// Return from current function block.
@ -62,9 +66,11 @@ enum RunResult<'a> {
NestedCall(FunctionContext<'a>), NestedCall(FunctionContext<'a>),
} }
impl Interpreter { impl<'store> Interpreter<'store> {
pub fn new() -> Interpreter { pub fn new(store: &mut Store) -> Interpreter {
Interpreter Interpreter {
store
}
} }
pub fn run_function(&mut self, function_context: FunctionContext) -> Result<Option<RuntimeValue>, Error> { pub fn run_function(&mut self, function_context: FunctionContext) -> Result<Option<RuntimeValue>, Error> {
@ -73,9 +79,9 @@ 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;
let function_return = { let function_return = {
let function_body = function_ref.module.function_body(function_ref.internal_index)?; let function_body = function_ref.resolve(self.store).body();
match function_body { match function_body {
Some(function_body) => { Some(function_body) => {
@ -95,8 +101,11 @@ impl Interpreter {
} }
let nested_context = CallerContext::nested(&mut function_context); let nested_context = CallerContext::nested(&mut function_context);
let result = function_ref.module.call_internal_function(nested_context, function_ref.internal_index)?; // TODO: Call host functions
RunResult::Return(result) // let result = function_ref.module.call_internal_function(nested_context, function_ref.internal_index)?;
// RunResult::Return(result)
panic!()
}, },
} }
}; };
@ -139,7 +148,7 @@ impl Interpreter {
}, },
InstructionOutcome::ExecuteCall(func_ref) => { InstructionOutcome::ExecuteCall(func_ref) => {
function_context.position += 1; function_context.position += 1;
return Ok(RunResult::NestedCall(function_context.nested(func_ref)?)); return Ok(RunResult::NestedCall(function_context.nested(self.store, func_ref)?));
}, },
InstructionOutcome::End => { InstructionOutcome::End => {
if function_context.frame_stack().is_empty() { if function_context.frame_stack().is_empty() {
@ -156,7 +165,7 @@ impl Interpreter {
})) }))
} }
fn run_instruction<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome<'a>, Error> { fn run_instruction<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome, Error> {
match opcode { match opcode {
&Opcode::Unreachable => self.run_unreachable(context), &Opcode::Unreachable => self.run_unreachable(context),
&Opcode::Nop => self.run_nop(context), &Opcode::Nop => self.run_nop(context),
@ -350,25 +359,25 @@ impl Interpreter {
} }
} }
fn run_unreachable<'a>(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_unreachable<'a>(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
Err(Error::Trap("programmatic".into())) Err(Error::Trap("programmatic".into()))
} }
fn run_nop<'a>(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_nop<'a>(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_block<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> { fn run_block<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> {
context.push_frame(labels, BlockFrameType::Block, block_type)?; context.push_frame(labels, BlockFrameType::Block, block_type)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_loop<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> { fn run_loop<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> {
context.push_frame(labels, BlockFrameType::Loop, block_type)?; context.push_frame(labels, BlockFrameType::Loop, block_type)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_if<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> { fn run_if<'a>(&mut self, context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> {
let branch = context.value_stack_mut().pop_as()?; let branch = context.value_stack_mut().pop_as()?;
let block_frame_type = if branch { BlockFrameType::IfTrue } else { let block_frame_type = if branch { BlockFrameType::IfTrue } else {
let else_pos = labels[&context.position]; let else_pos = labels[&context.position];
@ -383,23 +392,23 @@ impl Interpreter {
context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction) context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_else<'a>(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome<'a>, Error> { fn run_else<'a>(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome, Error> {
let end_pos = labels[&context.position]; let end_pos = labels[&context.position];
context.pop_frame(false)?; context.pop_frame(false)?;
context.position = end_pos; context.position = end_pos;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_end<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_end<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
context.pop_frame(false)?; context.pop_frame(false)?;
Ok(InstructionOutcome::End) Ok(InstructionOutcome::End)
} }
fn run_br<'a>(&mut self, _context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_br<'a>(&mut self, _context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Error> {
Ok(InstructionOutcome::Branch(label_idx as usize)) Ok(InstructionOutcome::Branch(label_idx as usize))
} }
fn run_br_if<'a>(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_br_if<'a>(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Error> {
if context.value_stack_mut().pop_as()? { if context.value_stack_mut().pop_as()? {
Ok(InstructionOutcome::Branch(label_idx as usize)) Ok(InstructionOutcome::Branch(label_idx as usize))
} else { } else {
@ -407,35 +416,38 @@ impl Interpreter {
} }
} }
fn run_br_table<'a>(&mut self, context: &mut FunctionContext, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_br_table<'a>(&mut self, context: &mut FunctionContext, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome, Error> {
let index: u32 = context.value_stack_mut().pop_as()?; let index: u32 = context.value_stack_mut().pop_as()?;
Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize)) Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize))
} }
fn run_return<'a>(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_return<'a>(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
Ok(InstructionOutcome::Return) Ok(InstructionOutcome::Return)
} }
fn run_call<'a>(&mut self, context: &mut FunctionContext<'a>, func_idx: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_call<'a>(&mut self, context: &mut FunctionContext<'a>, func_idx: u32) -> Result<InstructionOutcome, Error> {
Ok(InstructionOutcome::ExecuteCall(context.module().function_reference(ItemIndex::IndexSpace(func_idx), Some(context.externals))?)) let func = context.module().resolve_func(self.store, func_idx);
Ok(InstructionOutcome::ExecuteCall(func))
} }
fn run_call_indirect<'a>(&mut self, context: &mut FunctionContext<'a>, type_idx: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_call_indirect<'a>(&mut self, context: &mut FunctionContext<'a>, type_idx: u32) -> Result<InstructionOutcome, Error> {
let table_func_idx: u32 = context.value_stack_mut().pop_as()?; let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
let function_reference = context.module().function_reference_indirect(DEFAULT_TABLE_INDEX, type_idx, table_func_idx, Some(context.externals))?; let table = context.module().resolve_table(self.store, DEFAULT_TABLE_INDEX).resolve(self.store);
{ let func_ref = table.get(table_func_idx)?;
let required_function_type = context.module().function_type_by_index(type_idx)?;
let actual_function_type = function_reference.module.function_type(ItemIndex::Internal(function_reference.internal_index))?; let actual_function_type = func_ref.resolve(self.store).func_type().resolve(self.store);
if required_function_type != actual_function_type { let required_function_type = context.module().resolve_type(self.store, type_idx).resolve(self.store);
return Err(Error::Function(format!("expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(), if required_function_type != actual_function_type {
actual_function_type.params(), actual_function_type.return_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(InstructionOutcome::ExecuteCall(function_reference))
Ok(InstructionOutcome::ExecuteCall(func_ref))
} }
fn run_drop<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_drop<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
context context
.value_stack_mut() .value_stack_mut()
.pop() .pop()
@ -443,7 +455,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_select<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_select<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
context context
.value_stack_mut() .value_stack_mut()
.pop_triple() .pop_triple()
@ -459,59 +471,67 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_get_local<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_get_local<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
context.get_local(index as usize) context.get_local(index as usize)
.map(|value| context.value_stack_mut().push(value)) .map(|value| context.value_stack_mut().push(value))
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_set_local<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_set_local<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
let arg = context.value_stack_mut().pop()?; let arg = context.value_stack_mut().pop()?;
context.set_local(index as usize, arg) context.set_local(index as usize, arg)
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_tee_local<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_tee_local<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
let arg = context.value_stack().top()?.clone(); let arg = context.value_stack().top()?.clone();
context.set_local(index as usize, arg) context.set_local(index as usize, arg)
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_get_global<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_get_global<'a>(
context.module() &mut self,
.global(ItemIndex::IndexSpace(index), None, Some(context.externals)) context: &mut FunctionContext,
.and_then(|g| context.value_stack_mut().push(g.get()).map_err(Into::into)) index: u32,
.map(|_| InstructionOutcome::RunNextInstruction) ) -> Result<InstructionOutcome, Error> {
let global = context.module().resolve_global(&self.store, index);
let val = self.store.read_global(global);
context.value_stack_mut().push(val).map_err(Into::into)?;
Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_set_global<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> { fn run_set_global<'a>(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
context let val = context
.value_stack_mut() .value_stack_mut()
.pop() .pop()
.map_err(Into::into) .map_err(Into::into)?;
.and_then(|v| context.module().global(ItemIndex::IndexSpace(index), None, Some(context.externals)).and_then(|g| g.set(v)))
.map(|_| InstructionOutcome::RunNextInstruction) let global = context.module().resolve_global(&self.store, index);
self.store.write_global(global, val)?;
Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_load<'a, T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error> fn run_load<'a, T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T>, T: LittleEndianConvert { where RuntimeValue: From<T>, T: LittleEndianConvert {
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
context.module() let m = context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX)) .resolve_memory(self.store, DEFAULT_MEMORY_INDEX)
.and_then(|m| m.get(address, mem::size_of::<T>())) .resolve(self.store);
.and_then(|b| T::from_little_endian(b)) let b = m.get(address, mem::size_of::<T>())?;
.and_then(|n| context.value_stack_mut().push(n.into()).map_err(Into::into)) let n = T::from_little_endian(b)?;
.map(|_| InstructionOutcome::RunNextInstruction) context.value_stack_mut().push(n.into()).map_err(Into::into)?;
Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_load_extend<'a, T, U>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error> fn run_load_extend<'a, T, U>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error>
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert { where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
let stack_value: U = context.module() let m = context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX)) .resolve_memory(self.store, DEFAULT_MEMORY_INDEX)
.and_then(|m| m.get(address, mem::size_of::<T>())) .resolve(self.store);
.and_then(|b| T::from_little_endian(b)) let b = m.get(address, mem::size_of::<T>())?;
.map(|v| v.extend_into())?; let v = T::from_little_endian(b)?;
let stack_value: U = v.extend_into();
context context
.value_stack_mut() .value_stack_mut()
.push(stack_value.into()) .push(stack_value.into())
@ -519,17 +539,19 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_store<'a, T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error> fn run_store<'a, T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert { where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
let stack_value = context let stack_value = context
.value_stack_mut() .value_stack_mut()
.pop_as::<T>() .pop_as::<T>()
.map(|n| n.into_little_endian())?; .map(|n| n.into_little_endian())?;
let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?;
context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX)) let m = context.module()
.and_then(|m| m.set(address, &stack_value)) .resolve_memory(self.store, DEFAULT_MEMORY_INDEX)
.map(|_| InstructionOutcome::RunNextInstruction) .resolve(self.store);
m.set(address, &stack_value)?;
Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_store_wrap<'a, T, U>( fn run_store_wrap<'a, T, U>(
@ -537,7 +559,7 @@ impl Interpreter {
context: &mut FunctionContext, context: &mut FunctionContext,
_align: u32, _align: u32,
offset: u32, offset: u32,
) -> Result<InstructionOutcome<'a>, Error> ) -> Result<InstructionOutcome, Error>
where where
RuntimeValue: TryInto<T, Error>, RuntimeValue: TryInto<T, Error>,
T: WrapInto<U>, T: WrapInto<U>,
@ -550,40 +572,39 @@ impl Interpreter {
.and_then(|v| v.try_into())?; .and_then(|v| v.try_into())?;
let stack_value = stack_value.wrap_into().into_little_endian(); let stack_value = stack_value.wrap_into().into_little_endian();
let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?;
context.module() let m = context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX)) .resolve_memory(self.store, DEFAULT_MEMORY_INDEX)
.and_then(|m| m.set(address, &stack_value)) .resolve(self.store);
.map(|_| InstructionOutcome::RunNextInstruction) m.set(address, &stack_value)?;
Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_current_memory<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_current_memory<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
context.module() let m = context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX)) .resolve_memory(self.store, DEFAULT_MEMORY_INDEX)
.map(|m| m.size()) .resolve(self.store);
.and_then(|s| let s = m.size();
context context
.value_stack_mut() .value_stack_mut()
.push(RuntimeValue::I32(s as i32)) .push(RuntimeValue::I32(s as i32))
.map_err(Into::into) .map_err(Into::into)?;
) Ok(InstructionOutcome::RunNextInstruction)
.map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_grow_memory<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> { fn run_grow_memory<'a>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
let pages: u32 = context.value_stack_mut().pop_as()?; let pages: u32 = context.value_stack_mut().pop_as()?;
context.module() let m = context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX)) .resolve_memory(self.store, DEFAULT_MEMORY_INDEX)
.and_then(|m| m.grow(pages)) .resolve(self.store);
.and_then(|m| let m = m.grow(pages)?;
context context
.value_stack_mut() .value_stack_mut()
.push(RuntimeValue::I32(m as i32)) .push(RuntimeValue::I32(m as i32))
.map_err(Into::into) .map_err(Into::into)?;
) Ok(InstructionOutcome::RunNextInstruction)
.map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_const<'a>(&mut self, context: &mut FunctionContext, val: RuntimeValue) -> Result<InstructionOutcome<'a>, Error> { fn run_const<'a>(&mut self, context: &mut FunctionContext, val: RuntimeValue) -> Result<InstructionOutcome, Error> {
context context
.value_stack_mut() .value_stack_mut()
.push(val) .push(val)
@ -591,7 +612,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_eqz<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_eqz<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default { where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default {
context context
.value_stack_mut() .value_stack_mut()
@ -601,7 +622,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_eq<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_eq<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> { where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -611,7 +632,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_ne<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_ne<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> { where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -621,7 +642,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_lt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_lt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display {
context context
.value_stack_mut() .value_stack_mut()
@ -631,7 +652,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_gt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_gt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -641,7 +662,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_lte<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_lte<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -651,7 +672,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_gte<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_gte<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -661,7 +682,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_clz<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_clz<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -671,7 +692,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_ctz<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_ctz<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -681,7 +702,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_popcnt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_popcnt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -691,7 +712,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_add<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_add<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -701,7 +722,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_sub<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_sub<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -711,7 +732,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_mul<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_mul<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -721,7 +742,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_div<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_div<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -733,7 +754,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_rem<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_rem<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -745,7 +766,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_and<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_and<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> { where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -755,7 +776,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_or<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_or<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> { where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -765,7 +786,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_xor<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_xor<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> { where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -775,7 +796,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_shl<'a, T>(&mut self, context: &mut FunctionContext, mask: T) -> Result<InstructionOutcome<'a>, Error> fn run_shl<'a, T>(&mut self, context: &mut FunctionContext, mask: T) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> { where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
context context
.value_stack_mut() .value_stack_mut()
@ -785,7 +806,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_shr<'a, T, U>(&mut self, context: &mut FunctionContext, mask: U) -> Result<InstructionOutcome<'a>, Error> fn run_shr<'a, T, U>(&mut self, context: &mut FunctionContext, mask: U) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -797,7 +818,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_rotl<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_rotl<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -807,7 +828,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_rotr<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_rotr<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -817,7 +838,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_abs<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_abs<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -827,7 +848,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_neg<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_neg<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg { where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg {
context context
.value_stack_mut() .value_stack_mut()
@ -837,7 +858,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_ceil<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_ceil<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -847,7 +868,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_floor<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_floor<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -857,7 +878,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_trunc<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_trunc<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -867,7 +888,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_nearest<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_nearest<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -877,7 +898,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_sqrt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_sqrt<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -887,7 +908,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_min<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_min<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -897,7 +918,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_max<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_max<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -907,7 +928,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_copysign<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_copysign<'a, T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -917,7 +938,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_wrap<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_wrap<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> { where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> {
context context
.value_stack_mut() .value_stack_mut()
@ -927,7 +948,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_trunc_to_int<'a, T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_trunc_to_int<'a, T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, { where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, {
context context
.value_stack_mut() .value_stack_mut()
@ -938,7 +959,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_extend<'a, T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_extend<'a, T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> { where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> {
context context
.value_stack_mut() .value_stack_mut()
@ -950,7 +971,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_reinterpret<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> fn run_reinterpret<'a, T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> { where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> {
context context
.value_stack_mut() .value_stack_mut()
@ -962,10 +983,11 @@ impl Interpreter {
} }
impl<'a> FunctionContext<'a> { impl<'a> FunctionContext<'a> {
pub fn new(function: InternalFunctionReference<'a>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self { pub fn new(module: ModuleId, function: FuncId, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self {
FunctionContext { FunctionContext {
is_initialized: false, is_initialized: false,
function: function, function: function,
module: module,
externals: externals, externals: externals,
return_type: function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult), return_type: function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult),
value_stack: StackWithLimit::with_limit(value_stack_limit), value_stack: StackWithLimit::with_limit(value_stack_limit),
@ -975,17 +997,25 @@ impl<'a> FunctionContext<'a> {
} }
} }
pub fn nested(&mut self, function: InternalFunctionReference<'a>) -> Result<Self, Error> { pub fn nested(&mut self, store: &Store, function: FuncId) -> Result<Self, Error> {
let (function_locals, function_return_type) = { let (function_locals, module, function_return_type) = {
let function_type = function.module.function_type(ItemIndex::Internal(function.internal_index))?; let func_instance = function.resolve(store);
let module = match *func_instance {
FuncInstance::Defined { module, .. } => module,
FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
};
let function_type = func_instance.func_type().resolve(store);
// TODO: function_signature
let function_signature = FunctionSignature::Module(&function_type);
let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult); let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult);
let function_locals = prepare_function_args(&function_type, &mut self.value_stack)?; let function_locals = prepare_function_args(&function_signature, &mut self.value_stack)?;
(function_locals, function_return_type) (function_locals, module, function_return_type)
}; };
Ok(FunctionContext { Ok(FunctionContext {
is_initialized: false, is_initialized: false,
function: function, function: function,
module: module,
externals: self.externals, externals: self.externals,
return_type: function_return_type, return_type: function_return_type,
value_stack: StackWithLimit::with_limit(self.value_stack.limit() - self.value_stack.len()), value_stack: StackWithLimit::with_limit(self.value_stack.limit() - self.value_stack.len()),
@ -1011,15 +1041,15 @@ impl<'a> FunctionContext<'a> {
Ok(()) Ok(())
} }
pub fn module(&self) -> &Arc<ModuleInstanceInterface + 'a> { pub fn module(&self) -> ModuleId {
&self.function.module self.module
} }
pub fn externals(&self) -> &HashMap<String, Arc<ModuleInstanceInterface + 'a>> { pub fn externals(&self) -> &HashMap<String, Arc<ModuleInstanceInterface + 'a>> {
&self.externals &self.externals
} }
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome<'a>, Error> { pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome, Error> {
self.locals.get_mut(index) self.locals.get_mut(index)
.ok_or(Error::Local(format!("expected to have local with index {}", index))) .ok_or(Error::Local(format!("expected to have local with index {}", index)))
.and_then(|l| l.set(value)) .and_then(|l| l.set(value))

View File

@ -1,6 +1,7 @@
// TODO: remove this // TODO: remove this
#![allow(unused)] #![allow(unused)]
use std::sync::Arc;
use elements::{FuncBody, FunctionType, GlobalEntry, GlobalType, InitExpr, MemoryType, Module, use elements::{FuncBody, FunctionType, GlobalEntry, GlobalType, InitExpr, MemoryType, Module,
Opcode, TableType, Type}; Opcode, TableType, Type};
use interpreter::{Error, RuntimeValue, MemoryInstance, TableInstance, ExecutionParams, CallerContext, FunctionSignature}; use interpreter::{Error, RuntimeValue, MemoryInstance, TableInstance, ExecutionParams, CallerContext, FunctionSignature};
@ -12,10 +13,17 @@ use common::stack::StackWithLimit;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct TypeId(u32); pub struct TypeId(u32);
impl TypeId {
pub fn resolve<'s>(&self, store: &'s Store) -> &'s FunctionType {
store.resolve_type(*self)
}
}
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct ModuleId(u32); pub struct ModuleId(u32);
// TODO: Work on naming: resolve gets instances or ids? // TODO: Work on naming: resolve gets instances or ids?
// global_by_index vs resolve_global?
impl ModuleId { impl ModuleId {
pub fn resolve_memory(&self, store: &Store, idx: u32) -> MemoryId { pub fn resolve_memory(&self, store: &Store, idx: u32) -> MemoryId {
@ -25,6 +33,39 @@ impl ModuleId {
.get(idx as usize) .get(idx as usize)
.expect("Due to validation memory should exists") .expect("Due to validation memory should exists")
} }
pub fn resolve_table(&self, store: &Store, idx: u32) -> TableId {
let instance = store.resolve_module(*self);
*instance
.tables
.get(idx as usize)
.expect("Due to validation table should exists")
}
pub fn resolve_global(&self, store: &Store, idx: u32) -> GlobalId {
let instance = store.resolve_module(*self);
*instance
.globals
.get(idx as usize)
.expect("Due to validation global should exists")
}
pub fn resolve_func(&self, store: &Store, idx: u32) -> FuncId {
let instance = store.resolve_module(*self);
*instance
.funcs
.get(idx as usize)
.expect("Due to validation func should exists")
}
pub fn resolve_type(&self, store: &Store, idx: u32) -> TypeId {
let instance = store.resolve_module(*self);
*instance
.types
.get(idx as usize)
.expect("Due to validation type should exists")
}
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -34,16 +75,20 @@ pub struct HostFuncId(u32);
pub struct FuncId(u32); pub struct FuncId(u32);
impl FuncId { impl FuncId {
// TODO: Split? pub fn resolve<'s>(&self, store: &'s Store) -> &'s FuncInstance {
pub fn resolve_type<'s>(&self, store: &'s Store) -> &'s FunctionType { store.funcs.get(self.0 as usize).expect("ID should be always valid")
let func = store.funcs.get(self.0 as usize).expect("ID should be always valid");
store.resolve_type(func.func_type())
} }
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct TableId(u32); pub struct TableId(u32);
impl TableId {
pub fn resolve<'s>(&self, store: &'s Store) -> &'s TableInstance {
store.tables.get(self.0 as usize).expect("ID should be always valid")
}
}
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct MemoryId(u32); pub struct MemoryId(u32);
@ -67,7 +112,7 @@ pub enum FuncInstance {
Defined { Defined {
func_type: TypeId, func_type: TypeId,
module: ModuleId, module: ModuleId,
body: FuncBody, body: Arc<FuncBody>,
}, },
Host { Host {
func_type: TypeId, func_type: TypeId,
@ -76,13 +121,20 @@ pub enum FuncInstance {
} }
impl FuncInstance { impl FuncInstance {
fn func_type(&self) -> TypeId { pub fn func_type(&self) -> TypeId {
match *self { match *self {
FuncInstance::Defined { func_type, .. } | FuncInstance::Host { func_type, .. } => { FuncInstance::Defined { func_type, .. } | FuncInstance::Host { func_type, .. } => {
func_type func_type
} }
} }
} }
pub fn body(&self) -> Option<Arc<FuncBody>> {
match *self {
FuncInstance::Defined { ref body, .. } => Some(Arc::clone(body)),
FuncInstance::Host { .. } => None,
}
}
} }
pub struct GlobalInstance { pub struct GlobalInstance {
@ -158,7 +210,7 @@ impl Store {
let func = FuncInstance::Defined { let func = FuncInstance::Defined {
func_type, func_type,
module, module,
body, body: Arc::new(body),
}; };
self.funcs.push(func); self.funcs.push(func);
let func_id = self.funcs.len() - 1; let func_id = self.funcs.len() - 1;
@ -344,13 +396,28 @@ impl Store {
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 outer = CallerContext::topmost(&mut args, &externals); let outer = CallerContext::topmost(&mut args, &externals);
let func_type = func.resolve_type(self); let func_type = func.resolve(self).func_type().resolve(self);
let func_signature = FunctionSignature::Module(func_type); let func_signature = FunctionSignature::Module(func_type);
let args = prepare_function_args(&func_signature, outer.value_stack)?; let args = prepare_function_args(&func_signature, outer.value_stack)?;
let inner = FunctionContext::new(func, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &func_signature, args); let inner = FunctionContext::new(func, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &func_signature, args);
let interpreter = Interpreter::new(self); let interpreter = Interpreter::new(self);
interpreter.run_function(inner) interpreter.run_function(inner)
} }
pub fn write_global(&mut self, global: GlobalId, val: RuntimeValue) -> Result<(), Error> {
let global_instance = self.globals.get_mut(global.0 as usize).expect("ID should be always valid");
if !global_instance.mutable {
// TODO: better error message
return Err(Error::Validation("Can't write immutable global".into()));
}
global_instance.val = val;
Ok(())
}
pub fn read_global(&self, global: GlobalId) -> RuntimeValue {
let global_instance = self.globals.get_mut(global.0 as usize).expect("ID should be always valid");
global_instance.val
}
} }
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance, store: &Store) -> RuntimeValue { fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance, store: &Store) -> RuntimeValue {