Check global's type on instantiation.

This commit is contained in:
Sergey Pepyakin 2017-12-18 15:34:17 +03:00
parent 0e89639fe6
commit 9dd7a5dfaf
4 changed files with 26 additions and 13 deletions

View File

@ -1,4 +1,5 @@
use std::cell::Cell;
use elements::ValueType;
use interpreter::value::RuntimeValue;
use interpreter::Error;
@ -17,9 +18,8 @@ impl GlobalInstance {
}
pub fn set(&self, val: RuntimeValue) -> Result<(), Error> {
if !self.mutable {
return Err(Error::Validation("Can't set immutable global".into()));
}
assert!(self.mutable, "Attempt to change an immutable variable");
assert!(self.value_type() == val.value_type(), "Attempt to change variable type");
self.val.set(val);
Ok(())
}
@ -27,4 +27,12 @@ impl GlobalInstance {
pub fn get(&self) -> RuntimeValue {
self.val.get()
}
pub fn is_mutable(&self) -> bool {
self.mutable
}
pub fn value_type(&self) -> ValueType {
self.val.get().value_type()
}
}

View File

@ -198,8 +198,14 @@ impl<St> ModuleInstance<St> {
match_limits(memory.limits(), mt.limits())?;
instance.push_memory(Rc::clone(memory));
}
(&External::Global(ref _gl), &ExternVal::Global(ref global)) => {
// TODO: check globals
(&External::Global(ref gl), &ExternVal::Global(ref global)) => {
if gl.content_type() != global.value_type() {
return Err(Error::Initialization(format!(
"Expect global with {:?} type, but provided global with {:?} type",
gl.content_type(),
global.value_type(),
)));
}
instance.push_global(Rc::clone(global))
}
(expected_import, actual_extern_val) => {

View File

@ -1149,11 +1149,10 @@ 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> {
let mut args = function_type.params().iter().rev().map(|param_type| {
let mut args = function_type.params().iter().cloned().rev().map(|expected_type| {
let param_value = caller_stack.pop()?;
let actual_type = param_value.value_type();
let expected_type = (*param_type).into();
if actual_type != Some(expected_type) {
if actual_type != expected_type {
return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type)));
}

View File

@ -131,12 +131,12 @@ impl RuntimeValue {
}
/// Get variable type for this value.
pub fn value_type(&self) -> Option<ValueType> {
pub fn value_type(&self) -> ValueType {
match *self {
RuntimeValue::I32(_) => Some(ValueType::I32),
RuntimeValue::I64(_) => Some(ValueType::I64),
RuntimeValue::F32(_) => Some(ValueType::F32),
RuntimeValue::F64(_) => Some(ValueType::F64),
RuntimeValue::I32(_) => ValueType::I32,
RuntimeValue::I64(_) => ValueType::I64,
RuntimeValue::F32(_) => ValueType::F32,
RuntimeValue::F64(_) => ValueType::F64,
}
}
}