1use crate::{
2 WasmtimeStoreContext, WasmtimeStoreContextMut, handle_result, wasm_extern_t, wasm_globaltype_t,
3 wasm_store_t, wasm_val_t, wasmtime_error_t, wasmtime_val_t,
4};
5use std::mem::MaybeUninit;
6#[cfg(feature = "gc")]
7use wasmtime::RootScope;
8use wasmtime::{Extern, Global};
9
10#[derive(Clone)]
11#[repr(transparent)]
12pub struct wasm_global_t {
13 ext: wasm_extern_t,
14}
15
16wasmtime_c_api_macros::declare_ref!(wasm_global_t);
17
18impl wasm_global_t {
19 pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_global_t> {
20 match &e.which {
21 Extern::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }),
22 _ => None,
23 }
24 }
25
26 fn global(&self) -> Global {
27 match self.ext.which {
28 Extern::Global(g) => g,
29 _ => unsafe { std::hint::unreachable_unchecked() },
30 }
31 }
32}
33
34#[unsafe(no_mangle)]
35pub unsafe extern "C" fn wasm_global_new(
36 store: &mut wasm_store_t,
37 gt: &wasm_globaltype_t,
38 val: &wasm_val_t,
39) -> Option<Box<wasm_global_t>> {
40 match Global::new(store.store.context_mut(), gt.ty().ty.clone(), val.val()) {
41 Ok(global) => Some(Box::new(wasm_global_t {
42 ext: wasm_extern_t {
43 store: store.store.clone(),
44 which: global.into(),
45 },
46 })),
47 Err(_) => None,
48 }
49}
50
51#[unsafe(no_mangle)]
52pub extern "C" fn wasm_global_as_extern(g: &mut wasm_global_t) -> &mut wasm_extern_t {
53 &mut g.ext
54}
55
56#[unsafe(no_mangle)]
57pub extern "C" fn wasm_global_as_extern_const(g: &wasm_global_t) -> &wasm_extern_t {
58 &g.ext
59}
60
61#[unsafe(no_mangle)]
62pub unsafe extern "C" fn wasm_global_type(g: &wasm_global_t) -> Box<wasm_globaltype_t> {
63 let globaltype = g.global().ty(&g.ext.store.context());
64 Box::new(wasm_globaltype_t::new(globaltype))
65}
66
67#[unsafe(no_mangle)]
68pub unsafe extern "C" fn wasm_global_get(g: &mut wasm_global_t, out: &mut MaybeUninit<wasm_val_t>) {
69 let global = g.global();
70 out.write(wasm_val_t::from_val(global.get(g.ext.store.context_mut())));
71}
72
73#[unsafe(no_mangle)]
74pub unsafe extern "C" fn wasm_global_set(g: &mut wasm_global_t, val: &wasm_val_t) {
75 let global = g.global();
76 drop(global.set(g.ext.store.context_mut(), val.val()));
77}
78
79#[unsafe(no_mangle)]
80pub unsafe extern "C" fn wasmtime_global_new(
81 mut store: WasmtimeStoreContextMut<'_>,
82 gt: &wasm_globaltype_t,
83 val: &wasmtime_val_t,
84 ret: &mut Global,
85) -> Option<Box<wasmtime_error_t>> {
86 #[cfg(feature = "gc")]
87 let mut store = RootScope::new(&mut store);
88
89 let val = val.to_val(&mut store);
90 let global = Global::new(&mut store, gt.ty().ty.clone(), val);
91 handle_result(global, |global| {
92 *ret = global;
93 })
94}
95
96#[unsafe(no_mangle)]
97pub extern "C" fn wasmtime_global_type(
98 store: WasmtimeStoreContext<'_>,
99 global: &Global,
100) -> Box<wasm_globaltype_t> {
101 Box::new(wasm_globaltype_t::new(global.ty(store)))
102}
103
104#[unsafe(no_mangle)]
105pub extern "C" fn wasmtime_global_get(
106 store: WasmtimeStoreContextMut<'_>,
107 global: &Global,
108 val: &mut MaybeUninit<wasmtime_val_t>,
109) {
110 let mut store = store;
111
112 #[cfg(feature = "gc")]
113 let mut store = RootScope::new(&mut store);
114
115 let gval = global.get(&mut store);
116 val.write(wasmtime_val_t::from_val(&mut store, gval));
117}
118
119#[unsafe(no_mangle)]
120pub unsafe extern "C" fn wasmtime_global_set(
121 mut store: WasmtimeStoreContextMut<'_>,
122 global: &Global,
123 val: &wasmtime_val_t,
124) -> Option<Box<wasmtime_error_t>> {
125 #[cfg(feature = "gc")]
126 let mut store = RootScope::new(&mut store);
127
128 let val = val.to_val(&mut store);
129 handle_result(global.set(&mut store, val), |()| {})
130}