1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::fmt;
4
5type Indices<'s> = HashMap<&'s str, u32>;
10
11#[cfg_attr(test, derive(Debug))]
13pub struct Parsed<'s> {
14 pub module: Module<'s>,
15 pub type_indices: Indices<'s>,
16 pub func_indices: Indices<'s>,
17 pub table_indices: Indices<'s>,
18 pub mem_indices: Indices<'s>,
19 pub global_indices: Indices<'s>,
20}
21
22#[cfg_attr(test, derive(Debug))]
27pub struct Module<'s> {
28 pub start: usize,
29 pub id: Option<&'s str>,
30 pub types: Vec<TypeDef<'s>>,
31 pub exports: Vec<Export<'s>>,
32 pub funcs: Vec<Func<'s>>,
33 pub elems: Vec<Elem<'s>>,
34 pub tables: Vec<Table<'s>>,
35 pub data: Vec<Data<'s>>,
36 pub memories: Vec<Memory<'s>>,
37 pub globals: Vec<Global<'s>>,
38 pub entrypoint: Option<Start<'s>>,
39 pub implicit_type_uses: Vec<u32>,
40}
41
42#[cfg_attr(test, derive(Debug))]
44pub struct TypeDef<'s> {
45 pub start: usize,
46 pub id: Option<&'s str>,
47 pub ty: FuncType<'s>,
48}
49
50#[derive(Clone)]
52#[cfg_attr(test, derive(Debug))]
53pub struct FuncType<'s> {
54 pub start: usize,
55 pub params: Vec<Param<'s>>,
56 pub results: Vec<FuncResult>,
57}
58
59#[derive(Clone)]
61#[cfg_attr(test, derive(Debug))]
62pub struct Param<'s> {
63 pub start: usize,
64 pub id: Option<&'s str>,
65 pub ty: ValType,
66}
67
68#[derive(Clone)]
70#[cfg_attr(test, derive(Debug))]
71pub struct FuncResult {
72 pub start: usize,
73 pub ty: ValType,
74}
75
76#[derive(PartialEq, Clone, Copy)]
78#[cfg_attr(test, derive(Debug))]
79pub enum ValType {
80 I32,
81 I64,
82 F32,
83 F64,
84}
85
86impl fmt::Display for ValType {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 f.write_str(match self {
89 ValType::I32 => "i32",
90 ValType::I64 => "i64",
91 ValType::F32 => "f32",
92 ValType::F64 => "f64",
93 })
94 }
95}
96
97#[cfg_attr(test, derive(Debug))]
99pub struct Import<'s> {
100 pub mod_name: Name<'s>,
101 pub name: Name<'s>,
102}
103
104#[cfg_attr(test, derive(Debug))]
111pub struct Name<'s>(pub Cow<'s, str>);
112
113#[cfg_attr(test, derive(Debug, PartialEq))]
117pub enum TypeIndex<'s> {
118 Explicit(Index<'s>),
119 Implicit(u32),
120}
121
122#[cfg_attr(test, derive(Debug))]
124pub struct TypeUse<'s> {
125 pub start: usize,
126 pub idx: TypeIndex<'s>,
127 pub params: Vec<Param<'s>>,
128 pub results: Vec<FuncResult>,
129}
130
131pub struct ImplicitTypeUse<'s> {
133 pub start: usize,
134 pub params: Vec<Param<'s>>,
135 pub results: Vec<FuncResult>,
136}
137
138#[cfg_attr(test, derive(Debug, PartialEq))]
140pub enum Index<'s> {
141 Num(u32),
142 Ident(&'s str),
143}
144impl<'s> fmt::Display for Index<'s> {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 match self {
147 Index::Num(i) => write!(f, "{}", i),
148 Index::Ident(i) => write!(f, "{}", i),
149 }
150 }
151}
152
153#[cfg_attr(test, derive(Debug))]
156pub struct TableType {
157 pub limit: Limits,
158}
159
160#[cfg_attr(test, derive(Debug))]
162pub enum Limits {
163 Range { min: u32, max: u32 },
164 From { min: u32 },
165}
166
167#[cfg_attr(test, derive(Debug))]
169pub struct MemType {
170 pub limit: Limits,
171}
172
173#[cfg_attr(test, derive(Debug))]
175pub struct GlobalType {
176 pub mutable: bool,
177 pub ty: ValType,
178}
179
180#[cfg_attr(test, derive(Debug))]
182pub struct Export<'s> {
183 pub start: usize,
184 pub name: Name<'s>,
185 pub kind: ExportKind,
186 pub idx: Index<'s>,
187}
188
189#[cfg_attr(test, derive(Debug))]
191pub enum ExportKind {
192 Func,
193 Table,
194 Memory,
195 Global,
196}
197
198#[cfg_attr(test, derive(Debug))]
200pub enum FuncKind<'s> {
201 Import(Import<'s>),
202 Body {
203 locals: Vec<Local<'s>>,
204 body: Vec<Instruction<'s>>,
205 },
206}
207#[cfg_attr(test, derive(Debug))]
208pub struct Func<'s> {
209 pub start: usize,
210 pub id: Option<&'s str>,
211 pub ty: TypeUse<'s>,
212 pub kind: FuncKind<'s>,
213}
214
215#[cfg_attr(test, derive(Debug))]
217pub struct Local<'s> {
218 pub start: usize,
219 pub id: Option<&'s str>,
220 pub ty: ValType,
221}
222
223#[cfg_attr(test, derive(Debug))]
225pub struct Instruction<'s> {
226 pub start: usize,
227 pub kind: InsnKind<'s>,
228}
229
230#[cfg_attr(test, derive(Debug))]
232pub struct Mem {
233 pub align: u32,
234 pub offset: u32,
235}
236
237#[cfg_attr(test, derive(Debug))]
238pub enum InsnKind<'s> {
239 Block {
242 label: Option<&'s str>,
243 ty: Option<ValType>,
244 body: Vec<Instruction<'s>>,
245 id: Option<&'s str>,
246 },
247 Loop {
248 label: Option<&'s str>,
249 ty: Option<ValType>,
250 body: Vec<Instruction<'s>>,
251 id: Option<&'s str>,
252 },
253 If {
254 label: Option<&'s str>,
255 ty: Option<ValType>,
256 then_body: Vec<Instruction<'s>>,
257 else_id: Option<&'s str>,
258 else_body: Vec<Instruction<'s>>,
259 end_id: Option<&'s str>,
260 },
261 Unreachable,
262 Nop,
263 Br(Index<'s>),
264 BrIf(Index<'s>),
265 BrTable {
266 labels: Vec<Index<'s>>,
267 default_label: Index<'s>,
268 },
269 Return,
270 Call(Index<'s>),
271 CallIndirect(TypeUse<'s>),
272 Drop,
275 Select,
276 LocalGet(Index<'s>),
279 LocalSet(Index<'s>),
280 LocalTee(Index<'s>),
281 GlobalGet(Index<'s>),
282 GlobalSet(Index<'s>),
283 I32Load(Mem),
286 I64Load(Mem),
287 F32Load(Mem),
288 F64Load(Mem),
289 I32Load8S(Mem),
290 I32Load8U(Mem),
291 I32Load16S(Mem),
292 I32Load16U(Mem),
293 I64Load8S(Mem),
294 I64Load8U(Mem),
295 I64Load16S(Mem),
296 I64Load16U(Mem),
297 I64Load32S(Mem),
298 I64Load32U(Mem),
299 I32Store(Mem),
300 I64Store(Mem),
301 F32Store(Mem),
302 F64Store(Mem),
303 I32Store8(Mem),
304 I32Store16(Mem),
305 I64Store8(Mem),
306 I64Store16(Mem),
307 I64Store32(Mem),
308 MemorySize,
309 MemoryGrow,
310 I32Const(i32),
314 I64Const(i64),
315 F32Const(f32),
316 F64Const(f64),
317 I32Clz,
319 I32Ctz,
320 I32Popcnt,
321 I32Add,
322 I32Sub,
323 I32Mul,
324 I32DivS,
325 I32DivU,
326 I32RemS,
327 I32RemU,
328 I32And,
329 I32Or,
330 I32Xor,
331 I32Shl,
332 I32ShrS,
333 I32ShrU,
334 I32Rotl,
335 I32Rotr,
336 I64Clz,
338 I64Ctz,
339 I64Popcnt,
340 I64Add,
341 I64Sub,
342 I64Mul,
343 I64DivS,
344 I64DivU,
345 I64RemS,
346 I64RemU,
347 I64And,
348 I64Or,
349 I64Xor,
350 I64Shl,
351 I64ShrS,
352 I64ShrU,
353 I64Rotl,
354 I64Rotr,
355 F32Abs,
357 F32Neg,
358 F32Ceil,
359 F32Floor,
360 F32Trunc,
361 F32Nearest,
362 F32Sqrt,
363 F32Add,
364 F32Sub,
365 F32Mul,
366 F32Div,
367 F32Min,
368 F32Max,
369 F32Copysign,
370 F64Abs,
372 F64Neg,
373 F64Ceil,
374 F64Floor,
375 F64Trunc,
376 F64Nearest,
377 F64Sqrt,
378 F64Add,
379 F64Sub,
380 F64Mul,
381 F64Div,
382 F64Min,
383 F64Max,
384 F64Copysign,
385 I32Eqz,
387 I32Eq,
388 I32Ne,
389 I32LtS,
390 I32LtU,
391 I32GtS,
392 I32GtU,
393 I32LeS,
394 I32LeU,
395 I32GeS,
396 I32GeU,
397 I64Eqz,
399 I64Eq,
400 I64Ne,
401 I64LtS,
402 I64LtU,
403 I64GtS,
404 I64GtU,
405 I64LeS,
406 I64LeU,
407 I64GeS,
408 I64GeU,
409 F32Eq,
411 F32Ne,
412 F32Lt,
413 F32Gt,
414 F32Le,
415 F32Ge,
416 F64Eq,
418 F64Ne,
419 F64Lt,
420 F64Gt,
421 F64Le,
422 F64Ge,
423 I32WrapI64,
425 I32TruncF32S,
426 I32TruncF32U,
427 I32TruncF64S,
428 I32TruncF64U,
429 I64ExtendI32S,
430 I64ExtendI32U,
431 I64TruncF32S,
432 I64TruncF32U,
433 I64TruncF64S,
434 I64TruncF64U,
435 F32ConvertI32S,
436 F32ConvertI32U,
437 F32ConvertI64S,
438 F32ConvertI64U,
439 F32DemoteF64,
440 F64ConvertI32S,
441 F64ConvertI32U,
442 F64ConvertI64S,
443 F64ConvertI64U,
444 F64PromoteF32,
445 I32ReinterpretF32,
446 I64ReinterpretF64,
447 F32ReinterpretI32,
448 F64ReinterpretI64,
449 I32Extend8S,
451 I32Extend16S,
452 I64Extend8S,
453 I64Extend16S,
454 I64Extend32S,
455}
456
457impl<'s> InsnKind<'s> {
458 pub fn is_block(&self) -> bool {
459 use InsnKind::*;
460 matches!(self, Block { .. } | Loop { .. } | If { .. })
461 }
462}
463
464#[cfg_attr(test, derive(Debug))]
466pub struct Elem<'s> {
467 pub start: usize,
468 pub idx: Index<'s>,
469 pub offset: Vec<Instruction<'s>>,
470 pub init: Vec<Index<'s>>,
471}
472
473#[cfg_attr(test, derive(Debug))]
475pub struct Table<'s> {
476 pub start: usize,
477 pub id: Option<&'s str>,
478 pub ty: TableType,
479 pub import: Option<Import<'s>>,
480}
481
482#[cfg_attr(test, derive(Debug))]
484pub struct Data<'s> {
485 pub start: usize,
486 pub idx: Index<'s>,
487 pub offset: Vec<Instruction<'s>>,
488 pub data: Cow<'s, [u8]>,
489}
490
491#[cfg_attr(test, derive(Debug))]
493pub struct Memory<'s> {
494 pub start: usize,
495 pub id: Option<&'s str>,
496 pub ty: MemType,
497 pub import: Option<Import<'s>>,
498}
499
500#[cfg_attr(test, derive(Debug))]
502pub enum GlobalKind<'s> {
503 Import(Import<'s>),
504 Init(Vec<Instruction<'s>>),
505}
506#[cfg_attr(test, derive(Debug))]
507pub struct Global<'s> {
508 pub start: usize,
509 pub id: Option<&'s str>,
510 pub ty: GlobalType,
511 pub kind: GlobalKind<'s>,
512}
513
514#[cfg_attr(test, derive(Debug))]
516pub struct Start<'s> {
517 pub start: usize,
518 pub idx: Index<'s>,
519}
520
521#[cfg(test)]
522mod tests {
523 use super::*;
524
525 #[test]
526 fn insn_is_block() {
527 let insn = InsnKind::Block {
528 label: None,
529 ty: None,
530 body: vec![],
531 id: None,
532 };
533 assert!(insn.is_block());
534 assert!(!InsnKind::Nop.is_block());
535 }
536}