1use crate::{
6 backend::RunnableModule,
7 cache::{Artifact, Error as CacheError},
8 error,
9 import::ImportObject,
10 structures::{Map, TypedIndex},
11 types::{
12 ExportDescriptor, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit,
13 ImportDescriptor, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex,
14 ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex,
15 MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, TableIndex,
16 },
17 Instance,
18};
19
20use crate::backend::CacheGen;
21#[cfg(feature = "generate-debug-information")]
22use crate::jit_debug;
23use indexmap::IndexMap;
24use std::collections::HashMap;
25use std::sync::Arc;
26
27#[doc(hidden)]
29pub struct ModuleInner {
30 pub runnable_module: Arc<Box<dyn RunnableModule>>,
31 pub cache_gen: Box<dyn CacheGen>,
32 pub info: ModuleInfo,
33}
34
35#[derive(Clone, Debug, Serialize, Deserialize)]
37pub struct ModuleInfo {
38 pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
41 pub globals: Map<LocalGlobalIndex, GlobalInit>,
43 pub tables: Map<LocalTableIndex, TableDescriptor>,
45
46 pub imported_functions: Map<ImportedFuncIndex, ImportName>,
49 pub imported_memories: Map<ImportedMemoryIndex, (ImportName, MemoryDescriptor)>,
51 pub imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
53 pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
55
56 pub exports: IndexMap<String, ExportIndex>,
62
63 pub data_initializers: Vec<DataInitializer>,
65 pub elem_initializers: Vec<TableInitializer>,
67
68 pub start_func: Option<FuncIndex>,
70
71 pub func_assoc: Map<FuncIndex, SigIndex>,
73 pub signatures: Map<SigIndex, FuncSig>,
75 pub backend: String,
77
78 pub namespace_table: StringTable<NamespaceIndex>,
80 pub name_table: StringTable<NameIndex>,
82
83 pub em_symbol_map: Option<HashMap<u32, String>>,
85
86 pub custom_sections: HashMap<String, Vec<Vec<u8>>>,
88
89 pub generate_debug_info: bool,
92
93 #[cfg(feature = "generate-debug-information")]
94 #[serde(skip)]
95 pub(crate) debug_info_manager: jit_debug::JitCodeDebugInfoManager,
97}
98
99impl ModuleInfo {
100 pub fn import_custom_sections(&mut self, wasm: &[u8]) -> crate::error::ParseResult<()> {
102 let mut parser = wasmparser::ModuleReader::new(wasm)?;
103 while !parser.eof() {
104 let section = parser.read()?;
105 if let wasmparser::SectionCode::Custom { name, kind: _ } = section.code {
106 let mut reader = section.get_binary_reader();
107 let len = reader.bytes_remaining();
108 let bytes = reader.read_bytes(len)?;
109 let data = bytes.to_vec();
110 let name = name.to_string();
111 let entry: &mut Vec<Vec<u8>> = self.custom_sections.entry(name).or_default();
112 entry.push(data);
113 }
114 }
115 Ok(())
116 }
117}
118
119pub struct Module {
125 inner: Arc<ModuleInner>,
126}
127
128impl Module {
129 pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
130 Module { inner }
131 }
132
133 pub fn instantiate(&self, import_object: &ImportObject) -> error::Result<Instance> {
156 Instance::new(Arc::clone(&self.inner), import_object)
157 }
158
159 pub fn cache(&self) -> Result<Artifact, CacheError> {
161 let (backend_metadata, code) = self.inner.cache_gen.generate_cache()?;
162 Ok(Artifact::from_parts(
163 Box::new(self.inner.info.clone()),
164 backend_metadata,
165 code,
166 ))
167 }
168
169 pub fn info(&self) -> &ModuleInfo {
171 &self.inner.info
172 }
173
174 pub fn exports(&self) -> Vec<ExportDescriptor> {
176 self.inner.exports()
177 }
178
179 pub fn imports(&self) -> Vec<ImportDescriptor> {
182 let mut out = Vec::with_capacity(
183 self.inner.info.imported_functions.len()
184 + self.inner.info.imported_memories.len()
185 + self.inner.info.imported_tables.len()
186 + self.inner.info.imported_globals.len(),
187 );
188
189 fn get_import_name(
191 info: &ModuleInfo,
192 &ImportName {
193 namespace_index,
194 name_index,
195 }: &ImportName,
196 ) -> (String, String) {
197 let namespace = info.namespace_table.get(namespace_index).to_string();
198 let name = info.name_table.get(name_index).to_string();
199
200 (namespace, name)
201 }
202
203 let info = &self.inner.info;
204
205 let imported_functions = info.imported_functions.iter().map(|(idx, import_name)| {
206 let (namespace, name) = get_import_name(info, import_name);
207 let sig = info
208 .signatures
209 .get(*info.func_assoc.get(FuncIndex::new(idx.index())).unwrap())
210 .unwrap();
211 ImportDescriptor {
212 namespace,
213 name,
214 ty: sig.into(),
215 }
216 });
217 let imported_memories =
218 info.imported_memories
219 .values()
220 .map(|(import_name, memory_descriptor)| {
221 let (namespace, name) = get_import_name(info, import_name);
222 ImportDescriptor {
223 namespace,
224 name,
225 ty: memory_descriptor.into(),
226 }
227 });
228 let imported_tables =
229 info.imported_tables
230 .values()
231 .map(|(import_name, table_descriptor)| {
232 let (namespace, name) = get_import_name(info, import_name);
233 ImportDescriptor {
234 namespace,
235 name,
236 ty: table_descriptor.into(),
237 }
238 });
239 let imported_globals =
240 info.imported_globals
241 .values()
242 .map(|(import_name, global_descriptor)| {
243 let (namespace, name) = get_import_name(info, import_name);
244 ImportDescriptor {
245 namespace,
246 name,
247 ty: global_descriptor.into(),
248 }
249 });
250
251 out.extend(imported_functions);
252 out.extend(imported_memories);
253 out.extend(imported_tables);
254 out.extend(imported_globals);
255 out
256 }
257
258 pub fn custom_sections(&self, key: impl AsRef<str>) -> Option<&[Vec<u8>]> {
260 let key = key.as_ref();
261 self.inner.info.custom_sections.get(key).map(|v| v.as_ref())
262 }
263}
264
265impl Clone for Module {
266 fn clone(&self) -> Self {
267 Self {
268 inner: Arc::clone(&self.inner),
269 }
270 }
271}
272
273impl ModuleInner {
274 pub(crate) fn exports_iter(&self) -> impl Iterator<Item = ExportDescriptor> + '_ {
276 self.info
277 .exports
278 .iter()
279 .map(move |(name, &ei)| ExportDescriptor {
280 name,
281 ty: match ei {
282 ExportIndex::Func(f_idx) => {
283 let sig_idx = self.info.func_assoc[f_idx].into();
284 self.info.signatures[sig_idx].clone().into()
285 }
286 ExportIndex::Global(g_idx) => {
287 let info = &self.info;
288 let local_global_idx =
289 LocalGlobalIndex::new(g_idx.index() - info.imported_globals.len());
290 info.globals[local_global_idx].desc.into()
291 }
292 ExportIndex::Memory(m_idx) => {
293 let info = &self.info;
294 let local_memory_idx =
295 LocalMemoryIndex::new(m_idx.index() - info.imported_memories.len());
296 info.memories[local_memory_idx].into()
297 }
298 ExportIndex::Table(t_idx) => {
299 let info = &self.info;
300 let local_table_idx =
301 LocalTableIndex::new(t_idx.index() - info.imported_tables.len());
302 info.tables[local_table_idx].into()
303 }
304 },
305 })
306 }
307
308 pub fn exports(&self) -> Vec<ExportDescriptor> {
310 self.exports_iter().collect()
311 }
312}
313
314#[doc(hidden)]
315#[derive(Serialize, Deserialize, Debug, Clone)]
316pub struct ImportName {
317 pub namespace_index: NamespaceIndex,
318 pub name_index: NameIndex,
319}
320
321#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
328pub enum ExportIndex {
329 Func(FuncIndex),
332 Memory(MemoryIndex),
335 Global(GlobalIndex),
338 Table(TableIndex),
341}
342
343#[derive(Serialize, Deserialize, Debug, Clone)]
345pub struct DataInitializer {
346 pub memory_index: MemoryIndex,
348 pub base: Initializer,
350 #[cfg_attr(feature = "cache", serde(with = "serde_bytes"))]
352 pub data: Vec<u8>,
353}
354
355#[derive(Serialize, Deserialize, Debug, Clone)]
357pub struct TableInitializer {
358 pub table_index: TableIndex,
360 pub base: Initializer,
362 pub elements: Vec<FuncIndex>,
364}
365
366pub struct StringTableBuilder<K: TypedIndex> {
368 map: IndexMap<String, (K, u32, u32)>,
369 buffer: String,
370 count: u32,
371}
372
373impl<K: TypedIndex> StringTableBuilder<K> {
374 pub fn new() -> Self {
376 Self {
377 map: IndexMap::new(),
378 buffer: String::new(),
379 count: 0,
380 }
381 }
382
383 pub fn register<S>(&mut self, s: S) -> K
385 where
386 S: Into<String> + AsRef<str>,
387 {
388 let s_str = s.as_ref();
389
390 if self.map.contains_key(s_str) {
391 self.map[s_str].0
392 } else {
393 let offset = self.buffer.len();
394 let length = s_str.len();
395 let index = TypedIndex::new(self.count as _);
396
397 self.buffer.push_str(s_str);
398 self.map
399 .insert(s.into(), (index, offset as u32, length as u32));
400 self.count += 1;
401
402 index
403 }
404 }
405
406 pub fn finish(self) -> StringTable<K> {
408 let table = self
409 .map
410 .values()
411 .map(|(_, offset, length)| (*offset, *length))
412 .collect();
413
414 StringTable {
415 table,
416 buffer: self.buffer,
417 }
418 }
419}
420
421#[derive(Serialize, Deserialize, Debug, Clone)]
423pub struct StringTable<K: TypedIndex> {
424 table: Map<K, (u32, u32)>,
425 buffer: String,
426}
427
428impl<K: TypedIndex> StringTable<K> {
429 pub fn new() -> Self {
431 Self {
432 table: Map::new(),
433 buffer: String::new(),
434 }
435 }
436
437 pub fn get(&self, index: K) -> &str {
439 let (offset, length) = self.table[index];
440 let offset = offset as usize;
441 let length = length as usize;
442
443 &self.buffer[offset..offset + length]
444 }
445}
446
447#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)]
449pub struct NamespaceIndex(u32);
450
451impl TypedIndex for NamespaceIndex {
452 #[doc(hidden)]
453 fn new(index: usize) -> Self {
454 NamespaceIndex(index as _)
455 }
456
457 #[doc(hidden)]
458 fn index(&self) -> usize {
459 self.0 as usize
460 }
461}
462
463#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)]
465pub struct NameIndex(u32);
466
467impl TypedIndex for NameIndex {
468 #[doc(hidden)]
469 fn new(index: usize) -> Self {
470 NameIndex(index as _)
471 }
472
473 #[doc(hidden)]
474 fn index(&self) -> usize {
475 self.0 as usize
476 }
477}