1 #[cfg(feature = "component-model")]
2 use crate::runtime::vm::component::VMComponentContext;
3 use crate::runtime::vm::vmcontext::{
4     VMContext, VMFuncRef, VMGlobalDefinition, VMGlobalImport, VMGlobalKind, VMMemoryDefinition,
5     VMOpaqueContext, VMTableDefinition, VMTagDefinition,
6 };
7 use core::ptr::NonNull;
8 #[cfg(feature = "component-model")]
9 use wasmtime_environ::component::RuntimeComponentInstanceIndex;
10 use wasmtime_environ::{
11     DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, Global, Memory,
12     Table, Tag,
13 };
14 
15 /// The value of an export passed from one instance to another.
16 pub enum Export {
17     /// A function export value.
18     Function(ExportFunction),
19 
20     /// A table export value.
21     Table(ExportTable),
22 
23     /// A memory export value.
24     Memory(ExportMemory),
25 
26     /// A global export value.
27     Global(ExportGlobal),
28 
29     /// A tag export value.
30     Tag(ExportTag),
31 }
32 
33 /// A function export value.
34 #[derive(Debug, Clone, Copy)]
35 pub struct ExportFunction {
36     /// The `VMFuncRef` for this exported function.
37     ///
38     /// Note that exported functions cannot be a null funcref, so this is a
39     /// non-null pointer.
40     pub func_ref: NonNull<VMFuncRef>,
41 }
42 
43 // As part of the contract for using `ExportFunction`, synchronization
44 // properties must be upheld. Therefore, despite containing raw pointers,
45 // it is declared as Send/Sync.
46 unsafe impl Send for ExportFunction {}
47 unsafe impl Sync for ExportFunction {}
48 
49 impl From<ExportFunction> for Export {
50     fn from(func: ExportFunction) -> Export {
51         Export::Function(func)
52     }
53 }
54 
55 /// A table export value.
56 #[derive(Debug, Clone)]
57 pub struct ExportTable {
58     /// The address of the table descriptor.
59     pub definition: NonNull<VMTableDefinition>,
60     /// Pointer to the containing `VMContext`.
61     pub vmctx: NonNull<VMContext>,
62     /// The table declaration, used for compatibility checking.
63     pub table: Table,
64     /// The index at which the table is defined within the `vmctx`.
65     pub index: DefinedTableIndex,
66 }
67 
68 // See docs on send/sync for `ExportFunction` above.
69 unsafe impl Send for ExportTable {}
70 unsafe impl Sync for ExportTable {}
71 
72 impl From<ExportTable> for Export {
73     fn from(func: ExportTable) -> Export {
74         Export::Table(func)
75     }
76 }
77 
78 /// A memory export value.
79 #[derive(Debug, Clone)]
80 pub struct ExportMemory {
81     /// The address of the memory descriptor.
82     pub definition: NonNull<VMMemoryDefinition>,
83     /// Pointer to the containing `VMContext`.
84     pub vmctx: NonNull<VMContext>,
85     /// The memory declaration, used for compatibility checking.
86     pub memory: Memory,
87     /// The index at which the memory is defined within the `vmctx`.
88     pub index: DefinedMemoryIndex,
89 }
90 
91 // See docs on send/sync for `ExportFunction` above.
92 unsafe impl Send for ExportMemory {}
93 unsafe impl Sync for ExportMemory {}
94 
95 impl From<ExportMemory> for Export {
96     fn from(func: ExportMemory) -> Export {
97         Export::Memory(func)
98     }
99 }
100 
101 /// A global export value.
102 #[derive(Debug, Clone)]
103 pub struct ExportGlobal {
104     /// The address of the global storage.
105     pub definition: NonNull<VMGlobalDefinition>,
106 
107     /// Kind of exported global, or what's owning this global and how to find
108     /// it.
109     pub kind: ExportGlobalKind,
110 
111     /// The global declaration, used for compatibility checking.
112     pub global: Global,
113 }
114 
115 /// A global export value.
116 #[derive(Debug, Clone)]
117 pub enum ExportGlobalKind {
118     /// This global was created by the host or embedder and is stored within the
119     /// `Store` at the provided offset.
120     Host(DefinedGlobalIndex),
121 
122     /// This global was created as part of a core wasm instance.
123     Instance(NonNull<VMContext>, DefinedGlobalIndex),
124 
125     /// This global was created as flags for a component instance.
126     #[cfg(feature = "component-model")]
127     ComponentFlags(NonNull<VMComponentContext>, RuntimeComponentInstanceIndex),
128 }
129 
130 impl ExportGlobal {
131     pub fn from_vmimport(import: &VMGlobalImport, ty: Global) -> ExportGlobal {
132         let kind = match import.kind {
133             VMGlobalKind::Host(index) => ExportGlobalKind::Host(index),
134             VMGlobalKind::Instance(index) => ExportGlobalKind::Instance(
135                 unsafe { VMContext::from_opaque(import.vmctx.unwrap().as_non_null()) },
136                 index,
137             ),
138             #[cfg(feature = "component-model")]
139             VMGlobalKind::ComponentFlags(index) => ExportGlobalKind::ComponentFlags(
140                 unsafe { VMComponentContext::from_opaque(import.vmctx.unwrap().as_non_null()) },
141                 index,
142             ),
143         };
144         ExportGlobal {
145             definition: import.from.as_non_null(),
146             kind,
147             global: ty,
148         }
149     }
150 
151     pub fn vmimport(&self) -> VMGlobalImport {
152         let (vmctx, kind) = match self.kind {
153             ExportGlobalKind::Host(index) => (None, VMGlobalKind::Host(index)),
154             ExportGlobalKind::Instance(vmctx, index) => (
155                 Some(VMOpaqueContext::from_vmcontext(vmctx).into()),
156                 VMGlobalKind::Instance(index),
157             ),
158             #[cfg(feature = "component-model")]
159             ExportGlobalKind::ComponentFlags(vmctx, index) => (
160                 Some(VMOpaqueContext::from_vmcomponent(vmctx).into()),
161                 VMGlobalKind::ComponentFlags(index),
162             ),
163         };
164         VMGlobalImport {
165             from: self.definition.into(),
166             vmctx,
167             kind,
168         }
169     }
170 }
171 
172 // See docs on send/sync for `ExportFunction` above.
173 unsafe impl Send for ExportGlobal {}
174 unsafe impl Sync for ExportGlobal {}
175 
176 impl From<ExportGlobal> for Export {
177     fn from(func: ExportGlobal) -> Export {
178         Export::Global(func)
179     }
180 }
181 
182 /// A tag export value.
183 #[derive(Debug, Clone)]
184 pub struct ExportTag {
185     /// The address of the global storage.
186     pub definition: NonNull<VMTagDefinition>,
187     /// The instance that owns this tag.
188     pub vmctx: NonNull<VMContext>,
189     /// The global declaration, used for compatibility checking.
190     pub tag: Tag,
191     /// The index at which the tag is defined within the `vmctx`.
192     pub index: DefinedTagIndex,
193 }
194 
195 // See docs on send/sync for `ExportFunction` above.
196 unsafe impl Send for ExportTag {}
197 unsafe impl Sync for ExportTag {}
198 
199 impl From<ExportTag> for Export {
200     fn from(func: ExportTag) -> Export {
201         Export::Tag(func)
202     }
203 }
204