mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-20 18:26:54 +00:00
Remove variable.rs
This commit is contained in:
@ -15,7 +15,7 @@ use parity_wasm::elements::{self, ValueType, GlobalType, MemoryType, TableType,
|
|||||||
use parity_wasm::interpreter::{
|
use parity_wasm::interpreter::{
|
||||||
RuntimeValue,
|
RuntimeValue,
|
||||||
ProgramInstance,
|
ProgramInstance,
|
||||||
ItemIndex, ExportEntryType,
|
ItemIndex,
|
||||||
Error as InterpreterError,
|
Error as InterpreterError,
|
||||||
ImportResolver,
|
ImportResolver,
|
||||||
Imports,
|
Imports,
|
||||||
@ -278,7 +278,7 @@ pub fn spec(name: &str) {
|
|||||||
let spec_expected = runtime_values(expected);
|
let spec_expected = runtime_values(expected);
|
||||||
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
|
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
|
||||||
for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) {
|
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
|
// f32::NAN != f32::NAN
|
||||||
match spec_expected {
|
match spec_expected {
|
||||||
&RuntimeValue::F32(val) if val.is_nan() => match actual_result {
|
&RuntimeValue::F32(val) if val.is_nan() => match actual_result {
|
||||||
|
@ -137,7 +137,6 @@ mod runner;
|
|||||||
mod stack;
|
mod stack;
|
||||||
mod table;
|
mod table;
|
||||||
mod value;
|
mod value;
|
||||||
mod variable;
|
|
||||||
mod store;
|
mod store;
|
||||||
mod host;
|
mod host;
|
||||||
mod imports;
|
mod imports;
|
||||||
@ -146,11 +145,10 @@ mod imports;
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use self::memory::MemoryInstance;
|
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::table::TableInstance;
|
||||||
pub use self::program::ProgramInstance;
|
pub use self::program::ProgramInstance;
|
||||||
pub use self::value::RuntimeValue;
|
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::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg};
|
||||||
pub use self::imports::{ImportResolver, Imports};
|
pub use self::imports::{ImportResolver, Imports};
|
||||||
pub use self::store::{FuncInstance, ModuleInstance, GlobalInstance};
|
pub use self::store::{FuncInstance, ModuleInstance, GlobalInstance};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use elements::ResizableLimits;
|
use elements::ResizableLimits;
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::VariableType;
|
|
||||||
|
|
||||||
/// Execution context.
|
/// Execution context.
|
||||||
pub struct ExecutionParams<'a, St: 'static> {
|
pub struct ExecutionParams<'a, St: 'static> {
|
||||||
@ -8,15 +7,6 @@ pub struct ExecutionParams<'a, St: 'static> {
|
|||||||
pub state: &'a mut St,
|
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.
|
/// Item index in items index space.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ItemIndex {
|
pub enum ItemIndex {
|
||||||
|
@ -1048,7 +1048,7 @@ impl FunctionContext {
|
|||||||
self.is_initialized = true;
|
self.is_initialized = true;
|
||||||
|
|
||||||
let locals = locals.iter()
|
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))
|
.map(|vt| RuntimeValue::default(vt))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.locals.extend(locals);
|
self.locals.extend(locals);
|
||||||
@ -1152,7 +1152,7 @@ fn effective_address(address: u32, offset: u32) -> Result<u32, Error> {
|
|||||||
pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, Error> {
|
pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, Error> {
|
||||||
let mut args = function_type.params().iter().rev().map(|param_type| {
|
let mut args = function_type.params().iter().rev().map(|param_type| {
|
||||||
let param_value = caller_stack.pop()?;
|
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();
|
let expected_type = (*param_type).into();
|
||||||
if actual_type != Some(expected_type) {
|
if actual_type != Some(expected_type) {
|
||||||
return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type)));
|
return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type)));
|
||||||
|
@ -5,7 +5,6 @@ use parking_lot::RwLock;
|
|||||||
use elements::{TableType, ResizableLimits};
|
use elements::{TableType, ResizableLimits};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::module::check_limits;
|
use interpreter::module::check_limits;
|
||||||
use interpreter::variable::VariableType;
|
|
||||||
use interpreter::store::FuncInstance;
|
use interpreter::store::FuncInstance;
|
||||||
|
|
||||||
/// Table instance.
|
/// Table instance.
|
||||||
@ -18,12 +17,12 @@ pub struct TableInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for TableInstance {
|
impl fmt::Debug for TableInstance {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.debug_struct("TableInstance")
|
f.debug_struct("TableInstance")
|
||||||
.field("limits", &self.limits)
|
.field("limits", &self.limits)
|
||||||
.field("buffer.len", &self.buffer.read().len())
|
.field("buffer.len", &self.buffer.read().len())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableInstance {
|
impl TableInstance {
|
||||||
@ -43,11 +42,6 @@ impl TableInstance {
|
|||||||
&self.limits
|
&self.limits
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get variable type for this table.
|
|
||||||
pub fn variable_type(&self) -> VariableType {
|
|
||||||
panic!("TODO")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the specific value in the table
|
/// Get the specific value in the table
|
||||||
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> {
|
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> {
|
||||||
let buffer = self.buffer.read();
|
let buffer = self.buffer.read();
|
||||||
|
@ -2,15 +2,13 @@ use std::{i32, i64, u32, u64, f32};
|
|||||||
use std::io;
|
use std::io;
|
||||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::variable::VariableType;
|
use elements::ValueType;
|
||||||
|
|
||||||
|
|
||||||
// TODO: Get rid of Null and AnyFunc.
|
// TODO: Get rid of Null and AnyFunc.
|
||||||
/// Runtime value.
|
/// Runtime value.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum RuntimeValue {
|
pub enum RuntimeValue {
|
||||||
/// Null value.
|
|
||||||
Null,
|
|
||||||
/// 32b-length signed/unsigned int.
|
/// 32b-length signed/unsigned int.
|
||||||
I32(i32),
|
I32(i32),
|
||||||
/// 64b-length signed/unsigned int.
|
/// 64b-length signed/unsigned int.
|
||||||
@ -113,12 +111,12 @@ pub trait Float<T>: ArithmeticOps<T> {
|
|||||||
|
|
||||||
impl RuntimeValue {
|
impl RuntimeValue {
|
||||||
/// Creates new default value of given type.
|
/// Creates new default value of given type.
|
||||||
pub fn default(variable_type: VariableType) -> Self {
|
pub fn default(value_type: ValueType) -> Self {
|
||||||
match variable_type {
|
match value_type {
|
||||||
VariableType::I32 => RuntimeValue::I32(0),
|
ValueType::I32 => RuntimeValue::I32(0),
|
||||||
VariableType::I64 => RuntimeValue::I64(0),
|
ValueType::I64 => RuntimeValue::I64(0),
|
||||||
VariableType::F32 => RuntimeValue::F32(0f32),
|
ValueType::F32 => RuntimeValue::F32(0f32),
|
||||||
VariableType::F64 => RuntimeValue::F64(0f64),
|
ValueType::F64 => RuntimeValue::F64(0f64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,22 +130,13 @@ impl RuntimeValue {
|
|||||||
RuntimeValue::F64(f64_from_bits(val))
|
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.
|
/// Get variable type for this value.
|
||||||
pub fn variable_type(&self) -> Option<VariableType> {
|
pub fn value_type(&self) -> Option<ValueType> {
|
||||||
match *self {
|
match *self {
|
||||||
RuntimeValue::Null => None,
|
RuntimeValue::I32(_) => Some(ValueType::I32),
|
||||||
RuntimeValue::I32(_) => Some(VariableType::I32),
|
RuntimeValue::I64(_) => Some(ValueType::I64),
|
||||||
RuntimeValue::I64(_) => Some(VariableType::I64),
|
RuntimeValue::F32(_) => Some(ValueType::F32),
|
||||||
RuntimeValue::F32(_) => Some(VariableType::F32),
|
RuntimeValue::F64(_) => Some(ValueType::F64),
|
||||||
RuntimeValue::F64(_) => Some(VariableType::F64),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<VariableValue>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enum variable value.
|
|
||||||
enum VariableValue {
|
|
||||||
/// Internal value.
|
|
||||||
Internal(RuntimeValue),
|
|
||||||
/// External value.
|
|
||||||
External(Box<ExternalVariableValue>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariableInstance {
|
|
||||||
/// New variable instance
|
|
||||||
pub fn new(is_mutable: bool, variable_type: VariableType, value: RuntimeValue) -> Result<Self, Error> {
|
|
||||||
// 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, Error> {
|
|
||||||
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<ExternalVariableValue>) -> Result<Self, Error> {
|
|
||||||
// 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<ValueType> 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()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user