1 use alloc::{boxed::Box, vec::Vec};
2 use crate::io;
3 use super::{
4 	Serialize, Deserialize, Error,
5 	Uint8, VarUint32, CountedList, BlockType,
6 	Uint32, Uint64, CountedListWriter,
7 	VarInt32, VarInt64,
8 };
9 use core::fmt;
10 
11 /// List of instructions (usually inside a block section).
12 #[derive(Debug, Clone, PartialEq)]
13 pub struct Instructions(Vec<Instruction>);
14 
15 impl Instructions {
16 	/// New list of instructions from vector of instructions.
new(elements: Vec<Instruction>) -> Self17 	pub fn new(elements: Vec<Instruction>) -> Self {
18 		Instructions(elements)
19 	}
20 
21 	/// Empty expression with only `Instruction::End` instruction.
empty() -> Self22 	pub fn empty() -> Self {
23 		Instructions(vec![Instruction::End])
24 	}
25 
26 	/// List of individual instructions.
elements(&self) -> &[Instruction]27 	pub fn elements(&self) -> &[Instruction] { &self.0 }
28 
29 	/// Individual instructions, mutable.
elements_mut(&mut self) -> &mut Vec<Instruction>30 	pub fn elements_mut(&mut self) -> &mut Vec<Instruction> { &mut self.0 }
31 }
32 
33 impl Deserialize for Instructions {
34 	type Error = Error;
35 
deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>36 	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
37 		let mut instructions = Vec::new();
38 		let mut block_count = 1usize;
39 
40 		loop {
41 			let instruction = Instruction::deserialize(reader)?;
42 			if instruction.is_terminal() {
43 				block_count -= 1;
44 			} else if instruction.is_block() {
45 				block_count = block_count.checked_add(1).ok_or(Error::Other("too many instructions"))?;
46 			}
47 
48 			instructions.push(instruction);
49 			if block_count == 0 {
50 				break;
51 			}
52 		}
53 
54 		Ok(Instructions(instructions))
55 	}
56 }
57 
58 /// Initialization expression.
59 #[derive(Debug, Clone, PartialEq)]
60 pub struct InitExpr(Vec<Instruction>);
61 
62 impl InitExpr {
63 	/// New initialization expression from instruction list.
64 	///
65 	/// `code` must end with the `Instruction::End` instruction!
new(code: Vec<Instruction>) -> Self66 	pub fn new(code: Vec<Instruction>) -> Self {
67 		InitExpr(code)
68 	}
69 
70 	/// Empty expression with only `Instruction::End` instruction.
empty() -> Self71 	pub fn empty() -> Self {
72 		InitExpr(vec![Instruction::End])
73 	}
74 
75 	/// List of instructions used in the expression.
code(&self) -> &[Instruction]76 	pub fn code(&self) -> &[Instruction] {
77 		&self.0
78 	}
79 
80 	/// List of instructions used in the expression.
code_mut(&mut self) -> &mut Vec<Instruction>81 	pub fn code_mut(&mut self) -> &mut Vec<Instruction> {
82 		&mut self.0
83 	}
84 }
85 
86 impl Deserialize for InitExpr {
87 	type Error = Error;
88 
deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>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 /// Instruction.
106 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
107 #[allow(missing_docs)]
108 pub 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<BrTableData>),
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 	// All store/load instructions operate with 'memory immediates'
134 	// which represented here as (flag, offset) tuple
135 	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 	#[cfg(feature="atomics")]
299 	Atomics(AtomicsInstruction),
300 
301 	#[cfg(feature="simd")]
302 	Simd(SimdInstruction),
303 
304 	#[cfg(feature="sign_ext")]
305 	SignExt(SignExtInstruction),
306 
307 	#[cfg(feature="bulk")]
308 	Bulk(BulkInstruction),
309 }
310 
311 #[allow(missing_docs)]
312 #[cfg(feature="atomics")]
313 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
314 pub enum AtomicsInstruction {
315 	AtomicWake(MemArg),
316 	I32AtomicWait(MemArg),
317 	I64AtomicWait(MemArg),
318 
319 	I32AtomicLoad(MemArg),
320 	I64AtomicLoad(MemArg),
321 	I32AtomicLoad8u(MemArg),
322 	I32AtomicLoad16u(MemArg),
323 	I64AtomicLoad8u(MemArg),
324 	I64AtomicLoad16u(MemArg),
325 	I64AtomicLoad32u(MemArg),
326 	I32AtomicStore(MemArg),
327 	I64AtomicStore(MemArg),
328 	I32AtomicStore8u(MemArg),
329 	I32AtomicStore16u(MemArg),
330 	I64AtomicStore8u(MemArg),
331 	I64AtomicStore16u(MemArg),
332 	I64AtomicStore32u(MemArg),
333 
334 	I32AtomicRmwAdd(MemArg),
335 	I64AtomicRmwAdd(MemArg),
336 	I32AtomicRmwAdd8u(MemArg),
337 	I32AtomicRmwAdd16u(MemArg),
338 	I64AtomicRmwAdd8u(MemArg),
339 	I64AtomicRmwAdd16u(MemArg),
340 	I64AtomicRmwAdd32u(MemArg),
341 
342 	I32AtomicRmwSub(MemArg),
343 	I64AtomicRmwSub(MemArg),
344 	I32AtomicRmwSub8u(MemArg),
345 	I32AtomicRmwSub16u(MemArg),
346 	I64AtomicRmwSub8u(MemArg),
347 	I64AtomicRmwSub16u(MemArg),
348 	I64AtomicRmwSub32u(MemArg),
349 
350 	I32AtomicRmwAnd(MemArg),
351 	I64AtomicRmwAnd(MemArg),
352 	I32AtomicRmwAnd8u(MemArg),
353 	I32AtomicRmwAnd16u(MemArg),
354 	I64AtomicRmwAnd8u(MemArg),
355 	I64AtomicRmwAnd16u(MemArg),
356 	I64AtomicRmwAnd32u(MemArg),
357 
358 	I32AtomicRmwOr(MemArg),
359 	I64AtomicRmwOr(MemArg),
360 	I32AtomicRmwOr8u(MemArg),
361 	I32AtomicRmwOr16u(MemArg),
362 	I64AtomicRmwOr8u(MemArg),
363 	I64AtomicRmwOr16u(MemArg),
364 	I64AtomicRmwOr32u(MemArg),
365 
366 	I32AtomicRmwXor(MemArg),
367 	I64AtomicRmwXor(MemArg),
368 	I32AtomicRmwXor8u(MemArg),
369 	I32AtomicRmwXor16u(MemArg),
370 	I64AtomicRmwXor8u(MemArg),
371 	I64AtomicRmwXor16u(MemArg),
372 	I64AtomicRmwXor32u(MemArg),
373 
374 	I32AtomicRmwXchg(MemArg),
375 	I64AtomicRmwXchg(MemArg),
376 	I32AtomicRmwXchg8u(MemArg),
377 	I32AtomicRmwXchg16u(MemArg),
378 	I64AtomicRmwXchg8u(MemArg),
379 	I64AtomicRmwXchg16u(MemArg),
380 	I64AtomicRmwXchg32u(MemArg),
381 
382 	I32AtomicRmwCmpxchg(MemArg),
383 	I64AtomicRmwCmpxchg(MemArg),
384 	I32AtomicRmwCmpxchg8u(MemArg),
385 	I32AtomicRmwCmpxchg16u(MemArg),
386 	I64AtomicRmwCmpxchg8u(MemArg),
387 	I64AtomicRmwCmpxchg16u(MemArg),
388 	I64AtomicRmwCmpxchg32u(MemArg),
389 }
390 
391 #[allow(missing_docs)]
392 #[cfg(feature="simd")]
393 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
394 pub enum SimdInstruction {
395 	V128Const(Box<[u8; 16]>),
396 	V128Load(MemArg),
397 	V128Store(MemArg),
398 	I8x16Splat,
399 	I16x8Splat,
400 	I32x4Splat,
401 	I64x2Splat,
402 	F32x4Splat,
403 	F64x2Splat,
404 	I8x16ExtractLaneS(u8),
405 	I8x16ExtractLaneU(u8),
406 	I16x8ExtractLaneS(u8),
407 	I16x8ExtractLaneU(u8),
408 	I32x4ExtractLane(u8),
409 	I64x2ExtractLane(u8),
410 	F32x4ExtractLane(u8),
411 	F64x2ExtractLane(u8),
412 	I8x16ReplaceLane(u8),
413 	I16x8ReplaceLane(u8),
414 	I32x4ReplaceLane(u8),
415 	I64x2ReplaceLane(u8),
416 	F32x4ReplaceLane(u8),
417 	F64x2ReplaceLane(u8),
418 	V8x16Shuffle(Box<[u8; 16]>),
419 	I8x16Add,
420 	I16x8Add,
421 	I32x4Add,
422 	I64x2Add,
423 	I8x16Sub,
424 	I16x8Sub,
425 	I32x4Sub,
426 	I64x2Sub,
427 	I8x16Mul,
428 	I16x8Mul,
429 	I32x4Mul,
430 	// I64x2Mul,
431 	I8x16Neg,
432 	I16x8Neg,
433 	I32x4Neg,
434 	I64x2Neg,
435 	I8x16AddSaturateS,
436 	I8x16AddSaturateU,
437 	I16x8AddSaturateS,
438 	I16x8AddSaturateU,
439 	I8x16SubSaturateS,
440 	I8x16SubSaturateU,
441 	I16x8SubSaturateS,
442 	I16x8SubSaturateU,
443 	I8x16Shl,
444 	I16x8Shl,
445 	I32x4Shl,
446 	I64x2Shl,
447 	I8x16ShrS,
448 	I8x16ShrU,
449 	I16x8ShrS,
450 	I16x8ShrU,
451 	I32x4ShrS,
452 	I32x4ShrU,
453 	I64x2ShrS,
454 	I64x2ShrU,
455 	V128And,
456 	V128Or,
457 	V128Xor,
458 	V128Not,
459 	V128Bitselect,
460 	I8x16AnyTrue,
461 	I16x8AnyTrue,
462 	I32x4AnyTrue,
463 	I64x2AnyTrue,
464 	I8x16AllTrue,
465 	I16x8AllTrue,
466 	I32x4AllTrue,
467 	I64x2AllTrue,
468 	I8x16Eq,
469 	I16x8Eq,
470 	I32x4Eq,
471 	// I64x2Eq,
472 	F32x4Eq,
473 	F64x2Eq,
474 	I8x16Ne,
475 	I16x8Ne,
476 	I32x4Ne,
477 	// I64x2Ne,
478 	F32x4Ne,
479 	F64x2Ne,
480 	I8x16LtS,
481 	I8x16LtU,
482 	I16x8LtS,
483 	I16x8LtU,
484 	I32x4LtS,
485 	I32x4LtU,
486 	// I64x2LtS,
487 	// I64x2LtU,
488 	F32x4Lt,
489 	F64x2Lt,
490 	I8x16LeS,
491 	I8x16LeU,
492 	I16x8LeS,
493 	I16x8LeU,
494 	I32x4LeS,
495 	I32x4LeU,
496 	// I64x2LeS,
497 	// I64x2LeU,
498 	F32x4Le,
499 	F64x2Le,
500 	I8x16GtS,
501 	I8x16GtU,
502 	I16x8GtS,
503 	I16x8GtU,
504 	I32x4GtS,
505 	I32x4GtU,
506 	// I64x2GtS,
507 	// I64x2GtU,
508 	F32x4Gt,
509 	F64x2Gt,
510 	I8x16GeS,
511 	I8x16GeU,
512 	I16x8GeS,
513 	I16x8GeU,
514 	I32x4GeS,
515 	I32x4GeU,
516 	// I64x2GeS,
517 	// I64x2GeU,
518 	F32x4Ge,
519 	F64x2Ge,
520 	F32x4Neg,
521 	F64x2Neg,
522 	F32x4Abs,
523 	F64x2Abs,
524 	F32x4Min,
525 	F64x2Min,
526 	F32x4Max,
527 	F64x2Max,
528 	F32x4Add,
529 	F64x2Add,
530 	F32x4Sub,
531 	F64x2Sub,
532 	F32x4Div,
533 	F64x2Div,
534 	F32x4Mul,
535 	F64x2Mul,
536 	F32x4Sqrt,
537 	F64x2Sqrt,
538 	F32x4ConvertSI32x4,
539 	F32x4ConvertUI32x4,
540 	F64x2ConvertSI64x2,
541 	F64x2ConvertUI64x2,
542 	I32x4TruncSF32x4Sat,
543 	I32x4TruncUF32x4Sat,
544 	I64x2TruncSF64x2Sat,
545 	I64x2TruncUF64x2Sat,
546 }
547 
548 #[allow(missing_docs)]
549 #[cfg(feature="sign_ext")]
550 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
551 pub enum SignExtInstruction {
552 	I32Extend8S,
553 	I32Extend16S,
554 	I64Extend8S,
555 	I64Extend16S,
556 	I64Extend32S,
557 }
558 
559 #[allow(missing_docs)]
560 #[cfg(feature="bulk")]
561 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
562 pub enum BulkInstruction {
563 	MemoryInit(u32),
564 	MemoryDrop(u32),
565 	MemoryCopy,
566 	MemoryFill,
567 	TableInit(u32),
568 	TableDrop(u32),
569 	TableCopy,
570 }
571 
572 #[cfg(any(feature="simd", feature="atomics"))]
573 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
574 #[allow(missing_docs)]
575 pub struct MemArg {
576 	pub align: u8,
577 	pub offset: u32,
578 }
579 
580 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
581 #[allow(missing_docs)]
582 pub struct BrTableData {
583 	pub table: Box<[u32]>,
584 	pub default: u32,
585 }
586 
587 impl Instruction {
588 	/// Is this instruction starts the new block (which should end with terminal instruction).
is_block(&self) -> bool589 	pub fn is_block(&self) -> bool {
590 		match self {
591 			&Instruction::Block(_) | &Instruction::Loop(_) | &Instruction::If(_) => true,
592 			_ => false,
593 		}
594 	}
595 
596 	/// Is this instruction determines the termination of instruction sequence?
597 	///
598 	/// `true` for `Instruction::End`
is_terminal(&self) -> bool599 	pub fn is_terminal(&self) -> bool {
600 		match self {
601 			&Instruction::End => true,
602 			_ => false,
603 		}
604 	}
605 }
606 
607 #[allow(missing_docs)]
608 pub mod opcodes {
609 	pub const UNREACHABLE: u8 = 0x00;
610 	pub const NOP: u8 = 0x01;
611 	pub const BLOCK: u8 = 0x02;
612 	pub const LOOP: u8 = 0x03;
613 	pub const IF: u8 = 0x04;
614 	pub const ELSE: u8 = 0x05;
615 	pub const END: u8 = 0x0b;
616 	pub const BR: u8 = 0x0c;
617 	pub const BRIF: u8 = 0x0d;
618 	pub const BRTABLE: u8 = 0x0e;
619 	pub const RETURN: u8 = 0x0f;
620 	pub const CALL: u8 = 0x10;
621 	pub const CALLINDIRECT: u8 = 0x11;
622 	pub const DROP: u8 = 0x1a;
623 	pub const SELECT: u8 = 0x1b;
624 	pub const GETLOCAL: u8 = 0x20;
625 	pub const SETLOCAL: u8 = 0x21;
626 	pub const TEELOCAL: u8 = 0x22;
627 	pub const GETGLOBAL: u8 = 0x23;
628 	pub const SETGLOBAL: u8 = 0x24;
629 	pub const I32LOAD: u8 = 0x28;
630 	pub const I64LOAD: u8 = 0x29;
631 	pub const F32LOAD: u8 = 0x2a;
632 	pub const F64LOAD: u8 = 0x2b;
633 	pub const I32LOAD8S: u8 = 0x2c;
634 	pub const I32LOAD8U: u8 = 0x2d;
635 	pub const I32LOAD16S: u8 = 0x2e;
636 	pub const I32LOAD16U: u8 = 0x2f;
637 	pub const I64LOAD8S: u8 = 0x30;
638 	pub const I64LOAD8U: u8 = 0x31;
639 	pub const I64LOAD16S: u8 = 0x32;
640 	pub const I64LOAD16U: u8 = 0x33;
641 	pub const I64LOAD32S: u8 = 0x34;
642 	pub const I64LOAD32U: u8 = 0x35;
643 	pub const I32STORE: u8 = 0x36;
644 	pub const I64STORE: u8 = 0x37;
645 	pub const F32STORE: u8 = 0x38;
646 	pub const F64STORE: u8 = 0x39;
647 	pub const I32STORE8: u8 = 0x3a;
648 	pub const I32STORE16: u8 = 0x3b;
649 	pub const I64STORE8: u8 = 0x3c;
650 	pub const I64STORE16: u8 = 0x3d;
651 	pub const I64STORE32: u8 = 0x3e;
652 	pub const CURRENTMEMORY: u8 = 0x3f;
653 	pub const GROWMEMORY: u8 = 0x40;
654 	pub const I32CONST: u8 = 0x41;
655 	pub const I64CONST: u8 = 0x42;
656 	pub const F32CONST: u8 = 0x43;
657 	pub const F64CONST: u8 = 0x44;
658 	pub const I32EQZ: u8 = 0x45;
659 	pub const I32EQ: u8 = 0x46;
660 	pub const I32NE: u8 = 0x47;
661 	pub const I32LTS: u8 = 0x48;
662 	pub const I32LTU: u8 = 0x49;
663 	pub const I32GTS: u8 = 0x4a;
664 	pub const I32GTU: u8 = 0x4b;
665 	pub const I32LES: u8 = 0x4c;
666 	pub const I32LEU: u8 = 0x4d;
667 	pub const I32GES: u8 = 0x4e;
668 	pub const I32GEU: u8 = 0x4f;
669 	pub const I64EQZ: u8 = 0x50;
670 	pub const I64EQ: u8 = 0x51;
671 	pub const I64NE: u8 = 0x52;
672 	pub const I64LTS: u8 = 0x53;
673 	pub const I64LTU: u8 = 0x54;
674 	pub const I64GTS: u8 = 0x55;
675 	pub const I64GTU: u8 = 0x56;
676 	pub const I64LES: u8 = 0x57;
677 	pub const I64LEU: u8 = 0x58;
678 	pub const I64GES: u8 = 0x59;
679 	pub const I64GEU: u8 = 0x5a;
680 
681 	pub const F32EQ: u8 = 0x5b;
682 	pub const F32NE: u8 = 0x5c;
683 	pub const F32LT: u8 = 0x5d;
684 	pub const F32GT: u8 = 0x5e;
685 	pub const F32LE: u8 = 0x5f;
686 	pub const F32GE: u8 = 0x60;
687 
688 	pub const F64EQ: u8 = 0x61;
689 	pub const F64NE: u8 = 0x62;
690 	pub const F64LT: u8 = 0x63;
691 	pub const F64GT: u8 = 0x64;
692 	pub const F64LE: u8 = 0x65;
693 	pub const F64GE: u8 = 0x66;
694 
695 	pub const I32CLZ: u8 = 0x67;
696 	pub const I32CTZ: u8 = 0x68;
697 	pub const I32POPCNT: u8 = 0x69;
698 	pub const I32ADD: u8 = 0x6a;
699 	pub const I32SUB: u8 = 0x6b;
700 	pub const I32MUL: u8 = 0x6c;
701 	pub const I32DIVS: u8 = 0x6d;
702 	pub const I32DIVU: u8 = 0x6e;
703 	pub const I32REMS: u8 = 0x6f;
704 	pub const I32REMU: u8 = 0x70;
705 	pub const I32AND: u8 = 0x71;
706 	pub const I32OR: u8 = 0x72;
707 	pub const I32XOR: u8 = 0x73;
708 	pub const I32SHL: u8 = 0x74;
709 	pub const I32SHRS: u8 = 0x75;
710 	pub const I32SHRU: u8 = 0x76;
711 	pub const I32ROTL: u8 = 0x77;
712 	pub const I32ROTR: u8 = 0x78;
713 
714 	pub const I64CLZ: u8 = 0x79;
715 	pub const I64CTZ: u8 = 0x7a;
716 	pub const I64POPCNT: u8 = 0x7b;
717 	pub const I64ADD: u8 = 0x7c;
718 	pub const I64SUB: u8 = 0x7d;
719 	pub const I64MUL: u8 = 0x7e;
720 	pub const I64DIVS: u8 = 0x7f;
721 	pub const I64DIVU: u8 = 0x80;
722 	pub const I64REMS: u8 = 0x81;
723 	pub const I64REMU: u8 = 0x82;
724 	pub const I64AND: u8 = 0x83;
725 	pub const I64OR: u8 = 0x84;
726 	pub const I64XOR: u8 = 0x85;
727 	pub const I64SHL: u8 = 0x86;
728 	pub const I64SHRS: u8 = 0x87;
729 	pub const I64SHRU: u8 = 0x88;
730 	pub const I64ROTL: u8 = 0x89;
731 	pub const I64ROTR: u8 = 0x8a;
732 	pub const F32ABS: u8 = 0x8b;
733 	pub const F32NEG: u8 = 0x8c;
734 	pub const F32CEIL: u8 = 0x8d;
735 	pub const F32FLOOR: u8 = 0x8e;
736 	pub const F32TRUNC: u8 = 0x8f;
737 	pub const F32NEAREST: u8 = 0x90;
738 	pub const F32SQRT: u8 = 0x91;
739 	pub const F32ADD: u8 = 0x92;
740 	pub const F32SUB: u8 = 0x93;
741 	pub const F32MUL: u8 = 0x94;
742 	pub const F32DIV: u8 = 0x95;
743 	pub const F32MIN: u8 = 0x96;
744 	pub const F32MAX: u8 = 0x97;
745 	pub const F32COPYSIGN: u8 = 0x98;
746 	pub const F64ABS: u8 = 0x99;
747 	pub const F64NEG: u8 = 0x9a;
748 	pub const F64CEIL: u8 = 0x9b;
749 	pub const F64FLOOR: u8 = 0x9c;
750 	pub const F64TRUNC: u8 = 0x9d;
751 	pub const F64NEAREST: u8 = 0x9e;
752 	pub const F64SQRT: u8 = 0x9f;
753 	pub const F64ADD: u8 = 0xa0;
754 	pub const F64SUB: u8 = 0xa1;
755 	pub const F64MUL: u8 = 0xa2;
756 	pub const F64DIV: u8 = 0xa3;
757 	pub const F64MIN: u8 = 0xa4;
758 	pub const F64MAX: u8 = 0xa5;
759 	pub const F64COPYSIGN: u8 = 0xa6;
760 
761 	pub const I32WRAPI64: u8 = 0xa7;
762 	pub const I32TRUNCSF32: u8 = 0xa8;
763 	pub const I32TRUNCUF32: u8 = 0xa9;
764 	pub const I32TRUNCSF64: u8 = 0xaa;
765 	pub const I32TRUNCUF64: u8 = 0xab;
766 	pub const I64EXTENDSI32: u8 = 0xac;
767 	pub const I64EXTENDUI32: u8 = 0xad;
768 	pub const I64TRUNCSF32: u8 = 0xae;
769 	pub const I64TRUNCUF32: u8 = 0xaf;
770 	pub const I64TRUNCSF64: u8 = 0xb0;
771 	pub const I64TRUNCUF64: u8 = 0xb1;
772 	pub const F32CONVERTSI32: u8 = 0xb2;
773 	pub const F32CONVERTUI32: u8 = 0xb3;
774 	pub const F32CONVERTSI64: u8 = 0xb4;
775 	pub const F32CONVERTUI64: u8 = 0xb5;
776 	pub const F32DEMOTEF64: u8 = 0xb6;
777 	pub const F64CONVERTSI32: u8 = 0xb7;
778 	pub const F64CONVERTUI32: u8 = 0xb8;
779 	pub const F64CONVERTSI64: u8 = 0xb9;
780 	pub const F64CONVERTUI64: u8 = 0xba;
781 	pub const F64PROMOTEF32: u8 = 0xbb;
782 
783 	pub const I32REINTERPRETF32: u8 = 0xbc;
784 	pub const I64REINTERPRETF64: u8 = 0xbd;
785 	pub const F32REINTERPRETI32: u8 = 0xbe;
786 	pub const F64REINTERPRETI64: u8 = 0xbf;
787 
788 	#[cfg(feature="sign_ext")]
789 	pub mod sign_ext {
790 		pub const I32_EXTEND8_S: u8 = 0xc0;
791 		pub const I32_EXTEND16_S: u8 = 0xc1;
792 		pub const I64_EXTEND8_S: u8 = 0xc2;
793 		pub const I64_EXTEND16_S: u8 = 0xc3;
794 		pub const I64_EXTEND32_S: u8 = 0xc4;
795 	}
796 
797 	#[cfg(feature="atomics")]
798 	pub mod atomics {
799 		pub const ATOMIC_PREFIX: u8 = 0xfe;
800 		pub const ATOMIC_WAKE: u8 = 0x00;
801 		pub const I32_ATOMIC_WAIT: u8 = 0x01;
802 		pub const I64_ATOMIC_WAIT: u8 = 0x02;
803 
804 		pub const I32_ATOMIC_LOAD: u8 = 0x10;
805 		pub const I64_ATOMIC_LOAD: u8 = 0x11;
806 		pub const I32_ATOMIC_LOAD8U: u8 = 0x12;
807 		pub const I32_ATOMIC_LOAD16U: u8 = 0x13;
808 		pub const I64_ATOMIC_LOAD8U: u8 = 0x14;
809 		pub const I64_ATOMIC_LOAD16U: u8 = 0x15;
810 		pub const I64_ATOMIC_LOAD32U: u8 = 0x16;
811 		pub const I32_ATOMIC_STORE: u8 = 0x17;
812 		pub const I64_ATOMIC_STORE: u8 = 0x18;
813 		pub const I32_ATOMIC_STORE8U: u8 = 0x19;
814 		pub const I32_ATOMIC_STORE16U: u8 = 0x1a;
815 		pub const I64_ATOMIC_STORE8U: u8 = 0x1b;
816 		pub const I64_ATOMIC_STORE16U: u8 = 0x1c;
817 		pub const I64_ATOMIC_STORE32U: u8 = 0x1d;
818 
819 		pub const I32_ATOMIC_RMW_ADD: u8 = 0x1e;
820 		pub const I64_ATOMIC_RMW_ADD: u8 = 0x1f;
821 		pub const I32_ATOMIC_RMW_ADD8U: u8 = 0x20;
822 		pub const I32_ATOMIC_RMW_ADD16U: u8 = 0x21;
823 		pub const I64_ATOMIC_RMW_ADD8U: u8 = 0x22;
824 		pub const I64_ATOMIC_RMW_ADD16U: u8 = 0x23;
825 		pub const I64_ATOMIC_RMW_ADD32U: u8 = 0x24;
826 
827 		pub const I32_ATOMIC_RMW_SUB: u8 = 0x25;
828 		pub const I64_ATOMIC_RMW_SUB: u8 = 0x26;
829 		pub const I32_ATOMIC_RMW_SUB8U: u8 = 0x27;
830 		pub const I32_ATOMIC_RMW_SUB16U: u8 = 0x28;
831 		pub const I64_ATOMIC_RMW_SUB8U: u8 = 0x29;
832 		pub const I64_ATOMIC_RMW_SUB16U: u8 = 0x2a;
833 		pub const I64_ATOMIC_RMW_SUB32U: u8 = 0x2b;
834 
835 		pub const I32_ATOMIC_RMW_AND: u8 = 0x2c;
836 		pub const I64_ATOMIC_RMW_AND: u8 = 0x2d;
837 		pub const I32_ATOMIC_RMW_AND8U: u8 = 0x2e;
838 		pub const I32_ATOMIC_RMW_AND16U: u8 = 0x2f;
839 		pub const I64_ATOMIC_RMW_AND8U: u8 = 0x30;
840 		pub const I64_ATOMIC_RMW_AND16U: u8 = 0x31;
841 		pub const I64_ATOMIC_RMW_AND32U: u8 = 0x32;
842 
843 		pub const I32_ATOMIC_RMW_OR: u8 = 0x33;
844 		pub const I64_ATOMIC_RMW_OR: u8 = 0x34;
845 		pub const I32_ATOMIC_RMW_OR8U: u8 = 0x35;
846 		pub const I32_ATOMIC_RMW_OR16U: u8 = 0x36;
847 		pub const I64_ATOMIC_RMW_OR8U: u8 = 0x37;
848 		pub const I64_ATOMIC_RMW_OR16U: u8 = 0x38;
849 		pub const I64_ATOMIC_RMW_OR32U: u8 = 0x39;
850 
851 		pub const I32_ATOMIC_RMW_XOR: u8 = 0x3a;
852 		pub const I64_ATOMIC_RMW_XOR: u8 = 0x3b;
853 		pub const I32_ATOMIC_RMW_XOR8U: u8 = 0x3c;
854 		pub const I32_ATOMIC_RMW_XOR16U: u8 = 0x3d;
855 		pub const I64_ATOMIC_RMW_XOR8U: u8 = 0x3e;
856 		pub const I64_ATOMIC_RMW_XOR16U: u8 = 0x3f;
857 		pub const I64_ATOMIC_RMW_XOR32U: u8 = 0x40;
858 
859 		pub const I32_ATOMIC_RMW_XCHG: u8 = 0x41;
860 		pub const I64_ATOMIC_RMW_XCHG: u8 = 0x42;
861 		pub const I32_ATOMIC_RMW_XCHG8U: u8 = 0x43;
862 		pub const I32_ATOMIC_RMW_XCHG16U: u8 = 0x44;
863 		pub const I64_ATOMIC_RMW_XCHG8U: u8 = 0x45;
864 		pub const I64_ATOMIC_RMW_XCHG16U: u8 = 0x46;
865 		pub const I64_ATOMIC_RMW_XCHG32U: u8 = 0x47;
866 
867 		pub const I32_ATOMIC_RMW_CMPXCHG: u8 = 0x48;
868 		pub const I64_ATOMIC_RMW_CMPXCHG: u8 = 0x49;
869 		pub const I32_ATOMIC_RMW_CMPXCHG8U: u8 = 0x4a;
870 		pub const I32_ATOMIC_RMW_CMPXCHG16U: u8 = 0x4b;
871 		pub const I64_ATOMIC_RMW_CMPXCHG8U: u8 = 0x4c;
872 		pub const I64_ATOMIC_RMW_CMPXCHG16U: u8 = 0x4d;
873 		pub const I64_ATOMIC_RMW_CMPXCHG32U: u8 = 0x4e;
874 	}
875 
876 	#[cfg(feature="simd")]
877 	pub mod simd {
878 		// https://github.com/WebAssembly/simd/blob/master/proposals/simd/BinarySIMD.md
879 		pub const SIMD_PREFIX: u8 = 0xfd;
880 
881 		pub const V128_LOAD: u32 = 0x00;
882 		pub const V128_STORE: u32 = 0x01;
883 		pub const V128_CONST: u32 = 0x02;
884 		pub const V8X16_SHUFFLE: u32 = 0x03;
885 
886 		pub const I8X16_SPLAT: u32 = 0x04;
887 		pub const I8X16_EXTRACT_LANE_S: u32 = 0x05;
888 		pub const I8X16_EXTRACT_LANE_U: u32 = 0x06;
889 		pub const I8X16_REPLACE_LANE: u32 = 0x07;
890 		pub const I16X8_SPLAT: u32 = 0x08;
891 		pub const I16X8_EXTRACT_LANE_S: u32 = 0x09;
892 		pub const I16X8_EXTRACT_LANE_U: u32 = 0xa;
893 		pub const I16X8_REPLACE_LANE: u32 = 0x0b;
894 		pub const I32X4_SPLAT: u32 = 0x0c;
895 		pub const I32X4_EXTRACT_LANE: u32 = 0x0d;
896 		pub const I32X4_REPLACE_LANE: u32 = 0x0e;
897 		pub const I64X2_SPLAT: u32 = 0x0f;
898 		pub const I64X2_EXTRACT_LANE: u32 = 0x10;
899 		pub const I64X2_REPLACE_LANE: u32 = 0x11;
900 		pub const F32X4_SPLAT: u32 = 0x12;
901 		pub const F32X4_EXTRACT_LANE: u32 = 0x13;
902 		pub const F32X4_REPLACE_LANE: u32 = 0x14;
903 		pub const F64X2_SPLAT: u32 = 0x15;
904 		pub const F64X2_EXTRACT_LANE: u32 = 0x16;
905 		pub const F64X2_REPLACE_LANE: u32 = 0x17;
906 
907 		pub const I8X16_EQ: u32 = 0x18;
908 		pub const I8X16_NE: u32 = 0x19;
909 		pub const I8X16_LT_S: u32 = 0x1a;
910 		pub const I8X16_LT_U: u32 = 0x1b;
911 		pub const I8X16_GT_S: u32 = 0x1c;
912 		pub const I8X16_GT_U: u32 = 0x1d;
913 		pub const I8X16_LE_S: u32 = 0x1e;
914 		pub const I8X16_LE_U: u32 = 0x1f;
915 		pub const I8X16_GE_S: u32 = 0x20;
916 		pub const I8X16_GE_U: u32 = 0x21;
917 
918 		pub const I16X8_EQ: u32 = 0x22;
919 		pub const I16X8_NE: u32 = 0x23;
920 		pub const I16X8_LT_S: u32 = 0x24;
921 		pub const I16X8_LT_U: u32 = 0x25;
922 		pub const I16X8_GT_S: u32 = 0x26;
923 		pub const I16X8_GT_U: u32 = 0x27;
924 		pub const I16X8_LE_S: u32 = 0x28;
925 		pub const I16X8_LE_U: u32 = 0x29;
926 		pub const I16X8_GE_S: u32 = 0x2a;
927 		pub const I16X8_GE_U: u32 = 0x2b;
928 
929 		pub const I32X4_EQ: u32 = 0x2c;
930 		pub const I32X4_NE: u32 = 0x2d;
931 		pub const I32X4_LT_S: u32 = 0x2e;
932 		pub const I32X4_LT_U: u32 = 0x2f;
933 		pub const I32X4_GT_S: u32 = 0x30;
934 		pub const I32X4_GT_U: u32 = 0x31;
935 		pub const I32X4_LE_S: u32 = 0x32;
936 		pub const I32X4_LE_U: u32 = 0x33;
937 		pub const I32X4_GE_S: u32 = 0x34;
938 		pub const I32X4_GE_U: u32 = 0x35;
939 
940 		pub const F32X4_EQ: u32 = 0x40;
941 		pub const F32X4_NE: u32 = 0x41;
942 		pub const F32X4_LT: u32 = 0x42;
943 		pub const F32X4_GT: u32 = 0x43;
944 		pub const F32X4_LE: u32 = 0x44;
945 		pub const F32X4_GE: u32 = 0x45;
946 
947 		pub const F64X2_EQ: u32 = 0x46;
948 		pub const F64X2_NE: u32 = 0x47;
949 		pub const F64X2_LT: u32 = 0x48;
950 		pub const F64X2_GT: u32 = 0x49;
951 		pub const F64X2_LE: u32 = 0x4a;
952 		pub const F64X2_GE: u32 = 0x4b;
953 
954 		pub const V128_NOT: u32 = 0x4c;
955 		pub const V128_AND: u32 = 0x4d;
956 		pub const V128_OR: u32 = 0x4e;
957 		pub const V128_XOR: u32 = 0x4f;
958 		pub const V128_BITSELECT: u32 = 0x50;
959 
960 		pub const I8X16_NEG: u32 = 0x51;
961 		pub const I8X16_ANY_TRUE: u32 = 0x52;
962 		pub const I8X16_ALL_TRUE: u32 = 0x53;
963 		pub const I8X16_SHL: u32 = 0x54;
964 		pub const I8X16_SHR_S: u32 = 0x55;
965 		pub const I8X16_SHR_U: u32 = 0x56;
966 		pub const I8X16_ADD: u32 = 0x57;
967 		pub const I8X16_ADD_SATURATE_S: u32 = 0x58;
968 		pub const I8X16_ADD_SATURATE_U: u32 = 0x59;
969 		pub const I8X16_SUB: u32 = 0x5a;
970 		pub const I8X16_SUB_SATURATE_S: u32 = 0x5b;
971 		pub const I8X16_SUB_SATURATE_U: u32 = 0x5c;
972 		pub const I8X16_MUL: u32 = 0x5d;
973 
974 		pub const I16X8_NEG: u32 = 0x62;
975 		pub const I16X8_ANY_TRUE: u32 = 0x63;
976 		pub const I16X8_ALL_TRUE: u32 = 0x64;
977 		pub const I16X8_SHL: u32 = 0x65;
978 		pub const I16X8_SHR_S: u32 = 0x66;
979 		pub const I16X8_SHR_U: u32 = 0x67;
980 		pub const I16X8_ADD: u32 = 0x68;
981 		pub const I16X8_ADD_SATURATE_S: u32 = 0x69;
982 		pub const I16X8_ADD_SATURATE_U: u32 = 0x6a;
983 		pub const I16X8_SUB: u32 = 0x6b;
984 		pub const I16X8_SUB_SATURATE_S: u32 = 0x6c;
985 		pub const I16X8_SUB_SATURATE_U: u32 = 0x6d;
986 		pub const I16X8_MUL: u32 = 0x6e;
987 
988 		pub const I32X4_NEG: u32 = 0x73;
989 		pub const I32X4_ANY_TRUE: u32 = 0x74;
990 		pub const I32X4_ALL_TRUE: u32 = 0x75;
991 		pub const I32X4_SHL: u32 = 0x76;
992 		pub const I32X4_SHR_S: u32 = 0x77;
993 		pub const I32X4_SHR_U: u32 = 0x78;
994 		pub const I32X4_ADD: u32 = 0x79;
995 		pub const I32X4_ADD_SATURATE_S: u32 = 0x7a;
996 		pub const I32X4_ADD_SATURATE_U: u32 = 0x7b;
997 		pub const I32X4_SUB: u32 = 0x7c;
998 		pub const I32X4_SUB_SATURATE_S: u32 = 0x7d;
999 		pub const I32X4_SUB_SATURATE_U: u32 = 0x7e;
1000 		pub const I32X4_MUL: u32 = 0x7f;
1001 
1002 		pub const I64X2_NEG: u32 = 0x84;
1003 		pub const I64X2_ANY_TRUE: u32 = 0x85;
1004 		pub const I64X2_ALL_TRUE: u32 = 0x86;
1005 		pub const I64X2_SHL: u32 = 0x87;
1006 		pub const I64X2_SHR_S: u32 = 0x88;
1007 		pub const I64X2_SHR_U: u32 = 0x89;
1008 		pub const I64X2_ADD: u32 = 0x8a;
1009 		pub const I64X2_SUB: u32 = 0x8d;
1010 
1011 		pub const F32X4_ABS: u32 = 0x95;
1012 		pub const F32X4_NEG: u32 = 0x96;
1013 		pub const F32X4_SQRT: u32 = 0x97;
1014 		pub const F32X4_ADD: u32 = 0x9a;
1015 		pub const F32X4_SUB: u32 = 0x9b;
1016 		pub const F32X4_MUL: u32 = 0x9c;
1017 		pub const F32X4_DIV: u32 = 0x9d;
1018 		pub const F32X4_MIN: u32 = 0x9e;
1019 		pub const F32X4_MAX: u32 = 0x9f;
1020 
1021 		pub const F64X2_ABS: u32 = 0xa0;
1022 		pub const F64X2_NEG: u32 = 0xa1;
1023 		pub const F64X2_SQRT: u32 = 0xa2;
1024 		pub const F64X2_ADD: u32 = 0xa5;
1025 		pub const F64X2_SUB: u32 = 0xa6;
1026 		pub const F64X2_MUL: u32 = 0xa7;
1027 		pub const F64X2_DIV: u32 = 0xa8;
1028 		pub const F64X2_MIN: u32 = 0xa9;
1029 		pub const F64X2_MAX: u32 = 0xaa;
1030 
1031 		pub const I32X4_TRUNC_S_F32X4_SAT: u32 = 0xab;
1032 		pub const I32X4_TRUNC_U_F32X4_SAT: u32 = 0xac;
1033 		pub const I64X2_TRUNC_S_F64X2_SAT: u32 = 0xad;
1034 		pub const I64X2_TRUNC_U_F64X2_SAT: u32 = 0xae;
1035 
1036 		pub const F32X4_CONVERT_S_I32X4: u32 = 0xaf;
1037 		pub const F32X4_CONVERT_U_I32X4: u32 = 0xb0;
1038 		pub const F64X2_CONVERT_S_I64X2: u32 = 0xb1;
1039 		pub const F64X2_CONVERT_U_I64X2: u32 = 0xb2;
1040 	}
1041 
1042 	#[cfg(feature="bulk")]
1043 	pub mod bulk {
1044 		pub const BULK_PREFIX: u8 = 0xfc;
1045 		pub const MEMORY_INIT: u8 = 0x08;
1046 		pub const MEMORY_DROP: u8 = 0x09;
1047 		pub const MEMORY_COPY: u8 = 0x0a;
1048 		pub const MEMORY_FILL: u8 = 0x0b;
1049 		pub const TABLE_INIT: u8 = 0x0c;
1050 		pub const TABLE_DROP: u8 = 0x0d;
1051 		pub const TABLE_COPY: u8 = 0x0e;
1052 	}
1053 }
1054 
1055 impl Deserialize for Instruction {
1056 	type Error = Error;
1057 
deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>1058 	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
1059 		use self::Instruction::*;
1060 		use self::opcodes::*;
1061 
1062 		#[cfg(feature="sign_ext")]
1063 		use self::opcodes::sign_ext::*;
1064 
1065 		let val: u8 = Uint8::deserialize(reader)?.into();
1066 
1067 		Ok(
1068 			match val {
1069 				UNREACHABLE => Unreachable,
1070 				NOP => Nop,
1071 				BLOCK => Block(BlockType::deserialize(reader)?),
1072 				LOOP => Loop(BlockType::deserialize(reader)?),
1073 				IF => If(BlockType::deserialize(reader)?),
1074 				ELSE => Else,
1075 				END => End,
1076 
1077 				BR => Br(VarUint32::deserialize(reader)?.into()),
1078 				BRIF => BrIf(VarUint32::deserialize(reader)?.into()),
1079 				BRTABLE => {
1080 					let t1: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
1081 						.into_inner()
1082 						.into_iter()
1083 						.map(Into::into)
1084 						.collect();
1085 
1086 					BrTable(Box::new(BrTableData {
1087 						table: t1.into_boxed_slice(),
1088 						default: VarUint32::deserialize(reader)?.into(),
1089 					}))
1090 				},
1091 				RETURN => Return,
1092 				CALL => Call(VarUint32::deserialize(reader)?.into()),
1093 				CALLINDIRECT => {
1094 					let signature: u32 = VarUint32::deserialize(reader)?.into();
1095 					let table_ref: u8 = Uint8::deserialize(reader)?.into();
1096 					if table_ref != 0 { return Err(Error::InvalidTableReference(table_ref)); }
1097 
1098 					CallIndirect(
1099 						signature,
1100 						table_ref,
1101 					)
1102 				},
1103 				DROP => Drop,
1104 				SELECT => Select,
1105 
1106 				GETLOCAL => GetLocal(VarUint32::deserialize(reader)?.into()),
1107 				SETLOCAL => SetLocal(VarUint32::deserialize(reader)?.into()),
1108 				TEELOCAL => TeeLocal(VarUint32::deserialize(reader)?.into()),
1109 				GETGLOBAL => GetGlobal(VarUint32::deserialize(reader)?.into()),
1110 				SETGLOBAL => SetGlobal(VarUint32::deserialize(reader)?.into()),
1111 
1112 				I32LOAD => I32Load(
1113 					VarUint32::deserialize(reader)?.into(),
1114 					VarUint32::deserialize(reader)?.into()),
1115 
1116 				I64LOAD => I64Load(
1117 					VarUint32::deserialize(reader)?.into(),
1118 					VarUint32::deserialize(reader)?.into()),
1119 
1120 				F32LOAD => F32Load(
1121 					VarUint32::deserialize(reader)?.into(),
1122 					VarUint32::deserialize(reader)?.into()),
1123 
1124 				F64LOAD => F64Load(
1125 					VarUint32::deserialize(reader)?.into(),
1126 					VarUint32::deserialize(reader)?.into()),
1127 
1128 				I32LOAD8S => I32Load8S(
1129 					VarUint32::deserialize(reader)?.into(),
1130 					VarUint32::deserialize(reader)?.into()),
1131 
1132 				I32LOAD8U => I32Load8U(
1133 					VarUint32::deserialize(reader)?.into(),
1134 					VarUint32::deserialize(reader)?.into()),
1135 
1136 				I32LOAD16S => I32Load16S(
1137 					VarUint32::deserialize(reader)?.into(),
1138 					VarUint32::deserialize(reader)?.into()),
1139 
1140 				I32LOAD16U => I32Load16U(
1141 					VarUint32::deserialize(reader)?.into(),
1142 					VarUint32::deserialize(reader)?.into()),
1143 
1144 				I64LOAD8S => I64Load8S(
1145 					VarUint32::deserialize(reader)?.into(),
1146 					VarUint32::deserialize(reader)?.into()),
1147 
1148 				I64LOAD8U => I64Load8U(
1149 					VarUint32::deserialize(reader)?.into(),
1150 					VarUint32::deserialize(reader)?.into()),
1151 
1152 				I64LOAD16S => I64Load16S(
1153 					VarUint32::deserialize(reader)?.into(),
1154 					VarUint32::deserialize(reader)?.into()),
1155 
1156 				I64LOAD16U => I64Load16U(
1157 					VarUint32::deserialize(reader)?.into(),
1158 					VarUint32::deserialize(reader)?.into()),
1159 
1160 				I64LOAD32S => I64Load32S(
1161 					VarUint32::deserialize(reader)?.into(),
1162 					VarUint32::deserialize(reader)?.into()),
1163 
1164 				I64LOAD32U => I64Load32U(
1165 					VarUint32::deserialize(reader)?.into(),
1166 					VarUint32::deserialize(reader)?.into()),
1167 
1168 				I32STORE => I32Store(
1169 					VarUint32::deserialize(reader)?.into(),
1170 					VarUint32::deserialize(reader)?.into()),
1171 
1172 				I64STORE => I64Store(
1173 					VarUint32::deserialize(reader)?.into(),
1174 					VarUint32::deserialize(reader)?.into()),
1175 
1176 				F32STORE => F32Store(
1177 					VarUint32::deserialize(reader)?.into(),
1178 					VarUint32::deserialize(reader)?.into()),
1179 
1180 				F64STORE => F64Store(
1181 					VarUint32::deserialize(reader)?.into(),
1182 					VarUint32::deserialize(reader)?.into()),
1183 
1184 				I32STORE8 => I32Store8(
1185 					VarUint32::deserialize(reader)?.into(),
1186 					VarUint32::deserialize(reader)?.into()),
1187 
1188 				I32STORE16 => I32Store16(
1189 					VarUint32::deserialize(reader)?.into(),
1190 					VarUint32::deserialize(reader)?.into()),
1191 
1192 				I64STORE8 => I64Store8(
1193 					VarUint32::deserialize(reader)?.into(),
1194 					VarUint32::deserialize(reader)?.into()),
1195 
1196 				I64STORE16 => I64Store16(
1197 					VarUint32::deserialize(reader)?.into(),
1198 					VarUint32::deserialize(reader)?.into()),
1199 
1200 				I64STORE32 => I64Store32(
1201 					VarUint32::deserialize(reader)?.into(),
1202 					VarUint32::deserialize(reader)?.into()),
1203 
1204 
1205 				CURRENTMEMORY => {
1206 					let mem_ref: u8 = Uint8::deserialize(reader)?.into();
1207 					if mem_ref != 0 { return Err(Error::InvalidMemoryReference(mem_ref)); }
1208 					CurrentMemory(mem_ref)
1209 				},
1210 				GROWMEMORY => {
1211 					let mem_ref: u8 = Uint8::deserialize(reader)?.into();
1212 					if mem_ref != 0 { return Err(Error::InvalidMemoryReference(mem_ref)); }
1213 					GrowMemory(mem_ref)
1214 				}
1215 
1216 				I32CONST => I32Const(VarInt32::deserialize(reader)?.into()),
1217 				I64CONST => I64Const(VarInt64::deserialize(reader)?.into()),
1218 				F32CONST => F32Const(Uint32::deserialize(reader)?.into()),
1219 				F64CONST => F64Const(Uint64::deserialize(reader)?.into()),
1220 				I32EQZ => I32Eqz,
1221 				I32EQ => I32Eq,
1222 				I32NE => I32Ne,
1223 				I32LTS => I32LtS,
1224 				I32LTU => I32LtU,
1225 				I32GTS => I32GtS,
1226 				I32GTU => I32GtU,
1227 				I32LES => I32LeS,
1228 				I32LEU => I32LeU,
1229 				I32GES => I32GeS,
1230 				I32GEU => I32GeU,
1231 
1232 				I64EQZ => I64Eqz,
1233 				I64EQ => I64Eq,
1234 				I64NE => I64Ne,
1235 				I64LTS => I64LtS,
1236 				I64LTU => I64LtU,
1237 				I64GTS => I64GtS,
1238 				I64GTU => I64GtU,
1239 				I64LES => I64LeS,
1240 				I64LEU => I64LeU,
1241 				I64GES => I64GeS,
1242 				I64GEU => I64GeU,
1243 
1244 				F32EQ => F32Eq,
1245 				F32NE => F32Ne,
1246 				F32LT => F32Lt,
1247 				F32GT => F32Gt,
1248 				F32LE => F32Le,
1249 				F32GE => F32Ge,
1250 
1251 				F64EQ => F64Eq,
1252 				F64NE => F64Ne,
1253 				F64LT => F64Lt,
1254 				F64GT => F64Gt,
1255 				F64LE => F64Le,
1256 				F64GE => F64Ge,
1257 
1258 				I32CLZ => I32Clz,
1259 				I32CTZ => I32Ctz,
1260 				I32POPCNT => I32Popcnt,
1261 				I32ADD => I32Add,
1262 				I32SUB => I32Sub,
1263 				I32MUL => I32Mul,
1264 				I32DIVS => I32DivS,
1265 				I32DIVU => I32DivU,
1266 				I32REMS => I32RemS,
1267 				I32REMU => I32RemU,
1268 				I32AND => I32And,
1269 				I32OR => I32Or,
1270 				I32XOR => I32Xor,
1271 				I32SHL => I32Shl,
1272 				I32SHRS => I32ShrS,
1273 				I32SHRU => I32ShrU,
1274 				I32ROTL => I32Rotl,
1275 				I32ROTR => I32Rotr,
1276 
1277 				I64CLZ => I64Clz,
1278 				I64CTZ => I64Ctz,
1279 				I64POPCNT => I64Popcnt,
1280 				I64ADD => I64Add,
1281 				I64SUB => I64Sub,
1282 				I64MUL => I64Mul,
1283 				I64DIVS => I64DivS,
1284 				I64DIVU => I64DivU,
1285 				I64REMS => I64RemS,
1286 				I64REMU => I64RemU,
1287 				I64AND => I64And,
1288 				I64OR => I64Or,
1289 				I64XOR => I64Xor,
1290 				I64SHL => I64Shl,
1291 				I64SHRS => I64ShrS,
1292 				I64SHRU => I64ShrU,
1293 				I64ROTL => I64Rotl,
1294 				I64ROTR => I64Rotr,
1295 				F32ABS => F32Abs,
1296 				F32NEG => F32Neg,
1297 				F32CEIL => F32Ceil,
1298 				F32FLOOR => F32Floor,
1299 				F32TRUNC => F32Trunc,
1300 				F32NEAREST => F32Nearest,
1301 				F32SQRT => F32Sqrt,
1302 				F32ADD => F32Add,
1303 				F32SUB => F32Sub,
1304 				F32MUL => F32Mul,
1305 				F32DIV => F32Div,
1306 				F32MIN => F32Min,
1307 				F32MAX => F32Max,
1308 				F32COPYSIGN => F32Copysign,
1309 				F64ABS => F64Abs,
1310 				F64NEG => F64Neg,
1311 				F64CEIL => F64Ceil,
1312 				F64FLOOR => F64Floor,
1313 				F64TRUNC => F64Trunc,
1314 				F64NEAREST => F64Nearest,
1315 				F64SQRT => F64Sqrt,
1316 				F64ADD => F64Add,
1317 				F64SUB => F64Sub,
1318 				F64MUL => F64Mul,
1319 				F64DIV => F64Div,
1320 				F64MIN => F64Min,
1321 				F64MAX => F64Max,
1322 				F64COPYSIGN => F64Copysign,
1323 
1324 				I32WRAPI64 => I32WrapI64,
1325 				I32TRUNCSF32 => I32TruncSF32,
1326 				I32TRUNCUF32 => I32TruncUF32,
1327 				I32TRUNCSF64 => I32TruncSF64,
1328 				I32TRUNCUF64 => I32TruncUF64,
1329 				I64EXTENDSI32 => I64ExtendSI32,
1330 				I64EXTENDUI32 => I64ExtendUI32,
1331 				I64TRUNCSF32 => I64TruncSF32,
1332 				I64TRUNCUF32 => I64TruncUF32,
1333 				I64TRUNCSF64 => I64TruncSF64,
1334 				I64TRUNCUF64 => I64TruncUF64,
1335 				F32CONVERTSI32 => F32ConvertSI32,
1336 				F32CONVERTUI32 => F32ConvertUI32,
1337 				F32CONVERTSI64 => F32ConvertSI64,
1338 				F32CONVERTUI64 => F32ConvertUI64,
1339 				F32DEMOTEF64 => F32DemoteF64,
1340 				F64CONVERTSI32 => F64ConvertSI32,
1341 				F64CONVERTUI32 => F64ConvertUI32,
1342 				F64CONVERTSI64 => F64ConvertSI64,
1343 				F64CONVERTUI64 => F64ConvertUI64,
1344 				F64PROMOTEF32 => F64PromoteF32,
1345 
1346 				I32REINTERPRETF32 => I32ReinterpretF32,
1347 				I64REINTERPRETF64 => I64ReinterpretF64,
1348 				F32REINTERPRETI32 => F32ReinterpretI32,
1349 				F64REINTERPRETI64 => F64ReinterpretI64,
1350 
1351 				#[cfg(feature="sign_ext")]
1352 				I32_EXTEND8_S |
1353 				I32_EXTEND16_S |
1354 				I64_EXTEND8_S |
1355 				I64_EXTEND16_S |
1356 				I64_EXTEND32_S => match val {
1357 					I32_EXTEND8_S => SignExt(SignExtInstruction::I32Extend8S),
1358 					I32_EXTEND16_S => SignExt(SignExtInstruction::I32Extend16S),
1359 					I64_EXTEND8_S => SignExt(SignExtInstruction::I64Extend8S),
1360 					I64_EXTEND16_S => SignExt(SignExtInstruction::I64Extend16S),
1361 					I64_EXTEND32_S => SignExt(SignExtInstruction::I64Extend32S),
1362 					_ => return Err(Error::UnknownOpcode(val)),
1363 				}
1364 
1365 				#[cfg(feature="atomics")]
1366 				atomics::ATOMIC_PREFIX => return deserialize_atomic(reader),
1367 
1368 				#[cfg(feature="simd")]
1369 				simd::SIMD_PREFIX => return deserialize_simd(reader),
1370 
1371 				#[cfg(feature="bulk")]
1372 				bulk::BULK_PREFIX => return deserialize_bulk(reader),
1373 
1374 				_ => { return Err(Error::UnknownOpcode(val)); }
1375 			}
1376 		)
1377 	}
1378 }
1379 
1380 #[cfg(feature="atomics")]
deserialize_atomic<R: io::Read>(reader: &mut R) -> Result<Instruction, Error>1381 fn deserialize_atomic<R: io::Read>(reader: &mut R) -> Result<Instruction, Error> {
1382 	use self::AtomicsInstruction::*;
1383 	use self::opcodes::atomics::*;
1384 
1385 	let val: u8 = Uint8::deserialize(reader)?.into();
1386 	let mem = MemArg::deserialize(reader)?;
1387 	Ok(Instruction::Atomics(match val {
1388 		ATOMIC_WAKE => AtomicWake(mem),
1389 		I32_ATOMIC_WAIT => I32AtomicWait(mem),
1390 		I64_ATOMIC_WAIT => I64AtomicWait(mem),
1391 
1392 		I32_ATOMIC_LOAD => I32AtomicLoad(mem),
1393 		I64_ATOMIC_LOAD => I64AtomicLoad(mem),
1394 		I32_ATOMIC_LOAD8U => I32AtomicLoad8u(mem),
1395 		I32_ATOMIC_LOAD16U => I32AtomicLoad16u(mem),
1396 		I64_ATOMIC_LOAD8U => I64AtomicLoad8u(mem),
1397 		I64_ATOMIC_LOAD16U => I64AtomicLoad16u(mem),
1398 		I64_ATOMIC_LOAD32U => I64AtomicLoad32u(mem),
1399 		I32_ATOMIC_STORE => I32AtomicStore(mem),
1400 		I64_ATOMIC_STORE => I64AtomicStore(mem),
1401 		I32_ATOMIC_STORE8U => I32AtomicStore8u(mem),
1402 		I32_ATOMIC_STORE16U => I32AtomicStore16u(mem),
1403 		I64_ATOMIC_STORE8U => I64AtomicStore8u(mem),
1404 		I64_ATOMIC_STORE16U => I64AtomicStore16u(mem),
1405 		I64_ATOMIC_STORE32U => I64AtomicStore32u(mem),
1406 
1407 		I32_ATOMIC_RMW_ADD => I32AtomicRmwAdd(mem),
1408 		I64_ATOMIC_RMW_ADD => I64AtomicRmwAdd(mem),
1409 		I32_ATOMIC_RMW_ADD8U => I32AtomicRmwAdd8u(mem),
1410 		I32_ATOMIC_RMW_ADD16U => I32AtomicRmwAdd16u(mem),
1411 		I64_ATOMIC_RMW_ADD8U => I64AtomicRmwAdd8u(mem),
1412 		I64_ATOMIC_RMW_ADD16U => I64AtomicRmwAdd16u(mem),
1413 		I64_ATOMIC_RMW_ADD32U => I64AtomicRmwAdd32u(mem),
1414 
1415 		I32_ATOMIC_RMW_SUB => I32AtomicRmwSub(mem),
1416 		I64_ATOMIC_RMW_SUB => I64AtomicRmwSub(mem),
1417 		I32_ATOMIC_RMW_SUB8U => I32AtomicRmwSub8u(mem),
1418 		I32_ATOMIC_RMW_SUB16U => I32AtomicRmwSub16u(mem),
1419 		I64_ATOMIC_RMW_SUB8U => I64AtomicRmwSub8u(mem),
1420 		I64_ATOMIC_RMW_SUB16U => I64AtomicRmwSub16u(mem),
1421 		I64_ATOMIC_RMW_SUB32U => I64AtomicRmwSub32u(mem),
1422 
1423 		I32_ATOMIC_RMW_OR => I32AtomicRmwOr(mem),
1424 		I64_ATOMIC_RMW_OR => I64AtomicRmwOr(mem),
1425 		I32_ATOMIC_RMW_OR8U => I32AtomicRmwOr8u(mem),
1426 		I32_ATOMIC_RMW_OR16U => I32AtomicRmwOr16u(mem),
1427 		I64_ATOMIC_RMW_OR8U => I64AtomicRmwOr8u(mem),
1428 		I64_ATOMIC_RMW_OR16U => I64AtomicRmwOr16u(mem),
1429 		I64_ATOMIC_RMW_OR32U => I64AtomicRmwOr32u(mem),
1430 
1431 		I32_ATOMIC_RMW_XOR => I32AtomicRmwXor(mem),
1432 		I64_ATOMIC_RMW_XOR => I64AtomicRmwXor(mem),
1433 		I32_ATOMIC_RMW_XOR8U => I32AtomicRmwXor8u(mem),
1434 		I32_ATOMIC_RMW_XOR16U => I32AtomicRmwXor16u(mem),
1435 		I64_ATOMIC_RMW_XOR8U => I64AtomicRmwXor8u(mem),
1436 		I64_ATOMIC_RMW_XOR16U => I64AtomicRmwXor16u(mem),
1437 		I64_ATOMIC_RMW_XOR32U => I64AtomicRmwXor32u(mem),
1438 
1439 		I32_ATOMIC_RMW_XCHG => I32AtomicRmwXchg(mem),
1440 		I64_ATOMIC_RMW_XCHG => I64AtomicRmwXchg(mem),
1441 		I32_ATOMIC_RMW_XCHG8U => I32AtomicRmwXchg8u(mem),
1442 		I32_ATOMIC_RMW_XCHG16U => I32AtomicRmwXchg16u(mem),
1443 		I64_ATOMIC_RMW_XCHG8U => I64AtomicRmwXchg8u(mem),
1444 		I64_ATOMIC_RMW_XCHG16U => I64AtomicRmwXchg16u(mem),
1445 		I64_ATOMIC_RMW_XCHG32U => I64AtomicRmwXchg32u(mem),
1446 
1447 		I32_ATOMIC_RMW_CMPXCHG => I32AtomicRmwCmpxchg(mem),
1448 		I64_ATOMIC_RMW_CMPXCHG => I64AtomicRmwCmpxchg(mem),
1449 		I32_ATOMIC_RMW_CMPXCHG8U => I32AtomicRmwCmpxchg8u(mem),
1450 		I32_ATOMIC_RMW_CMPXCHG16U => I32AtomicRmwCmpxchg16u(mem),
1451 		I64_ATOMIC_RMW_CMPXCHG8U => I64AtomicRmwCmpxchg8u(mem),
1452 		I64_ATOMIC_RMW_CMPXCHG16U => I64AtomicRmwCmpxchg16u(mem),
1453 		I64_ATOMIC_RMW_CMPXCHG32U => I64AtomicRmwCmpxchg32u(mem),
1454 
1455 		_ => return Err(Error::UnknownOpcode(val)),
1456 	}))
1457 }
1458 
1459 #[cfg(feature="simd")]
deserialize_simd<R: io::Read>(reader: &mut R) -> Result<Instruction, Error>1460 fn deserialize_simd<R: io::Read>(reader: &mut R) -> Result<Instruction, Error> {
1461 	use self::SimdInstruction::*;
1462 	use self::opcodes::simd::*;
1463 
1464 	let val = VarUint32::deserialize(reader)?.into();
1465 	Ok(Instruction::Simd(match val {
1466 		V128_CONST => {
1467 			let mut buf = [0; 16];
1468 			reader.read(&mut buf)?;
1469 			V128Const(Box::new(buf))
1470 		}
1471 		V128_LOAD => V128Load(MemArg::deserialize(reader)?),
1472 		V128_STORE => V128Store(MemArg::deserialize(reader)?),
1473 		I8X16_SPLAT => I8x16Splat,
1474 		I16X8_SPLAT => I16x8Splat,
1475 		I32X4_SPLAT => I32x4Splat,
1476 		I64X2_SPLAT => I64x2Splat,
1477 		F32X4_SPLAT => F32x4Splat,
1478 		F64X2_SPLAT => F64x2Splat,
1479 		I8X16_EXTRACT_LANE_S => I8x16ExtractLaneS(Uint8::deserialize(reader)?.into()),
1480 		I8X16_EXTRACT_LANE_U => I8x16ExtractLaneU(Uint8::deserialize(reader)?.into()),
1481 		I16X8_EXTRACT_LANE_S => I16x8ExtractLaneS(Uint8::deserialize(reader)?.into()),
1482 		I16X8_EXTRACT_LANE_U => I16x8ExtractLaneU(Uint8::deserialize(reader)?.into()),
1483 		I32X4_EXTRACT_LANE => I32x4ExtractLane(Uint8::deserialize(reader)?.into()),
1484 		I64X2_EXTRACT_LANE => I64x2ExtractLane(Uint8::deserialize(reader)?.into()),
1485 		F32X4_EXTRACT_LANE => F32x4ExtractLane(Uint8::deserialize(reader)?.into()),
1486 		F64X2_EXTRACT_LANE => F64x2ExtractLane(Uint8::deserialize(reader)?.into()),
1487 		I8X16_REPLACE_LANE => I8x16ReplaceLane(Uint8::deserialize(reader)?.into()),
1488 		I16X8_REPLACE_LANE => I16x8ReplaceLane(Uint8::deserialize(reader)?.into()),
1489 		I32X4_REPLACE_LANE => I32x4ReplaceLane(Uint8::deserialize(reader)?.into()),
1490 		I64X2_REPLACE_LANE => I64x2ReplaceLane(Uint8::deserialize(reader)?.into()),
1491 		F32X4_REPLACE_LANE => F32x4ReplaceLane(Uint8::deserialize(reader)?.into()),
1492 		F64X2_REPLACE_LANE => F64x2ReplaceLane(Uint8::deserialize(reader)?.into()),
1493 		V8X16_SHUFFLE => {
1494 			let mut buf = [0; 16];
1495 			reader.read(&mut buf)?;
1496 			V8x16Shuffle(Box::new(buf))
1497 		}
1498 		I8X16_ADD => I8x16Add,
1499 		I16X8_ADD => I16x8Add,
1500 		I32X4_ADD => I32x4Add,
1501 		I64X2_ADD => I64x2Add,
1502 		I8X16_SUB => I8x16Sub,
1503 		I16X8_SUB => I16x8Sub,
1504 		I32X4_SUB => I32x4Sub,
1505 		I64X2_SUB => I64x2Sub,
1506 		I8X16_MUL => I8x16Mul,
1507 		I16X8_MUL => I16x8Mul,
1508 		I32X4_MUL => I32x4Mul,
1509 		// I64X2_MUL => I64x2Mul,
1510 		I8X16_NEG => I8x16Neg,
1511 		I16X8_NEG => I16x8Neg,
1512 		I32X4_NEG => I32x4Neg,
1513 		I64X2_NEG => I64x2Neg,
1514 
1515 		I8X16_ADD_SATURATE_S => I8x16AddSaturateS,
1516 		I8X16_ADD_SATURATE_U => I8x16AddSaturateU,
1517 		I16X8_ADD_SATURATE_S => I16x8AddSaturateS,
1518 		I16X8_ADD_SATURATE_U => I16x8AddSaturateU,
1519 		I8X16_SUB_SATURATE_S => I8x16SubSaturateS,
1520 		I8X16_SUB_SATURATE_U => I8x16SubSaturateU,
1521 		I16X8_SUB_SATURATE_S => I16x8SubSaturateS,
1522 		I16X8_SUB_SATURATE_U => I16x8SubSaturateU,
1523 		I8X16_SHL => I8x16Shl,
1524 		I16X8_SHL => I16x8Shl,
1525 		I32X4_SHL => I32x4Shl,
1526 		I64X2_SHL => I64x2Shl,
1527 		I8X16_SHR_S => I8x16ShrS,
1528 		I8X16_SHR_U => I8x16ShrU,
1529 		I16X8_SHR_S => I16x8ShrS,
1530 		I16X8_SHR_U => I16x8ShrU,
1531 		I32X4_SHR_S => I32x4ShrS,
1532 		I32X4_SHR_U => I32x4ShrU,
1533 		I64X2_SHR_S => I64x2ShrS,
1534 		I64X2_SHR_U => I64x2ShrU,
1535 		V128_AND => V128And,
1536 		V128_OR => V128Or,
1537 		V128_XOR => V128Xor,
1538 		V128_NOT => V128Not,
1539 		V128_BITSELECT => V128Bitselect,
1540 		I8X16_ANY_TRUE => I8x16AnyTrue,
1541 		I16X8_ANY_TRUE => I16x8AnyTrue,
1542 		I32X4_ANY_TRUE => I32x4AnyTrue,
1543 		I64X2_ANY_TRUE => I64x2AnyTrue,
1544 		I8X16_ALL_TRUE => I8x16AllTrue,
1545 		I16X8_ALL_TRUE => I16x8AllTrue,
1546 		I32X4_ALL_TRUE => I32x4AllTrue,
1547 		I64X2_ALL_TRUE => I64x2AllTrue,
1548 		I8X16_EQ => I8x16Eq,
1549 		I16X8_EQ => I16x8Eq,
1550 		I32X4_EQ => I32x4Eq,
1551 		// I64X2_EQ => I64x2Eq,
1552 		F32X4_EQ => F32x4Eq,
1553 		F64X2_EQ => F64x2Eq,
1554 		I8X16_NE => I8x16Ne,
1555 		I16X8_NE => I16x8Ne,
1556 		I32X4_NE => I32x4Ne,
1557 		// I64X2_NE => I64x2Ne,
1558 		F32X4_NE => F32x4Ne,
1559 		F64X2_NE => F64x2Ne,
1560 		I8X16_LT_S => I8x16LtS,
1561 		I8X16_LT_U => I8x16LtU,
1562 		I16X8_LT_S => I16x8LtS,
1563 		I16X8_LT_U => I16x8LtU,
1564 		I32X4_LT_S => I32x4LtS,
1565 		I32X4_LT_U => I32x4LtU,
1566 		// I64X2_LT_S => I64x2LtS,
1567 		// I64X2_LT_U => I64x2LtU,
1568 		F32X4_LT => F32x4Lt,
1569 		F64X2_LT => F64x2Lt,
1570 		I8X16_LE_S => I8x16LeS,
1571 		I8X16_LE_U => I8x16LeU,
1572 		I16X8_LE_S => I16x8LeS,
1573 		I16X8_LE_U => I16x8LeU,
1574 		I32X4_LE_S => I32x4LeS,
1575 		I32X4_LE_U => I32x4LeU,
1576 		// I64X2_LE_S => I64x2LeS,
1577 		// I64X2_LE_U => I64x2LeU,
1578 		F32X4_LE => F32x4Le,
1579 		F64X2_LE => F64x2Le,
1580 		I8X16_GT_S => I8x16GtS,
1581 		I8X16_GT_U => I8x16GtU,
1582 		I16X8_GT_S => I16x8GtS,
1583 		I16X8_GT_U => I16x8GtU,
1584 		I32X4_GT_S => I32x4GtS,
1585 		I32X4_GT_U => I32x4GtU,
1586 		// I64X2_GT_S => I64x2GtS,
1587 		// I64X2_GT_U => I64x2GtU,
1588 		F32X4_GT => F32x4Gt,
1589 		F64X2_GT => F64x2Gt,
1590 		I8X16_GE_S => I8x16GeS,
1591 		I8X16_GE_U => I8x16GeU,
1592 		I16X8_GE_S => I16x8GeS,
1593 		I16X8_GE_U => I16x8GeU,
1594 		I32X4_GE_S => I32x4GeS,
1595 		I32X4_GE_U => I32x4GeU,
1596 		// I64X2_GE_S => I64x2GeS,
1597 		// I64X2_GE_U => I64x2GeU,
1598 		F32X4_GE => F32x4Ge,
1599 		F64X2_GE => F64x2Ge,
1600 		F32X4_NEG => F32x4Neg,
1601 		F64X2_NEG => F64x2Neg,
1602 		F32X4_ABS => F32x4Abs,
1603 		F64X2_ABS => F64x2Abs,
1604 		F32X4_MIN => F32x4Min,
1605 		F64X2_MIN => F64x2Min,
1606 		F32X4_MAX => F32x4Max,
1607 		F64X2_MAX => F64x2Max,
1608 		F32X4_ADD => F32x4Add,
1609 		F64X2_ADD => F64x2Add,
1610 		F32X4_SUB => F32x4Sub,
1611 		F64X2_SUB => F64x2Sub,
1612 		F32X4_DIV => F32x4Div,
1613 		F64X2_DIV => F64x2Div,
1614 		F32X4_MUL => F32x4Mul,
1615 		F64X2_MUL => F64x2Mul,
1616 		F32X4_SQRT => F32x4Sqrt,
1617 		F64X2_SQRT => F64x2Sqrt,
1618 		F32X4_CONVERT_S_I32X4 => F32x4ConvertSI32x4,
1619 		F32X4_CONVERT_U_I32X4 => F32x4ConvertUI32x4,
1620 		F64X2_CONVERT_S_I64X2 => F64x2ConvertSI64x2,
1621 		F64X2_CONVERT_U_I64X2 => F64x2ConvertUI64x2,
1622 		I32X4_TRUNC_S_F32X4_SAT => I32x4TruncSF32x4Sat,
1623 		I32X4_TRUNC_U_F32X4_SAT => I32x4TruncUF32x4Sat,
1624 		I64X2_TRUNC_S_F64X2_SAT => I64x2TruncSF64x2Sat,
1625 		I64X2_TRUNC_U_F64X2_SAT => I64x2TruncUF64x2Sat,
1626 
1627 		_ => return Err(Error::UnknownSimdOpcode(val)),
1628 	}))
1629 }
1630 
1631 #[cfg(feature="bulk")]
deserialize_bulk<R: io::Read>(reader: &mut R) -> Result<Instruction, Error>1632 fn deserialize_bulk<R: io::Read>(reader: &mut R) -> Result<Instruction, Error> {
1633 	use self::BulkInstruction::*;
1634 	use self::opcodes::bulk::*;
1635 
1636 	let val: u8 = Uint8::deserialize(reader)?.into();
1637 	Ok(Instruction::Bulk(match val {
1638 		MEMORY_INIT => {
1639 			if u8::from(Uint8::deserialize(reader)?) != 0 {
1640 				return Err(Error::UnknownOpcode(val))
1641 			}
1642 			MemoryInit(VarUint32::deserialize(reader)?.into())
1643 		}
1644 		MEMORY_DROP => MemoryDrop(VarUint32::deserialize(reader)?.into()),
1645 		MEMORY_FILL => {
1646 			if u8::from(Uint8::deserialize(reader)?) != 0 {
1647 				return Err(Error::UnknownOpcode(val))
1648 			}
1649 			MemoryFill
1650 		}
1651 		MEMORY_COPY => {
1652 			if u8::from(Uint8::deserialize(reader)?) != 0 {
1653 				return Err(Error::UnknownOpcode(val))
1654 			}
1655 			MemoryCopy
1656 		}
1657 
1658 		TABLE_INIT => {
1659 			if u8::from(Uint8::deserialize(reader)?) != 0 {
1660 				return Err(Error::UnknownOpcode(val))
1661 			}
1662 			TableInit(VarUint32::deserialize(reader)?.into())
1663 		}
1664 		TABLE_DROP => TableDrop(VarUint32::deserialize(reader)?.into()),
1665 		TABLE_COPY => {
1666 			if u8::from(Uint8::deserialize(reader)?) != 0 {
1667 				return Err(Error::UnknownOpcode(val))
1668 			}
1669 			TableCopy
1670 		}
1671 
1672 		_ => return Err(Error::UnknownOpcode(val)),
1673 	}))
1674 }
1675 
1676 #[cfg(any(feature="simd", feature="atomics"))]
1677 impl Deserialize for MemArg {
1678 	type Error = Error;
1679 
deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>1680 	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
1681 		let align = Uint8::deserialize(reader)?;
1682 		let offset = VarUint32::deserialize(reader)?;
1683 		Ok(MemArg { align: align.into(), offset: offset.into() })
1684 	}
1685 }
1686 
1687 macro_rules! op {
1688 	($writer: expr, $byte: expr) => ({
1689 		let b: u8 = $byte;
1690 		$writer.write(&[b])?;
1691 	});
1692 	($writer: expr, $byte: expr, $s: block) => ({
1693 		op!($writer, $byte);
1694 		$s;
1695 	});
1696 }
1697 
1698 #[cfg(feature="atomics")]
1699 macro_rules! atomic {
1700 	($writer: expr, $byte: expr, $mem:expr) => ({
1701 		$writer.write(&[ATOMIC_PREFIX, $byte])?;
1702 		MemArg::serialize($mem, $writer)?;
1703 	});
1704 }
1705 
1706 #[cfg(feature="simd")]
1707 macro_rules! simd {
1708 	($writer: expr, $byte: expr, $other:expr) => ({
1709 		$writer.write(&[SIMD_PREFIX])?;
1710 		VarUint32::from($byte).serialize($writer)?;
1711 		$other;
1712 	})
1713 }
1714 
1715 #[cfg(feature="bulk")]
1716 macro_rules! bulk {
1717 	($writer: expr, $byte: expr) => ({
1718 		$writer.write(&[BULK_PREFIX, $byte])?;
1719 	});
1720 	($writer: expr, $byte: expr, $remaining:expr) => ({
1721 		bulk!($writer, $byte);
1722 		$remaining;
1723 	});
1724 }
1725 
1726 impl Serialize for Instruction {
1727 	type Error = Error;
1728 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>1729 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
1730 		use self::Instruction::*;
1731 		use self::opcodes::*;
1732 
1733 		match self {
1734 			Unreachable => op!(writer, UNREACHABLE),
1735 			Nop => op!(writer, NOP),
1736 			Block(block_type) => op!(writer, BLOCK, {
1737 			   block_type.serialize(writer)?;
1738 			}),
1739 			Loop(block_type) => op!(writer, LOOP, {
1740 			   block_type.serialize(writer)?;
1741 			}),
1742 			If(block_type) => op!(writer, IF, {
1743 			   block_type.serialize(writer)?;
1744 			}),
1745 			Else => op!(writer, ELSE),
1746 			End => op!(writer, END),
1747 			Br(idx) => op!(writer, BR, {
1748 				VarUint32::from(idx).serialize(writer)?;
1749 			}),
1750 			BrIf(idx) => op!(writer, BRIF, {
1751 				VarUint32::from(idx).serialize(writer)?;
1752 			}),
1753 			BrTable(ref table) => op!(writer, BRTABLE, {
1754 				let list_writer = CountedListWriter::<VarUint32, _>(
1755 					table.table.len(),
1756 					table.table.into_iter().map(|x| VarUint32::from(*x)),
1757 				);
1758 				list_writer.serialize(writer)?;
1759 				VarUint32::from(table.default).serialize(writer)?;
1760 			}),
1761 			Return => op!(writer, RETURN),
1762 			Call(index) => op!(writer, CALL, {
1763 				VarUint32::from(index).serialize(writer)?;
1764 			}),
1765 			CallIndirect(index, reserved) => op!(writer, CALLINDIRECT, {
1766 				VarUint32::from(index).serialize(writer)?;
1767 				Uint8::from(reserved).serialize(writer)?;
1768 			}),
1769 			Drop => op!(writer, DROP),
1770 			Select => op!(writer, SELECT),
1771 			GetLocal(index) => op!(writer, GETLOCAL, {
1772 				VarUint32::from(index).serialize(writer)?;
1773 			}),
1774 			SetLocal(index) => op!(writer, SETLOCAL, {
1775 				VarUint32::from(index).serialize(writer)?;
1776 			}),
1777 			TeeLocal(index) => op!(writer, TEELOCAL, {
1778 				VarUint32::from(index).serialize(writer)?;
1779 			}),
1780 			GetGlobal(index) => op!(writer, GETGLOBAL, {
1781 				VarUint32::from(index).serialize(writer)?;
1782 			}),
1783 			SetGlobal(index) => op!(writer, SETGLOBAL, {
1784 				VarUint32::from(index).serialize(writer)?;
1785 			}),
1786 			I32Load(flags, offset) => op!(writer, I32LOAD, {
1787 				VarUint32::from(flags).serialize(writer)?;
1788 				VarUint32::from(offset).serialize(writer)?;
1789 			}),
1790 			I64Load(flags, offset) => op!(writer, I64LOAD, {
1791 				VarUint32::from(flags).serialize(writer)?;
1792 				VarUint32::from(offset).serialize(writer)?;
1793 			}),
1794 			F32Load(flags, offset) => op!(writer, F32LOAD, {
1795 				VarUint32::from(flags).serialize(writer)?;
1796 				VarUint32::from(offset).serialize(writer)?;
1797 			}),
1798 			F64Load(flags, offset) => op!(writer, F64LOAD, {
1799 				VarUint32::from(flags).serialize(writer)?;
1800 				VarUint32::from(offset).serialize(writer)?;
1801 			}),
1802 			I32Load8S(flags, offset) => op!(writer, I32LOAD8S, {
1803 				VarUint32::from(flags).serialize(writer)?;
1804 				VarUint32::from(offset).serialize(writer)?;
1805 			}),
1806 			I32Load8U(flags, offset) => op!(writer, I32LOAD8U, {
1807 				VarUint32::from(flags).serialize(writer)?;
1808 				VarUint32::from(offset).serialize(writer)?;
1809 			}),
1810 			I32Load16S(flags, offset) => op!(writer, I32LOAD16S, {
1811 				VarUint32::from(flags).serialize(writer)?;
1812 				VarUint32::from(offset).serialize(writer)?;
1813 			}),
1814 			I32Load16U(flags, offset) => op!(writer, I32LOAD16U, {
1815 				VarUint32::from(flags).serialize(writer)?;
1816 				VarUint32::from(offset).serialize(writer)?;
1817 			}),
1818 			I64Load8S(flags, offset) => op!(writer, I64LOAD8S, {
1819 				VarUint32::from(flags).serialize(writer)?;
1820 				VarUint32::from(offset).serialize(writer)?;
1821 			}),
1822 			I64Load8U(flags, offset) => op!(writer, I64LOAD8U, {
1823 				VarUint32::from(flags).serialize(writer)?;
1824 				VarUint32::from(offset).serialize(writer)?;
1825 			}),
1826 			I64Load16S(flags, offset) => op!(writer, I64LOAD16S, {
1827 				VarUint32::from(flags).serialize(writer)?;
1828 				VarUint32::from(offset).serialize(writer)?;
1829 			}),
1830 			I64Load16U(flags, offset) => op!(writer, I64LOAD16U, {
1831 				VarUint32::from(flags).serialize(writer)?;
1832 				VarUint32::from(offset).serialize(writer)?;
1833 			}),
1834 			I64Load32S(flags, offset) => op!(writer, I64LOAD32S, {
1835 				VarUint32::from(flags).serialize(writer)?;
1836 				VarUint32::from(offset).serialize(writer)?;
1837 			}),
1838 			I64Load32U(flags, offset) => op!(writer, I64LOAD32U, {
1839 				VarUint32::from(flags).serialize(writer)?;
1840 				VarUint32::from(offset).serialize(writer)?;
1841 			}),
1842 			I32Store(flags, offset) => op!(writer, I32STORE, {
1843 				VarUint32::from(flags).serialize(writer)?;
1844 				VarUint32::from(offset).serialize(writer)?;
1845 			}),
1846 			I64Store(flags, offset) => op!(writer, I64STORE, {
1847 				VarUint32::from(flags).serialize(writer)?;
1848 				VarUint32::from(offset).serialize(writer)?;
1849 			}),
1850 			F32Store(flags, offset) => op!(writer, F32STORE, {
1851 				VarUint32::from(flags).serialize(writer)?;
1852 				VarUint32::from(offset).serialize(writer)?;
1853 			}),
1854 			F64Store(flags, offset) => op!(writer, F64STORE, {
1855 				VarUint32::from(flags).serialize(writer)?;
1856 				VarUint32::from(offset).serialize(writer)?;
1857 			}),
1858 			I32Store8(flags, offset) => op!(writer, I32STORE8, {
1859 				VarUint32::from(flags).serialize(writer)?;
1860 				VarUint32::from(offset).serialize(writer)?;
1861 			}),
1862 			I32Store16(flags, offset) => op!(writer, I32STORE16, {
1863 				VarUint32::from(flags).serialize(writer)?;
1864 				VarUint32::from(offset).serialize(writer)?;
1865 			}),
1866 			I64Store8(flags, offset) => op!(writer, I64STORE8, {
1867 				VarUint32::from(flags).serialize(writer)?;
1868 				VarUint32::from(offset).serialize(writer)?;
1869 			}),
1870 			I64Store16(flags, offset) => op!(writer, I64STORE16, {
1871 				VarUint32::from(flags).serialize(writer)?;
1872 				VarUint32::from(offset).serialize(writer)?;
1873 			}),
1874 			I64Store32(flags, offset) => op!(writer, I64STORE32, {
1875 				VarUint32::from(flags).serialize(writer)?;
1876 				VarUint32::from(offset).serialize(writer)?;
1877 			}),
1878 			CurrentMemory(flag) => op!(writer, CURRENTMEMORY, {
1879 				Uint8::from(flag).serialize(writer)?;
1880 			}),
1881 			GrowMemory(flag) => op!(writer, GROWMEMORY, {
1882 				Uint8::from(flag).serialize(writer)?;
1883 			}),
1884 			I32Const(def) => op!(writer, I32CONST, {
1885 				VarInt32::from(def).serialize(writer)?;
1886 			}),
1887 			I64Const(def) => op!(writer, I64CONST, {
1888 				VarInt64::from(def).serialize(writer)?;
1889 			}),
1890 			F32Const(def) => op!(writer, F32CONST, {
1891 				Uint32::from(def).serialize(writer)?;
1892 			}),
1893 			F64Const(def) => op!(writer, F64CONST, {
1894 				Uint64::from(def).serialize(writer)?;
1895 			}),
1896 			I32Eqz => op!(writer, I32EQZ),
1897 			I32Eq => op!(writer, I32EQ),
1898 			I32Ne => op!(writer, I32NE),
1899 			I32LtS => op!(writer, I32LTS),
1900 			I32LtU => op!(writer, I32LTU),
1901 			I32GtS => op!(writer, I32GTS),
1902 			I32GtU => op!(writer, I32GTU),
1903 			I32LeS => op!(writer, I32LES),
1904 			I32LeU => op!(writer, I32LEU),
1905 			I32GeS => op!(writer, I32GES),
1906 			I32GeU => op!(writer, I32GEU),
1907 
1908 			I64Eqz => op!(writer, I64EQZ),
1909 			I64Eq => op!(writer, I64EQ),
1910 			I64Ne => op!(writer, I64NE),
1911 			I64LtS => op!(writer, I64LTS),
1912 			I64LtU => op!(writer, I64LTU),
1913 			I64GtS => op!(writer, I64GTS),
1914 			I64GtU => op!(writer, I64GTU),
1915 			I64LeS => op!(writer, I64LES),
1916 			I64LeU => op!(writer, I64LEU),
1917 			I64GeS => op!(writer, I64GES),
1918 			I64GeU => op!(writer, I64GEU),
1919 
1920 			F32Eq => op!(writer, F32EQ),
1921 			F32Ne => op!(writer, F32NE),
1922 			F32Lt => op!(writer, F32LT),
1923 			F32Gt => op!(writer, F32GT),
1924 			F32Le => op!(writer, F32LE),
1925 			F32Ge => op!(writer, F32GE),
1926 
1927 			F64Eq => op!(writer, F64EQ),
1928 			F64Ne => op!(writer, F64NE),
1929 			F64Lt => op!(writer, F64LT),
1930 			F64Gt => op!(writer, F64GT),
1931 			F64Le => op!(writer, F64LE),
1932 			F64Ge => op!(writer, F64GE),
1933 
1934 			I32Clz => op!(writer, I32CLZ),
1935 			I32Ctz => op!(writer, I32CTZ),
1936 			I32Popcnt => op!(writer, I32POPCNT),
1937 			I32Add => op!(writer, I32ADD),
1938 			I32Sub => op!(writer, I32SUB),
1939 			I32Mul => op!(writer, I32MUL),
1940 			I32DivS => op!(writer, I32DIVS),
1941 			I32DivU => op!(writer, I32DIVU),
1942 			I32RemS => op!(writer, I32REMS),
1943 			I32RemU => op!(writer, I32REMU),
1944 			I32And => op!(writer, I32AND),
1945 			I32Or => op!(writer, I32OR),
1946 			I32Xor => op!(writer, I32XOR),
1947 			I32Shl => op!(writer, I32SHL),
1948 			I32ShrS => op!(writer, I32SHRS),
1949 			I32ShrU => op!(writer, I32SHRU),
1950 			I32Rotl => op!(writer, I32ROTL),
1951 			I32Rotr => op!(writer, I32ROTR),
1952 
1953 			I64Clz => op!(writer, I64CLZ),
1954 			I64Ctz => op!(writer, I64CTZ),
1955 			I64Popcnt => op!(writer, I64POPCNT),
1956 			I64Add => op!(writer, I64ADD),
1957 			I64Sub => op!(writer, I64SUB),
1958 			I64Mul => op!(writer, I64MUL),
1959 			I64DivS => op!(writer, I64DIVS),
1960 			I64DivU => op!(writer, I64DIVU),
1961 			I64RemS => op!(writer, I64REMS),
1962 			I64RemU => op!(writer, I64REMU),
1963 			I64And => op!(writer, I64AND),
1964 			I64Or => op!(writer, I64OR),
1965 			I64Xor => op!(writer, I64XOR),
1966 			I64Shl => op!(writer, I64SHL),
1967 			I64ShrS => op!(writer, I64SHRS),
1968 			I64ShrU => op!(writer, I64SHRU),
1969 			I64Rotl => op!(writer, I64ROTL),
1970 			I64Rotr => op!(writer, I64ROTR),
1971 			F32Abs => op!(writer, F32ABS),
1972 			F32Neg => op!(writer, F32NEG),
1973 			F32Ceil => op!(writer, F32CEIL),
1974 			F32Floor => op!(writer, F32FLOOR),
1975 			F32Trunc => op!(writer, F32TRUNC),
1976 			F32Nearest => op!(writer, F32NEAREST),
1977 			F32Sqrt => op!(writer, F32SQRT),
1978 			F32Add => op!(writer, F32ADD),
1979 			F32Sub => op!(writer, F32SUB),
1980 			F32Mul => op!(writer, F32MUL),
1981 			F32Div => op!(writer, F32DIV),
1982 			F32Min => op!(writer, F32MIN),
1983 			F32Max => op!(writer, F32MAX),
1984 			F32Copysign => op!(writer, F32COPYSIGN),
1985 			F64Abs => op!(writer, F64ABS),
1986 			F64Neg => op!(writer, F64NEG),
1987 			F64Ceil => op!(writer, F64CEIL),
1988 			F64Floor => op!(writer, F64FLOOR),
1989 			F64Trunc => op!(writer, F64TRUNC),
1990 			F64Nearest => op!(writer, F64NEAREST),
1991 			F64Sqrt => op!(writer, F64SQRT),
1992 			F64Add => op!(writer, F64ADD),
1993 			F64Sub => op!(writer, F64SUB),
1994 			F64Mul => op!(writer, F64MUL),
1995 			F64Div => op!(writer, F64DIV),
1996 			F64Min => op!(writer, F64MIN),
1997 			F64Max => op!(writer, F64MAX),
1998 			F64Copysign => op!(writer, F64COPYSIGN),
1999 
2000 			I32WrapI64 => op!(writer, I32WRAPI64),
2001 			I32TruncSF32 => op!(writer, I32TRUNCSF32),
2002 			I32TruncUF32 => op!(writer, I32TRUNCUF32),
2003 			I32TruncSF64 => op!(writer, I32TRUNCSF64),
2004 			I32TruncUF64 => op!(writer, I32TRUNCUF64),
2005 			I64ExtendSI32 => op!(writer, I64EXTENDSI32),
2006 			I64ExtendUI32 => op!(writer, I64EXTENDUI32),
2007 			I64TruncSF32 => op!(writer, I64TRUNCSF32),
2008 			I64TruncUF32 => op!(writer, I64TRUNCUF32),
2009 			I64TruncSF64 => op!(writer, I64TRUNCSF64),
2010 			I64TruncUF64 => op!(writer, I64TRUNCUF64),
2011 			F32ConvertSI32 => op!(writer, F32CONVERTSI32),
2012 			F32ConvertUI32 => op!(writer, F32CONVERTUI32),
2013 			F32ConvertSI64 => op!(writer, F32CONVERTSI64),
2014 			F32ConvertUI64 => op!(writer, F32CONVERTUI64),
2015 			F32DemoteF64 => op!(writer, F32DEMOTEF64),
2016 			F64ConvertSI32 => op!(writer, F64CONVERTSI32),
2017 			F64ConvertUI32 => op!(writer, F64CONVERTUI32),
2018 			F64ConvertSI64 => op!(writer, F64CONVERTSI64),
2019 			F64ConvertUI64 => op!(writer, F64CONVERTUI64),
2020 			F64PromoteF32 => op!(writer, F64PROMOTEF32),
2021 
2022 			I32ReinterpretF32 => op!(writer, I32REINTERPRETF32),
2023 			I64ReinterpretF64 => op!(writer, I64REINTERPRETF64),
2024 			F32ReinterpretI32 => op!(writer, F32REINTERPRETI32),
2025 			F64ReinterpretI64 => op!(writer, F64REINTERPRETI64),
2026 
2027 			#[cfg(feature="sign_ext")]
2028 			SignExt(ref a) => match *a {
2029 				SignExtInstruction::I32Extend8S => op!(writer, sign_ext::I32_EXTEND8_S),
2030 				SignExtInstruction::I32Extend16S => op!(writer, sign_ext::I32_EXTEND16_S),
2031 				SignExtInstruction::I64Extend8S => op!(writer, sign_ext::I64_EXTEND8_S),
2032 				SignExtInstruction::I64Extend16S => op!(writer, sign_ext::I64_EXTEND16_S),
2033 				SignExtInstruction::I64Extend32S => op!(writer, sign_ext::I64_EXTEND32_S),
2034 			}
2035 
2036 			#[cfg(feature="atomics")]
2037 			Atomics(a) => return a.serialize(writer),
2038 
2039 			#[cfg(feature="simd")]
2040 			Simd(a) => return a.serialize(writer),
2041 
2042 			#[cfg(feature="bulk")]
2043 			Bulk(a) => return a.serialize(writer),
2044 		}
2045 
2046 		Ok(())
2047 	}
2048 }
2049 
2050 #[cfg(feature="atomics")]
2051 impl Serialize for AtomicsInstruction {
2052 	type Error = Error;
2053 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>2054 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2055 		use self::AtomicsInstruction::*;
2056 		use self::opcodes::atomics::*;
2057 
2058 		match self {
2059 			AtomicWake(m) => atomic!(writer, ATOMIC_WAKE, m),
2060 			I32AtomicWait(m) => atomic!(writer, I32_ATOMIC_WAIT, m),
2061 			I64AtomicWait(m) => atomic!(writer, I64_ATOMIC_WAIT, m),
2062 
2063 			I32AtomicLoad(m) => atomic!(writer, I32_ATOMIC_LOAD, m),
2064 			I64AtomicLoad(m) => atomic!(writer, I64_ATOMIC_LOAD, m),
2065 			I32AtomicLoad8u(m) => atomic!(writer, I32_ATOMIC_LOAD8U, m),
2066 			I32AtomicLoad16u(m) => atomic!(writer, I32_ATOMIC_LOAD16U, m),
2067 			I64AtomicLoad8u(m) => atomic!(writer, I64_ATOMIC_LOAD8U, m),
2068 			I64AtomicLoad16u(m) => atomic!(writer, I64_ATOMIC_LOAD16U, m),
2069 			I64AtomicLoad32u(m) => atomic!(writer, I64_ATOMIC_LOAD32U, m),
2070 			I32AtomicStore(m) => atomic!(writer, I32_ATOMIC_STORE, m),
2071 			I64AtomicStore(m) => atomic!(writer, I64_ATOMIC_STORE, m),
2072 			I32AtomicStore8u(m) => atomic!(writer, I32_ATOMIC_STORE8U, m),
2073 			I32AtomicStore16u(m) => atomic!(writer, I32_ATOMIC_STORE16U, m),
2074 			I64AtomicStore8u(m) => atomic!(writer, I64_ATOMIC_STORE8U, m),
2075 			I64AtomicStore16u(m) => atomic!(writer, I64_ATOMIC_STORE16U, m),
2076 			I64AtomicStore32u(m) => atomic!(writer, I64_ATOMIC_STORE32U, m),
2077 
2078 			I32AtomicRmwAdd(m) => atomic!(writer, I32_ATOMIC_RMW_ADD, m),
2079 			I64AtomicRmwAdd(m) => atomic!(writer, I64_ATOMIC_RMW_ADD, m),
2080 			I32AtomicRmwAdd8u(m) => atomic!(writer, I32_ATOMIC_RMW_ADD8U, m),
2081 			I32AtomicRmwAdd16u(m) => atomic!(writer, I32_ATOMIC_RMW_ADD16U, m),
2082 			I64AtomicRmwAdd8u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD8U, m),
2083 			I64AtomicRmwAdd16u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD16U, m),
2084 			I64AtomicRmwAdd32u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD32U, m),
2085 
2086 			I32AtomicRmwSub(m) => atomic!(writer, I32_ATOMIC_RMW_SUB, m),
2087 			I64AtomicRmwSub(m) => atomic!(writer, I64_ATOMIC_RMW_SUB, m),
2088 			I32AtomicRmwSub8u(m) => atomic!(writer, I32_ATOMIC_RMW_SUB8U, m),
2089 			I32AtomicRmwSub16u(m) => atomic!(writer, I32_ATOMIC_RMW_SUB16U, m),
2090 			I64AtomicRmwSub8u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB8U, m),
2091 			I64AtomicRmwSub16u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB16U, m),
2092 			I64AtomicRmwSub32u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB32U, m),
2093 
2094 			I32AtomicRmwAnd(m) => atomic!(writer, I32_ATOMIC_RMW_AND, m),
2095 			I64AtomicRmwAnd(m) => atomic!(writer, I64_ATOMIC_RMW_AND, m),
2096 			I32AtomicRmwAnd8u(m) => atomic!(writer, I32_ATOMIC_RMW_AND8U, m),
2097 			I32AtomicRmwAnd16u(m) => atomic!(writer, I32_ATOMIC_RMW_AND16U, m),
2098 			I64AtomicRmwAnd8u(m) => atomic!(writer, I64_ATOMIC_RMW_AND8U, m),
2099 			I64AtomicRmwAnd16u(m) => atomic!(writer, I64_ATOMIC_RMW_AND16U, m),
2100 			I64AtomicRmwAnd32u(m) => atomic!(writer, I64_ATOMIC_RMW_AND32U, m),
2101 
2102 			I32AtomicRmwOr(m) => atomic!(writer, I32_ATOMIC_RMW_OR, m),
2103 			I64AtomicRmwOr(m) => atomic!(writer, I64_ATOMIC_RMW_OR, m),
2104 			I32AtomicRmwOr8u(m) => atomic!(writer, I32_ATOMIC_RMW_OR8U, m),
2105 			I32AtomicRmwOr16u(m) => atomic!(writer, I32_ATOMIC_RMW_OR16U, m),
2106 			I64AtomicRmwOr8u(m) => atomic!(writer, I64_ATOMIC_RMW_OR8U, m),
2107 			I64AtomicRmwOr16u(m) => atomic!(writer, I64_ATOMIC_RMW_OR16U, m),
2108 			I64AtomicRmwOr32u(m) => atomic!(writer, I64_ATOMIC_RMW_OR32U, m),
2109 
2110 			I32AtomicRmwXor(m) => atomic!(writer, I32_ATOMIC_RMW_XOR, m),
2111 			I64AtomicRmwXor(m) => atomic!(writer, I64_ATOMIC_RMW_XOR, m),
2112 			I32AtomicRmwXor8u(m) => atomic!(writer, I32_ATOMIC_RMW_XOR8U, m),
2113 			I32AtomicRmwXor16u(m) => atomic!(writer, I32_ATOMIC_RMW_XOR16U, m),
2114 			I64AtomicRmwXor8u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR8U, m),
2115 			I64AtomicRmwXor16u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR16U, m),
2116 			I64AtomicRmwXor32u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR32U, m),
2117 
2118 			I32AtomicRmwXchg(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG, m),
2119 			I64AtomicRmwXchg(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG, m),
2120 			I32AtomicRmwXchg8u(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG8U, m),
2121 			I32AtomicRmwXchg16u(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG16U, m),
2122 			I64AtomicRmwXchg8u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG8U, m),
2123 			I64AtomicRmwXchg16u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG16U, m),
2124 			I64AtomicRmwXchg32u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG32U, m),
2125 
2126 			I32AtomicRmwCmpxchg(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG, m),
2127 			I64AtomicRmwCmpxchg(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG, m),
2128 			I32AtomicRmwCmpxchg8u(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG8U, m),
2129 			I32AtomicRmwCmpxchg16u(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG16U, m),
2130 			I64AtomicRmwCmpxchg8u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG8U, m),
2131 			I64AtomicRmwCmpxchg16u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG16U, m),
2132 			I64AtomicRmwCmpxchg32u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG32U, m),
2133 		}
2134 
2135 		Ok(())
2136 	}
2137 }
2138 
2139 #[cfg(feature="simd")]
2140 impl Serialize for SimdInstruction {
2141 	type Error = Error;
2142 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>2143 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2144 		use self::SimdInstruction::*;
2145 		use self::opcodes::simd::*;
2146 
2147 		match self {
2148 			V128Const(ref c) => simd!(writer, V128_CONST, writer.write(&c[..])?),
2149 			V128Load(m) => simd!(writer, V128_LOAD, MemArg::serialize(m, writer)?),
2150 			V128Store(m) => simd!(writer, V128_STORE, MemArg::serialize(m, writer)?),
2151 			I8x16Splat => simd!(writer, I8X16_SPLAT, ()),
2152 			I16x8Splat => simd!(writer, I16X8_SPLAT, ()),
2153 			I32x4Splat => simd!(writer, I32X4_SPLAT, ()),
2154 			I64x2Splat => simd!(writer, I64X2_SPLAT, ()),
2155 			F32x4Splat => simd!(writer, F32X4_SPLAT, ()),
2156 			F64x2Splat => simd!(writer, F64X2_SPLAT, ()),
2157 			I8x16ExtractLaneS(i) => simd!(writer, I8X16_EXTRACT_LANE_S, writer.write(&[i])?),
2158 			I8x16ExtractLaneU(i) => simd!(writer, I8X16_EXTRACT_LANE_U, writer.write(&[i])?),
2159 			I16x8ExtractLaneS(i) => simd!(writer, I16X8_EXTRACT_LANE_S, writer.write(&[i])?),
2160 			I16x8ExtractLaneU(i) => simd!(writer, I16X8_EXTRACT_LANE_U, writer.write(&[i])?),
2161 			I32x4ExtractLane(i) => simd!(writer, I32X4_EXTRACT_LANE, writer.write(&[i])?),
2162 			I64x2ExtractLane(i) => simd!(writer, I64X2_EXTRACT_LANE, writer.write(&[i])?),
2163 			F32x4ExtractLane(i) => simd!(writer, F32X4_EXTRACT_LANE, writer.write(&[i])?),
2164 			F64x2ExtractLane(i) => simd!(writer, F64X2_EXTRACT_LANE, writer.write(&[i])?),
2165 			I8x16ReplaceLane(i) => simd!(writer, I8X16_REPLACE_LANE, writer.write(&[i])?),
2166 			I16x8ReplaceLane(i) => simd!(writer, I16X8_REPLACE_LANE, writer.write(&[i])?),
2167 			I32x4ReplaceLane(i) => simd!(writer, I32X4_REPLACE_LANE, writer.write(&[i])?),
2168 			I64x2ReplaceLane(i) => simd!(writer, I64X2_REPLACE_LANE, writer.write(&[i])?),
2169 			F32x4ReplaceLane(i) => simd!(writer, F32X4_REPLACE_LANE, writer.write(&[i])?),
2170 			F64x2ReplaceLane(i) => simd!(writer, F64X2_REPLACE_LANE, writer.write(&[i])?),
2171 			V8x16Shuffle(ref i) => simd!(writer, V8X16_SHUFFLE, writer.write(&i[..])?),
2172 			I8x16Add => simd!(writer, I8X16_ADD, ()),
2173 			I16x8Add => simd!(writer, I16X8_ADD, ()),
2174 			I32x4Add => simd!(writer, I32X4_ADD, ()),
2175 			I64x2Add => simd!(writer, I64X2_ADD, ()),
2176 			I8x16Sub => simd!(writer, I8X16_SUB, ()),
2177 			I16x8Sub => simd!(writer, I16X8_SUB, ()),
2178 			I32x4Sub => simd!(writer, I32X4_SUB, ()),
2179 			I64x2Sub => simd!(writer, I64X2_SUB, ()),
2180 			I8x16Mul => simd!(writer, I8X16_MUL, ()),
2181 			I16x8Mul => simd!(writer, I16X8_MUL, ()),
2182 			I32x4Mul => simd!(writer, I32X4_MUL, ()),
2183 			// I64x2Mul => simd!(writer, I64X2_MUL, ()),
2184 			I8x16Neg => simd!(writer, I8X16_NEG, ()),
2185 			I16x8Neg => simd!(writer, I16X8_NEG, ()),
2186 			I32x4Neg => simd!(writer, I32X4_NEG, ()),
2187 			I64x2Neg => simd!(writer, I64X2_NEG, ()),
2188 			I8x16AddSaturateS => simd!(writer, I8X16_ADD_SATURATE_S, ()),
2189 			I8x16AddSaturateU => simd!(writer, I8X16_ADD_SATURATE_U, ()),
2190 			I16x8AddSaturateS => simd!(writer, I16X8_ADD_SATURATE_S, ()),
2191 			I16x8AddSaturateU => simd!(writer, I16X8_ADD_SATURATE_U, ()),
2192 			I8x16SubSaturateS => simd!(writer, I8X16_SUB_SATURATE_S, ()),
2193 			I8x16SubSaturateU => simd!(writer, I8X16_SUB_SATURATE_U, ()),
2194 			I16x8SubSaturateS => simd!(writer, I16X8_SUB_SATURATE_S, ()),
2195 			I16x8SubSaturateU => simd!(writer, I16X8_SUB_SATURATE_U, ()),
2196 			I8x16Shl => simd!(writer, I8X16_SHL, ()),
2197 			I16x8Shl => simd!(writer, I16X8_SHL, ()),
2198 			I32x4Shl => simd!(writer, I32X4_SHL, ()),
2199 			I64x2Shl => simd!(writer, I64X2_SHL, ()),
2200 			I8x16ShrS => simd!(writer, I8X16_SHR_S, ()),
2201 			I8x16ShrU => simd!(writer, I8X16_SHR_U, ()),
2202 			I16x8ShrS => simd!(writer, I16X8_SHR_S, ()),
2203 			I16x8ShrU => simd!(writer, I16X8_SHR_U, ()),
2204 			I32x4ShrU => simd!(writer, I32X4_SHR_U, ()),
2205 			I32x4ShrS => simd!(writer, I32X4_SHR_S, ()),
2206 			I64x2ShrU => simd!(writer, I64X2_SHR_U, ()),
2207 			I64x2ShrS => simd!(writer, I64X2_SHR_S, ()),
2208 			V128And => simd!(writer, V128_AND, ()),
2209 			V128Or => simd!(writer, V128_OR, ()),
2210 			V128Xor => simd!(writer, V128_XOR, ()),
2211 			V128Not => simd!(writer, V128_NOT, ()),
2212 			V128Bitselect => simd!(writer, V128_BITSELECT, ()),
2213 			I8x16AnyTrue => simd!(writer, I8X16_ANY_TRUE, ()),
2214 			I16x8AnyTrue => simd!(writer, I16X8_ANY_TRUE, ()),
2215 			I32x4AnyTrue => simd!(writer, I32X4_ANY_TRUE, ()),
2216 			I64x2AnyTrue => simd!(writer, I64X2_ANY_TRUE, ()),
2217 			I8x16AllTrue => simd!(writer, I8X16_ALL_TRUE, ()),
2218 			I16x8AllTrue => simd!(writer, I16X8_ALL_TRUE, ()),
2219 			I32x4AllTrue => simd!(writer, I32X4_ALL_TRUE, ()),
2220 			I64x2AllTrue => simd!(writer, I64X2_ALL_TRUE, ()),
2221 			I8x16Eq => simd!(writer, I8X16_EQ, ()),
2222 			I16x8Eq => simd!(writer, I16X8_EQ, ()),
2223 			I32x4Eq => simd!(writer, I32X4_EQ, ()),
2224 			// I64x2Eq => simd!(writer, I64X2_EQ, ()),
2225 			F32x4Eq => simd!(writer, F32X4_EQ, ()),
2226 			F64x2Eq => simd!(writer, F64X2_EQ, ()),
2227 			I8x16Ne => simd!(writer, I8X16_NE, ()),
2228 			I16x8Ne => simd!(writer, I16X8_NE, ()),
2229 			I32x4Ne => simd!(writer, I32X4_NE, ()),
2230 			// I64x2Ne => simd!(writer, I64X2_NE, ()),
2231 			F32x4Ne => simd!(writer, F32X4_NE, ()),
2232 			F64x2Ne => simd!(writer, F64X2_NE, ()),
2233 			I8x16LtS => simd!(writer, I8X16_LT_S, ()),
2234 			I8x16LtU => simd!(writer, I8X16_LT_U, ()),
2235 			I16x8LtS => simd!(writer, I16X8_LT_S, ()),
2236 			I16x8LtU => simd!(writer, I16X8_LT_U, ()),
2237 			I32x4LtS => simd!(writer, I32X4_LT_S, ()),
2238 			I32x4LtU => simd!(writer, I32X4_LT_U, ()),
2239 			// I64x2LtS => simd!(writer, I64X2_LT_S, ()),
2240 			// I64x2LtU => simd!(writer, I64X2_LT_U, ()),
2241 			F32x4Lt => simd!(writer, F32X4_LT, ()),
2242 			F64x2Lt => simd!(writer, F64X2_LT, ()),
2243 			I8x16LeS => simd!(writer, I8X16_LE_S, ()),
2244 			I8x16LeU => simd!(writer, I8X16_LE_U, ()),
2245 			I16x8LeS => simd!(writer, I16X8_LE_S, ()),
2246 			I16x8LeU => simd!(writer, I16X8_LE_U, ()),
2247 			I32x4LeS => simd!(writer, I32X4_LE_S, ()),
2248 			I32x4LeU => simd!(writer, I32X4_LE_U, ()),
2249 			// I64x2LeS => simd!(writer, I64X2_LE_S, ()),
2250 			// I64x2LeU => simd!(writer, I64X2_LE_U, ()),
2251 			F32x4Le => simd!(writer, F32X4_LE, ()),
2252 			F64x2Le => simd!(writer, F64X2_LE, ()),
2253 			I8x16GtS => simd!(writer, I8X16_GT_S, ()),
2254 			I8x16GtU => simd!(writer, I8X16_GT_U, ()),
2255 			I16x8GtS => simd!(writer, I16X8_GT_S, ()),
2256 			I16x8GtU => simd!(writer, I16X8_GT_U, ()),
2257 			I32x4GtS => simd!(writer, I32X4_GT_S, ()),
2258 			I32x4GtU => simd!(writer, I32X4_GT_U, ()),
2259 			// I64x2GtS => simd!(writer, I64X2_GT_S, ()),
2260 			// I64x2GtU => simd!(writer, I64X2_GT_U, ()),
2261 			F32x4Gt => simd!(writer, F32X4_GT, ()),
2262 			F64x2Gt => simd!(writer, F64X2_GT, ()),
2263 			I8x16GeS => simd!(writer, I8X16_GE_S, ()),
2264 			I8x16GeU => simd!(writer, I8X16_GE_U, ()),
2265 			I16x8GeS => simd!(writer, I16X8_GE_S, ()),
2266 			I16x8GeU => simd!(writer, I16X8_GE_U, ()),
2267 			I32x4GeS => simd!(writer, I32X4_GE_S, ()),
2268 			I32x4GeU => simd!(writer, I32X4_GE_U, ()),
2269 			// I64x2GeS => simd!(writer, I64X2_GE_S, ()),
2270 			// I64x2GeU => simd!(writer, I64X2_GE_U, ()),
2271 			F32x4Ge => simd!(writer, F32X4_GE, ()),
2272 			F64x2Ge => simd!(writer, F64X2_GE, ()),
2273 			F32x4Neg => simd!(writer, F32X4_NEG, ()),
2274 			F64x2Neg => simd!(writer, F64X2_NEG, ()),
2275 			F32x4Abs => simd!(writer, F32X4_ABS, ()),
2276 			F64x2Abs => simd!(writer, F64X2_ABS, ()),
2277 			F32x4Min => simd!(writer, F32X4_MIN, ()),
2278 			F64x2Min => simd!(writer, F64X2_MIN, ()),
2279 			F32x4Max => simd!(writer, F32X4_MAX, ()),
2280 			F64x2Max => simd!(writer, F64X2_MAX, ()),
2281 			F32x4Add => simd!(writer, F32X4_ADD, ()),
2282 			F64x2Add => simd!(writer, F64X2_ADD, ()),
2283 			F32x4Sub => simd!(writer, F32X4_SUB, ()),
2284 			F64x2Sub => simd!(writer, F64X2_SUB, ()),
2285 			F32x4Div => simd!(writer, F32X4_DIV, ()),
2286 			F64x2Div => simd!(writer, F64X2_DIV, ()),
2287 			F32x4Mul => simd!(writer, F32X4_MUL, ()),
2288 			F64x2Mul => simd!(writer, F64X2_MUL, ()),
2289 			F32x4Sqrt => simd!(writer, F32X4_SQRT, ()),
2290 			F64x2Sqrt => simd!(writer, F64X2_SQRT, ()),
2291 			F32x4ConvertSI32x4 => simd!(writer, F32X4_CONVERT_S_I32X4, ()),
2292 			F32x4ConvertUI32x4 => simd!(writer, F32X4_CONVERT_U_I32X4, ()),
2293 			F64x2ConvertSI64x2 => simd!(writer, F64X2_CONVERT_S_I64X2, ()),
2294 			F64x2ConvertUI64x2 => simd!(writer, F64X2_CONVERT_U_I64X2, ()),
2295 			I32x4TruncSF32x4Sat => simd!(writer, I32X4_TRUNC_S_F32X4_SAT, ()),
2296 			I32x4TruncUF32x4Sat => simd!(writer, I32X4_TRUNC_U_F32X4_SAT, ()),
2297 			I64x2TruncSF64x2Sat => simd!(writer, I64X2_TRUNC_S_F64X2_SAT, ()),
2298 			I64x2TruncUF64x2Sat => simd!(writer, I64X2_TRUNC_U_F64X2_SAT, ()),
2299 		}
2300 
2301 		Ok(())
2302 	}
2303 }
2304 
2305 #[cfg(feature="bulk")]
2306 impl Serialize for BulkInstruction {
2307 	type Error = Error;
2308 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>2309 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2310 		use self::BulkInstruction::*;
2311 		use self::opcodes::bulk::*;
2312 
2313 		match self {
2314 			MemoryInit(seg) => bulk!(writer, MEMORY_INIT, {
2315 				Uint8::from(0).serialize(writer)?;
2316 				VarUint32::from(seg).serialize(writer)?;
2317 			}),
2318 			MemoryDrop(seg) => bulk!(writer, MEMORY_DROP, VarUint32::from(seg).serialize(writer)?),
2319 			MemoryFill => bulk!(writer, MEMORY_FILL, Uint8::from(0).serialize(writer)?),
2320 			MemoryCopy => bulk!(writer, MEMORY_COPY, Uint8::from(0).serialize(writer)?),
2321 			TableInit(seg) => bulk!(writer, TABLE_INIT, {
2322 				Uint8::from(0).serialize(writer)?;
2323 				VarUint32::from(seg).serialize(writer)?;
2324 			}),
2325 			TableDrop(seg) => bulk!(writer, TABLE_DROP, VarUint32::from(seg).serialize(writer)?),
2326 			TableCopy => bulk!(writer, TABLE_COPY, Uint8::from(0).serialize(writer)?),
2327 		}
2328 
2329 		Ok(())
2330 	}
2331 }
2332 
2333 #[cfg(any(feature="simd", feature="atomics"))]
2334 impl Serialize for MemArg {
2335 	type Error = Error;
2336 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>2337 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2338 		Uint8::from(self.align).serialize(writer)?;
2339 		VarUint32::from(self.offset).serialize(writer)?;
2340 		Ok(())
2341 	}
2342 }
2343 
2344 macro_rules! fmt_op {
2345 	($f: expr, $mnemonic: expr) => ({
2346 		write!($f, "{}", $mnemonic)
2347 	});
2348 	($f: expr, $mnemonic: expr, $immediate: expr) => ({
2349 		write!($f, "{} {}", $mnemonic, $immediate)
2350 	});
2351 	($f: expr, $mnemonic: expr, $immediate1: expr, $immediate2: expr) => ({
2352 		write!($f, "{} {} {}", $mnemonic, $immediate1, $immediate2)
2353 	});
2354 }
2355 
2356 impl fmt::Display for Instruction {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2357 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2358 		use self::Instruction::*;
2359 
2360 		match *self {
2361 			Unreachable => fmt_op!(f, "unreachable"),
2362 			Nop => fmt_op!(f, "nop"),
2363 			Block(BlockType::NoResult) => fmt_op!(f, "block"),
2364 			Block(BlockType::Value(value_type)) => fmt_op!(f, "block", value_type),
2365 			Loop(BlockType::NoResult) => fmt_op!(f, "loop"),
2366 			Loop(BlockType::Value(value_type)) => fmt_op!(f, "loop", value_type),
2367 			If(BlockType::NoResult) => fmt_op!(f, "if"),
2368 			If(BlockType::Value(value_type)) => fmt_op!(f, "if", value_type),
2369 			Else => fmt_op!(f, "else"),
2370 			End => fmt_op!(f, "end"),
2371 			Br(idx) => fmt_op!(f, "br",  idx),
2372 			BrIf(idx) => fmt_op!(f, "br_if",  idx),
2373 			BrTable(ref table) => fmt_op!(f, "br_table", table.default),
2374 			Return => fmt_op!(f, "return"),
2375 			Call(index) => fmt_op!(f, "call", index),
2376 			CallIndirect(index, _) =>  fmt_op!(f, "call_indirect", index),
2377 			Drop => fmt_op!(f, "drop"),
2378 			Select => fmt_op!(f, "select"),
2379 			GetLocal(index) => fmt_op!(f, "get_local", index),
2380 			SetLocal(index) => fmt_op!(f, "set_local", index),
2381 			TeeLocal(index) => fmt_op!(f, "tee_local", index),
2382 			GetGlobal(index) => fmt_op!(f, "get_global", index),
2383 			SetGlobal(index) => fmt_op!(f, "set_global", index),
2384 
2385 			I32Load(_, 0) => write!(f, "i32.load"),
2386 			I32Load(_, offset) => write!(f, "i32.load offset={}", offset),
2387 
2388 			I64Load(_, 0) => write!(f, "i64.load"),
2389 			I64Load(_, offset) => write!(f, "i64.load offset={}", offset),
2390 
2391 			F32Load(_, 0) => write!(f, "f32.load"),
2392 			F32Load(_, offset) => write!(f, "f32.load offset={}", offset),
2393 
2394 			F64Load(_, 0) => write!(f, "f64.load"),
2395 			F64Load(_, offset) => write!(f, "f64.load offset={}", offset),
2396 
2397 			I32Load8S(_, 0) => write!(f, "i32.load8_s"),
2398 			I32Load8S(_, offset) => write!(f, "i32.load8_s offset={}", offset),
2399 
2400 			I32Load8U(_, 0) => write!(f, "i32.load8_u"),
2401 			I32Load8U(_, offset) => write!(f, "i32.load8_u offset={}", offset),
2402 
2403 			I32Load16S(_, 0) => write!(f, "i32.load16_s"),
2404 			I32Load16S(_, offset) => write!(f, "i32.load16_s offset={}", offset),
2405 
2406 			I32Load16U(_, 0) => write!(f, "i32.load16_u"),
2407 			I32Load16U(_, offset) => write!(f, "i32.load16_u offset={}", offset),
2408 
2409 			I64Load8S(_, 0) => write!(f, "i64.load8_s"),
2410 			I64Load8S(_, offset) => write!(f, "i64.load8_s offset={}", offset),
2411 
2412 			I64Load8U(_, 0) => write!(f, "i64.load8_u"),
2413 			I64Load8U(_, offset) => write!(f, "i64.load8_u offset={}", offset),
2414 
2415 			I64Load16S(_, 0) => write!(f, "i64.load16_s"),
2416 			I64Load16S(_, offset) => write!(f, "i64.load16_s offset={}", offset),
2417 
2418 			I64Load16U(_, 0) => write!(f, "i64.load16_u"),
2419 			I64Load16U(_, offset) => write!(f, "i64.load16_u offset={}", offset),
2420 
2421 			I64Load32S(_, 0) => write!(f, "i64.load32_s"),
2422 			I64Load32S(_, offset) => write!(f, "i64.load32_s offset={}", offset),
2423 
2424 			I64Load32U(_, 0) => write!(f, "i64.load32_u"),
2425 			I64Load32U(_, offset) => write!(f, "i64.load32_u offset={}", offset),
2426 
2427 			I32Store(_, 0) => write!(f, "i32.store"),
2428 			I32Store(_, offset) => write!(f, "i32.store offset={}", offset),
2429 
2430 			I64Store(_, 0) => write!(f, "i64.store"),
2431 			I64Store(_, offset) => write!(f, "i64.store offset={}", offset),
2432 
2433 			F32Store(_, 0) => write!(f, "f32.store"),
2434 			F32Store(_, offset) => write!(f, "f32.store offset={}", offset),
2435 
2436 			F64Store(_, 0) => write!(f, "f64.store"),
2437 			F64Store(_, offset) => write!(f, "f64.store offset={}", offset),
2438 
2439 			I32Store8(_, 0) => write!(f, "i32.store8"),
2440 			I32Store8(_, offset) => write!(f, "i32.store8 offset={}", offset),
2441 
2442 			I32Store16(_, 0) => write!(f, "i32.store16"),
2443 			I32Store16(_, offset) => write!(f, "i32.store16 offset={}", offset),
2444 
2445 			I64Store8(_, 0) => write!(f, "i64.store8"),
2446 			I64Store8(_, offset) => write!(f, "i64.store8 offset={}", offset),
2447 
2448 			I64Store16(_, 0) => write!(f, "i64.store16"),
2449 			I64Store16(_, offset) => write!(f, "i64.store16 offset={}", offset),
2450 
2451 			I64Store32(_, 0) => write!(f, "i64.store32"),
2452 			I64Store32(_, offset) => write!(f, "i64.store32 offset={}", offset),
2453 
2454 			CurrentMemory(_) => fmt_op!(f, "current_memory"),
2455 			GrowMemory(_) => fmt_op!(f, "grow_memory"),
2456 
2457 			I32Const(def) => fmt_op!(f, "i32.const", def),
2458 			I64Const(def) => fmt_op!(f, "i64.const", def),
2459 			F32Const(def) => fmt_op!(f, "f32.const", def),
2460 			F64Const(def) => fmt_op!(f, "f64.const", def),
2461 
2462 			I32Eq => write!(f, "i32.eq"),
2463 			I32Eqz => write!(f, "i32.eqz"),
2464 			I32Ne => write!(f, "i32.ne"),
2465 			I32LtS => write!(f, "i32.lt_s"),
2466 			I32LtU => write!(f, "i32.lt_u"),
2467 			I32GtS => write!(f, "i32.gt_s"),
2468 			I32GtU => write!(f, "i32.gt_u"),
2469 			I32LeS => write!(f, "i32.le_s"),
2470 			I32LeU => write!(f, "i32.le_u"),
2471 			I32GeS => write!(f, "i32.ge_s"),
2472 			I32GeU => write!(f, "i32.ge_u"),
2473 
2474 			I64Eq => write!(f, "i64.eq"),
2475 			I64Eqz => write!(f, "i64.eqz"),
2476 			I64Ne => write!(f, "i64.ne"),
2477 			I64LtS => write!(f, "i64.lt_s"),
2478 			I64LtU => write!(f, "i64.lt_u"),
2479 			I64GtS => write!(f, "i64.gt_s"),
2480 			I64GtU => write!(f, "i64.gt_u"),
2481 			I64LeS => write!(f, "i64.le_s"),
2482 			I64LeU => write!(f, "i64.le_u"),
2483 			I64GeS => write!(f, "i64.ge_s"),
2484 			I64GeU => write!(f, "i64.ge_u"),
2485 
2486 			F32Eq => write!(f, "f32.eq"),
2487 			F32Ne => write!(f, "f32.ne"),
2488 			F32Lt => write!(f, "f32.lt"),
2489 			F32Gt => write!(f, "f32.gt"),
2490 			F32Le => write!(f, "f32.le"),
2491 			F32Ge => write!(f, "f32.ge"),
2492 
2493 			F64Eq => write!(f, "f64.eq"),
2494 			F64Ne => write!(f, "f64.ne"),
2495 			F64Lt => write!(f, "f64.lt"),
2496 			F64Gt => write!(f, "f64.gt"),
2497 			F64Le => write!(f, "f64.le"),
2498 			F64Ge => write!(f, "f64.ge"),
2499 
2500 			I32Clz => write!(f, "i32.clz"),
2501 			I32Ctz => write!(f, "i32.ctz"),
2502 			I32Popcnt => write!(f, "i32.popcnt"),
2503 			I32Add => write!(f, "i32.add"),
2504 			I32Sub => write!(f, "i32.sub"),
2505 			I32Mul => write!(f, "i32.mul"),
2506 			I32DivS => write!(f, "i32.div_s"),
2507 			I32DivU => write!(f, "i32.div_u"),
2508 			I32RemS => write!(f, "i32.rem_s"),
2509 			I32RemU => write!(f, "i32.rem_u"),
2510 			I32And => write!(f, "i32.and"),
2511 			I32Or => write!(f, "i32.or"),
2512 			I32Xor => write!(f, "i32.xor"),
2513 			I32Shl => write!(f, "i32.shl"),
2514 			I32ShrS => write!(f, "i32.shr_s"),
2515 			I32ShrU => write!(f, "i32.shr_u"),
2516 			I32Rotl => write!(f, "i32.rotl"),
2517 			I32Rotr => write!(f, "i32.rotr"),
2518 
2519 			I64Clz => write!(f, "i64.clz"),
2520 			I64Ctz => write!(f, "i64.ctz"),
2521 			I64Popcnt => write!(f, "i64.popcnt"),
2522 			I64Add => write!(f, "i64.add"),
2523 			I64Sub => write!(f, "i64.sub"),
2524 			I64Mul => write!(f, "i64.mul"),
2525 			I64DivS => write!(f, "i64.div_s"),
2526 			I64DivU => write!(f, "i64.div_u"),
2527 			I64RemS => write!(f, "i64.rem_s"),
2528 			I64RemU => write!(f, "i64.rem_u"),
2529 			I64And => write!(f, "i64.and"),
2530 			I64Or => write!(f, "i64.or"),
2531 			I64Xor => write!(f, "i64.xor"),
2532 			I64Shl => write!(f, "i64.shl"),
2533 			I64ShrS => write!(f, "i64.shr_s"),
2534 			I64ShrU => write!(f, "i64.shr_u"),
2535 			I64Rotl => write!(f, "i64.rotl"),
2536 			I64Rotr => write!(f, "i64.rotr"),
2537 
2538 			F32Abs => write!(f, "f32.abs"),
2539 			F32Neg => write!(f, "f32.neg"),
2540 			F32Ceil => write!(f, "f32.ceil"),
2541 			F32Floor => write!(f, "f32.floor"),
2542 			F32Trunc => write!(f, "f32.trunc"),
2543 			F32Nearest => write!(f, "f32.nearest"),
2544 			F32Sqrt => write!(f, "f32.sqrt"),
2545 			F32Add => write!(f, "f32.add"),
2546 			F32Sub => write!(f, "f32.sub"),
2547 			F32Mul => write!(f, "f32.mul"),
2548 			F32Div => write!(f, "f32.div"),
2549 			F32Min => write!(f, "f32.min"),
2550 			F32Max => write!(f, "f32.max"),
2551 			F32Copysign => write!(f, "f32.copysign"),
2552 
2553 			F64Abs => write!(f, "f64.abs"),
2554 			F64Neg => write!(f, "f64.neg"),
2555 			F64Ceil => write!(f, "f64.ceil"),
2556 			F64Floor => write!(f, "f64.floor"),
2557 			F64Trunc => write!(f, "f64.trunc"),
2558 			F64Nearest => write!(f, "f64.nearest"),
2559 			F64Sqrt => write!(f, "f64.sqrt"),
2560 			F64Add => write!(f, "f64.add"),
2561 			F64Sub => write!(f, "f64.sub"),
2562 			F64Mul => write!(f, "f64.mul"),
2563 			F64Div => write!(f, "f64.div"),
2564 			F64Min => write!(f, "f64.min"),
2565 			F64Max => write!(f, "f64.max"),
2566 			F64Copysign => write!(f, "f64.copysign"),
2567 
2568 			I32WrapI64 => write!(f, "i32.wrap/i64"),
2569 			I32TruncSF32 => write!(f, "i32.trunc_s/f32"),
2570 			I32TruncUF32 => write!(f, "i32.trunc_u/f32"),
2571 			I32TruncSF64 => write!(f, "i32.trunc_s/f64"),
2572 			I32TruncUF64 => write!(f, "i32.trunc_u/f64"),
2573 
2574 			I64ExtendSI32 => write!(f, "i64.extend_s/i32"),
2575 			I64ExtendUI32 => write!(f, "i64.extend_u/i32"),
2576 
2577 			I64TruncSF32 => write!(f, "i64.trunc_s/f32"),
2578 			I64TruncUF32 => write!(f, "i64.trunc_u/f32"),
2579 			I64TruncSF64 => write!(f, "i64.trunc_s/f64"),
2580 			I64TruncUF64 => write!(f, "i64.trunc_u/f64"),
2581 
2582 			F32ConvertSI32 => write!(f, "f32.convert_s/i32"),
2583 			F32ConvertUI32 => write!(f, "f32.convert_u/i32"),
2584 			F32ConvertSI64 => write!(f, "f32.convert_s/i64"),
2585 			F32ConvertUI64 => write!(f, "f32.convert_u/i64"),
2586 			F32DemoteF64 => write!(f, "f32.demote/f64"),
2587 
2588 			F64ConvertSI32 => write!(f, "f64.convert_s/i32"),
2589 			F64ConvertUI32 => write!(f, "f64.convert_u/i32"),
2590 			F64ConvertSI64 => write!(f, "f64.convert_s/i64"),
2591 			F64ConvertUI64 => write!(f, "f64.convert_u/i64"),
2592 			F64PromoteF32 => write!(f, "f64.promote/f32"),
2593 
2594 			I32ReinterpretF32 => write!(f, "i32.reinterpret/f32"),
2595 			I64ReinterpretF64 => write!(f, "i64.reinterpret/f64"),
2596 			F32ReinterpretI32 => write!(f, "f32.reinterpret/i32"),
2597 			F64ReinterpretI64 => write!(f, "f64.reinterpret/i64"),
2598 
2599 			#[cfg(feature="sign_ext")]
2600 			SignExt(ref i) => match i {
2601 				SignExtInstruction::I32Extend8S => write!(f, "i32.extend8_s"),
2602 				SignExtInstruction::I32Extend16S => write!(f, "i32.extend16_s"),
2603 				SignExtInstruction::I64Extend8S => write!(f, "i64.extend8_s"),
2604 				SignExtInstruction::I64Extend16S => write!(f, "i64.extend16_s"),
2605 				SignExtInstruction::I64Extend32S => write!(f, "i64.extend32_s"),
2606 			}
2607 
2608 			#[cfg(feature="atomics")]
2609 			Atomics(ref i) => i.fmt(f),
2610 
2611 			#[cfg(feature="simd")]
2612 			Simd(ref i) => i.fmt(f),
2613 
2614 			#[cfg(feature="bulk")]
2615 			Bulk(ref i) => i.fmt(f),
2616 		}
2617 	}
2618 }
2619 
2620 #[cfg(feature="atomics")]
2621 impl fmt::Display for AtomicsInstruction {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2622 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2623 		use self::AtomicsInstruction::*;
2624 
2625 		match *self {
2626 			AtomicWake(_) => write!(f, "atomic.wake"),
2627 			I32AtomicWait(_) => write!(f, "i32.atomic.wait"),
2628 			I64AtomicWait(_) => write!(f, "i64.atomic.wait"),
2629 
2630 			I32AtomicLoad(_) => write!(f, "i32.atomic.load"),
2631 			I64AtomicLoad(_) => write!(f, "i64.atomic.load"),
2632 			I32AtomicLoad8u(_) => write!(f, "i32.atomic.load8_u"),
2633 			I32AtomicLoad16u(_) => write!(f, "i32.atomic.load16_u"),
2634 			I64AtomicLoad8u(_) => write!(f, "i64.atomic.load8_u"),
2635 			I64AtomicLoad16u(_) => write!(f, "i64.atomic.load16_u"),
2636 			I64AtomicLoad32u(_) => write!(f, "i64.atomic.load32_u"),
2637 			I32AtomicStore(_) => write!(f, "i32.atomic.store"),
2638 			I64AtomicStore(_) => write!(f, "i64.atomic.store"),
2639 			I32AtomicStore8u(_) => write!(f, "i32.atomic.store8_u"),
2640 			I32AtomicStore16u(_) => write!(f, "i32.atomic.store16_u"),
2641 			I64AtomicStore8u(_) => write!(f, "i64.atomic.store8_u"),
2642 			I64AtomicStore16u(_) => write!(f, "i64.atomic.store16_u"),
2643 			I64AtomicStore32u(_) => write!(f, "i64.atomic.store32_u"),
2644 
2645 			I32AtomicRmwAdd(_) => write!(f, "i32.atomic.rmw.add"),
2646 			I64AtomicRmwAdd(_) => write!(f, "i64.atomic.rmw.add"),
2647 			I32AtomicRmwAdd8u(_) => write!(f, "i32.atomic.rmw8_u.add"),
2648 			I32AtomicRmwAdd16u(_) => write!(f, "i32.atomic.rmw16_u.add"),
2649 			I64AtomicRmwAdd8u(_) => write!(f, "i64.atomic.rmw8_u.add"),
2650 			I64AtomicRmwAdd16u(_) => write!(f, "i64.atomic.rmw16_u.add"),
2651 			I64AtomicRmwAdd32u(_) => write!(f, "i64.atomic.rmw32_u.add"),
2652 
2653 			I32AtomicRmwSub(_) => write!(f, "i32.atomic.rmw.sub"),
2654 			I64AtomicRmwSub(_) => write!(f, "i64.atomic.rmw.sub"),
2655 			I32AtomicRmwSub8u(_) => write!(f, "i32.atomic.rmw8_u.sub"),
2656 			I32AtomicRmwSub16u(_) => write!(f, "i32.atomic.rmw16_u.sub"),
2657 			I64AtomicRmwSub8u(_) => write!(f, "i64.atomic.rmw8_u.sub"),
2658 			I64AtomicRmwSub16u(_) => write!(f, "i64.atomic.rmw16_u.sub"),
2659 			I64AtomicRmwSub32u(_) => write!(f, "i64.atomic.rmw32_u.sub"),
2660 
2661 			I32AtomicRmwAnd(_) => write!(f, "i32.atomic.rmw.and"),
2662 			I64AtomicRmwAnd(_) => write!(f, "i64.atomic.rmw.and"),
2663 			I32AtomicRmwAnd8u(_) => write!(f, "i32.atomic.rmw8_u.and"),
2664 			I32AtomicRmwAnd16u(_) => write!(f, "i32.atomic.rmw16_u.and"),
2665 			I64AtomicRmwAnd8u(_) => write!(f, "i64.atomic.rmw8_u.and"),
2666 			I64AtomicRmwAnd16u(_) => write!(f, "i64.atomic.rmw16_u.and"),
2667 			I64AtomicRmwAnd32u(_) => write!(f, "i64.atomic.rmw32_u.and"),
2668 
2669 			I32AtomicRmwOr(_) => write!(f, "i32.atomic.rmw.or"),
2670 			I64AtomicRmwOr(_) => write!(f, "i64.atomic.rmw.or"),
2671 			I32AtomicRmwOr8u(_) => write!(f, "i32.atomic.rmw8_u.or"),
2672 			I32AtomicRmwOr16u(_) => write!(f, "i32.atomic.rmw16_u.or"),
2673 			I64AtomicRmwOr8u(_) => write!(f, "i64.atomic.rmw8_u.or"),
2674 			I64AtomicRmwOr16u(_) => write!(f, "i64.atomic.rmw16_u.or"),
2675 			I64AtomicRmwOr32u(_) => write!(f, "i64.atomic.rmw32_u.or"),
2676 
2677 			I32AtomicRmwXor(_) => write!(f, "i32.atomic.rmw.xor"),
2678 			I64AtomicRmwXor(_) => write!(f, "i64.atomic.rmw.xor"),
2679 			I32AtomicRmwXor8u(_) => write!(f, "i32.atomic.rmw8_u.xor"),
2680 			I32AtomicRmwXor16u(_) => write!(f, "i32.atomic.rmw16_u.xor"),
2681 			I64AtomicRmwXor8u(_) => write!(f, "i64.atomic.rmw8_u.xor"),
2682 			I64AtomicRmwXor16u(_) => write!(f, "i64.atomic.rmw16_u.xor"),
2683 			I64AtomicRmwXor32u(_) => write!(f, "i64.atomic.rmw32_u.xor"),
2684 
2685 			I32AtomicRmwXchg(_) => write!(f, "i32.atomic.rmw.xchg"),
2686 			I64AtomicRmwXchg(_) => write!(f, "i64.atomic.rmw.xchg"),
2687 			I32AtomicRmwXchg8u(_) => write!(f, "i32.atomic.rmw8_u.xchg"),
2688 			I32AtomicRmwXchg16u(_) => write!(f, "i32.atomic.rmw16_u.xchg"),
2689 			I64AtomicRmwXchg8u(_) => write!(f, "i64.atomic.rmw8_u.xchg"),
2690 			I64AtomicRmwXchg16u(_) => write!(f, "i64.atomic.rmw16_u.xchg"),
2691 			I64AtomicRmwXchg32u(_) => write!(f, "i64.atomic.rmw32_u.xchg"),
2692 
2693 			I32AtomicRmwCmpxchg(_) => write!(f, "i32.atomic.rmw.cmpxchg"),
2694 			I64AtomicRmwCmpxchg(_) => write!(f, "i64.atomic.rmw.cmpxchg"),
2695 			I32AtomicRmwCmpxchg8u(_) => write!(f, "i32.atomic.rmw8_u.cmpxchg"),
2696 			I32AtomicRmwCmpxchg16u(_) => write!(f, "i32.atomic.rmw16_u.cmpxchg"),
2697 			I64AtomicRmwCmpxchg8u(_) => write!(f, "i64.atomic.rmw8_u.cmpxchg"),
2698 			I64AtomicRmwCmpxchg16u(_) => write!(f, "i64.atomic.rmw16_u.cmpxchg"),
2699 			I64AtomicRmwCmpxchg32u(_) => write!(f, "i64.atomic.rmw32_u.cmpxchg"),
2700 		}
2701 	}
2702 }
2703 
2704 #[cfg(feature="simd")]
2705 impl fmt::Display for SimdInstruction {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2706 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2707 		use self::SimdInstruction::*;
2708 
2709 		match *self {
2710 			V128Const(_) => write!(f, "v128.const"),
2711 			V128Load(_) => write!(f, "v128.load"),
2712 			V128Store(_) => write!(f, "v128.store"),
2713 			I8x16Splat => write!(f, "i8x16.splat"),
2714 			I16x8Splat => write!(f, "i16x8.splat"),
2715 			I32x4Splat => write!(f, "i32x4.splat"),
2716 			I64x2Splat => write!(f, "i64x2.splat"),
2717 			F32x4Splat => write!(f, "f32x4.splat"),
2718 			F64x2Splat => write!(f, "f64x2.splat"),
2719 			I8x16ExtractLaneS(_) => write!(f, "i8x16.extract_lane_s"),
2720 			I8x16ExtractLaneU(_) => write!(f, "i8x16.extract_lane_u"),
2721 			I16x8ExtractLaneS(_) => write!(f, "i16x8.extract_lane_s"),
2722 			I16x8ExtractLaneU(_) => write!(f, "i16x8.extract_lane_u"),
2723 			I32x4ExtractLane(_) => write!(f, "i32x4.extract_lane"),
2724 			I64x2ExtractLane(_) => write!(f, "i64x2.extract_lane"),
2725 			F32x4ExtractLane(_) => write!(f, "f32x4.extract_lane"),
2726 			F64x2ExtractLane(_) => write!(f, "f64x2.extract_lane"),
2727 			I8x16ReplaceLane(_) => write!(f, "i8x16.replace_lane"),
2728 			I16x8ReplaceLane(_) => write!(f, "i16x8.replace_lane"),
2729 			I32x4ReplaceLane(_) => write!(f, "i32x4.replace_lane"),
2730 			I64x2ReplaceLane(_) => write!(f, "i64x2.replace_lane"),
2731 			F32x4ReplaceLane(_) => write!(f, "f32x4.replace_lane"),
2732 			F64x2ReplaceLane(_) => write!(f, "f64x2.replace_lane"),
2733 			V8x16Shuffle(_) => write!(f, "v8x16.shuffle"),
2734 			I8x16Add => write!(f, "i8x16.add"),
2735 			I16x8Add => write!(f, "i16x8.add"),
2736 			I32x4Add => write!(f, "i32x4.add"),
2737 			I64x2Add => write!(f, "i64x2.add"),
2738 			I8x16Sub => write!(f, "i8x16.sub"),
2739 			I16x8Sub => write!(f, "i16x8.sub"),
2740 			I32x4Sub => write!(f, "i32x4.sub"),
2741 			I64x2Sub => write!(f, "i64x2.sub"),
2742 			I8x16Mul => write!(f, "i8x16.mul"),
2743 			I16x8Mul => write!(f, "i16x8.mul"),
2744 			I32x4Mul => write!(f, "i32x4.mul"),
2745 			// I64x2Mul => write!(f, "i64x2.mul"),
2746 			I8x16Neg => write!(f, "i8x16.neg"),
2747 			I16x8Neg => write!(f, "i16x8.neg"),
2748 			I32x4Neg => write!(f, "i32x4.neg"),
2749 			I64x2Neg => write!(f, "i64x2.neg"),
2750 			I8x16AddSaturateS => write!(f, "i8x16.add_saturate_s"),
2751 			I8x16AddSaturateU => write!(f, "i8x16.add_saturate_u"),
2752 			I16x8AddSaturateS => write!(f, "i16x8.add_saturate_S"),
2753 			I16x8AddSaturateU => write!(f, "i16x8.add_saturate_u"),
2754 			I8x16SubSaturateS => write!(f, "i8x16.sub_saturate_S"),
2755 			I8x16SubSaturateU => write!(f, "i8x16.sub_saturate_u"),
2756 			I16x8SubSaturateS => write!(f, "i16x8.sub_saturate_S"),
2757 			I16x8SubSaturateU => write!(f, "i16x8.sub_saturate_u"),
2758 			I8x16Shl => write!(f, "i8x16.shl"),
2759 			I16x8Shl => write!(f, "i16x8.shl"),
2760 			I32x4Shl => write!(f, "i32x4.shl"),
2761 			I64x2Shl => write!(f, "i64x2.shl"),
2762 			I8x16ShrS => write!(f, "i8x16.shr_s"),
2763 			I8x16ShrU => write!(f, "i8x16.shr_u"),
2764 			I16x8ShrS => write!(f, "i16x8.shr_s"),
2765 			I16x8ShrU => write!(f, "i16x8.shr_u"),
2766 			I32x4ShrS => write!(f, "i32x4.shr_s"),
2767 			I32x4ShrU => write!(f, "i32x4.shr_u"),
2768 			I64x2ShrS => write!(f, "i64x2.shr_s"),
2769 			I64x2ShrU => write!(f, "i64x2.shr_u"),
2770 			V128And => write!(f, "v128.and"),
2771 			V128Or => write!(f, "v128.or"),
2772 			V128Xor => write!(f, "v128.xor"),
2773 			V128Not => write!(f, "v128.not"),
2774 			V128Bitselect => write!(f, "v128.bitselect"),
2775 			I8x16AnyTrue => write!(f, "i8x16.any_true"),
2776 			I16x8AnyTrue => write!(f, "i16x8.any_true"),
2777 			I32x4AnyTrue => write!(f, "i32x4.any_true"),
2778 			I64x2AnyTrue => write!(f, "i64x2.any_true"),
2779 			I8x16AllTrue => write!(f, "i8x16.all_true"),
2780 			I16x8AllTrue => write!(f, "i16x8.all_true"),
2781 			I32x4AllTrue => write!(f, "i32x4.all_true"),
2782 			I64x2AllTrue => write!(f, "i64x2.all_true"),
2783 			I8x16Eq => write!(f, "i8x16.eq"),
2784 			I16x8Eq => write!(f, "i16x8.eq"),
2785 			I32x4Eq => write!(f, "i32x4.eq"),
2786 			// I64x2Eq => write!(f, "i64x2.eq"),
2787 			F32x4Eq => write!(f, "f32x4.eq"),
2788 			F64x2Eq => write!(f, "f64x2.eq"),
2789 			I8x16Ne => write!(f, "i8x16.ne"),
2790 			I16x8Ne => write!(f, "i16x8.ne"),
2791 			I32x4Ne => write!(f, "i32x4.ne"),
2792 			// I64x2Ne => write!(f, "i64x2.ne"),
2793 			F32x4Ne => write!(f, "f32x4.ne"),
2794 			F64x2Ne => write!(f, "f64x2.ne"),
2795 			I8x16LtS => write!(f, "i8x16.lt_s"),
2796 			I8x16LtU => write!(f, "i8x16.lt_u"),
2797 			I16x8LtS => write!(f, "i16x8.lt_s"),
2798 			I16x8LtU => write!(f, "i16x8.lt_u"),
2799 			I32x4LtS => write!(f, "i32x4.lt_s"),
2800 			I32x4LtU => write!(f, "i32x4.lt_u"),
2801 			// I64x2LtS => write!(f, "// I64x2.lt_s"),
2802 			// I64x2LtU => write!(f, "// I64x2.lt_u"),
2803 			F32x4Lt => write!(f, "f32x4.lt"),
2804 			F64x2Lt => write!(f, "f64x2.lt"),
2805 			I8x16LeS => write!(f, "i8x16.le_s"),
2806 			I8x16LeU => write!(f, "i8x16.le_u"),
2807 			I16x8LeS => write!(f, "i16x8.le_s"),
2808 			I16x8LeU => write!(f, "i16x8.le_u"),
2809 			I32x4LeS => write!(f, "i32x4.le_s"),
2810 			I32x4LeU => write!(f, "i32x4.le_u"),
2811 			// I64x2LeS => write!(f, "// I64x2.le_s"),
2812 			// I64x2LeU => write!(f, "// I64x2.le_u"),
2813 			F32x4Le => write!(f, "f32x4.le"),
2814 			F64x2Le => write!(f, "f64x2.le"),
2815 			I8x16GtS => write!(f, "i8x16.gt_s"),
2816 			I8x16GtU => write!(f, "i8x16.gt_u"),
2817 			I16x8GtS => write!(f, "i16x8.gt_s"),
2818 			I16x8GtU => write!(f, "i16x8.gt_u"),
2819 			I32x4GtS => write!(f, "i32x4.gt_s"),
2820 			I32x4GtU => write!(f, "i32x4.gt_u"),
2821 			// I64x2GtS => write!(f, "// I64x2.gt_s"),
2822 			// I64x2GtU => write!(f, "// I64x2.gt_u"),
2823 			F32x4Gt => write!(f, "f32x4.gt"),
2824 			F64x2Gt => write!(f, "f64x2.gt"),
2825 			I8x16GeS => write!(f, "i8x16.ge_s"),
2826 			I8x16GeU => write!(f, "i8x16.ge_u"),
2827 			I16x8GeS => write!(f, "i16x8.ge_s"),
2828 			I16x8GeU => write!(f, "i16x8.ge_u"),
2829 			I32x4GeS => write!(f, "i32x4.ge_s"),
2830 			I32x4GeU => write!(f, "i32x4.ge_u"),
2831 			// I64x2GeS => write!(f, "// I64x2.ge_s"),
2832 			// I64x2GeU => write!(f, "// I64x2.ge_u"),
2833 			F32x4Ge => write!(f, "f32x4.ge"),
2834 			F64x2Ge => write!(f, "f64x2.ge"),
2835 			F32x4Neg => write!(f, "f32x4.neg"),
2836 			F64x2Neg => write!(f, "f64x2.neg"),
2837 			F32x4Abs => write!(f, "f32x4.abs"),
2838 			F64x2Abs => write!(f, "f64x2.abs"),
2839 			F32x4Min => write!(f, "f32x4.min"),
2840 			F64x2Min => write!(f, "f64x2.min"),
2841 			F32x4Max => write!(f, "f32x4.max"),
2842 			F64x2Max => write!(f, "f64x2.max"),
2843 			F32x4Add => write!(f, "f32x4.add"),
2844 			F64x2Add => write!(f, "f64x2.add"),
2845 			F32x4Sub => write!(f, "f32x4.sub"),
2846 			F64x2Sub => write!(f, "f64x2.sub"),
2847 			F32x4Div => write!(f, "f32x4.div"),
2848 			F64x2Div => write!(f, "f64x2.div"),
2849 			F32x4Mul => write!(f, "f32x4.mul"),
2850 			F64x2Mul => write!(f, "f64x2.mul"),
2851 			F32x4Sqrt => write!(f, "f32x4.sqrt"),
2852 			F64x2Sqrt => write!(f, "f64x2.sqrt"),
2853 			F32x4ConvertSI32x4 => write!(f, "f32x4.convert_s/i32x4"),
2854 			F32x4ConvertUI32x4 => write!(f, "f32x4.convert_u/i32x4"),
2855 			F64x2ConvertSI64x2 => write!(f, "f64x2.convert_s/i64x2"),
2856 			F64x2ConvertUI64x2 => write!(f, "f64x2.convert_u/i64x2"),
2857 			I32x4TruncSF32x4Sat => write!(f, "i32x4.trunc_s/f32x4:sat"),
2858 			I32x4TruncUF32x4Sat => write!(f, "i32x4.trunc_u/f32x4:sat"),
2859 			I64x2TruncSF64x2Sat => write!(f, "i64x2.trunc_s/f64x2:sat"),
2860 			I64x2TruncUF64x2Sat => write!(f, "i64x2.trunc_u/f64x2:sat"),
2861 		}
2862 	}
2863 }
2864 
2865 #[cfg(feature="bulk")]
2866 impl fmt::Display for BulkInstruction {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2867 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2868 		use self::BulkInstruction::*;
2869 
2870 		match *self {
2871 			MemoryInit(_) => write!(f, "memory.init"),
2872 			MemoryDrop(_) => write!(f, "memory.drop"),
2873 			MemoryFill => write!(f, "memory.fill"),
2874 			MemoryCopy => write!(f, "memory.copy"),
2875 			TableInit(_) => write!(f, "table.init"),
2876 			TableDrop(_) => write!(f, "table.drop"),
2877 			TableCopy => write!(f, "table.copy"),
2878 		}
2879 	}
2880 }
2881 
2882 impl Serialize for Instructions {
2883 	type Error = Error;
2884 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>2885 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2886 		for op in self.0.into_iter() {
2887 			op.serialize(writer)?;
2888 		}
2889 
2890 		Ok(())
2891 	}
2892 }
2893 
2894 impl Serialize for InitExpr {
2895 	type Error = Error;
2896 
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>2897 	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2898 		for op in self.0.into_iter() {
2899 			op.serialize(writer)?;
2900 		}
2901 
2902 		Ok(())
2903 	}
2904 }
2905 
2906 #[test]
ifelse()2907 fn ifelse() {
2908 	// see if-else.wast/if-else.wasm
2909 	let instruction_list = super::deserialize_buffer::<Instructions>(&[0x04, 0x7F, 0x41, 0x05, 0x05, 0x41, 0x07, 0x0B, 0x0B])
2910 		.expect("valid hex of if instruction");
2911 	let instructions = instruction_list.elements();
2912 	match &instructions[0] {
2913 		&Instruction::If(_) => (),
2914 		_ => panic!("Should be deserialized as if instruction"),
2915 	}
2916 	let before_else = instructions.iter().skip(1)
2917 		.take_while(|op| match **op { Instruction::Else => false, _ => true }).count();
2918 	let after_else = instructions.iter().skip(1)
2919 		.skip_while(|op| match **op { Instruction::Else => false, _ => true })
2920 		.take_while(|op| match **op { Instruction::End => false, _ => true })
2921 		.count()
2922 		- 1; // minus Instruction::Else itself
2923 	assert_eq!(before_else, after_else);
2924 }
2925 
2926 #[test]
display()2927 fn display() {
2928 	let instruction = Instruction::GetLocal(0);
2929 	assert_eq!("get_local 0", format!("{}", instruction));
2930 
2931 	let instruction = Instruction::F64Store(0, 24);
2932 	assert_eq!("f64.store offset=24", format!("{}", instruction));
2933 
2934 	let instruction = Instruction::I64Store(0, 0);
2935 	assert_eq!("i64.store", format!("{}", instruction));
2936 }
2937 
2938 #[test]
size_off()2939 fn size_off() {
2940 	assert!(::std::mem::size_of::<Instruction>() <= 24);
2941 }
2942 
2943 #[test]
instructions_hashset()2944 fn instructions_hashset() {
2945 	use self::Instruction::{Call, Block, Drop};
2946 	use super::types::{BlockType::Value, ValueType};
2947 
2948 	let set: std::collections::HashSet<Instruction> =
2949 		vec![Call(1), Block(Value(ValueType::I32)), Drop].into_iter().collect();
2950 	assert_eq!(set.contains(&Drop), true)
2951 }
2952