wasmtime/trampoline/
global.rs

1use crate::store::{InstanceId, StoreOpaque};
2use crate::trampoline::create_handle;
3use crate::{GlobalType, Mutability, Val};
4use anyhow::Result;
5use wasmtime_environ::{
6    AnyfuncIndex, EntityIndex, Global, GlobalInit, Module, ModuleType, SignatureIndex,
7};
8use wasmtime_runtime::VMFunctionImport;
9
10pub fn create_global(store: &mut StoreOpaque, gt: &GlobalType, val: Val) -> Result<InstanceId> {
11    let mut module = Module::new();
12    let mut func_imports = Vec::new();
13    let mut externref_init = None;
14    let mut one_signature = None;
15
16    let global = Global {
17        wasm_ty: gt.content().to_wasm_type(),
18        mutability: match gt.mutability() {
19            Mutability::Const => false,
20            Mutability::Var => true,
21        },
22        initializer: match val {
23            Val::I32(i) => GlobalInit::I32Const(i),
24            Val::I64(i) => GlobalInit::I64Const(i),
25            Val::F32(f) => GlobalInit::F32Const(f),
26            Val::F64(f) => GlobalInit::F64Const(f),
27            Val::V128(i) => GlobalInit::V128Const(i.into()),
28            Val::ExternRef(None) | Val::FuncRef(None) => GlobalInit::RefNullConst,
29            Val::ExternRef(Some(x)) => {
30                // There is no `GlobalInit` variant for using an existing
31                // `externref` that isn't an import (because Wasm can't create
32                // an `externref` by itself). Therefore, initialize the global
33                // as null, and then monkey patch it after instantiation below.
34                externref_init = Some(x);
35                GlobalInit::RefNullConst
36            }
37            Val::FuncRef(Some(f)) => {
38                // Add a function import to the stub module, and then initialize
39                // our global with a `ref.func` to grab that imported function.
40                let f = f.caller_checked_anyfunc(store);
41                let f = unsafe { f.as_ref() };
42                let sig_id = SignatureIndex::from_u32(0);
43                one_signature = Some(f.type_index);
44                module.types.push(ModuleType::Function(sig_id));
45                let func_index = module.push_escaped_function(sig_id, AnyfuncIndex::from_u32(0));
46                module.num_imported_funcs = 1;
47                module.num_escaped_funcs = 1;
48                module
49                    .initializers
50                    .push(wasmtime_environ::Initializer::Import {
51                        name: "".into(),
52                        field: "".into(),
53                        index: EntityIndex::Function(func_index),
54                    });
55
56                func_imports.push(VMFunctionImport {
57                    body: f.func_ptr,
58                    vmctx: f.vmctx,
59                });
60
61                GlobalInit::RefFunc(func_index)
62            }
63        },
64    };
65
66    let global_id = module.globals.push(global);
67    module
68        .exports
69        .insert(String::new(), EntityIndex::Global(global_id));
70    let id = create_handle(module, store, Box::new(()), &func_imports, one_signature)?;
71
72    if let Some(x) = externref_init {
73        let instance = store.instance_mut(id);
74        let g = instance.get_exported_global(global_id);
75        unsafe {
76            *(*g.definition).as_externref_mut() = Some(x.inner);
77        }
78    }
79
80    Ok(id)
81}