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 std::cell::Cell;
use elements::ValueType;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
use interpreter::Error; use interpreter::Error;
@ -17,9 +18,8 @@ impl GlobalInstance {
} }
pub fn set(&self, val: RuntimeValue) -> Result<(), Error> { pub fn set(&self, val: RuntimeValue) -> Result<(), Error> {
if !self.mutable { assert!(self.mutable, "Attempt to change an immutable variable");
return Err(Error::Validation("Can't set immutable global".into())); assert!(self.value_type() == val.value_type(), "Attempt to change variable type");
}
self.val.set(val); self.val.set(val);
Ok(()) Ok(())
} }
@ -27,4 +27,12 @@ impl GlobalInstance {
pub fn get(&self) -> RuntimeValue { pub fn get(&self) -> RuntimeValue {
self.val.get() 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())?; match_limits(memory.limits(), mt.limits())?;
instance.push_memory(Rc::clone(memory)); instance.push_memory(Rc::clone(memory));
} }
(&External::Global(ref _gl), &ExternVal::Global(ref global)) => { (&External::Global(ref gl), &ExternVal::Global(ref global)) => {
// TODO: check globals 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)) instance.push_global(Rc::clone(global))
} }
(expected_import, actual_extern_val) => { (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> { 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 param_value = caller_stack.pop()?;
let actual_type = param_value.value_type(); let actual_type = param_value.value_type();
let expected_type = (*param_type).into(); if actual_type != 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)));
} }

View File

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