1#![forbid(unsafe_code)]
2#![warn(clippy::dbg_macro)]
3
4pub mod source;
5
6use std::borrow::Cow;
7use std::fmt;
8
9#[derive(Clone, Debug, PartialEq)]
11pub struct Root<'s, S: source::Source> {
12 pub module: Module<'s>,
13 pub source: S,
14}
15
16pub type FuncIdx = u32;
21pub type TableIdx = u32;
22pub type MemIdx = u32;
23pub type GlobalIdx = u32;
24pub type TypeIdx = u32;
25pub type LocalIdx = u32;
26pub type LabelIdx = u32;
27
28#[derive(Clone, Debug, Default, PartialEq)]
30pub struct Module<'s> {
31 pub start: usize,
32 pub id: Option<&'s str>,
33 pub types: Vec<FuncType>,
34 pub exports: Vec<Export<'s>>,
35 pub funcs: Vec<Func<'s>>,
36 pub elems: Vec<ElemSegment>,
37 pub tables: Vec<Table<'s>>,
38 pub data: Vec<DataSegment<'s>>,
39 pub memories: Vec<Memory<'s>>,
40 pub globals: Vec<Global<'s>>,
41 pub entrypoint: Option<StartFunction>,
42}
43
44#[derive(Debug, Clone, PartialEq)]
46pub struct Import<'s> {
47 pub mod_name: Name<'s>,
48 pub name: Name<'s>,
49}
50
51#[derive(Debug, PartialEq, Clone)]
53pub struct FuncType {
54 pub start: usize,
55 pub params: Vec<ValType>,
56 pub results: Vec<ValType>,
57}
58
59#[derive(PartialEq, Clone, Copy, Debug)]
61pub enum ValType {
62 I32,
63 I64,
64 F32,
65 F64,
66}
67
68impl ValType {
69 #[must_use]
70 pub fn bytes(self) -> usize {
71 match self {
72 Self::I32 | Self::F32 => 4,
73 Self::I64 | Self::F64 => 8,
74 }
75 }
76}
77
78impl AsRef<str> for ValType {
79 fn as_ref(&self) -> &str {
80 match self {
81 Self::I32 => "i32",
82 Self::I64 => "i64",
83 Self::F32 => "f32",
84 Self::F64 => "f64",
85 }
86 }
87}
88
89impl fmt::Display for ValType {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 f.write_str(self.as_ref())
92 }
93}
94
95pub trait AsValType {
96 const VAL_TYPE: ValType;
97}
98
99impl AsValType for i32 {
100 const VAL_TYPE: ValType = ValType::I32;
101}
102
103impl AsValType for i64 {
104 const VAL_TYPE: ValType = ValType::I64;
105}
106
107impl AsValType for f32 {
108 const VAL_TYPE: ValType = ValType::F32;
109}
110
111impl AsValType for f64 {
112 const VAL_TYPE: ValType = ValType::F64;
113}
114
115#[derive(Debug, Clone, PartialEq)]
122pub struct Name<'s>(pub Cow<'s, str>);
123
124#[derive(Debug, Clone, PartialEq)]
127pub struct TableType {
128 pub limit: Limits,
129}
130
131#[derive(Debug, Clone, PartialEq)]
133pub enum Limits {
134 Range(u32, u32),
135 From(u32),
136}
137
138#[derive(Debug, Clone, PartialEq)]
140pub struct MemType {
141 pub limit: Limits,
142}
143
144#[derive(Debug, Clone, PartialEq)]
146pub enum ExportKind {
147 Func(FuncIdx),
148 Table(TableIdx),
149 Memory(MemIdx),
150 Global(GlobalIdx),
151}
152
153#[derive(Debug, Clone, PartialEq)]
154pub struct Export<'s> {
155 pub start: usize,
156 pub name: Name<'s>,
157 pub kind: ExportKind,
158}
159
160#[derive(Debug, Clone, PartialEq)]
162pub enum FuncKind<'s> {
163 Import(Import<'s>),
164 Body {
165 locals: Vec<ValType>,
166 expr: Vec<Instruction>,
167 },
168}
169
170#[derive(Debug, Clone, PartialEq)]
171pub struct Func<'s> {
172 pub start: usize,
173 pub idx: TypeIdx,
174 pub kind: FuncKind<'s>,
175}
176
177#[derive(Debug, Clone, PartialEq)]
179pub struct Instruction {
180 pub start: usize,
181 pub kind: InsnKind,
182}
183
184#[derive(Debug, Clone, PartialEq)]
186pub struct Mem {
187 pub align: u32,
188 pub offset: u32,
189}
190
191#[derive(Debug, Clone, PartialEq)]
193pub enum InsnKind {
194 Block {
197 ty: Option<ValType>, body: Vec<Instruction>,
199 },
200 Loop {
201 ty: Option<ValType>, body: Vec<Instruction>,
203 },
204 If {
205 ty: Option<ValType>, then_body: Vec<Instruction>,
207 else_body: Vec<Instruction>,
208 },
209 Unreachable,
210 Nop,
211 Br(LabelIdx),
212 BrIf(LabelIdx),
213 BrTable {
214 labels: Vec<LabelIdx>,
215 default_label: LabelIdx,
216 },
217 Return,
218 Call(FuncIdx),
219 CallIndirect(TypeIdx),
220 Drop,
223 Select,
224 LocalGet(LocalIdx),
227 LocalSet(LocalIdx),
228 LocalTee(LocalIdx),
229 GlobalGet(GlobalIdx),
230 GlobalSet(GlobalIdx),
231 I32Load(Mem),
234 I64Load(Mem),
235 F32Load(Mem),
236 F64Load(Mem),
237 I32Load8S(Mem),
238 I32Load8U(Mem),
239 I32Load16S(Mem),
240 I32Load16U(Mem),
241 I64Load8S(Mem),
242 I64Load8U(Mem),
243 I64Load16S(Mem),
244 I64Load16U(Mem),
245 I64Load32S(Mem),
246 I64Load32U(Mem),
247 I32Store(Mem),
248 I64Store(Mem),
249 F32Store(Mem),
250 F64Store(Mem),
251 I32Store8(Mem),
252 I32Store16(Mem),
253 I64Store8(Mem),
254 I64Store16(Mem),
255 I64Store32(Mem),
256 MemorySize,
257 MemoryGrow,
258 I32Const(i32),
262 I64Const(i64),
263 F32Const(f32),
264 F64Const(f64),
265 I32Clz,
267 I32Ctz,
268 I32Popcnt,
269 I32Add,
270 I32Sub,
271 I32Mul,
272 I32DivS,
273 I32DivU,
274 I32RemS,
275 I32RemU,
276 I32And,
277 I32Or,
278 I32Xor,
279 I32Shl,
280 I32ShrS,
281 I32ShrU,
282 I32Rotl,
283 I32Rotr,
284 I64Clz,
286 I64Ctz,
287 I64Popcnt,
288 I64Add,
289 I64Sub,
290 I64Mul,
291 I64DivS,
292 I64DivU,
293 I64RemS,
294 I64RemU,
295 I64And,
296 I64Or,
297 I64Xor,
298 I64Shl,
299 I64ShrS,
300 I64ShrU,
301 I64Rotl,
302 I64Rotr,
303 F32Abs,
305 F32Neg,
306 F32Ceil,
307 F32Floor,
308 F32Trunc,
309 F32Nearest,
310 F32Sqrt,
311 F32Add,
312 F32Sub,
313 F32Mul,
314 F32Div,
315 F32Min,
316 F32Max,
317 F32Copysign,
318 F64Abs,
320 F64Neg,
321 F64Ceil,
322 F64Floor,
323 F64Trunc,
324 F64Nearest,
325 F64Sqrt,
326 F64Add,
327 F64Sub,
328 F64Mul,
329 F64Div,
330 F64Min,
331 F64Max,
332 F64Copysign,
333 I32Eqz,
335 I32Eq,
336 I32Ne,
337 I32LtS,
338 I32LtU,
339 I32GtS,
340 I32GtU,
341 I32LeS,
342 I32LeU,
343 I32GeS,
344 I32GeU,
345 I64Eqz,
347 I64Eq,
348 I64Ne,
349 I64LtS,
350 I64LtU,
351 I64GtS,
352 I64GtU,
353 I64LeS,
354 I64LeU,
355 I64GeS,
356 I64GeU,
357 F32Eq,
359 F32Ne,
360 F32Lt,
361 F32Gt,
362 F32Le,
363 F32Ge,
364 F64Eq,
366 F64Ne,
367 F64Lt,
368 F64Gt,
369 F64Le,
370 F64Ge,
371 I32WrapI64,
373 I32TruncF32S,
374 I32TruncF32U,
375 I32TruncF64S,
376 I32TruncF64U,
377 I64ExtendI32S,
378 I64ExtendI32U,
379 I64TruncF32S,
380 I64TruncF32U,
381 I64TruncF64S,
382 I64TruncF64U,
383 F32ConvertI32S,
384 F32ConvertI32U,
385 F32ConvertI64S,
386 F32ConvertI64U,
387 F32DemoteF64,
388 F64ConvertI32S,
389 F64ConvertI32U,
390 F64ConvertI64S,
391 F64ConvertI64U,
392 F64PromoteF32,
393 I32ReinterpretF32,
394 I64ReinterpretF64,
395 F32ReinterpretI32,
396 F64ReinterpretI64,
397 I32Extend8S,
398 I32Extend16S,
399 I64Extend8S,
400 I64Extend16S,
401 I64Extend32S,
402}
403
404impl InsnKind {
405 #[must_use]
406 pub fn name(&self) -> &'static str {
407 use InsnKind::*;
408 match self {
409 Block { .. } => "block",
410 Loop { .. } => "loop",
411 If { .. } => "if",
412 Unreachable => "unreachable",
413 Nop => "nop",
414 Br(_) => "br",
415 BrIf(_) => "br_if",
416 BrTable { .. } => "br_table",
417 Return => "return",
418 Call(_) => "call",
419 CallIndirect(_) => "call_indirect",
420 Drop => "drop",
421 Select => "select",
422 LocalGet(_) => "local.get",
423 LocalSet(_) => "local.set",
424 LocalTee(_) => "local.tee",
425 GlobalGet(_) => "global.get",
426 GlobalSet(_) => "global.set",
427 I32Load(_) => "i32.load",
428 I64Load(_) => "i64.load",
429 F32Load(_) => "f32.load",
430 F64Load(_) => "f64.load",
431 I32Load8S(_) => "i32.load8_s",
432 I32Load8U(_) => "i32.load8_u",
433 I32Load16S(_) => "i32.load16_s",
434 I32Load16U(_) => "i32.load16_u",
435 I64Load8S(_) => "i64.load8_s",
436 I64Load8U(_) => "i64.load8_u",
437 I64Load16S(_) => "i64.load16_s",
438 I64Load16U(_) => "i64.load16_u",
439 I64Load32S(_) => "i64.load32_s",
440 I64Load32U(_) => "i64.load32_u",
441 I32Store(_) => "i32.store",
442 I64Store(_) => "i64.store",
443 F32Store(_) => "f32.store",
444 F64Store(_) => "f64.store",
445 I32Store8(_) => "i32.store8",
446 I32Store16(_) => "i32.store16",
447 I64Store8(_) => "i64.store8",
448 I64Store16(_) => "i64.store16",
449 I64Store32(_) => "i64.store32",
450 MemorySize => "memory.size",
451 MemoryGrow => "memory.grow",
452 I32Const(_) => "i32.const",
453 I64Const(_) => "i64.const",
454 F32Const(_) => "f32.const",
455 F64Const(_) => "f64.const",
456 I32Clz => "i32.clz",
457 I32Ctz => "i32.ctz",
458 I32Popcnt => "i32.popcnt",
459 I32Add => "i32.add",
460 I32Sub => "i32.sub",
461 I32Mul => "i32.mul",
462 I32DivS => "i32.div_s",
463 I32DivU => "i32.div_u",
464 I32RemS => "i32.rem_s",
465 I32RemU => "i32.rem_u",
466 I32And => "i32.and",
467 I32Or => "i32.or",
468 I32Xor => "i32.xor",
469 I32Shl => "i32.shl",
470 I32ShrS => "i32.shr_s",
471 I32ShrU => "i32.shr_u",
472 I32Rotl => "i32.rotl",
473 I32Rotr => "i32.rotr",
474 I64Clz => "i64.clz",
475 I64Ctz => "i64.ctz",
476 I64Popcnt => "i64.popcnd",
477 I64Add => "i64.add",
478 I64Sub => "i64.sub",
479 I64Mul => "i64.mul",
480 I64DivS => "i64.div_s",
481 I64DivU => "i64.div_u",
482 I64RemS => "i64.rem_s",
483 I64RemU => "i64.rem_u",
484 I64And => "i64.and",
485 I64Or => "i64.or",
486 I64Xor => "i64.xor",
487 I64Shl => "i64.shl",
488 I64ShrS => "i64.shr_s",
489 I64ShrU => "i64.shr_u",
490 I64Rotl => "i64.rotl",
491 I64Rotr => "i64.rotr",
492 F32Abs => "f32.abs",
493 F32Neg => "f32.neg",
494 F32Ceil => "f32.ceil",
495 F32Floor => "f32.floor",
496 F32Trunc => "f32.trunc",
497 F32Nearest => "f32.nearest",
498 F32Sqrt => "f32.sqrt",
499 F32Add => "f32.add",
500 F32Sub => "f32.sub",
501 F32Mul => "f32.mul",
502 F32Div => "f32.div",
503 F32Min => "f32.min",
504 F32Max => "f32.max",
505 F32Copysign => "f32.copysign",
506 F64Abs => "f64.abs",
507 F64Neg => "f64.neg",
508 F64Ceil => "f64.ceil",
509 F64Floor => "f64.floor",
510 F64Trunc => "f64.trunc",
511 F64Nearest => "f64.nearest",
512 F64Sqrt => "f64.sqrt",
513 F64Add => "f64.add",
514 F64Sub => "f64.sub",
515 F64Mul => "f64.mul",
516 F64Div => "f64.div",
517 F64Min => "f64.min",
518 F64Max => "f64.max",
519 F64Copysign => "f64.copysign",
520 I32Eqz => "i32.eqz",
522 I32Eq => "i32.eq",
523 I32Ne => "i32.ne",
524 I32LtS => "i32.lt_s",
525 I32LtU => "i32.lt_u",
526 I32GtS => "i32.gt_s",
527 I32GtU => "i32.gt_u",
528 I32LeS => "i32.le_s",
529 I32LeU => "i32.le_u",
530 I32GeS => "i32.ge_s",
531 I32GeU => "i32.ge_u",
532 I64Eqz => "i64.eqz",
534 I64Eq => "i64.eq",
535 I64Ne => "i64.ne",
536 I64LtS => "i64.lt_s",
537 I64LtU => "i64.lt_u",
538 I64GtS => "i64.gt_s",
539 I64GtU => "i64.gt_u",
540 I64LeS => "i64.le_s",
541 I64LeU => "i64.le_u",
542 I64GeS => "i64.ge_s",
543 I64GeU => "i64.ge_u",
544 F32Eq => "f32.eq",
546 F32Ne => "f32.ne",
547 F32Lt => "f32.lt",
548 F32Gt => "f32.gt",
549 F32Le => "f32.le",
550 F32Ge => "f32.ge",
551 F64Eq => "f64.eq",
553 F64Ne => "f64.ne",
554 F64Lt => "f64.lt",
555 F64Gt => "f64.gt",
556 F64Le => "f64.le",
557 F64Ge => "f64.ge",
558 I32WrapI64 => "i32.wrap_i64",
560 I32TruncF32S => "i32.trunc_f32_s",
561 I32TruncF32U => "i32.trunc_f32_u",
562 I32TruncF64S => "i32.trunc_f64_s",
563 I32TruncF64U => "i32.trunc_f64_u",
564 I64ExtendI32S => "i64.extend_i32_s",
565 I64ExtendI32U => "i64.extend_i32_u",
566 I64TruncF32S => "i64.trunc_f32_s",
567 I64TruncF32U => "i64.trunc_f32_u",
568 I64TruncF64S => "i64.trunc_f64_s",
569 I64TruncF64U => "i64.trunc_f64_u",
570 F32ConvertI32S => "f32.convert_i32_s",
571 F32ConvertI32U => "f32.convert_i32_u",
572 F32ConvertI64S => "f32.convert_i64_s",
573 F32ConvertI64U => "f32.convert_i64_u",
574 F32DemoteF64 => "f32.demote_f64",
575 F64ConvertI32S => "f64.convert_i32_s",
576 F64ConvertI32U => "f64.convert_i32_u",
577 F64ConvertI64S => "f64.convert_i64_s",
578 F64ConvertI64U => "f64.convert_i64_u",
579 F64PromoteF32 => "f64.promote_f32",
580 I32ReinterpretF32 => "i32.reinterpret_f32",
581 I64ReinterpretF64 => "i64.reinterpret_f64",
582 F32ReinterpretI32 => "f32.reinterpret_i32",
583 F64ReinterpretI64 => "f64.reinterpret_i64",
584 I32Extend8S => "i32.extend8_s",
586 I32Extend16S => "i32.extend16_s",
587 I64Extend8S => "i64.extend8_s",
588 I64Extend16S => "i64.extend16_s",
589 I64Extend32S => "i64.extend32_s",
590 }
591 }
592}
593
594#[derive(Debug, Clone, PartialEq)]
596pub struct ElemSegment {
597 pub start: usize,
598 pub idx: TableIdx,
599 pub offset: Vec<Instruction>, pub init: Vec<FuncIdx>,
601}
602
603#[derive(Debug, Clone, PartialEq)]
605pub struct Table<'s> {
606 pub start: usize,
607 pub ty: TableType,
608 pub import: Option<Import<'s>>,
609}
610
611#[derive(Debug, Clone, PartialEq)]
613pub struct DataSegment<'s> {
614 pub start: usize,
615 pub idx: MemIdx,
616 pub offset: Vec<Instruction>, pub data: Cow<'s, [u8]>,
618}
619
620#[derive(Debug, Clone, PartialEq)]
622pub struct Memory<'s> {
623 pub start: usize,
624 pub ty: MemType,
625 pub import: Option<Import<'s>>,
626}
627
628#[derive(Debug, Clone, PartialEq)]
631pub enum GlobalKind<'s> {
632 Import(Import<'s>),
633 Init(Vec<Instruction>), }
635
636#[derive(Debug, Clone, PartialEq)]
637pub struct Global<'s> {
638 pub start: usize,
639 pub mutable: bool,
640 pub ty: ValType,
641 pub kind: GlobalKind<'s>,
642}
643
644#[derive(Debug, Clone, PartialEq)]
646pub struct StartFunction {
647 pub start: usize,
648 pub idx: FuncIdx,
649}