wasmer_runtime_core_x/
global.rs

1//! The global module contains data structures and helper functions used to
2//! manipulate and access Wasm globals.
3use crate::{
4    export::Export,
5    import::IsExport,
6    types::{GlobalDescriptor, Type, Value},
7    vm,
8};
9use std::{
10    fmt,
11    sync::{Arc, Mutex},
12};
13
14/// A handle to a Wasm Global
15pub struct Global {
16    desc: GlobalDescriptor,
17    storage: Arc<Mutex<vm::LocalGlobal>>,
18}
19
20impl Global {
21    /// Create a new `Global` value.
22    ///
23    /// Usage:
24    ///
25    /// ```
26    /// # use wasmer_runtime_core::global::Global;
27    /// # use wasmer_runtime_core::types::Value;
28    /// let global = Global::new(Value::I32(42));
29    /// ```
30    pub fn new(value: Value) -> Self {
31        Self::new_internal(value, false)
32    }
33
34    /// Create a new, mutable `Global` value.
35    ///
36    /// Usage:
37    ///
38    /// ```
39    /// # use wasmer_runtime_core::global::Global;
40    /// # use wasmer_runtime_core::types::Value;
41    /// let global = Global::new_mutable(Value::I32(42));
42    /// ```
43    pub fn new_mutable(value: Value) -> Self {
44        Self::new_internal(value, true)
45    }
46
47    fn new_internal(value: Value, mutable: bool) -> Self {
48        let desc = GlobalDescriptor {
49            mutable,
50            ty: value.ty(),
51        };
52
53        let local_global = vm::LocalGlobal {
54            data: match value {
55                Value::I32(x) => x as u128,
56                Value::I64(x) => x as u128,
57                Value::F32(x) => x.to_bits() as u128,
58                Value::F64(x) => x.to_bits() as u128,
59                Value::V128(x) => x,
60            },
61        };
62
63        Self {
64            desc,
65            storage: Arc::new(Mutex::new(local_global)),
66        }
67    }
68
69    /// Get the [`GlobalDescriptor`] generated for this global.
70    ///
71    /// [`GlobalDescriptor`]: struct.GlobalDescriptor.html
72    pub fn descriptor(&self) -> GlobalDescriptor {
73        self.desc
74    }
75
76    /// Set the value help by this global.
77    ///
78    /// This method will panic if the value is
79    /// the wrong type.
80    pub fn set(&self, value: Value) {
81        if self.desc.mutable {
82            if self.desc.ty == value.ty() {
83                let local_global = vm::LocalGlobal {
84                    data: match value {
85                        Value::I32(x) => x as u128,
86                        Value::I64(x) => x as u128,
87                        Value::F32(x) => x.to_bits() as u128,
88                        Value::F64(x) => x.to_bits() as u128,
89                        Value::V128(x) => x,
90                    },
91                };
92                let mut storage = self.storage.lock().unwrap();
93                *storage = local_global;
94            } else {
95                panic!("Wrong type for setting this global")
96            }
97        } else {
98            panic!("Cannot modify global immutable by default")
99        }
100    }
101
102    /// Get the value held by this global.
103    pub fn get(&self) -> Value {
104        let storage = self.storage.lock().unwrap();
105        let data = storage.data;
106
107        match self.desc.ty {
108            Type::I32 => Value::I32(data as i32),
109            Type::I64 => Value::I64(data as i64),
110            Type::F32 => Value::F32(f32::from_bits(data as u32)),
111            Type::F64 => Value::F64(f64::from_bits(data as u64)),
112            Type::V128 => Value::V128(data),
113        }
114    }
115
116    // TODO: think about this and if this should now be unsafe
117    pub(crate) fn vm_local_global(&mut self) -> *mut vm::LocalGlobal {
118        let mut storage = self.storage.lock().unwrap();
119        &mut *storage
120    }
121}
122
123impl IsExport for Global {
124    fn to_export(&self) -> Export {
125        Export::Global(self.clone())
126    }
127}
128
129impl Clone for Global {
130    fn clone(&self) -> Self {
131        Self {
132            desc: self.desc,
133            storage: Arc::clone(&self.storage),
134        }
135    }
136}
137
138impl fmt::Debug for Global {
139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140        f.debug_struct("Global")
141            .field("desc", &self.desc)
142            .field("value", &self.get())
143            .finish()
144    }
145}