marine_core/module/
wit_instance.rs1use super::wit_prelude::*;
18use super::marine_module::MModule;
19use super::IRecordType;
20use crate::MResult;
21
22use marine_wasm_backend_traits::AsContextMut;
23use marine_wasm_backend_traits::STANDARD_MEMORY_EXPORT_NAME;
24use marine_wasm_backend_traits::DelayedContextLifetime;
25use marine_wasm_backend_traits::WasmBackend;
26use marine_wasm_backend_traits::Instance;
27
28use marine_it_interfaces::MITInterfaces;
29use marine_it_interfaces::ITAstType;
30
31use wasmer_it::interpreter::wasm;
32use wasmer_it::interpreter::wasm::structures::LocalImportIndex;
33use wasmer_it::interpreter::wasm::structures::Memory;
34use wasmer_it::interpreter::wasm::structures::TypedIndex;
35
36use std::collections::HashMap;
37use std::sync::Arc;
38
39pub type MRecordTypes = HashMap<u64, Arc<IRecordType>>;
40
41#[derive(Clone)]
43pub(super) struct ITInstance<WB: WasmBackend> {
44 funcs: HashMap<usize, WITFunction<WB>>,
46
47 memories: Vec<<WB as WasmBackend>::Memory>,
49
50 record_types_by_id: MRecordTypes,
52}
53
54impl<WB: WasmBackend> ITInstance<WB> {
55 pub(super) fn new(
56 wasm_instance: &<WB as WasmBackend>::Instance,
57 store: &mut <WB as WasmBackend>::Store,
58 module_name: &str,
59 wit: &MITInterfaces<'_>,
60 modules: &HashMap<String, MModule<WB>>,
61 ) -> MResult<Self> {
62 let mut exports = Self::extract_raw_exports(wasm_instance, store, wit)?;
63 let imports = Self::extract_imports(module_name, modules, wit, exports.len())?;
64 let memories = Self::extract_memories(wasm_instance, store);
65
66 exports.extend(imports);
67 let funcs = exports;
68
69 let record_types_by_id = Self::extract_record_types(wit);
70
71 Ok(Self {
72 funcs,
73 memories,
74 record_types_by_id,
75 })
76 }
77
78 fn extract_raw_exports(
79 wasm_instance: &<WB as WasmBackend>::Instance,
80 store: &mut <WB as WasmBackend>::Store,
81 it: &MITInterfaces<'_>,
82 ) -> MResult<HashMap<usize, WITFunction<WB>>> {
83 it.exports()
84 .enumerate()
85 .map(|(export_id, export)| {
86 let export_func = wasm_instance.get_function(store, export.name)?;
87 Ok((
88 export_id,
89 WITFunction::from_export(store, export_func, export.name.to_string())?,
90 ))
91 })
92 .collect()
93 }
94
95 fn extract_imports(
97 module_name: &str,
98 modules: &HashMap<String, MModule<WB>>,
99 wit: &MITInterfaces<'_>,
100 start_index: usize,
101 ) -> MResult<HashMap<usize, WITFunction<WB>>> {
102 wit.imports()
103 .filter(|import| {
104 wit.adapter_types_by_core_type(import.function_type)
105 .is_some()
106 })
107 .enumerate()
108 .map(|(idx, import)| match modules.get(import.namespace) {
109 Some(module) => {
110 use wasmer_it::ast::Type;
111 let (arguments, output_types) =
112 match wit.type_by_idx_r(import.function_type - 2)? {
113 Type::Function {
114 arguments,
115 output_types,
116 } => (arguments.clone(), output_types.clone()),
117 ty => {
118 return Err(MError::IncorrectWIT(format!(
119 "IT should has Type::Function, but {:?} met",
120 ty
121 )))
122 }
123 };
124
125 let func = WITFunction::from_import(
126 module,
127 module_name,
128 import.name,
129 arguments,
130 output_types,
131 )?;
132
133 Ok((start_index + idx, func))
134 }
135 None => Err(MError::NoSuchModule(import.namespace.to_string())),
136 })
137 .collect::<MResult<HashMap<_, _>>>()
138 }
139
140 fn extract_memories(
141 wasm_instance: &<WB as WasmBackend>::Instance,
142 store: &mut <WB as WasmBackend>::Store,
143 ) -> Vec<<WB as WasmBackend>::Memory> {
144 use marine_wasm_backend_traits::Export::Memory;
145
146 let mut memories = wasm_instance
147 .export_iter(store.as_context_mut())
148 .filter_map(|(_, export)| match export {
149 Memory(memory) => Some(memory),
150 _ => None,
151 })
152 .collect::<Vec<_>>();
153
154 if let Ok(memory) = wasm_instance.get_memory(store, STANDARD_MEMORY_EXPORT_NAME) {
155 memories.push(memory);
156 }
157
158 memories
159 }
160
161 fn extract_record_types(wit: &MITInterfaces<'_>) -> MRecordTypes {
162 let (record_types_by_id, _) = wit.types().fold(
163 (HashMap::new(), 0u64),
164 |(mut record_types_by_id, id), ty| {
165 match ty {
166 ITAstType::Record(record_type) => {
167 record_types_by_id.insert(id, record_type.clone());
168 }
169 ITAstType::Function { .. } => {}
170 };
171 (record_types_by_id, id + 1)
172 },
173 );
174
175 record_types_by_id
176 }
177}
178
179impl<WB: WasmBackend>
180 wasm::structures::Instance<
181 ITExport,
182 WITFunction<WB>,
183 <WB as WasmBackend>::Memory,
184 <WB as WasmBackend>::MemoryView,
185 DelayedContextLifetime<WB>,
186 > for ITInstance<WB>
187{
188 fn export(&self, _export_name: &str) -> Option<&ITExport> {
189 None
191 }
192
193 fn local_or_import<I: TypedIndex + LocalImportIndex>(
194 &self,
195 index: I,
196 ) -> Option<&WITFunction<WB>> {
197 self.funcs.get(&index.index())
198 }
199
200 fn memory(&self, index: usize) -> Option<&<WB as WasmBackend>::Memory> {
201 if index >= self.memories.len() {
202 None
203 } else {
204 Some(&self.memories[index])
205 }
206 }
207
208 fn memory_view(&self, index: usize) -> Option<<WB as WasmBackend>::MemoryView> {
209 if index >= self.memories.len() {
210 return None;
211 }
212
213 let memory = &self.memories[index];
214 let view: <WB as WasmBackend>::MemoryView = memory.view();
215 Some(view)
216 }
217
218 fn wit_record_by_id(&self, index: u64) -> Option<&Arc<IRecordType>> {
219 self.record_types_by_id.get(&index)
220 }
221}