wasmtime/runtime/trampoline/
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
use crate::runtime::vm::{StoreBox, VMGlobalDefinition};
use crate::store::{AutoAssertNoGc, StoreOpaque};
use crate::{GlobalType, Mutability, Result, RootedGcRefImpl, Val};
use core::ptr::{self, NonNull};

#[repr(C)]
pub struct VMHostGlobalContext {
    pub(crate) ty: GlobalType,
    pub(crate) global: VMGlobalDefinition,
}

pub fn generate_global_export(
    store: &mut StoreOpaque,
    ty: GlobalType,
    val: Val,
) -> Result<crate::runtime::vm::ExportGlobal> {
    let global = wasmtime_environ::Global {
        wasm_ty: ty.content().to_wasm_type(),
        mutability: match ty.mutability() {
            Mutability::Const => false,
            Mutability::Var => true,
        },
    };
    let ctx = StoreBox::new(VMHostGlobalContext {
        ty,
        global: VMGlobalDefinition::new(),
    });

    let mut store = AutoAssertNoGc::new(store);
    let definition = unsafe {
        let global = &mut ctx.get().as_mut().global;
        match val {
            Val::I32(x) => *global.as_i32_mut() = x,
            Val::I64(x) => *global.as_i64_mut() = x,
            Val::F32(x) => *global.as_f32_bits_mut() = x,
            Val::F64(x) => *global.as_f64_bits_mut() = x,
            Val::V128(x) => global.set_u128(x.into()),
            Val::FuncRef(f) => {
                *global.as_func_ref_mut() =
                    f.map_or(ptr::null_mut(), |f| f.vm_func_ref(&mut store).as_ptr());
            }
            Val::ExternRef(x) => {
                let new = match x {
                    None => None,
                    #[cfg_attr(not(feature = "gc"), allow(unreachable_patterns))]
                    Some(x) => Some(x.try_gc_ref(&store)?.unchecked_copy()),
                };
                let new = new.as_ref();
                global.write_gc_ref(store.gc_store_mut()?, new);
            }
            Val::AnyRef(a) => {
                let new = match a {
                    None => None,
                    #[cfg_attr(not(feature = "gc"), allow(unreachable_patterns))]
                    Some(a) => Some(a.try_gc_ref(&store)?.unchecked_copy()),
                };
                let new = new.as_ref();
                global.write_gc_ref(store.gc_store_mut()?, new);
            }
        }
        global
    };

    store.host_globals().push(ctx);
    Ok(crate::runtime::vm::ExportGlobal {
        definition: NonNull::from(definition),
        vmctx: None,
        global,
    })
}