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