parity_wasm/elements/
ops.rs

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