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