diff --git a/spec/src/run.rs b/spec/src/run.rs index 0ac924f..f9b2991 100644 --- a/spec/src/run.rs +++ b/spec/src/run.rs @@ -15,7 +15,7 @@ use parity_wasm::elements::{self, ValueType, GlobalType, MemoryType, TableType, use parity_wasm::interpreter::{ RuntimeValue, ProgramInstance, - ItemIndex, ExportEntryType, + ItemIndex, Error as InterpreterError, ImportResolver, Imports, @@ -278,7 +278,7 @@ pub fn spec(name: &str) { let spec_expected = runtime_values(expected); let actual_result = result.into_iter().collect::>(); for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) { - assert_eq!(actual_result.variable_type(), spec_expected.variable_type()); + assert_eq!(actual_result.value_type(), spec_expected.value_type()); // f32::NAN != f32::NAN match spec_expected { &RuntimeValue::F32(val) if val.is_nan() => match actual_result { diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index ccf2af8..5b983fe 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -137,7 +137,6 @@ mod runner; mod stack; mod table; mod value; -mod variable; mod store; mod host; mod imports; @@ -146,11 +145,10 @@ mod imports; mod tests; pub use self::memory::MemoryInstance; -pub use self::module::{ItemIndex, ExportEntryType, ExecutionParams}; +pub use self::module::{ItemIndex, ExecutionParams}; pub use self::table::TableInstance; pub use self::program::ProgramInstance; pub use self::value::RuntimeValue; -pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue}; pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg}; pub use self::imports::{ImportResolver, Imports}; pub use self::store::{FuncInstance, ModuleInstance, GlobalInstance}; diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index 2873104..ee94c8f 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -1,6 +1,5 @@ use elements::ResizableLimits; use interpreter::Error; -use interpreter::VariableType; /// Execution context. pub struct ExecutionParams<'a, St: 'static> { @@ -8,15 +7,6 @@ pub struct ExecutionParams<'a, St: 'static> { pub state: &'a mut St, } -/// Export type. -#[derive(Debug, Clone)] -pub enum ExportEntryType { - /// Any type. - Any, - /// Type of global. - Global(VariableType), -} - /// Item index in items index space. #[derive(Debug, Clone, Copy)] pub enum ItemIndex { diff --git a/src/interpreter/runner.rs b/src/interpreter/runner.rs index 94c8637..77552b1 100644 --- a/src/interpreter/runner.rs +++ b/src/interpreter/runner.rs @@ -1048,7 +1048,7 @@ impl FunctionContext { self.is_initialized = true; let locals = locals.iter() - .flat_map(|l| repeat(l.value_type().into()).take(l.count() as usize)) + .flat_map(|l| repeat(l.value_type()).take(l.count() as usize)) .map(|vt| RuntimeValue::default(vt)) .collect::>(); self.locals.extend(locals); @@ -1152,7 +1152,7 @@ fn effective_address(address: u32, offset: u32) -> Result { pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit) -> Result, Error> { let mut args = function_type.params().iter().rev().map(|param_type| { let param_value = caller_stack.pop()?; - let actual_type = param_value.variable_type(); + let actual_type = param_value.value_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))); diff --git a/src/interpreter/table.rs b/src/interpreter/table.rs index bd16edf..03b3609 100644 --- a/src/interpreter/table.rs +++ b/src/interpreter/table.rs @@ -5,7 +5,6 @@ use parking_lot::RwLock; use elements::{TableType, ResizableLimits}; use interpreter::Error; use interpreter::module::check_limits; -use interpreter::variable::VariableType; use interpreter::store::FuncInstance; /// Table instance. @@ -18,12 +17,12 @@ pub struct TableInstance { } impl fmt::Debug for TableInstance { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("TableInstance") + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("TableInstance") .field("limits", &self.limits) .field("buffer.len", &self.buffer.read().len()) .finish() - } + } } impl TableInstance { @@ -43,11 +42,6 @@ impl TableInstance { &self.limits } - /// Get variable type for this table. - pub fn variable_type(&self) -> VariableType { - panic!("TODO") - } - /// Get the specific value in the table pub fn get(&self, offset: u32) -> Result, Error> { let buffer = self.buffer.read(); diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index d4e9771..bab3adf 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -2,15 +2,13 @@ use std::{i32, i64, u32, u64, f32}; use std::io; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use interpreter::Error; -use interpreter::variable::VariableType; +use elements::ValueType; // TODO: Get rid of Null and AnyFunc. /// Runtime value. #[derive(Copy, Clone, Debug, PartialEq)] pub enum RuntimeValue { - /// Null value. - Null, /// 32b-length signed/unsigned int. I32(i32), /// 64b-length signed/unsigned int. @@ -113,12 +111,12 @@ pub trait Float: ArithmeticOps { impl RuntimeValue { /// Creates new default value of given type. - pub fn default(variable_type: VariableType) -> Self { - match variable_type { - VariableType::I32 => RuntimeValue::I32(0), - VariableType::I64 => RuntimeValue::I64(0), - VariableType::F32 => RuntimeValue::F32(0f32), - VariableType::F64 => RuntimeValue::F64(0f64), + pub fn default(value_type: ValueType) -> Self { + match value_type { + ValueType::I32 => RuntimeValue::I32(0), + ValueType::I64 => RuntimeValue::I64(0), + ValueType::F32 => RuntimeValue::F32(0f32), + ValueType::F64 => RuntimeValue::F64(0f64), } } @@ -132,22 +130,13 @@ impl RuntimeValue { RuntimeValue::F64(f64_from_bits(val)) } - /// Returns true if value is null. - pub fn is_null(&self) -> bool { - match *self { - RuntimeValue::Null => true, - _ => false, - } - } - /// Get variable type for this value. - pub fn variable_type(&self) -> Option { + pub fn value_type(&self) -> Option { match *self { - RuntimeValue::Null => None, - RuntimeValue::I32(_) => Some(VariableType::I32), - RuntimeValue::I64(_) => Some(VariableType::I64), - RuntimeValue::F32(_) => Some(VariableType::F32), - RuntimeValue::F64(_) => Some(VariableType::F64), + RuntimeValue::I32(_) => Some(ValueType::I32), + RuntimeValue::I64(_) => Some(ValueType::I64), + RuntimeValue::F32(_) => Some(ValueType::F32), + RuntimeValue::F64(_) => Some(ValueType::F64), } } } diff --git a/src/interpreter/variable.rs b/src/interpreter/variable.rs deleted file mode 100644 index 7778e84..0000000 --- a/src/interpreter/variable.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::fmt; -use parking_lot::RwLock; -use elements::{GlobalType, ValueType}; -use interpreter::Error; -use interpreter::value::RuntimeValue; - -/// Variable type. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum VariableType { - /// i32 value. - I32, - /// i64 value. - I64, - /// f32 value. - F32, - /// f64 value. - F64, -} - -/// Externally stored variable value. -/// -/// WebAssembly specificaiton [requires][0] that if a global variable is immutable, then -/// it should remain unchanged. To comply with specification you should ensure this invariant holds. -/// -/// [0]: https://webassembly.github.io/spec/appendix/properties.html#global-instance -pub trait ExternalVariableValue { - /// Get variable value. - fn get(&self) -> RuntimeValue; - - /// Set variable value. - fn set(&mut self, value: RuntimeValue) -> Result<(), Error>; -} - -/// Variable instance. -#[derive(Debug)] -pub struct VariableInstance { - /// Is mutable? - is_mutable: bool, - /// Variable type. - variable_type: VariableType, - /// Global value. - value: RwLock, -} - -/// Enum variable value. -enum VariableValue { - /// Internal value. - Internal(RuntimeValue), - /// External value. - External(Box), -} - -impl VariableInstance { - /// New variable instance - pub fn new(is_mutable: bool, variable_type: VariableType, value: RuntimeValue) -> Result { - // TODO: there is nothing about null value in specification + there is nothing about initializing missing table elements? => runtime check for nulls - if !value.is_null() && value.variable_type() != Some(variable_type) { - return Err(Error::Variable(format!("trying to initialize variable of type {:?} with value of type {:?}", variable_type, value.variable_type()))); - } - - Ok(VariableInstance { - is_mutable: is_mutable, - variable_type: variable_type, - value: RwLock::new(VariableValue::Internal(value)), - }) - } - - /// New global variable - pub fn new_global(global_type: &GlobalType, value: RuntimeValue) -> Result { - Self::new(global_type.is_mutable(), global_type.content_type().into(), value) - } - - /// New global with externally stored value. - pub fn new_external_global(is_mutable: bool, variable_type: VariableType, value: Box) -> Result { - // TODO: there is nothing about null value in specification + there is nothing about initializing missing table elements? => runtime check for nulls - let current_value = value.get(); - if !current_value.is_null() && current_value.variable_type() != Some(variable_type) { - return Err(Error::Variable(format!("trying to initialize variable of type {:?} with value of type {:?}", variable_type, current_value.variable_type()))); - } - - Ok(VariableInstance { - is_mutable: is_mutable, - variable_type: variable_type, - value: RwLock::new(VariableValue::External(value)), - }) - } - - /// Is mutable - pub fn is_mutable(&self) -> bool { - self.is_mutable - } - - /// Get variable type. - pub fn variable_type(&self) -> VariableType { - self.variable_type - } - - /// Get the value of the variable instance - pub fn get(&self) -> RuntimeValue { - self.value.read().get() - } - - /// Set the value of the variable instance - pub fn set(&self, value: RuntimeValue) -> Result<(), Error> { - if !self.is_mutable { - return Err(Error::Variable("trying to update immutable variable".into())); - } - if value.variable_type() != Some(self.variable_type) { - return Err(Error::Variable(format!("trying to update variable of type {:?} with value of type {:?}", self.variable_type, value.variable_type()))); - } - - self.value.write().set(value) - } -} - -impl VariableValue { - fn get(&self) -> RuntimeValue { - match *self { - VariableValue::Internal(ref value) => value.clone(), - VariableValue::External(ref value) => value.get(), - } - } - - fn set(&mut self, new_value: RuntimeValue) -> Result<(), Error> { - match *self { - VariableValue::Internal(ref mut value) => { - *value = new_value; - Ok(()) - }, - VariableValue::External(ref mut value) => value.set(new_value), - } - } -} - -impl From for VariableType { - fn from(vt: ValueType) -> VariableType { - match vt { - ValueType::I32 => VariableType::I32, - ValueType::I64 => VariableType::I64, - ValueType::F32 => VariableType::F32, - ValueType::F64 => VariableType::F64, - } - } -} - -impl fmt::Debug for VariableValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - VariableValue::Internal(ref value) => write!(f, "Variable.Internal({:?})", value), - VariableValue::External(ref value) => write!(f, "Variable.External({:?})", value.get()), - } - } -}