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 borsh::{BorshDeserialize, BorshSerialize};
24use core::convert::TryFrom;
25use indexmap::IndexMap;
26use std::collections::HashMap;
27use std::hash::Hash;
28use std::io::Write;
29use std::sync::Arc;
30
31#[doc(hidden)]
33pub struct ModuleInner {
34 pub runnable_module: Arc<Box<dyn RunnableModule>>,
35 pub cache_gen: Box<dyn CacheGen>,
36 pub info: ModuleInfo,
37}
38
39#[derive(Clone, Debug, Serialize, Deserialize, Default)]
41pub struct ExportsMap {
42 pub map: IndexMap<String, ExportIndex>,
44}
45
46#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
48pub struct ModuleInfo {
49 pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
52 pub globals: Map<LocalGlobalIndex, GlobalInit>,
54 pub tables: Map<LocalTableIndex, TableDescriptor>,
56
57 pub imported_functions: Map<ImportedFuncIndex, ImportName>,
60 pub imported_memories: Map<ImportedMemoryIndex, (ImportName, MemoryDescriptor)>,
62 pub imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
64 pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
66
67 pub exports: ExportsMap,
73
74 pub data_initializers: Vec<DataInitializer>,
76 pub elem_initializers: Vec<TableInitializer>,
78
79 pub start_func: Option<FuncIndex>,
81
82 pub func_assoc: Map<FuncIndex, SigIndex>,
84 pub signatures: Map<SigIndex, FuncSig>,
86 pub backend: String,
88
89 pub namespace_table: StringTable<NamespaceIndex>,
91 pub name_table: StringTable<NameIndex>,
93
94 pub em_symbol_map: Option<HashMap<u32, String>>,
96
97 pub custom_sections: HashMap<String, Vec<Vec<u8>>>,
99
100 pub generate_debug_info: bool,
103
104 #[cfg(feature = "generate-debug-information")]
105 #[serde(skip)]
106 #[borsh(skip)]
107 pub(crate) debug_info_manager: jit_debug::JitCodeDebugInfoManager,
109}
110
111impl BorshSerialize for ExportsMap {
112 fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
113 u32::try_from(self.map.len())
114 .map_err(|_| std::io::ErrorKind::InvalidInput)?
115 .serialize(writer)?;
116 for (key, value) in &self.map {
117 key.serialize(writer)?;
118 value.serialize(writer)?;
119 }
120 Ok(())
121 }
122}
123
124impl BorshDeserialize for ExportsMap {
125 fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
126 let len = u32::deserialize_reader(reader)?;
127 let mut result = IndexMap::with_capacity(len as usize);
129
130 for _ in 0..len {
131 let key = String::deserialize_reader(reader)?;
132 let value = ExportIndex::deserialize_reader(reader)?;
133 result.insert(key, value);
134 }
135 Ok(ExportsMap { map: result })
136 }
137}
138
139impl ModuleInfo {
140 pub fn import_custom_sections(&mut self, wasm: &[u8]) -> crate::error::ParseResult<()> {
142 let mut parser = wasmparser::ModuleReader::new(wasm)?;
143 while !parser.eof() {
144 let section = parser.read()?;
145 if let wasmparser::SectionCode::Custom { name, kind: _ } = section.code {
146 let mut reader = section.get_binary_reader();
147 let len = reader.bytes_remaining();
148 let bytes = reader.read_bytes(len)?;
149 let data = bytes.to_vec();
150 let name = name.to_string();
151 let entry: &mut Vec<Vec<u8>> = self.custom_sections.entry(name).or_default();
152 entry.push(data);
153 }
154 }
155 Ok(())
156 }
157}
158
159pub struct Module {
165 inner: Arc<ModuleInner>,
166}
167
168impl Module {
169 pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
170 Module { inner }
171 }
172
173 pub fn instantiate(&self, import_object: &ImportObject) -> error::Result<Instance> {
196 Instance::new(Arc::clone(&self.inner), import_object)
197 }
198
199 pub fn cache(&self) -> Result<Artifact, CacheError> {
201 let (backend_metadata, code) = self.inner.cache_gen.generate_cache()?;
202 Ok(Artifact::from_parts(
203 Box::new(self.inner.info.clone()),
204 backend_metadata,
205 code,
206 ))
207 }
208
209 pub fn info(&self) -> &ModuleInfo {
211 &self.inner.info
212 }
213
214 pub fn exports(&self) -> Vec<ExportDescriptor> {
216 self.inner.exports()
217 }
218
219 pub fn imports(&self) -> Vec<ImportDescriptor> {
222 let mut out = Vec::with_capacity(
223 self.inner.info.imported_functions.len()
224 + self.inner.info.imported_memories.len()
225 + self.inner.info.imported_tables.len()
226 + self.inner.info.imported_globals.len(),
227 );
228
229 fn get_import_name(
231 info: &ModuleInfo,
232 &ImportName {
233 namespace_index,
234 name_index,
235 }: &ImportName,
236 ) -> (String, String) {
237 let namespace = info.namespace_table.get(namespace_index).to_string();
238 let name = info.name_table.get(name_index).to_string();
239
240 (namespace, name)
241 }
242
243 let info = &self.inner.info;
244
245 let imported_functions = info.imported_functions.iter().map(|(idx, import_name)| {
246 let (namespace, name) = get_import_name(info, import_name);
247 let sig = info
248 .signatures
249 .get(*info.func_assoc.get(FuncIndex::new(idx.index())).unwrap())
250 .unwrap();
251 ImportDescriptor {
252 namespace,
253 name,
254 ty: sig.into(),
255 }
256 });
257 let imported_memories =
258 info.imported_memories
259 .values()
260 .map(|(import_name, memory_descriptor)| {
261 let (namespace, name) = get_import_name(info, import_name);
262 ImportDescriptor {
263 namespace,
264 name,
265 ty: memory_descriptor.into(),
266 }
267 });
268 let imported_tables =
269 info.imported_tables
270 .values()
271 .map(|(import_name, table_descriptor)| {
272 let (namespace, name) = get_import_name(info, import_name);
273 ImportDescriptor {
274 namespace,
275 name,
276 ty: table_descriptor.into(),
277 }
278 });
279 let imported_globals =
280 info.imported_globals
281 .values()
282 .map(|(import_name, global_descriptor)| {
283 let (namespace, name) = get_import_name(info, import_name);
284 ImportDescriptor {
285 namespace,
286 name,
287 ty: global_descriptor.into(),
288 }
289 });
290
291 out.extend(imported_functions);
292 out.extend(imported_memories);
293 out.extend(imported_tables);
294 out.extend(imported_globals);
295 out
296 }
297
298 pub fn custom_sections(&self, key: impl AsRef<str>) -> Option<&[Vec<u8>]> {
300 let key = key.as_ref();
301 self.inner.info.custom_sections.get(key).map(|v| v.as_ref())
302 }
303}
304
305impl Clone for Module {
306 fn clone(&self) -> Self {
307 Self {
308 inner: Arc::clone(&self.inner),
309 }
310 }
311}
312
313impl ModuleInner {
314 pub(crate) fn exports_iter(&self) -> impl Iterator<Item = ExportDescriptor> + '_ {
316 self.info
317 .exports
318 .map
319 .iter()
320 .map(move |(name, &ei)| ExportDescriptor {
321 name,
322 ty: match ei {
323 ExportIndex::Func(f_idx) => {
324 let sig_idx = self.info.func_assoc[f_idx].into();
325 self.info.signatures[sig_idx].clone().into()
326 }
327 ExportIndex::Global(g_idx) => {
328 let info = &self.info;
329 let local_global_idx =
330 LocalGlobalIndex::new(g_idx.index() - info.imported_globals.len());
331 info.globals[local_global_idx].desc.into()
332 }
333 ExportIndex::Memory(m_idx) => {
334 let info = &self.info;
335 let local_memory_idx =
336 LocalMemoryIndex::new(m_idx.index() - info.imported_memories.len());
337 info.memories[local_memory_idx].into()
338 }
339 ExportIndex::Table(t_idx) => {
340 let info = &self.info;
341 let local_table_idx =
342 LocalTableIndex::new(t_idx.index() - info.imported_tables.len());
343 info.tables[local_table_idx].into()
344 }
345 },
346 })
347 }
348
349 pub fn exports(&self) -> Vec<ExportDescriptor> {
351 self.exports_iter().collect()
352 }
353}
354
355#[doc(hidden)]
356#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
357pub struct ImportName {
358 pub namespace_index: NamespaceIndex,
359 pub name_index: NameIndex,
360}
361
362#[derive(
369 Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize,
370)]
371pub enum ExportIndex {
372 Func(FuncIndex),
375 Memory(MemoryIndex),
378 Global(GlobalIndex),
381 Table(TableIndex),
384}
385
386#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
388pub struct DataInitializer {
389 pub memory_index: MemoryIndex,
391 pub base: Initializer,
393 #[cfg_attr(feature = "cache", serde(with = "serde_bytes"))]
395 pub data: Vec<u8>,
396}
397
398#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
400pub struct TableInitializer {
401 pub table_index: TableIndex,
403 pub base: Initializer,
405 pub elements: Vec<FuncIndex>,
407}
408
409pub struct StringTableBuilder<K: TypedIndex> {
411 map: IndexMap<String, (K, u32, u32)>,
412 buffer: String,
413 count: u32,
414}
415
416impl<K: TypedIndex> StringTableBuilder<K> {
417 pub fn new() -> Self {
419 Self {
420 map: IndexMap::new(),
421 buffer: String::new(),
422 count: 0,
423 }
424 }
425
426 pub fn register<S>(&mut self, s: S) -> K
428 where
429 S: Into<String> + AsRef<str>,
430 {
431 let s_str = s.as_ref();
432
433 if self.map.contains_key(s_str) {
434 self.map[s_str].0
435 } else {
436 let offset = self.buffer.len();
437 let length = s_str.len();
438 let index = TypedIndex::new(self.count as _);
439
440 self.buffer.push_str(s_str);
441 self.map
442 .insert(s.into(), (index, offset as u32, length as u32));
443 self.count += 1;
444
445 index
446 }
447 }
448
449 pub fn finish(self) -> StringTable<K> {
451 let table = self
452 .map
453 .values()
454 .map(|(_, offset, length)| (*offset, *length))
455 .collect();
456
457 StringTable {
458 table,
459 buffer: self.buffer,
460 }
461 }
462}
463
464#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
466pub struct StringTable<K: TypedIndex> {
467 table: Map<K, (u32, u32)>,
468 buffer: String,
469}
470
471impl<K: TypedIndex> StringTable<K> {
472 pub fn new() -> Self {
474 Self {
475 table: Map::new(),
476 buffer: String::new(),
477 }
478 }
479
480 pub fn get(&self, index: K) -> &str {
482 let (offset, length) = self.table[index];
483 let offset = offset as usize;
484 let length = length as usize;
485
486 &self.buffer[offset..offset + length]
487 }
488}
489
490#[derive(
492 Serialize,
493 Deserialize,
494 Debug,
495 Copy,
496 Clone,
497 PartialEq,
498 Eq,
499 Hash,
500 BorshSerialize,
501 BorshDeserialize,
502)]
503pub struct NamespaceIndex(u32);
504
505impl TypedIndex for NamespaceIndex {
506 #[doc(hidden)]
507 fn new(index: usize) -> Self {
508 NamespaceIndex(index as _)
509 }
510
511 #[doc(hidden)]
512 fn index(&self) -> usize {
513 self.0 as usize
514 }
515}
516
517#[derive(
519 Serialize,
520 Deserialize,
521 Debug,
522 Copy,
523 Clone,
524 PartialEq,
525 Eq,
526 Hash,
527 BorshSerialize,
528 BorshDeserialize,
529)]
530pub struct NameIndex(u32);
531
532impl TypedIndex for NameIndex {
533 #[doc(hidden)]
534 fn new(index: usize) -> Self {
535 NameIndex(index as _)
536 }
537
538 #[doc(hidden)]
539 fn index(&self) -> usize {
540 self.0 as usize
541 }
542}