11use super :: create_handle:: create_handle;
22use crate :: trampoline:: StoreInstanceHandle ;
33use crate :: { GlobalType , Mutability , Store , Val } ;
4- use anyhow:: { bail , Result } ;
4+ use anyhow:: Result ;
55use wasmtime_environ:: entity:: PrimaryMap ;
66use wasmtime_environ:: { wasm, EntityIndex , Module } ;
7+ use wasmtime_runtime:: VMFunctionImport ;
78
89pub fn create_global ( store : & Store , gt : & GlobalType , val : Val ) -> Result < StoreInstanceHandle > {
10+ let mut module = Module :: new ( ) ;
11+ let mut func_imports = PrimaryMap :: new ( ) ;
12+ let mut externref_init = None ;
13+
914 let global = wasm:: Global {
1015 wasm_ty : gt. content ( ) . to_wasm_type ( ) ,
11- ty : match gt. content ( ) . get_wasmtime_type ( ) {
12- Some ( t) => t,
13- None => bail ! ( "cannot support {:?} as a wasm global type" , gt. content( ) ) ,
14- } ,
16+ ty : gt. content ( ) . get_wasmtime_type ( ) ,
1517 mutability : match gt. mutability ( ) {
1618 Mutability :: Const => false ,
1719 Mutability :: Var => true ,
@@ -21,10 +23,42 @@ pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreIn
2123 Val :: I64 ( i) => wasm:: GlobalInit :: I64Const ( i) ,
2224 Val :: F32 ( f) => wasm:: GlobalInit :: F32Const ( f) ,
2325 Val :: F64 ( f) => wasm:: GlobalInit :: F64Const ( f) ,
26+ Val :: ExternRef ( None ) | Val :: FuncRef ( None ) => wasm:: GlobalInit :: RefNullConst ,
27+ Val :: ExternRef ( Some ( x) ) => {
28+ // There is no `GlobalInit` variant for using an existing
29+ // `externref` that isn't an import (because Wasm can't create
30+ // an `externref` by itself). Therefore, initialize the global
31+ // as null, and then monkey patch it after instantiation below.
32+ externref_init = Some ( x) ;
33+ wasm:: GlobalInit :: RefNullConst
34+ }
35+ Val :: FuncRef ( Some ( f) ) => {
36+ // Add a function import to the stub module, and then initialize
37+ // our global with a `ref.func` to grab that imported function.
38+ let shared_sig_index = f. sig_index ( ) ;
39+ let local_sig_index = module
40+ . local
41+ . signatures
42+ . push ( store. lookup_wasm_and_native_signatures ( shared_sig_index) ) ;
43+ let func_index = module. local . functions . push ( local_sig_index) ;
44+ module. local . num_imported_funcs = 1 ;
45+ module
46+ . imports
47+ . push ( ( "" . into ( ) , "" . into ( ) , EntityIndex :: Function ( func_index) ) ) ;
48+
49+ let f = f. caller_checked_anyfunc ( ) ;
50+ let f = unsafe { f. as_ref ( ) } ;
51+ func_imports. push ( VMFunctionImport {
52+ body : f. func_ptr ,
53+ vmctx : f. vmctx ,
54+ } ) ;
55+
56+ wasm:: GlobalInit :: RefFunc ( func_index)
57+ }
2458 _ => unimplemented ! ( "create_global for {:?}" , gt) ,
2559 } ,
2660 } ;
27- let mut module = Module :: new ( ) ;
61+
2862 let global_id = module. local . globals . push ( global) ;
2963 module
3064 . exports
@@ -35,6 +69,17 @@ pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreIn
3569 PrimaryMap :: new ( ) ,
3670 Default :: default ( ) ,
3771 Box :: new ( ( ) ) ,
72+ func_imports,
3873 ) ?;
74+
75+ if let Some ( x) = externref_init {
76+ match handle. lookup ( "global" ) . unwrap ( ) {
77+ wasmtime_runtime:: Export :: Global ( g) => unsafe {
78+ * ( * g. definition ) . as_externref_mut ( ) = Some ( x. inner ) ;
79+ } ,
80+ _ => unreachable ! ( ) ,
81+ }
82+ }
83+
3984 Ok ( handle)
4085}
0 commit comments