Next Generation WASM Microkernel Operating System
at trap_handler 109 lines 4.0 kB view raw
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}