1use std::{io, fmt};
2use super::{
3 Serialize, Deserialize, Error, VarUint7,
4 VarUint1, VarUint32, CountedList, BlockType,
5 Uint32, Uint64, CountedListWriter,
6 VarInt32, VarInt64,
7};
8
9#[derive(Debug, PartialEq, Clone)]
11pub struct Opcodes(Vec<Opcode>);
12
13impl Opcodes {
14 pub fn new(elements: Vec<Opcode>) -> Self {
16 Opcodes(elements)
17 }
18
19 pub fn empty() -> Self {
21 Opcodes(vec![Opcode::End])
22 }
23
24 pub fn elements(&self) -> &[Opcode] { &self.0 }
26
27 pub fn elements_mut(&mut self) -> &mut Vec<Opcode> { &mut self.0 }
29}
30
31impl Deserialize for Opcodes {
32 type Error = Error;
33
34 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
35 let mut opcodes = Vec::new();
36 let mut block_count = 1usize;
37
38 loop {
39 let opcode = Opcode::deserialize(reader)?;
40 if opcode.is_terminal() {
41 block_count -= 1;
42 } else if opcode.is_block() {
43 block_count = block_count.checked_add(1).ok_or(Error::Other("too many opcodes"))?;
44 }
45
46 opcodes.push(opcode);
47 if block_count == 0 {
48 break;
49 }
50 }
51
52 Ok(Opcodes(opcodes))
53 }
54}
55
56#[derive(Debug, Clone)]
58pub struct InitExpr(Vec<Opcode>);
59
60impl InitExpr {
61 pub fn new(code: Vec<Opcode>) -> Self {
64 InitExpr(code)
65 }
66
67 pub fn empty() -> Self {
69 InitExpr(vec![Opcode::End])
70 }
71
72 pub fn code(&self) -> &[Opcode] {
74 &self.0
75 }
76
77 pub fn code_mut(&mut self) -> &mut Vec<Opcode> {
79 &mut self.0
80 }
81}
82
83impl Deserialize for InitExpr {
85 type Error = Error;
86
87 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
88 let mut opcodes = Vec::new();
89
90 loop {
91 let opcode = Opcode::deserialize(reader)?;
92 let is_terminal = opcode.is_terminal();
93 opcodes.push(opcode);
94 if is_terminal {
95 break;
96 }
97 }
98
99 Ok(InitExpr(opcodes))
100 }
101}
102
103#[derive(Clone, Debug, PartialEq)]
105#[allow(missing_docs)]
106pub enum Opcode {
107 Unreachable,
108 Nop,
109 Block(BlockType),
110 Loop(BlockType),
111 If(BlockType),
112 Else,
113 End,
114 Br(u32),
115 BrIf(u32),
116 BrTable(Vec<u32>, u32),
117 Return,
118
119 Call(u32),
120 CallIndirect(u32, bool),
121
122 Drop,
123 Select,
124
125 GetLocal(u32),
126 SetLocal(u32),
127 TeeLocal(u32),
128 GetGlobal(u32),
129 SetGlobal(u32),
130
131 I32Load(u32, u32),
134 I64Load(u32, u32),
135 F32Load(u32, u32),
136 F64Load(u32, u32),
137 I32Load8S(u32, u32),
138 I32Load8U(u32, u32),
139 I32Load16S(u32, u32),
140 I32Load16U(u32, u32),
141 I64Load8S(u32, u32),
142 I64Load8U(u32, u32),
143 I64Load16S(u32, u32),
144 I64Load16U(u32, u32),
145 I64Load32S(u32, u32),
146 I64Load32U(u32, u32),
147 I32Store(u32, u32),
148 I64Store(u32, u32),
149 F32Store(u32, u32),
150 F64Store(u32, u32),
151 I32Store8(u32, u32),
152 I32Store16(u32, u32),
153 I64Store8(u32, u32),
154 I64Store16(u32, u32),
155 I64Store32(u32, u32),
156
157 CurrentMemory(bool),
158 GrowMemory(bool),
159
160 I32Const(i32),
161 I64Const(i64),
162 F32Const(u32),
163 F64Const(u64),
164
165 I32Eqz,
166 I32Eq,
167 I32Ne,
168 I32LtS,
169 I32LtU,
170 I32GtS,
171 I32GtU,
172 I32LeS,
173 I32LeU,
174 I32GeS,
175 I32GeU,
176
177 I64Eqz,
178 I64Eq,
179 I64Ne,
180 I64LtS,
181 I64LtU,
182 I64GtS,
183 I64GtU,
184 I64LeS,
185 I64LeU,
186 I64GeS,
187 I64GeU,
188
189 F32Eq,
190 F32Ne,
191 F32Lt,
192 F32Gt,
193 F32Le,
194 F32Ge,
195
196 F64Eq,
197 F64Ne,
198 F64Lt,
199 F64Gt,
200 F64Le,
201 F64Ge,
202
203 I32Clz,
204 I32Ctz,
205 I32Popcnt,
206 I32Add,
207 I32Sub,
208 I32Mul,
209 I32DivS,
210 I32DivU,
211 I32RemS,
212 I32RemU,
213 I32And,
214 I32Or,
215 I32Xor,
216 I32Shl,
217 I32ShrS,
218 I32ShrU,
219 I32Rotl,
220 I32Rotr,
221
222 I64Clz,
223 I64Ctz,
224 I64Popcnt,
225 I64Add,
226 I64Sub,
227 I64Mul,
228 I64DivS,
229 I64DivU,
230 I64RemS,
231 I64RemU,
232 I64And,
233 I64Or,
234 I64Xor,
235 I64Shl,
236 I64ShrS,
237 I64ShrU,
238 I64Rotl,
239 I64Rotr,
240 F32Abs,
241 F32Neg,
242 F32Ceil,
243 F32Floor,
244 F32Trunc,
245 F32Nearest,
246 F32Sqrt,
247 F32Add,
248 F32Sub,
249 F32Mul,
250 F32Div,
251 F32Min,
252 F32Max,
253 F32Copysign,
254 F64Abs,
255 F64Neg,
256 F64Ceil,
257 F64Floor,
258 F64Trunc,
259 F64Nearest,
260 F64Sqrt,
261 F64Add,
262 F64Sub,
263 F64Mul,
264 F64Div,
265 F64Min,
266 F64Max,
267 F64Copysign,
268
269 I32WarpI64,
270 I32TruncSF32,
271 I32TruncUF32,
272 I32TruncSF64,
273 I32TruncUF64,
274 I64ExtendSI32,
275 I64ExtendUI32,
276 I64TruncSF32,
277 I64TruncUF32,
278 I64TruncSF64,
279 I64TruncUF64,
280 F32ConvertSI32,
281 F32ConvertUI32,
282 F32ConvertSI64,
283 F32ConvertUI64,
284 F32DemoteF64,
285 F64ConvertSI32,
286 F64ConvertUI32,
287 F64ConvertSI64,
288 F64ConvertUI64,
289 F64PromoteF32,
290
291 I32ReinterpretF32,
292 I64ReinterpretF64,
293 F32ReinterpretI32,
294 F64ReinterpretI64,
295}
296
297impl Opcode {
298 pub fn is_block(&self) -> bool {
300 match self {
301 &Opcode::Block(_) | &Opcode::Loop(_) | &Opcode::If(_) => true,
302 _ => false,
303 }
304 }
305
306 pub fn is_terminal(&self) -> bool {
309 match self {
310 &Opcode::End => true,
311 _ => false,
312 }
313 }
314}
315
316impl Deserialize for Opcode {
317 type Error = Error;
318
319 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
320 use self::Opcode::*;
321
322 let val: u8 = VarUint7::deserialize(reader)?.into();
323
324 Ok(
325 match val {
326 0x00 => Unreachable,
327 0x01 => Nop,
328 0x02 => Block(BlockType::deserialize(reader)?),
329 0x03 => Loop(BlockType::deserialize(reader)?),
330 0x04 => If(BlockType::deserialize(reader)?),
331 0x05 => Else,
332 0x0b => End,
333
334 0x0c => Br(VarUint32::deserialize(reader)?.into()),
335 0x0d => BrIf(VarUint32::deserialize(reader)?.into()),
336 0x0e => {
337 let t1: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
338 .into_inner()
339 .into_iter()
340 .map(Into::into)
341 .collect();
342
343 BrTable(t1, VarUint32::deserialize(reader)?.into())
344 },
345 0x0f => Return,
346 0x10 => Call(VarUint32::deserialize(reader)?.into()),
347 0x11 => CallIndirect(
348 VarUint32::deserialize(reader)?.into(),
349 VarUint1::deserialize(reader)?.into()),
350 0x1a => Drop,
351 0x1b => Select,
352
353 0x20 => GetLocal(VarUint32::deserialize(reader)?.into()),
354 0x21 => SetLocal(VarUint32::deserialize(reader)?.into()),
355 0x22 => TeeLocal(VarUint32::deserialize(reader)?.into()),
356 0x23 => GetGlobal(VarUint32::deserialize(reader)?.into()),
357 0x24 => SetGlobal(VarUint32::deserialize(reader)?.into()),
358
359 0x28 => I32Load(
360 VarUint32::deserialize(reader)?.into(),
361 VarUint32::deserialize(reader)?.into()),
362
363 0x29 => I64Load(
364 VarUint32::deserialize(reader)?.into(),
365 VarUint32::deserialize(reader)?.into()),
366
367 0x2a => F32Load(
368 VarUint32::deserialize(reader)?.into(),
369 VarUint32::deserialize(reader)?.into()),
370
371 0x2b => F64Load(
372 VarUint32::deserialize(reader)?.into(),
373 VarUint32::deserialize(reader)?.into()),
374
375 0x2c => I32Load8S(
376 VarUint32::deserialize(reader)?.into(),
377 VarUint32::deserialize(reader)?.into()),
378
379 0x2d => I32Load8U(
380 VarUint32::deserialize(reader)?.into(),
381 VarUint32::deserialize(reader)?.into()),
382
383 0x2e => I32Load16S(
384 VarUint32::deserialize(reader)?.into(),
385 VarUint32::deserialize(reader)?.into()),
386
387 0x2f => I32Load16U(
388 VarUint32::deserialize(reader)?.into(),
389 VarUint32::deserialize(reader)?.into()),
390
391 0x30 => I64Load8S(
392 VarUint32::deserialize(reader)?.into(),
393 VarUint32::deserialize(reader)?.into()),
394
395 0x31 => I64Load8U(
396 VarUint32::deserialize(reader)?.into(),
397 VarUint32::deserialize(reader)?.into()),
398
399 0x32 => I64Load16S(
400 VarUint32::deserialize(reader)?.into(),
401 VarUint32::deserialize(reader)?.into()),
402
403 0x33 => I64Load16U(
404 VarUint32::deserialize(reader)?.into(),
405 VarUint32::deserialize(reader)?.into()),
406
407 0x34 => I64Load32S(
408 VarUint32::deserialize(reader)?.into(),
409 VarUint32::deserialize(reader)?.into()),
410
411 0x35 => I64Load32U(
412 VarUint32::deserialize(reader)?.into(),
413 VarUint32::deserialize(reader)?.into()),
414
415 0x36 => I32Store(
416 VarUint32::deserialize(reader)?.into(),
417 VarUint32::deserialize(reader)?.into()),
418
419 0x37 => I64Store(
420 VarUint32::deserialize(reader)?.into(),
421 VarUint32::deserialize(reader)?.into()),
422
423 0x38 => F32Store(
424 VarUint32::deserialize(reader)?.into(),
425 VarUint32::deserialize(reader)?.into()),
426
427 0x39 => F64Store(
428 VarUint32::deserialize(reader)?.into(),
429 VarUint32::deserialize(reader)?.into()),
430
431 0x3a => I32Store8(
432 VarUint32::deserialize(reader)?.into(),
433 VarUint32::deserialize(reader)?.into()),
434
435 0x3b => I32Store16(
436 VarUint32::deserialize(reader)?.into(),
437 VarUint32::deserialize(reader)?.into()),
438
439 0x3c => I64Store8(
440 VarUint32::deserialize(reader)?.into(),
441 VarUint32::deserialize(reader)?.into()),
442
443 0x3d => I64Store16(
444 VarUint32::deserialize(reader)?.into(),
445 VarUint32::deserialize(reader)?.into()),
446
447 0x3e => I64Store32(
448 VarUint32::deserialize(reader)?.into(),
449 VarUint32::deserialize(reader)?.into()),
450
451
452 0x3f => CurrentMemory(VarUint1::deserialize(reader)?.into()),
453 0x40 => GrowMemory(VarUint1::deserialize(reader)?.into()),
454
455 0x41 => I32Const(VarInt32::deserialize(reader)?.into()),
456 0x42 => I64Const(VarInt64::deserialize(reader)?.into()),
457 0x43 => F32Const(Uint32::deserialize(reader)?.into()),
458 0x44 => F64Const(Uint64::deserialize(reader)?.into()),
459 0x45 => I32Eqz,
460 0x46 => I32Eq,
461 0x47 => I32Ne,
462 0x48 => I32LtS,
463 0x49 => I32LtU,
464 0x4a => I32GtS,
465 0x4b => I32GtU,
466 0x4c => I32LeS,
467 0x4d => I32LeU,
468 0x4e => I32GeS,
469 0x4f => I32GeU,
470
471 0x50 => I64Eqz,
472 0x51 => I64Eq,
473 0x52 => I64Ne,
474 0x53 => I64LtS,
475 0x54 => I64LtU,
476 0x55 => I64GtS,
477 0x56 => I64GtU,
478 0x57 => I64LeS,
479 0x58 => I64LeU,
480 0x59 => I64GeS,
481 0x5a => I64GeU,
482
483 0x5b => F32Eq,
484 0x5c => F32Ne,
485 0x5d => F32Lt,
486 0x5e => F32Gt,
487 0x5f => F32Le,
488 0x60 => F32Ge,
489
490 0x61 => F64Eq,
491 0x62 => F64Ne,
492 0x63 => F64Lt,
493 0x64 => F64Gt,
494 0x65 => F64Le,
495 0x66 => F64Ge,
496
497 0x67 => I32Clz,
498 0x68 => I32Ctz,
499 0x69 => I32Popcnt,
500 0x6a => I32Add,
501 0x6b => I32Sub,
502 0x6c => I32Mul,
503 0x6d => I32DivS,
504 0x6e => I32DivU,
505 0x6f => I32RemS,
506 0x70 => I32RemU,
507 0x71 => I32And,
508 0x72 => I32Or,
509 0x73 => I32Xor,
510 0x74 => I32Shl,
511 0x75 => I32ShrS,
512 0x76 => I32ShrU,
513 0x77 => I32Rotl,
514 0x78 => I32Rotr,
515
516 0x79 => I64Clz,
517 0x7a => I64Ctz,
518 0x7b => I64Popcnt,
519 0x7c => I64Add,
520 0x7d => I64Sub,
521 0x7e => I64Mul,
522 0x7f => I64DivS,
523 0x80 => I64DivU,
524 0x81 => I64RemS,
525 0x82 => I64RemU,
526 0x83 => I64And,
527 0x84 => I64Or,
528 0x85 => I64Xor,
529 0x86 => I64Shl,
530 0x87 => I64ShrS,
531 0x88 => I64ShrU,
532 0x89 => I64Rotl,
533 0x8a => I64Rotr,
534 0x8b => F32Abs,
535 0x8c => F32Neg,
536 0x8d => F32Ceil,
537 0x8e => F32Floor,
538 0x8f => F32Trunc,
539 0x90 => F32Nearest,
540 0x91 => F32Sqrt,
541 0x92 => F32Add,
542 0x93 => F32Sub,
543 0x94 => F32Mul,
544 0x95 => F32Div,
545 0x96 => F32Min,
546 0x97 => F32Max,
547 0x98 => F32Copysign,
548 0x99 => F64Abs,
549 0x9a => F64Neg,
550 0x9b => F64Ceil,
551 0x9c => F64Floor,
552 0x9d => F64Trunc,
553 0x9e => F64Nearest,
554 0x9f => F64Sqrt,
555 0xa0 => F64Add,
556 0xa1 => F64Sub,
557 0xa2 => F64Mul,
558 0xa3 => F64Div,
559 0xa4 => F64Min,
560 0xa5 => F64Max,
561 0xa6 => F64Copysign,
562
563 0xa7 => I32WarpI64,
564 0xa8 => I32TruncSF32,
565 0xa9 => I32TruncUF32,
566 0xaa => I32TruncSF64,
567 0xab => I32TruncUF64,
568 0xac => I64ExtendSI32,
569 0xad => I64ExtendUI32,
570 0xae => I64TruncSF32,
571 0xaf => I64TruncUF32,
572 0xb0 => I64TruncSF64,
573 0xb1 => I64TruncUF64,
574 0xb2 => F32ConvertSI32,
575 0xb3 => F32ConvertUI32,
576 0xb4 => F32ConvertSI64,
577 0xb5 => F32ConvertUI64,
578 0xb6 => F32DemoteF64,
579 0xb7 => F64ConvertSI32,
580 0xb8 => F64ConvertUI32,
581 0xb9 => F64ConvertSI64,
582 0xba => F64ConvertUI64,
583 0xbb => F64PromoteF32,
584
585 0xbc => I32ReinterpretF32,
586 0xbd => I64ReinterpretF64,
587 0xbe => F32ReinterpretI32,
588 0xbf => F64ReinterpretI64,
589
590 _ => { return Err(Error::UnknownOpcode(val)); }
591 }
592 )
593 }
594}
595
596macro_rules! op {
597 ($writer: expr, $byte: expr) => ({
598 let b: u8 = $byte;
599 $writer.write_all(&[b])?;
600 });
601 ($writer: expr, $byte: expr, $s: block) => ({
602 op!($writer, $byte);
603 $s;
604 });
605}
606
607impl Serialize for Opcode {
608 type Error = Error;
609
610 fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
611 use self::Opcode::*;
612
613 match self {
614 Unreachable => op!(writer, 0x00),
615 Nop => op!(writer, 0x01),
616 Block(block_type) => op!(writer, 0x02, {
617 block_type.serialize(writer)?;
618 }),
619 Loop(block_type) => op!(writer, 0x03, {
620 block_type.serialize(writer)?;
621 }),
622 If(block_type) => op!(writer, 0x04, {
623 block_type.serialize(writer)?;
624 }),
625 Else => op!(writer, 0x05),
626 End => op!(writer, 0x0b),
627 Br(idx) => op!(writer, 0x0c, {
628 VarUint32::from(idx).serialize(writer)?;
629 }),
630 BrIf(idx) => op!(writer, 0x0d, {
631 VarUint32::from(idx).serialize(writer)?;
632 }),
633 BrTable(table, default) => op!(writer, 0x0e, {
634 let list_writer = CountedListWriter::<VarUint32, _>(
635 table.len(),
636 table.into_iter().map(Into::into),
637 );
638 list_writer.serialize(writer)?;
639 VarUint32::from(default).serialize(writer)?;
640 }),
641 Return => op!(writer, 0x0f),
642 Call(index) => op!(writer, 0x10, {
643 VarUint32::from(index).serialize(writer)?;
644 }),
645 CallIndirect(index, reserved) => op!(writer, 0x11, {
646 VarUint32::from(index).serialize(writer)?;
647 VarUint1::from(reserved).serialize(writer)?;
648 }),
649 Drop => op!(writer, 0x1a),
650 Select => op!(writer, 0x1b),
651 GetLocal(index) => op!(writer, 0x20, {
652 VarUint32::from(index).serialize(writer)?;
653 }),
654 SetLocal(index) => op!(writer, 0x21, {
655 VarUint32::from(index).serialize(writer)?;
656 }),
657 TeeLocal(index) => op!(writer, 0x22, {
658 VarUint32::from(index).serialize(writer)?;
659 }),
660 GetGlobal(index) => op!(writer, 0x23, {
661 VarUint32::from(index).serialize(writer)?;
662 }),
663 SetGlobal(index) => op!(writer, 0x24, {
664 VarUint32::from(index).serialize(writer)?;
665 }),
666 I32Load(flags, offset) => op!(writer, 0x28, {
667 VarUint32::from(flags).serialize(writer)?;
668 VarUint32::from(offset).serialize(writer)?;
669 }),
670 I64Load(flags, offset) => op!(writer, 0x29, {
671 VarUint32::from(flags).serialize(writer)?;
672 VarUint32::from(offset).serialize(writer)?;
673 }),
674 F32Load(flags, offset) => op!(writer, 0x2a, {
675 VarUint32::from(flags).serialize(writer)?;
676 VarUint32::from(offset).serialize(writer)?;
677 }),
678 F64Load(flags, offset) => op!(writer, 0x2b, {
679 VarUint32::from(flags).serialize(writer)?;
680 VarUint32::from(offset).serialize(writer)?;
681 }),
682 I32Load8S(flags, offset) => op!(writer, 0x2c, {
683 VarUint32::from(flags).serialize(writer)?;
684 VarUint32::from(offset).serialize(writer)?;
685 }),
686 I32Load8U(flags, offset) => op!(writer, 0x2d, {
687 VarUint32::from(flags).serialize(writer)?;
688 VarUint32::from(offset).serialize(writer)?;
689 }),
690 I32Load16S(flags, offset) => op!(writer, 0x2e, {
691 VarUint32::from(flags).serialize(writer)?;
692 VarUint32::from(offset).serialize(writer)?;
693 }),
694 I32Load16U(flags, offset) => op!(writer, 0x2f, {
695 VarUint32::from(flags).serialize(writer)?;
696 VarUint32::from(offset).serialize(writer)?;
697 }),
698 I64Load8S(flags, offset) => op!(writer, 0x30, {
699 VarUint32::from(flags).serialize(writer)?;
700 VarUint32::from(offset).serialize(writer)?;
701 }),
702 I64Load8U(flags, offset) => op!(writer, 0x31, {
703 VarUint32::from(flags).serialize(writer)?;
704 VarUint32::from(offset).serialize(writer)?;
705 }),
706 I64Load16S(flags, offset) => op!(writer, 0x32, {
707 VarUint32::from(flags).serialize(writer)?;
708 VarUint32::from(offset).serialize(writer)?;
709 }),
710 I64Load16U(flags, offset) => op!(writer, 0x33, {
711 VarUint32::from(flags).serialize(writer)?;
712 VarUint32::from(offset).serialize(writer)?;
713 }),
714 I64Load32S(flags, offset) => op!(writer, 0x34, {
715 VarUint32::from(flags).serialize(writer)?;
716 VarUint32::from(offset).serialize(writer)?;
717 }),
718 I64Load32U(flags, offset) => op!(writer, 0x35, {
719 VarUint32::from(flags).serialize(writer)?;
720 VarUint32::from(offset).serialize(writer)?;
721 }),
722 I32Store(flags, offset) => op!(writer, 0x36, {
723 VarUint32::from(flags).serialize(writer)?;
724 VarUint32::from(offset).serialize(writer)?;
725 }),
726 I64Store(flags, offset) => op!(writer, 0x37, {
727 VarUint32::from(flags).serialize(writer)?;
728 VarUint32::from(offset).serialize(writer)?;
729 }),
730 F32Store(flags, offset) => op!(writer, 0x38, {
731 VarUint32::from(flags).serialize(writer)?;
732 VarUint32::from(offset).serialize(writer)?;
733 }),
734 F64Store(flags, offset) => op!(writer, 0x39, {
735 VarUint32::from(flags).serialize(writer)?;
736 VarUint32::from(offset).serialize(writer)?;
737 }),
738 I32Store8(flags, offset) => op!(writer, 0x3a, {
739 VarUint32::from(flags).serialize(writer)?;
740 VarUint32::from(offset).serialize(writer)?;
741 }),
742 I32Store16(flags, offset) => op!(writer, 0x3b, {
743 VarUint32::from(flags).serialize(writer)?;
744 VarUint32::from(offset).serialize(writer)?;
745 }),
746 I64Store8(flags, offset) => op!(writer, 0x3c, {
747 VarUint32::from(flags).serialize(writer)?;
748 VarUint32::from(offset).serialize(writer)?;
749 }),
750 I64Store16(flags, offset) => op!(writer, 0x3d, {
751 VarUint32::from(flags).serialize(writer)?;
752 VarUint32::from(offset).serialize(writer)?;
753 }),
754 I64Store32(flags, offset) => op!(writer, 0x3e, {
755 VarUint32::from(flags).serialize(writer)?;
756 VarUint32::from(offset).serialize(writer)?;
757 }),
758 CurrentMemory(flag) => op!(writer, 0x3f, {
759 VarUint1::from(flag).serialize(writer)?;
760 }),
761 GrowMemory(flag) => op!(writer, 0x40, {
762 VarUint1::from(flag).serialize(writer)?;
763 }),
764 I32Const(def) => op!(writer, 0x41, {
765 VarInt32::from(def).serialize(writer)?;
766 }),
767 I64Const(def) => op!(writer, 0x42, {
768 VarInt64::from(def).serialize(writer)?;
769 }),
770 F32Const(def) => op!(writer, 0x43, {
771 Uint32::from(def).serialize(writer)?;
772 }),
773 F64Const(def) => op!(writer, 0x44, {
774 Uint64::from(def).serialize(writer)?;
775 }),
776 I32Eqz => op!(writer, 0x45),
777 I32Eq => op!(writer, 0x46),
778 I32Ne => op!(writer, 0x47),
779 I32LtS => op!(writer, 0x48),
780 I32LtU => op!(writer, 0x49),
781 I32GtS => op!(writer, 0x4a),
782 I32GtU => op!(writer, 0x4b),
783 I32LeS => op!(writer, 0x4c),
784 I32LeU => op!(writer, 0x4d),
785 I32GeS => op!(writer, 0x4e),
786 I32GeU => op!(writer, 0x4f),
787
788 I64Eqz => op!(writer, 0x50),
789 I64Eq => op!(writer, 0x51),
790 I64Ne => op!(writer, 0x52),
791 I64LtS => op!(writer, 0x53),
792 I64LtU => op!(writer, 0x54),
793 I64GtS => op!(writer, 0x55),
794 I64GtU => op!(writer, 0x56),
795 I64LeS => op!(writer, 0x57),
796 I64LeU => op!(writer, 0x58),
797 I64GeS => op!(writer, 0x59),
798 I64GeU => op!(writer, 0x5a),
799
800 F32Eq => op!(writer, 0x5b),
801 F32Ne => op!(writer, 0x5c),
802 F32Lt => op!(writer, 0x5d),
803 F32Gt => op!(writer, 0x5e),
804 F32Le => op!(writer, 0x5f),
805 F32Ge => op!(writer, 0x60),
806
807 F64Eq => op!(writer, 0x61),
808 F64Ne => op!(writer, 0x62),
809 F64Lt => op!(writer, 0x63),
810 F64Gt => op!(writer, 0x64),
811 F64Le => op!(writer, 0x65),
812 F64Ge => op!(writer, 0x66),
813
814 I32Clz => op!(writer, 0x67),
815 I32Ctz => op!(writer, 0x68),
816 I32Popcnt => op!(writer, 0x69),
817 I32Add => op!(writer, 0x6a),
818 I32Sub => op!(writer, 0x6b),
819 I32Mul => op!(writer, 0x6c),
820 I32DivS => op!(writer, 0x6d),
821 I32DivU => op!(writer, 0x6e),
822 I32RemS => op!(writer, 0x6f),
823 I32RemU => op!(writer, 0x70),
824 I32And => op!(writer, 0x71),
825 I32Or => op!(writer, 0x72),
826 I32Xor => op!(writer, 0x73),
827 I32Shl => op!(writer, 0x74),
828 I32ShrS => op!(writer, 0x75),
829 I32ShrU => op!(writer, 0x76),
830 I32Rotl => op!(writer, 0x77),
831 I32Rotr => op!(writer, 0x78),
832
833 I64Clz => op!(writer, 0x79),
834 I64Ctz => op!(writer, 0x7a),
835 I64Popcnt => op!(writer, 0x7b),
836 I64Add => op!(writer, 0x7c),
837 I64Sub => op!(writer, 0x7d),
838 I64Mul => op!(writer, 0x7e),
839 I64DivS => op!(writer, 0x7f),
840 I64DivU => op!(writer, 0x80),
841 I64RemS => op!(writer, 0x81),
842 I64RemU => op!(writer, 0x82),
843 I64And => op!(writer, 0x83),
844 I64Or => op!(writer, 0x84),
845 I64Xor => op!(writer, 0x85),
846 I64Shl => op!(writer, 0x86),
847 I64ShrS => op!(writer, 0x87),
848 I64ShrU => op!(writer, 0x88),
849 I64Rotl => op!(writer, 0x89),
850 I64Rotr => op!(writer, 0x8a),
851 F32Abs => op!(writer, 0x8b),
852 F32Neg => op!(writer, 0x8c),
853 F32Ceil => op!(writer, 0x8d),
854 F32Floor => op!(writer, 0x8e),
855 F32Trunc => op!(writer, 0x8f),
856 F32Nearest => op!(writer, 0x90),
857 F32Sqrt => op!(writer, 0x91),
858 F32Add => op!(writer, 0x92),
859 F32Sub => op!(writer, 0x93),
860 F32Mul => op!(writer, 0x94),
861 F32Div => op!(writer, 0x95),
862 F32Min => op!(writer, 0x96),
863 F32Max => op!(writer, 0x97),
864 F32Copysign => op!(writer, 0x98),
865 F64Abs => op!(writer, 0x99),
866 F64Neg => op!(writer, 0x9a),
867 F64Ceil => op!(writer, 0x9b),
868 F64Floor => op!(writer, 0x9c),
869 F64Trunc => op!(writer, 0x9d),
870 F64Nearest => op!(writer, 0x9e),
871 F64Sqrt => op!(writer, 0x9f),
872 F64Add => op!(writer, 0xa0),
873 F64Sub => op!(writer, 0xa1),
874 F64Mul => op!(writer, 0xa2),
875 F64Div => op!(writer, 0xa3),
876 F64Min => op!(writer, 0xa4),
877 F64Max => op!(writer, 0xa5),
878 F64Copysign => op!(writer, 0xa6),
879
880 I32WarpI64 => op!(writer, 0xa7),
881 I32TruncSF32 => op!(writer, 0xa8),
882 I32TruncUF32 => op!(writer, 0xa9),
883 I32TruncSF64 => op!(writer, 0xaa),
884 I32TruncUF64 => op!(writer, 0xab),
885 I64ExtendSI32 => op!(writer, 0xac),
886 I64ExtendUI32 => op!(writer, 0xad),
887 I64TruncSF32 => op!(writer, 0xae),
888 I64TruncUF32 => op!(writer, 0xaf),
889 I64TruncSF64 => op!(writer, 0xb0),
890 I64TruncUF64 => op!(writer, 0xb1),
891 F32ConvertSI32 => op!(writer, 0xb2),
892 F32ConvertUI32 => op!(writer, 0xb3),
893 F32ConvertSI64 => op!(writer, 0xb4),
894 F32ConvertUI64 => op!(writer, 0xb5),
895 F32DemoteF64 => op!(writer, 0xb6),
896 F64ConvertSI32 => op!(writer, 0xb7),
897 F64ConvertUI32 => op!(writer, 0xb8),
898 F64ConvertSI64 => op!(writer, 0xb9),
899 F64ConvertUI64 => op!(writer, 0xba),
900 F64PromoteF32 => op!(writer, 0xbb),
901
902 I32ReinterpretF32 => op!(writer, 0xbc),
903 I64ReinterpretF64 => op!(writer, 0xbd),
904 F32ReinterpretI32 => op!(writer, 0xbe),
905 F64ReinterpretI64 => op!(writer, 0xbf),
906 }
907
908 Ok(())
909 }
910}
911
912macro_rules! fmt_op {
913 ($f: expr, $mnemonic: expr) => ({
914 write!($f, "{}", $mnemonic)
915 });
916 ($f: expr, $mnemonic: expr, $immediate: expr) => ({
917 write!($f, "{} {}", $mnemonic, $immediate)
918 });
919 ($f: expr, $mnemonic: expr, $immediate1: expr, $immediate2: expr) => ({
920 write!($f, "{} {} {}", $mnemonic, $immediate1, $immediate2)
921 });
922}
923
924impl fmt::Display for Opcode {
925 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
926 use self::Opcode::*;
927 use super::BlockType;
928
929 match *self {
930 Unreachable => fmt_op!(f, "unreachable"),
931 Nop => fmt_op!(f, "nop"),
932 Block(BlockType::NoResult) => fmt_op!(f, "block"),
933 Block(BlockType::Value(value_type)) => fmt_op!(f, "block", value_type),
934 Loop(BlockType::NoResult) => fmt_op!(f, "loop"),
935 Loop(BlockType::Value(value_type)) => fmt_op!(f, "loop", value_type),
936 If(BlockType::NoResult) => fmt_op!(f, "if"),
937 If(BlockType::Value(value_type)) => fmt_op!(f, "if", value_type),
938 Else => fmt_op!(f, "else"),
939 End => fmt_op!(f, "end"),
940 Br(idx) => fmt_op!(f, "br", idx),
941 BrIf(idx) => fmt_op!(f, "br_if", idx),
942 BrTable(_, default) => fmt_op!(f, "br_table", default),
943 Return => fmt_op!(f, "return"),
944 Call(index) => fmt_op!(f, "call", index),
945 CallIndirect(index, _) => fmt_op!(f, "call_indirect", index),
946 Drop => fmt_op!(f, "drop"),
947 Select => fmt_op!(f, "select"),
948 GetLocal(index) => fmt_op!(f, "get_local", index),
949 SetLocal(index) => fmt_op!(f, "set_local", index),
950 TeeLocal(index) => fmt_op!(f, "tee_local", index),
951 GetGlobal(index) => fmt_op!(f, "get_global", index),
952 SetGlobal(index) => fmt_op!(f, "set_global", index),
953
954 I32Load(_, 0) => write!(f, "i32.load"),
955 I32Load(_, offset) => write!(f, "i32.load offset={}", offset),
956
957 I64Load(_, 0) => write!(f, "i64.load"),
958 I64Load(_, offset) => write!(f, "i64.load offset={}", offset),
959
960 F32Load(_, 0) => write!(f, "f32.load"),
961 F32Load(_, offset) => write!(f, "f32.load offset={}", offset),
962
963 F64Load(_, 0) => write!(f, "f64.load"),
964 F64Load(_, offset) => write!(f, "f64.load offset={}", offset),
965
966 I32Load8S(_, 0) => write!(f, "i32.load8_s"),
967 I32Load8S(_, offset) => write!(f, "i32.load8_s offset={}", offset),
968
969 I32Load8U(_, 0) => write!(f, "i32.load8_u"),
970 I32Load8U(_, offset) => write!(f, "i32.load8_u offset={}", offset),
971
972 I32Load16S(_, 0) => write!(f, "i32.load16_s"),
973 I32Load16S(_, offset) => write!(f, "i32.load16_s offset={}", offset),
974
975 I32Load16U(_, 0) => write!(f, "i32.load16_u"),
976 I32Load16U(_, offset) => write!(f, "i32.load16_u offset={}", offset),
977
978 I64Load8S(_, 0) => write!(f, "i64.load8_s"),
979 I64Load8S(_, offset) => write!(f, "i64.load8_s offset={}", offset),
980
981 I64Load8U(_, 0) => write!(f, "i64.load8_u"),
982 I64Load8U(_, offset) => write!(f, "i64.load8_u offset={}", offset),
983
984 I64Load16S(_, 0) => write!(f, "i64.load16_s"),
985 I64Load16S(_, offset) => write!(f, "i64.load16_s offset={}", offset),
986
987 I64Load16U(_, 0) => write!(f, "i64.load16_u"),
988 I64Load16U(_, offset) => write!(f, "i64.load16_u offset={}", offset),
989
990 I64Load32S(_, 0) => write!(f, "i64.load32_s"),
991 I64Load32S(_, offset) => write!(f, "i64.load32_s offset={}", offset),
992
993 I64Load32U(_, 0) => write!(f, "i64.load32_u"),
994 I64Load32U(_, offset) => write!(f, "i64.load32_u offset={}", offset),
995
996 I32Store(_, 0) => write!(f, "i32.store"),
997 I32Store(_, offset) => write!(f, "i32.store offset={}", offset),
998
999 I64Store(_, 0) => write!(f, "i64.store"),
1000 I64Store(_, offset) => write!(f, "i64.store offset={}", offset),
1001
1002 F32Store(_, 0) => write!(f, "f32.store"),
1003 F32Store(_, offset) => write!(f, "f32.store offset={}", offset),
1004
1005 F64Store(_, 0) => write!(f, "f64.store"),
1006 F64Store(_, offset) => write!(f, "f64.store offset={}", offset),
1007
1008 I32Store8(_, 0) => write!(f, "i32.store8"),
1009 I32Store8(_, offset) => write!(f, "i32.store8 offset={}", offset),
1010
1011 I32Store16(_, 0) => write!(f, "i32.store16"),
1012 I32Store16(_, offset) => write!(f, "i32.store16 offset={}", offset),
1013
1014 I64Store8(_, 0) => write!(f, "i64.store8"),
1015 I64Store8(_, offset) => write!(f, "i64.store8 offset={}", offset),
1016
1017 I64Store16(_, 0) => write!(f, "i64.store16"),
1018 I64Store16(_, offset) => write!(f, "i64.store16 offset={}", offset),
1019
1020 I64Store32(_, 0) => write!(f, "i64.store32"),
1021 I64Store32(_, offset) => write!(f, "i64.store32 offset={}", offset),
1022
1023 CurrentMemory(_) => fmt_op!(f, "current_memory"),
1024 GrowMemory(_) => fmt_op!(f, "grow_memory"),
1025
1026 I32Const(def) => fmt_op!(f, "i32.const", def),
1027 I64Const(def) => fmt_op!(f, "i64.const", def),
1028 F32Const(def) => fmt_op!(f, "f32.const", def),
1029 F64Const(def) => fmt_op!(f, "f64.const", def),
1030
1031 I32Eq => write!(f, "i32.eq"),
1032 I32Eqz => write!(f, "i32.eqz"),
1033 I32Ne => write!(f, "i32.ne"),
1034 I32LtS => write!(f, "i32.lt_s"),
1035 I32LtU => write!(f, "i32.lt_u"),
1036 I32GtS => write!(f, "i32.gt_s"),
1037 I32GtU => write!(f, "i32.gt_u"),
1038 I32LeS => write!(f, "i32.le_s"),
1039 I32LeU => write!(f, "i32.le_u"),
1040 I32GeS => write!(f, "i32.ge_s"),
1041 I32GeU => write!(f, "i32.ge_u"),
1042
1043 I64Eq => write!(f, "i64.eq"),
1044 I64Eqz => write!(f, "i64.eqz"),
1045 I64Ne => write!(f, "i64.ne"),
1046 I64LtS => write!(f, "i64.lt_s"),
1047 I64LtU => write!(f, "i64.lt_u"),
1048 I64GtS => write!(f, "i64.gt_s"),
1049 I64GtU => write!(f, "i64.gt_u"),
1050 I64LeS => write!(f, "i64.le_s"),
1051 I64LeU => write!(f, "i64.le_u"),
1052 I64GeS => write!(f, "i64.ge_s"),
1053 I64GeU => write!(f, "i64.ge_u"),
1054
1055 F32Eq => write!(f, "f32.eq"),
1056 F32Ne => write!(f, "f32.ne"),
1057 F32Lt => write!(f, "f32.lt"),
1058 F32Gt => write!(f, "f32.gt"),
1059 F32Le => write!(f, "f32.le"),
1060 F32Ge => write!(f, "f32.ge"),
1061
1062 F64Eq => write!(f, "f64.eq"),
1063 F64Ne => write!(f, "f64.ne"),
1064 F64Lt => write!(f, "f64.lt"),
1065 F64Gt => write!(f, "f64.gt"),
1066 F64Le => write!(f, "f64.le"),
1067 F64Ge => write!(f, "f64.ge"),
1068
1069 I32Clz => write!(f, "i32.clz"),
1070 I32Ctz => write!(f, "i32.ctz"),
1071 I32Popcnt => write!(f, "i32.popcnt"),
1072 I32Add => write!(f, "i32.add"),
1073 I32Sub => write!(f, "i32.sub"),
1074 I32Mul => write!(f, "i32.mul"),
1075 I32DivS => write!(f, "i32.div_s"),
1076 I32DivU => write!(f, "i32.div_u"),
1077 I32RemS => write!(f, "i32.rem_s"),
1078 I32RemU => write!(f, "i32.rem_u"),
1079 I32And => write!(f, "i32.and"),
1080 I32Or => write!(f, "i32.or"),
1081 I32Xor => write!(f, "i32.xor"),
1082 I32Shl => write!(f, "i32.shl"),
1083 I32ShrS => write!(f, "i32.shr_s"),
1084 I32ShrU => write!(f, "i32.shr_u"),
1085 I32Rotl => write!(f, "i32.rotl"),
1086 I32Rotr => write!(f, "i32.rotr"),
1087
1088 I64Clz => write!(f, "i64.clz"),
1089 I64Ctz => write!(f, "i64.ctz"),
1090 I64Popcnt => write!(f, "i64.popcnt"),
1091 I64Add => write!(f, "i64.add"),
1092 I64Sub => write!(f, "i64.sub"),
1093 I64Mul => write!(f, "i64.mul"),
1094 I64DivS => write!(f, "i64.div_s"),
1095 I64DivU => write!(f, "i64.div_u"),
1096 I64RemS => write!(f, "i64.rem_s"),
1097 I64RemU => write!(f, "i64.rem_u"),
1098 I64And => write!(f, "i64.and"),
1099 I64Or => write!(f, "i64.or"),
1100 I64Xor => write!(f, "i64.xor"),
1101 I64Shl => write!(f, "i64.shl"),
1102 I64ShrS => write!(f, "i64.shr_s"),
1103 I64ShrU => write!(f, "i64.shr_u"),
1104 I64Rotl => write!(f, "i64.rotl"),
1105 I64Rotr => write!(f, "i64.rotr"),
1106
1107 F32Abs => write!(f, "f32.abs"),
1108 F32Neg => write!(f, "f32.neg"),
1109 F32Ceil => write!(f, "f32.ceil"),
1110 F32Floor => write!(f, "f32.floor"),
1111 F32Trunc => write!(f, "f32.trunc"),
1112 F32Nearest => write!(f, "f32.nearest"),
1113 F32Sqrt => write!(f, "f32.sqrt"),
1114 F32Add => write!(f, "f32.add"),
1115 F32Sub => write!(f, "f32.sub"),
1116 F32Mul => write!(f, "f32.mul"),
1117 F32Div => write!(f, "f32.div"),
1118 F32Min => write!(f, "f32.min"),
1119 F32Max => write!(f, "f32.max"),
1120 F32Copysign => write!(f, "f32.copysign"),
1121
1122 F64Abs => write!(f, "f64.abs"),
1123 F64Neg => write!(f, "f64.neg"),
1124 F64Ceil => write!(f, "f64.ceil"),
1125 F64Floor => write!(f, "f64.floor"),
1126 F64Trunc => write!(f, "f64.trunc"),
1127 F64Nearest => write!(f, "f64.nearest"),
1128 F64Sqrt => write!(f, "f64.sqrt"),
1129 F64Add => write!(f, "f64.add"),
1130 F64Sub => write!(f, "f64.sub"),
1131 F64Mul => write!(f, "f64.mul"),
1132 F64Div => write!(f, "f64.div"),
1133 F64Min => write!(f, "f64.min"),
1134 F64Max => write!(f, "f64.max"),
1135 F64Copysign => write!(f, "f64.copysign"),
1136
1137 I32WarpI64 => write!(f, "i32.wrap/i64"),
1138 I32TruncSF32 => write!(f, "i32.trunc_s/f32"),
1139 I32TruncUF32 => write!(f, "i32.trunc_u/f32"),
1140 I32TruncSF64 => write!(f, "i32.trunc_s/f64"),
1141 I32TruncUF64 => write!(f, "i32.trunc_u/f64"),
1142
1143 I64ExtendSI32 => write!(f, "i64.extend_s/i32"),
1144 I64ExtendUI32 => write!(f, "i64.extend_u/i32"),
1145
1146 I64TruncSF32 => write!(f, "i64.trunc_s/f32"),
1147 I64TruncUF32 => write!(f, "i64.trunc_u/f32"),
1148 I64TruncSF64 => write!(f, "i64.trunc_s/f64"),
1149 I64TruncUF64 => write!(f, "i64.trunc_u/f64"),
1150
1151 F32ConvertSI32 => write!(f, "f32.convert_s/i32"),
1152 F32ConvertUI32 => write!(f, "f32.convert_u/i32"),
1153 F32ConvertSI64 => write!(f, "f32.convert_s/i64"),
1154 F32ConvertUI64 => write!(f, "f32.convert_u/i64"),
1155 F32DemoteF64 => write!(f, "f32.demote/f64"),
1156
1157 F64ConvertSI32 => write!(f, "f64.convert_s/i32"),
1158 F64ConvertUI32 => write!(f, "f64.convert_u/i32"),
1159 F64ConvertSI64 => write!(f, "f64.convert_s/i64"),
1160 F64ConvertUI64 => write!(f, "f64.convert_u/i64"),
1161 F64PromoteF32 => write!(f, "f64.promote/f32"),
1162
1163 I32ReinterpretF32 => write!(f, "i32.reinterpret/f32"),
1164 I64ReinterpretF64 => write!(f, "i64.reinterpret/f64"),
1165 F32ReinterpretI32 => write!(f, "f32.reinterpret/i32"),
1166 F64ReinterpretI64 => write!(f, "f64.reinterpret/i64"),
1167 }
1168 }
1169}
1170
1171impl Serialize for Opcodes {
1172 type Error = Error;
1173
1174 fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
1175 for op in self.0.into_iter() {
1176 op.serialize(writer)?;
1177 }
1178
1179 Ok(())
1180 }
1181}
1182
1183impl Serialize for InitExpr {
1184 type Error = Error;
1185
1186 fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
1187 for op in self.0.into_iter() {
1188 op.serialize(writer)?;
1189 }
1190
1191 Ok(())
1192 }
1193}
1194
1195#[test]
1196fn ifelse() {
1197 let opcode = super::deserialize_buffer::<Opcodes>(&[0x04, 0x7F, 0x41, 0x05, 0x05, 0x41, 0x07, 0x0B, 0x0B])
1199 .expect("valid hex of if instruction");
1200 let opcodes = opcode.elements();
1201 match &opcodes[0] {
1202 &Opcode::If(_) => (),
1203 _ => panic!("Should be deserialized as if opcode"),
1204 }
1205 let before_else = opcodes.iter().skip(1)
1206 .take_while(|op| match **op { Opcode::Else => false, _ => true }).count();
1207 let after_else = opcodes.iter().skip(1)
1208 .skip_while(|op| match **op { Opcode::Else => false, _ => true })
1209 .take_while(|op| match **op { Opcode::End => false, _ => true })
1210 .count()
1211 - 1; assert_eq!(before_else, after_else);
1213}
1214
1215#[test]
1216fn display() {
1217 let opcode = Opcode::GetLocal(0);
1218 assert_eq!("get_local 0", format!("{}", opcode));
1219
1220 let opcode = Opcode::F64Store(0, 24);
1221 assert_eq!("f64.store offset=24", format!("{}", opcode));
1222
1223 let opcode = Opcode::I64Store(0, 0);
1224 assert_eq!("i64.store", format!("{}", opcode));
1225}