Next Generation WASM Microkernel Operating System
1// Copyright 2025 Jonas Kruckenberg
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::wasm::Func;
9use crate::wasm::store::{StoreOpaque, Stored};
10use crate::wasm::types::{GlobalType, HeapTypeInner, Mutability, ValType};
11use crate::wasm::values::{Ref, Val};
12use crate::wasm::vm::{ExportedGlobal, VMGlobalDefinition, VMGlobalImport, VmPtr};
13use anyhow::{Context, bail};
14use core::ptr;
15use core::ptr::NonNull;
16
17#[derive(Clone, Copy, Debug)]
18pub struct Global(Stored<ExportedGlobal>);
19
20impl Global {
21 pub fn new(store: &mut StoreOpaque, ty: GlobalType, val: Val) -> crate::Result<Self> {
22 val.ensure_matches_ty(store, ty.content())?;
23
24 // Safety: we checked above that the types match
25 let definition = unsafe {
26 let vmval = val.to_vmval(store)?;
27
28 let def = VMGlobalDefinition::from_vmval(store, ty.content().to_wasm_type(), vmval)?;
29 store.add_host_global(def)
30 };
31
32 let stored = store.add_global(ExportedGlobal {
33 definition,
34 vmctx: None,
35 global: ty.to_wasm_global(),
36 });
37 Ok(Self(stored))
38 }
39
40 pub fn ty(self, store: &StoreOpaque) -> GlobalType {
41 let export = &store[self.0];
42 GlobalType::from_wasm_global(store.engine(), &export.global)
43 }
44
45 pub fn get(&self, store: &mut StoreOpaque) -> Val {
46 // Safety: TODO
47 unsafe {
48 let export = &store[self.0];
49 let def = export.definition.as_ref();
50
51 match self.ty(store).content() {
52 ValType::I32 => Val::I32(*def.as_i32()),
53 ValType::I64 => Val::I64(*def.as_i64()),
54 ValType::F32 => Val::F32(*def.as_u32()),
55 ValType::F64 => Val::F64(*def.as_u64()),
56 ValType::V128 => Val::V128(def.get_u128()),
57 ValType::Ref(ref_ty) => {
58 let reference: Ref = match ref_ty.heap_type().inner {
59 HeapTypeInner::Func | HeapTypeInner::ConcreteFunc(_) => {
60 Func::from_vm_func_ref(store, NonNull::new(def.as_func_ref()).unwrap())
61 .into()
62 }
63 HeapTypeInner::NoFunc => Ref::Func(None),
64 _ => todo!(),
65 };
66 reference.into()
67 }
68 }
69 }
70 }
71
72 pub fn set(&self, store: &mut StoreOpaque, val: Val) -> crate::Result<()> {
73 let global_ty = self.ty(store);
74 if global_ty.mutability() != Mutability::Var {
75 bail!("immutable global cannot be set");
76 }
77 val.ensure_matches_ty(store, global_ty.content())
78 .context("type mismatch: attempt to set global to value of wrong type")?;
79
80 // Safety: TODO
81 unsafe {
82 let def = store[self.0].definition.as_mut();
83 match val {
84 Val::I32(i) => *def.as_i32_mut() = i,
85 Val::I64(i) => *def.as_i64_mut() = i,
86 Val::F32(f) => *def.as_u32_mut() = f,
87 Val::F64(f) => *def.as_u64_mut() = f,
88 Val::V128(i) => def.set_u128(i),
89 Val::FuncRef(f) => {
90 *def.as_func_ref_mut() =
91 f.map_or(ptr::null_mut(), |f| f.vm_func_ref(store).as_ptr());
92 }
93 }
94 }
95
96 Ok(())
97 }
98
99 pub(super) fn from_exported_global(store: &mut StoreOpaque, export: ExportedGlobal) -> Self {
100 let stored = store.add_global(export);
101 Self(stored)
102 }
103 pub(super) fn as_vmglobal_import(self, store: &mut StoreOpaque) -> VMGlobalImport {
104 let export = &store[self.0];
105 VMGlobalImport {
106 from: VmPtr::from(export.definition),
107 }
108 }
109}