2019-01-28 18:59:05 +00:00
|
|
|
use crate::{
|
2019-01-28 19:55:44 +00:00
|
|
|
export::Export,
|
|
|
|
import::IsExport,
|
2019-01-29 21:04:42 +00:00
|
|
|
types::{GlobalDescriptor, Type, Value},
|
2019-01-28 18:59:05 +00:00
|
|
|
vm,
|
|
|
|
};
|
2019-01-28 19:55:44 +00:00
|
|
|
use std::{cell::RefCell, fmt, rc::Rc};
|
2019-01-28 18:59:05 +00:00
|
|
|
|
|
|
|
pub struct Global {
|
2019-01-29 21:04:42 +00:00
|
|
|
desc: GlobalDescriptor,
|
2019-01-28 19:02:53 +00:00
|
|
|
storage: Rc<RefCell<vm::LocalGlobal>>,
|
2019-01-28 18:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Global {
|
|
|
|
pub fn new(value: Value) -> Self {
|
2019-01-29 20:49:51 +00:00
|
|
|
Self::new_internal(value, false)
|
2019-01-28 18:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_mutable(value: Value) -> Self {
|
2019-01-29 20:49:51 +00:00
|
|
|
Self::new_internal(value, true)
|
2019-01-28 18:59:05 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 20:49:51 +00:00
|
|
|
fn new_internal(value: Value, mutable: bool) -> Self {
|
2019-01-29 21:04:42 +00:00
|
|
|
let desc = GlobalDescriptor {
|
2019-01-28 18:59:05 +00:00
|
|
|
mutable,
|
|
|
|
ty: value.ty(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let local_global = vm::LocalGlobal {
|
|
|
|
data: match value {
|
|
|
|
Value::I32(x) => x as u64,
|
|
|
|
Value::I64(x) => x as u64,
|
|
|
|
Value::F32(x) => x.to_bits() as u64,
|
|
|
|
Value::F64(x) => x.to_bits(),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
Self {
|
|
|
|
desc,
|
2019-01-28 19:55:44 +00:00
|
|
|
storage: Rc::new(RefCell::new(local_global)),
|
2019-01-28 18:59:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-29 21:04:42 +00:00
|
|
|
pub fn descriptor(&self) -> GlobalDescriptor {
|
2019-01-28 18:59:05 +00:00
|
|
|
self.desc
|
|
|
|
}
|
|
|
|
|
2019-01-28 19:02:53 +00:00
|
|
|
pub fn set(&self, value: Value) {
|
2019-01-28 18:59:05 +00:00
|
|
|
if self.desc.mutable {
|
|
|
|
if self.desc.ty == value.ty() {
|
|
|
|
let local_global = vm::LocalGlobal {
|
|
|
|
data: match value {
|
|
|
|
Value::I32(x) => x as u64,
|
|
|
|
Value::I64(x) => x as u64,
|
|
|
|
Value::F32(x) => x.to_bits() as u64,
|
|
|
|
Value::F64(x) => x.to_bits(),
|
|
|
|
},
|
|
|
|
};
|
2019-01-28 19:02:53 +00:00
|
|
|
*self.storage.borrow_mut() = local_global;
|
2019-01-28 18:59:05 +00:00
|
|
|
} else {
|
|
|
|
panic!("Wrong type for setting this global")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
panic!("Cannot modify global immutable by default")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(&self) -> Value {
|
2019-01-28 19:02:53 +00:00
|
|
|
let data = self.storage.borrow().data;
|
2019-01-28 18:59:05 +00:00
|
|
|
|
|
|
|
match self.desc.ty {
|
|
|
|
Type::I32 => Value::I32(data as i32),
|
|
|
|
Type::I64 => Value::I64(data as i64),
|
|
|
|
Type::F32 => Value::F32(f32::from_bits(data as u32)),
|
|
|
|
Type::F64 => Value::F64(f64::from_bits(data)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn vm_local_global(&mut self) -> *mut vm::LocalGlobal {
|
2019-01-28 19:02:53 +00:00
|
|
|
&mut *self.storage.borrow_mut()
|
2019-01-28 18:59:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 19:55:44 +00:00
|
|
|
impl IsExport for Global {
|
|
|
|
fn to_export(&mut self) -> Export {
|
|
|
|
Export::Global(self.clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 18:59:05 +00:00
|
|
|
impl Clone for Global {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
desc: self.desc,
|
|
|
|
storage: Rc::clone(&self.storage),
|
|
|
|
}
|
|
|
|
}
|
2019-01-28 19:55:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for Global {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
f.debug_struct("Global")
|
|
|
|
.field("desc", &self.desc)
|
|
|
|
.field("value", &self.get())
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|