wasmi_c_api/global.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
use crate::{wasm_extern_t, wasm_globaltype_t, wasm_store_t, wasm_val_t};
use alloc::boxed::Box;
use core::{hint, mem::MaybeUninit};
use wasmi::{Extern, Global};
/// A Wasm global variable.
///
/// Wraps [`Global`].
#[derive(Clone)]
#[repr(transparent)]
pub struct wasm_global_t {
inner: wasm_extern_t,
}
wasmi_c_api_macros::declare_ref!(wasm_global_t);
impl wasm_global_t {
pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_global_t> {
match &e.which {
Extern::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }),
_ => None,
}
}
pub(crate) fn try_from_mut(e: &mut wasm_extern_t) -> Option<&mut wasm_global_t> {
match &mut e.which {
Extern::Global(_) => Some(unsafe { &mut *(e as *mut _ as *mut _) }),
_ => None,
}
}
/// Returns the underlying [`Global`] of the [`wasm_global_t`].
fn global(&self) -> Global {
match self.inner.which {
Extern::Global(g) => g,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
/// Creates a new [`wasm_global_t`] from the given [`wasm_globaltype_t`] and [`wasm_val_t`].
///
/// Returns a `null` pointer if `ty` and `val` does not match.
///
/// Wraps [`Global::new`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_global_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_global_new(
store: &mut wasm_store_t,
ty: &wasm_globaltype_t,
val: &wasm_val_t,
) -> Option<Box<wasm_global_t>> {
let val = val.to_val();
let ty = ty.ty().ty;
if val.ty() != ty.content() {
return None;
}
let global = Global::new(store.inner.context_mut(), val, ty.mutability());
Some(Box::new(wasm_global_t {
inner: wasm_extern_t {
store: store.inner.clone(),
which: global.into(),
},
}))
}
/// Returns the [`wasm_global_t`] as mutable reference to [`wasm_extern_t`].
#[no_mangle]
pub extern "C" fn wasm_global_as_extern(g: &mut wasm_global_t) -> &mut wasm_extern_t {
&mut g.inner
}
/// Returns the [`wasm_global_t`] as shared reference to [`wasm_extern_t`].
#[no_mangle]
pub extern "C" fn wasm_global_as_extern_const(g: &wasm_global_t) -> &wasm_extern_t {
&g.inner
}
/// Returns the [`wasm_globaltype_t`] of the [`wasm_global_t`].
///
/// Wraps [`Global::ty`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_global_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_global_type(g: &wasm_global_t) -> Box<wasm_globaltype_t> {
let globaltype = g.global().ty(g.inner.store.context());
Box::new(wasm_globaltype_t::new(globaltype))
}
/// Returns the current value of the [`wasm_global_t`].
///
/// Wraps [`Global::get`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_global_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_global_get(g: &mut wasm_global_t, out: &mut MaybeUninit<wasm_val_t>) {
let global = g.global();
crate::initialize(
out,
wasm_val_t::from(global.get(g.inner.store.context_mut())),
);
}
/// Sets the current value of the [`wasm_global_t`].
///
/// Wraps [`Global::set`].
///
/// # Safety
///
/// - It is the caller's responsibility that `val` matches the type of `g`.
/// - It is the caller's responsibility not to alias the [`wasm_global_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_global_set(g: &mut wasm_global_t, val: &wasm_val_t) {
let global = g.global();
drop(global.set(g.inner.store.context_mut(), val.to_val()));
}