Struct wasmtime::GlobalType

source ·
pub struct GlobalType { /* private fields */ }
Expand description

A WebAssembly global descriptor.

This type describes an instance of a global in a WebAssembly module. Globals are local to an Instance and are either immutable or mutable.

Implementations§

Creates a new global descriptor of the specified content type and whether or not it’s mutable.

Examples found in repository?
src/types.rs (line 273)
266
267
268
269
270
271
272
273
274
    pub(crate) fn from_wasmtime_global(global: &Global) -> GlobalType {
        let ty = ValType::from_wasm_type(&global.wasm_ty);
        let mutability = if global.mutability {
            Mutability::Var
        } else {
            Mutability::Const
        };
        GlobalType::new(ty, mutability)
    }

Returns the value type of this global descriptor.

Examples found in repository?
src/externals.rs (line 252)
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    fn _new(store: &mut StoreOpaque, ty: GlobalType, val: Val) -> Result<Global> {
        if !val.comes_from_same_store(store) {
            bail!("cross-`Store` globals are not supported");
        }
        if val.ty() != *ty.content() {
            bail!("value provided does not match the type of this global");
        }
        unsafe {
            let wasmtime_export = generate_global_export(store, &ty, val)?;
            Ok(Global::from_wasmtime_global(wasmtime_export, store))
        }
    }

    /// Returns the underlying type of this `global`.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this global.
    pub fn ty(&self, store: impl AsContext) -> GlobalType {
        let store = store.as_context();
        let ty = &store[self.0].global;
        GlobalType::from_wasmtime_global(&ty)
    }

    /// Returns the current [`Val`] of this global.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this global.
    pub fn get(&self, mut store: impl AsContextMut) -> Val {
        unsafe {
            let store = store.as_context_mut();
            let definition = &*store[self.0].definition;
            match self.ty(&store).content() {
                ValType::I32 => Val::from(*definition.as_i32()),
                ValType::I64 => Val::from(*definition.as_i64()),
                ValType::F32 => Val::F32(*definition.as_u32()),
                ValType::F64 => Val::F64(*definition.as_u64()),
                ValType::ExternRef => Val::ExternRef(
                    definition
                        .as_externref()
                        .clone()
                        .map(|inner| ExternRef { inner }),
                ),
                ValType::FuncRef => {
                    Val::FuncRef(Func::from_raw(store, definition.as_anyfunc() as usize))
                }
                ValType::V128 => Val::V128(*definition.as_u128()),
            }
        }
    }

    /// Attempts to set the current value of this global to [`Val`].
    ///
    /// # Errors
    ///
    /// Returns an error if this global has a different type than `Val`, if
    /// it's not a mutable global, or if `val` comes from a different store than
    /// the one provided.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this global.
    pub fn set(&self, mut store: impl AsContextMut, val: Val) -> Result<()> {
        let store = store.as_context_mut().0;
        let ty = self.ty(&store);
        if ty.mutability() != Mutability::Var {
            bail!("immutable global cannot be set");
        }
        let ty = ty.content();
        if val.ty() != *ty {
            bail!("global of type {:?} cannot be set to {:?}", ty, val.ty());
        }
        if !val.comes_from_same_store(store) {
            bail!("cross-`Store` values are not supported");
        }
        unsafe {
            let definition = &mut *store[self.0].definition;
            match val {
                Val::I32(i) => *definition.as_i32_mut() = i,
                Val::I64(i) => *definition.as_i64_mut() = i,
                Val::F32(f) => *definition.as_u32_mut() = f,
                Val::F64(f) => *definition.as_u64_mut() = f,
                Val::FuncRef(f) => {
                    *definition.as_anyfunc_mut() = f.map_or(ptr::null(), |f| {
                        f.caller_checked_anyfunc(store).as_ptr().cast()
                    });
                }
                Val::ExternRef(x) => {
                    let old = mem::replace(definition.as_externref_mut(), x.map(|x| x.inner));
                    drop(old);
                }
                Val::V128(i) => *definition.as_u128_mut() = i,
            }
        }
        Ok(())
    }
More examples
Hide additional examples
src/trampoline/global.rs (line 17)
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
71
72
73
74
75
76
77
78
79
80
81
pub fn create_global(store: &mut StoreOpaque, gt: &GlobalType, val: Val) -> Result<InstanceId> {
    let mut module = Module::new();
    let mut func_imports = Vec::new();
    let mut externref_init = None;
    let mut one_signature = None;

    let global = Global {
        wasm_ty: gt.content().to_wasm_type(),
        mutability: match gt.mutability() {
            Mutability::Const => false,
            Mutability::Var => true,
        },
        initializer: match val {
            Val::I32(i) => GlobalInit::I32Const(i),
            Val::I64(i) => GlobalInit::I64Const(i),
            Val::F32(f) => GlobalInit::F32Const(f),
            Val::F64(f) => GlobalInit::F64Const(f),
            Val::V128(i) => GlobalInit::V128Const(i.into()),
            Val::ExternRef(None) | Val::FuncRef(None) => GlobalInit::RefNullConst,
            Val::ExternRef(Some(x)) => {
                // There is no `GlobalInit` variant for using an existing
                // `externref` that isn't an import (because Wasm can't create
                // an `externref` by itself). Therefore, initialize the global
                // as null, and then monkey patch it after instantiation below.
                externref_init = Some(x);
                GlobalInit::RefNullConst
            }
            Val::FuncRef(Some(f)) => {
                // Add a function import to the stub module, and then initialize
                // our global with a `ref.func` to grab that imported function.
                let f = f.caller_checked_anyfunc(store);
                let f = unsafe { f.as_ref() };
                let sig_id = SignatureIndex::from_u32(0);
                one_signature = Some(f.type_index);
                module.types.push(ModuleType::Function(sig_id));
                let func_index = module.push_escaped_function(sig_id, AnyfuncIndex::from_u32(0));
                module.num_imported_funcs = 1;
                module.num_escaped_funcs = 1;
                module
                    .initializers
                    .push(wasmtime_environ::Initializer::Import {
                        name: "".into(),
                        field: "".into(),
                        index: EntityIndex::Function(func_index),
                    });

                func_imports.push(VMFunctionImport {
                    body: f.func_ptr,
                    vmctx: f.vmctx,
                });

                GlobalInit::RefFunc(func_index)
            }
        },
    };

    let global_id = module.globals.push(global);
    module
        .exports
        .insert(String::new(), EntityIndex::Global(global_id));
    let id = create_handle(module, store, Box::new(()), &func_imports, one_signature)?;

    if let Some(x) = externref_init {
        let instance = store.instance_mut(id);
        let g = instance.get_exported_global(global_id);
        unsafe {
            *(*g.definition).as_externref_mut() = Some(x.inner);
        }
    }

    Ok(id)
}

Returns whether or not this global is mutable.

Examples found in repository?
src/externals.rs (line 314)
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    pub fn set(&self, mut store: impl AsContextMut, val: Val) -> Result<()> {
        let store = store.as_context_mut().0;
        let ty = self.ty(&store);
        if ty.mutability() != Mutability::Var {
            bail!("immutable global cannot be set");
        }
        let ty = ty.content();
        if val.ty() != *ty {
            bail!("global of type {:?} cannot be set to {:?}", ty, val.ty());
        }
        if !val.comes_from_same_store(store) {
            bail!("cross-`Store` values are not supported");
        }
        unsafe {
            let definition = &mut *store[self.0].definition;
            match val {
                Val::I32(i) => *definition.as_i32_mut() = i,
                Val::I64(i) => *definition.as_i64_mut() = i,
                Val::F32(f) => *definition.as_u32_mut() = f,
                Val::F64(f) => *definition.as_u64_mut() = f,
                Val::FuncRef(f) => {
                    *definition.as_anyfunc_mut() = f.map_or(ptr::null(), |f| {
                        f.caller_checked_anyfunc(store).as_ptr().cast()
                    });
                }
                Val::ExternRef(x) => {
                    let old = mem::replace(definition.as_externref_mut(), x.map(|x| x.inner));
                    drop(old);
                }
                Val::V128(i) => *definition.as_u128_mut() = i,
            }
        }
        Ok(())
    }
More examples
Hide additional examples
src/trampoline/global.rs (line 18)
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
71
72
73
74
75
76
77
78
79
80
81
pub fn create_global(store: &mut StoreOpaque, gt: &GlobalType, val: Val) -> Result<InstanceId> {
    let mut module = Module::new();
    let mut func_imports = Vec::new();
    let mut externref_init = None;
    let mut one_signature = None;

    let global = Global {
        wasm_ty: gt.content().to_wasm_type(),
        mutability: match gt.mutability() {
            Mutability::Const => false,
            Mutability::Var => true,
        },
        initializer: match val {
            Val::I32(i) => GlobalInit::I32Const(i),
            Val::I64(i) => GlobalInit::I64Const(i),
            Val::F32(f) => GlobalInit::F32Const(f),
            Val::F64(f) => GlobalInit::F64Const(f),
            Val::V128(i) => GlobalInit::V128Const(i.into()),
            Val::ExternRef(None) | Val::FuncRef(None) => GlobalInit::RefNullConst,
            Val::ExternRef(Some(x)) => {
                // There is no `GlobalInit` variant for using an existing
                // `externref` that isn't an import (because Wasm can't create
                // an `externref` by itself). Therefore, initialize the global
                // as null, and then monkey patch it after instantiation below.
                externref_init = Some(x);
                GlobalInit::RefNullConst
            }
            Val::FuncRef(Some(f)) => {
                // Add a function import to the stub module, and then initialize
                // our global with a `ref.func` to grab that imported function.
                let f = f.caller_checked_anyfunc(store);
                let f = unsafe { f.as_ref() };
                let sig_id = SignatureIndex::from_u32(0);
                one_signature = Some(f.type_index);
                module.types.push(ModuleType::Function(sig_id));
                let func_index = module.push_escaped_function(sig_id, AnyfuncIndex::from_u32(0));
                module.num_imported_funcs = 1;
                module.num_escaped_funcs = 1;
                module
                    .initializers
                    .push(wasmtime_environ::Initializer::Import {
                        name: "".into(),
                        field: "".into(),
                        index: EntityIndex::Function(func_index),
                    });

                func_imports.push(VMFunctionImport {
                    body: f.func_ptr,
                    vmctx: f.vmctx,
                });

                GlobalInit::RefFunc(func_index)
            }
        },
    };

    let global_id = module.globals.push(global);
    module
        .exports
        .insert(String::new(), EntityIndex::Global(global_id));
    let id = create_handle(module, store, Box::new(()), &func_imports, one_signature)?;

    if let Some(x) = externref_init {
        let instance = store.instance_mut(id);
        let g = instance.get_exported_global(global_id);
        unsafe {
            *(*g.definition).as_externref_mut() = Some(x.inner);
        }
    }

    Ok(id)
}

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Compare self to key and return true if they are equal.

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
Should always be Self
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.