macro_rules! for_each_vm_type {
($mac:ident) => { ... };
}Expand description
Invoke the given macro $mac once, passing it the definitions of each of the
VM* types whose layout is shared between the runtime, compilation offsets,
and Cranelift alias regions.
This is a higher-order macro: callers define a macro_rules! macro that
matches the grammar defined below and pass its name as an argument to this
macro’s invocation, e.g. for_each_vm_type!(define_vm_types).
§Grammar
Each type is either a struct or a #[repr(C, _)] enum, preceded by:
-
Doc-comment attributes (
#[doc = "..."]). -
An optional
#[cfg(...)]attribute, gating the type on the Cargo features whose code actually uses it.Only the runtime’s
structdefinition (and its layout test) is gated by it. A type’s offsets and alias regions are always generated because thewasmtime-environandwasmtime-internal-craneliftcrates do not have Cargo features for all the various Wasm features. -
An optional
#[derive(...)]attribute. -
A
#[repr(...)]attribute. -
A
#[snake_name = <ident>]attribute giving the type’s name insnake_case, used to generate accessor method names.
Each field may be preceded by doc-comment attributes and, optionally, these marker attributes, in this order:
-
#[aggregate]: this field is a composite (a nested struct or array) rather than a single scalar. Compiled Wasm code accesses such a field’s interior piecewise, so there is no one Cranelift type for the field as a whole and no alias-region accessor is generated for it. The field’s offset is still generated, since that is what interior accesses are computed relative to. -
#[indexed]: this field is a fixed-size array of a scalar type, whose elements compiled Wasm code accesses individually by a compile-time constant index. Like#[aggregate], the field has no single Cranelift type; unlike#[aggregate], its elements all do, so an alias-region accessor taking that index is generated for it and each element gets its own alias region. -
#[readonly]and/or#[can_move]: describe how Cranelift may treat loads and stores of that field.
§Enums
A type may also be an enum, which must be #[repr(C, $tag)] for an
integer $tag:
#[derive(Debug)]
#[repr(C, u32)]
#[snake_name = vm_example]
pub enum VMExample {
#[snake_name = variant_a]
VariantA {
field: u32,
} = 0,
#[snake_name = variant_b]
VariantB {
other: u64,
} = 1,
}Rust lays such an enum out as a #[repr(C)] struct of a $tag tag followed
by a union of the variants, which is what lets the same offset machinery
describe it. The C is what guarantees that, so it is required.
Beyond a struct’s rules, each variant needs an explicit discriminant (the
tag values compiled code compares against), braces even when empty, and its
own #[snake_name] for its generated accessors. Variant fields take a
struct field’s marker attributes but no visibility.
An enum gets two alias regions rather than a struct’s one per field: one for the tag, one shared by all variants’ fields, because they overlap.