1use alloc::collections::BTreeMap;
2use alloc::string::String;
3use core::default;
4use core::iter::{empty, once};
5use impl_trait_for_tuples::impl_for_tuples;
6
7use super::{
8 ControlTag, Func, FuncDecl, Global, HeapType, Memory, ModuleDisplay, Signature, StorageType,
9 Table, Type, WithMutablility,
10};
11use crate::entity::{EntityRef, EntityVec};
12use crate::ir::{Debug, DebugMap, FunctionBody};
13use crate::{backend, frontend};
14use alloc::vec;
15use alloc::vec::Vec;
16use anyhow::Result;
17use either::Either;
18use indexmap::IndexMap;
19
20pub use crate::frontend::FrontendOptions;
21
22#[derive(Clone, Debug)]
23pub struct Module<'a> {
24 pub orig_bytes: Option<&'a [u8]>,
28 pub funcs: EntityVec<Func, FuncDecl<'a>>,
32 pub signatures: EntityVec<Signature, SignatureData>,
35 pub globals: EntityVec<Global, GlobalData>,
37 pub tables: EntityVec<Table, TableData>,
39 pub imports: Vec<Import>,
42 pub exports: Vec<Export>,
44 pub memories: EntityVec<Memory, MemoryData>,
46 pub control_tags: EntityVec<ControlTag, ControlTagData>,
48 pub start_func: Option<Func>,
50 pub debug: Debug,
53 pub debug_map: DebugMap,
55 pub custom_sections: BTreeMap<String, Vec<u8>>,
56}
57#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
58pub struct ControlTagData {
59 pub sig: Signature,
61}
62#[non_exhaustive]
63#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
64pub enum SignatureData {
65 Func {
66 params: Vec<Type>,
69 returns: Vec<Type>,
73 shared: bool,
75 },
76 Struct {
77 fields: Vec<WithMutablility<StorageType>>,
79 shared: bool,
81 },
82 Array {
83 ty: WithMutablility<StorageType>,
85 shared: bool,
87 },
88 Import {
89 like: HeapType,
90 shared: bool,
91 },
92 #[default]
93 None,
94}
95
96impl SignatureData {
97 pub fn shared(&self) -> bool {
98 match self {
99 SignatureData::Func {
100 params,
101 returns,
102 shared,
103 } => *shared,
104 SignatureData::Struct { fields, shared } => *shared,
105 SignatureData::Array { ty, shared } => *shared,
106 SignatureData::Import { like, shared } => *shared,
107 SignatureData::None => todo!(),
108 }
109 }
110}
111
112pub const WASM_PAGE: usize = 0x1_0000; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
117pub struct MemoryData {
118 pub initial_pages: usize,
120 pub maximum_pages: Option<usize>,
122 pub segments: Vec<MemorySegment>,
124 pub memory64: bool,
125 pub shared: bool,
126 pub page_size_log2: Option<u32>,
127}
128
129#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
130pub struct MemorySegment {
131 pub offset: usize,
133 pub data: Vec<u8>,
135}
136
137#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
138pub struct TableData {
139 pub ty: Type,
141 pub initial: u64,
142 pub max: Option<u64>,
144 pub func_elements: Option<Vec<Func>>,
148 pub table64: bool,
149}
150
151#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
152pub struct GlobalData {
153 pub ty: Type,
155 pub value: Option<u64>,
159 pub mutable: bool,
161}
162
163impl From<&wasmparser::SubType> for SignatureData {
164 fn from(fty: &wasmparser::SubType) -> Self {
165 match &fty.composite_type.inner {
166 wasmparser::CompositeInnerType::Func(func_type) => Self::Func {
167 params: func_type
168 .params()
169 .iter()
170 .map(|&ty| ty.into())
171 .collect::<Vec<Type>>(),
172 returns: func_type
173 .results()
174 .iter()
175 .map(|&ty| ty.into())
176 .collect::<Vec<Type>>(),
177 shared: fty.composite_type.shared,
178 },
179 wasmparser::CompositeInnerType::Array(array_type) => Self::Array {
180 ty: array_type.0.clone().into(),
181 shared: fty.composite_type.shared,
182 },
183 wasmparser::CompositeInnerType::Struct(struct_type) => Self::Struct {
184 fields: struct_type.fields.iter().map(|&ty| ty.into()).collect(),
185 shared: fty.composite_type.shared,
186 },
187 _ => todo!(),
188 }
189 }
190}
191impl From<wasmparser::SubType> for SignatureData {
192 fn from(fty: wasmparser::SubType) -> Self {
193 (&fty).into()
194 }
195}
196
197impl From<&SignatureData> for wasm_encoder::SubType {
198 fn from(value: &SignatureData) -> Self {
199 match value {
200 SignatureData::Func {
201 params,
202 returns,
203 shared,
204 } => wasm_encoder::SubType {
205 is_final: true,
206 supertype_idx: None,
207 composite_type: wasm_encoder::CompositeType {
208 inner: wasm_encoder::CompositeInnerType::Func(wasm_encoder::FuncType::new(
209 params.iter().cloned().map(|a| a.into()),
210 returns.iter().cloned().map(|a| a.into()),
211 )),
212 shared: *shared,
213 },
214 },
215 SignatureData::None => todo!(),
216 SignatureData::Struct { fields, shared } => wasm_encoder::SubType {
217 is_final: true,
218 supertype_idx: None,
219 composite_type: wasm_encoder::CompositeType {
220 inner: wasm_encoder::CompositeInnerType::Struct(wasm_encoder::StructType {
221 fields: fields.iter().cloned().map(|a| a.into()).collect(),
222 }),
223 shared: *shared,
224 },
225 },
226 SignatureData::Array { ty, shared } => wasm_encoder::SubType {
227 is_final: true,
228 supertype_idx: None,
229 composite_type: wasm_encoder::CompositeType {
230 inner: wasm_encoder::CompositeInnerType::Array(wasm_encoder::ArrayType(
231 ty.clone().into(),
232 )),
233 shared: *shared,
234 },
235 },
236 SignatureData::Import { like, shared } => todo!(),
237 }
238 }
239}
240
241impl Signature {
242 pub fn is_backref(&self, module: &Module) -> bool {
243 return match &module.signatures[*self] {
244 SignatureData::Func {
245 params, returns, ..
246 } => params
247 .iter()
248 .chain(returns.iter())
249 .flat_map(|a| a.sigs())
250 .any(|sig| sig.index() >= self.index()),
251 _ => false,
252 };
253 }
254}
255
256impl Type {
257 pub fn sigs<'a>(&'a self) -> impl Iterator<Item = Signature> + 'a {
258 match self {
259 Type::Heap(h) => match &h.value {
260 HeapType::Sig { sig_index } => Either::Right(once(*sig_index)),
261 _ => Either::Left(empty()),
262 },
263 _ => Either::Left(empty()),
264 }
265 }
266}
267
268#[derive(Clone, Debug)]
269pub struct Import {
270 pub module: String,
272 pub name: String,
275 pub kind: ImportKind,
277}
278
279#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
280#[non_exhaustive]
281pub enum ImportKind {
282 Table(Table),
284 Func(Func),
286 Global(Global),
288 Memory(Memory),
290 ControlTag(ControlTag),
292 Type(Signature),
294}
295
296impl core::fmt::Display for ImportKind {
297 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
298 match self {
299 ImportKind::Table(table) => write!(f, "{}", table)?,
300 ImportKind::Func(func) => write!(f, "{}", func)?,
301 ImportKind::Global(global) => write!(f, "{}", global)?,
302 ImportKind::Memory(mem) => write!(f, "{}", mem)?,
303 ImportKind::ControlTag(control_tag) => write!(f, "{}", control_tag)?,
304 ImportKind::Type(t) => write!(f, "{}", t)?,
305 }
306 Ok(())
307 }
308}
309
310#[derive(Clone, Debug)]
311pub struct Export {
312 pub name: String,
314 pub kind: ExportKind,
316}
317
318#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
319#[non_exhaustive]
320pub enum ExportKind {
321 Table(Table),
323 Func(Func),
325 Global(Global),
327 Memory(Memory),
329 ControlTag(ControlTag),
331 Type(Signature),
333}
334
335pub fn x2i(x: ExportKind) -> ImportKind {
336 match x {
337 ExportKind::Table(a) => ImportKind::Table(a),
338 ExportKind::Func(a) => ImportKind::Func(a),
339 ExportKind::Global(a) => ImportKind::Global(a),
340 ExportKind::Memory(a) => ImportKind::Memory(a),
341 ExportKind::ControlTag(control_tag) => ImportKind::ControlTag(control_tag),
342 ExportKind::Type(t) => ImportKind::Type(t),
343 }
344}
345pub fn i2x(x: ImportKind) -> ExportKind {
346 match x {
347 ImportKind::Table(a) => ExportKind::Table(a),
348 ImportKind::Func(a) => ExportKind::Func(a),
349 ImportKind::Global(a) => ExportKind::Global(a),
350 ImportKind::Memory(a) => ExportKind::Memory(a),
351 ImportKind::ControlTag(control_tag) => ExportKind::ControlTag(control_tag),
352 ImportKind::Type(t) => ExportKind::Type(t),
353 }
354}
355
356impl core::fmt::Display for ExportKind {
357 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
358 match self {
359 ExportKind::Table(table) => write!(f, "{}", table)?,
360 ExportKind::Func(func) => write!(f, "{}", func)?,
361 ExportKind::Global(global) => write!(f, "{}", global)?,
362 ExportKind::Memory(memory) => write!(f, "{}", memory)?,
363 ExportKind::ControlTag(control_tag) => write!(f, "{}", control_tag)?,
364 ExportKind::Type(t) => write!(f, "{}", t)?,
365 }
366 Ok(())
367 }
368}
369
370impl<'a> Module<'a> {
371 pub fn empty() -> Module<'static> {
389 Module {
390 orig_bytes: None,
391 funcs: EntityVec::default(),
392 signatures: EntityVec::default(),
393 globals: EntityVec::default(),
394 tables: EntityVec::default(),
395 imports: vec![],
396 exports: vec![],
397 memories: EntityVec::default(),
398 start_func: None,
399 debug: Debug::default(),
400 debug_map: DebugMap::default(),
401 custom_sections: Default::default(),
402 control_tags: Default::default(),
403 }
404 }
405
406 pub fn from_wasm_bytes(bytes: &'a [u8], options: &FrontendOptions) -> Result<Self> {
409 frontend::wasm_to_ir(bytes, options)
410 }
411
412 pub fn without_orig_bytes(self) -> Module<'static> {
423 Module {
424 orig_bytes: None,
425 funcs: EntityVec::from(
426 self.funcs
427 .into_vec()
428 .into_iter()
429 .map(|decl| decl.without_orig_bytes())
430 .collect::<Vec<_>>(),
431 ),
432 signatures: self.signatures,
433 globals: self.globals,
434 tables: self.tables,
435 imports: self.imports,
436 exports: self.exports,
437 memories: self.memories,
438 start_func: self.start_func,
439 debug: self.debug,
440 debug_map: self.debug_map,
441 custom_sections: self.custom_sections,
442 control_tags: self.control_tags,
443 }
444 }
445}
446
447impl<'a> Module<'a> {
448 pub fn to_wasm_bytes(&self) -> Result<Vec<u8>> {
463 backend::compile(self).map(|a| a.finish())
464 }
465 pub fn to_encoded_module(&self) -> Result<wasm_encoder::Module> {
466 backend::compile(self)
467 }
468
469 pub fn per_func_body<F: Fn(&mut FunctionBody)>(&mut self, f: F) {
470 for func_decl in self.funcs.values_mut() {
471 if let Some(body) = func_decl.body_mut() {
472 f(body);
473 }
474 }
475 }
476
477 pub fn take_per_func_body<F: FnMut(&mut Self, &mut FunctionBody)>(&mut self, mut f: F) {
478 for func_decl in self.funcs.iter().collect::<Vec<_>>() {
479 let mut x = core::mem::take(&mut self.funcs[func_decl]);
480 if let Some(body) = x.body_mut() {
481 f(self, body);
482 }
483 self.funcs[func_decl] = x;
484 }
485 }
486
487 pub fn try_per_func_body<F: FnMut(&mut FunctionBody) -> Result<(), E>, E>(
488 &mut self,
489 mut f: F,
490 ) -> Result<(), E> {
491 for func_decl in self.funcs.values_mut() {
492 if let Some(body) = func_decl.body_mut() {
493 f(body)?;
494 }
495 }
496 Ok(())
497 }
498
499 pub fn try_take_per_func_body<F: FnMut(&mut Self, &mut FunctionBody) -> Result<(), E>, E>(
500 &mut self,
501 mut f: F,
502 ) -> Result<(), E> {
503 for func_decl in self.funcs.iter().collect::<Vec<_>>() {
504 let mut x = core::mem::take(&mut self.funcs[func_decl]);
505 let mut y = None;
506 if let Some(body) = x.body_mut() {
507 y = Some(f(self, body));
508 }
509 self.funcs[func_decl] = x;
510 if let Some(z) = y {
511 z?;
512 }
513 }
514 Ok(())
515 }
516
517 pub fn expand_func<'b>(&'b mut self, id: Func) -> Result<&'b mut FuncDecl<'a>> {
520 if let FuncDecl::Lazy(..) = self.funcs[id] {
521 let mut func = self.funcs[id].clone();
523 func.parse(self)?;
524 self.funcs[id] = func;
525 }
526 Ok(&mut self.funcs[id])
527 }
528
529 pub fn clone_and_expand_body(&self, id: Func) -> Result<FunctionBody> {
534 let mut body = self.funcs[id].clone();
535 body.parse(self)?;
536 Ok(match body {
537 FuncDecl::Body(_, _, body) => body,
538 _ => unreachable!(),
539 })
540 }
541
542 pub fn expand_all_funcs(&mut self) -> Result<()> {
545 for id in 0..self.funcs.len() {
546 let id = Func::new(id);
547 self.expand_func(id)?;
548 }
549 Ok(())
550 }
551
552 pub fn display<'b>(&'b self) -> ModuleDisplay<'b>
555 where
556 'b: 'a,
557 {
558 ModuleDisplay { module: self }
559 }
560
561 pub(crate) fn with_orig_bytes(orig_bytes: &'a [u8]) -> Module<'a> {
565 Module {
566 orig_bytes: Some(orig_bytes),
567 funcs: EntityVec::default(),
568 signatures: EntityVec::default(),
569 globals: EntityVec::default(),
570 tables: EntityVec::default(),
571 imports: vec![],
572 exports: vec![],
573 memories: EntityVec::default(),
574 start_func: None,
575 debug: Debug::default(),
576 debug_map: DebugMap::default(),
577 custom_sections: BTreeMap::default(),
578 control_tags: EntityVec::default(),
579 }
580 }
581}
582#[impl_for_tuples(12)]
583pub trait FuncCollector {
584 fn collect_func(&mut self, f: Func);
585}
586impl<'a, T: FuncCollector> FuncCollector for &'a mut T {
587 fn collect_func(&mut self, f: Func) {
588 FuncCollector::collect_func(&mut **self, f);
589 }
590}
591
592#[cfg(test)]
593mod test {
594 use super::*;
595
596 #[test]
597 fn empty_module_valid() {
598 let module = Module::empty();
599 let _ = module.to_wasm_bytes().unwrap();
600 }
601}