casper_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, u32),
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_lead: u8 = Uint8::deserialize(reader)?.into();
1091
1092				#[cfg(feature = "call_indirect_overlong")]
1093				let table_ref = if table_ref_lead & 0x80 == 0 {
1094					// If the most significant bit is not set, this is old
1095					// behavior where the leading byte is the table reference
1096					u32::from(table_ref_lead)
1097				} else {
1098					// Otherwise, the leading byte represents the length of the
1099					// table reference to load as VarInt
1100					VarUint32::deserialize_with_first(reader, table_ref_lead)?.into()
1101				};
1102
1103				#[cfg(not(feature = "call_indirect_overlong"))]
1104				let table_ref = {
1105					if table_ref_lead != 0 {
1106						return Err(Error::InvalidTableReference(table_ref_lead));
1107					}
1108					u32::from(table_ref_lead)
1109				};
1110
1111				CallIndirect(signature, table_ref)
1112			},
1113			DROP => Drop,
1114			SELECT => Select,
1115
1116			GETLOCAL => GetLocal(VarUint32::deserialize(reader)?.into()),
1117			SETLOCAL => SetLocal(VarUint32::deserialize(reader)?.into()),
1118			TEELOCAL => TeeLocal(VarUint32::deserialize(reader)?.into()),
1119			GETGLOBAL => GetGlobal(VarUint32::deserialize(reader)?.into()),
1120			SETGLOBAL => SetGlobal(VarUint32::deserialize(reader)?.into()),
1121
1122			I32LOAD => I32Load(
1123				VarUint32::deserialize(reader)?.into(),
1124				VarUint32::deserialize(reader)?.into(),
1125			),
1126
1127			I64LOAD => I64Load(
1128				VarUint32::deserialize(reader)?.into(),
1129				VarUint32::deserialize(reader)?.into(),
1130			),
1131
1132			F32LOAD => F32Load(
1133				VarUint32::deserialize(reader)?.into(),
1134				VarUint32::deserialize(reader)?.into(),
1135			),
1136
1137			F64LOAD => F64Load(
1138				VarUint32::deserialize(reader)?.into(),
1139				VarUint32::deserialize(reader)?.into(),
1140			),
1141
1142			I32LOAD8S => I32Load8S(
1143				VarUint32::deserialize(reader)?.into(),
1144				VarUint32::deserialize(reader)?.into(),
1145			),
1146
1147			I32LOAD8U => I32Load8U(
1148				VarUint32::deserialize(reader)?.into(),
1149				VarUint32::deserialize(reader)?.into(),
1150			),
1151
1152			I32LOAD16S => I32Load16S(
1153				VarUint32::deserialize(reader)?.into(),
1154				VarUint32::deserialize(reader)?.into(),
1155			),
1156
1157			I32LOAD16U => I32Load16U(
1158				VarUint32::deserialize(reader)?.into(),
1159				VarUint32::deserialize(reader)?.into(),
1160			),
1161
1162			I64LOAD8S => I64Load8S(
1163				VarUint32::deserialize(reader)?.into(),
1164				VarUint32::deserialize(reader)?.into(),
1165			),
1166
1167			I64LOAD8U => I64Load8U(
1168				VarUint32::deserialize(reader)?.into(),
1169				VarUint32::deserialize(reader)?.into(),
1170			),
1171
1172			I64LOAD16S => I64Load16S(
1173				VarUint32::deserialize(reader)?.into(),
1174				VarUint32::deserialize(reader)?.into(),
1175			),
1176
1177			I64LOAD16U => I64Load16U(
1178				VarUint32::deserialize(reader)?.into(),
1179				VarUint32::deserialize(reader)?.into(),
1180			),
1181
1182			I64LOAD32S => I64Load32S(
1183				VarUint32::deserialize(reader)?.into(),
1184				VarUint32::deserialize(reader)?.into(),
1185			),
1186
1187			I64LOAD32U => I64Load32U(
1188				VarUint32::deserialize(reader)?.into(),
1189				VarUint32::deserialize(reader)?.into(),
1190			),
1191
1192			I32STORE => I32Store(
1193				VarUint32::deserialize(reader)?.into(),
1194				VarUint32::deserialize(reader)?.into(),
1195			),
1196
1197			I64STORE => I64Store(
1198				VarUint32::deserialize(reader)?.into(),
1199				VarUint32::deserialize(reader)?.into(),
1200			),
1201
1202			F32STORE => F32Store(
1203				VarUint32::deserialize(reader)?.into(),
1204				VarUint32::deserialize(reader)?.into(),
1205			),
1206
1207			F64STORE => F64Store(
1208				VarUint32::deserialize(reader)?.into(),
1209				VarUint32::deserialize(reader)?.into(),
1210			),
1211
1212			I32STORE8 => I32Store8(
1213				VarUint32::deserialize(reader)?.into(),
1214				VarUint32::deserialize(reader)?.into(),
1215			),
1216
1217			I32STORE16 => I32Store16(
1218				VarUint32::deserialize(reader)?.into(),
1219				VarUint32::deserialize(reader)?.into(),
1220			),
1221
1222			I64STORE8 => I64Store8(
1223				VarUint32::deserialize(reader)?.into(),
1224				VarUint32::deserialize(reader)?.into(),
1225			),
1226
1227			I64STORE16 => I64Store16(
1228				VarUint32::deserialize(reader)?.into(),
1229				VarUint32::deserialize(reader)?.into(),
1230			),
1231
1232			I64STORE32 => I64Store32(
1233				VarUint32::deserialize(reader)?.into(),
1234				VarUint32::deserialize(reader)?.into(),
1235			),
1236
1237			CURRENTMEMORY => {
1238				let mem_ref: u8 = Uint8::deserialize(reader)?.into();
1239				if mem_ref != 0 {
1240					return Err(Error::InvalidMemoryReference(mem_ref));
1241				}
1242				CurrentMemory(mem_ref)
1243			},
1244			GROWMEMORY => {
1245				let mem_ref: u8 = Uint8::deserialize(reader)?.into();
1246				if mem_ref != 0 {
1247					return Err(Error::InvalidMemoryReference(mem_ref));
1248				}
1249				GrowMemory(mem_ref)
1250			},
1251
1252			I32CONST => I32Const(VarInt32::deserialize(reader)?.into()),
1253			I64CONST => I64Const(VarInt64::deserialize(reader)?.into()),
1254			F32CONST => F32Const(Uint32::deserialize(reader)?.into()),
1255			F64CONST => F64Const(Uint64::deserialize(reader)?.into()),
1256			I32EQZ => I32Eqz,
1257			I32EQ => I32Eq,
1258			I32NE => I32Ne,
1259			I32LTS => I32LtS,
1260			I32LTU => I32LtU,
1261			I32GTS => I32GtS,
1262			I32GTU => I32GtU,
1263			I32LES => I32LeS,
1264			I32LEU => I32LeU,
1265			I32GES => I32GeS,
1266			I32GEU => I32GeU,
1267
1268			I64EQZ => I64Eqz,
1269			I64EQ => I64Eq,
1270			I64NE => I64Ne,
1271			I64LTS => I64LtS,
1272			I64LTU => I64LtU,
1273			I64GTS => I64GtS,
1274			I64GTU => I64GtU,
1275			I64LES => I64LeS,
1276			I64LEU => I64LeU,
1277			I64GES => I64GeS,
1278			I64GEU => I64GeU,
1279
1280			F32EQ => F32Eq,
1281			F32NE => F32Ne,
1282			F32LT => F32Lt,
1283			F32GT => F32Gt,
1284			F32LE => F32Le,
1285			F32GE => F32Ge,
1286
1287			F64EQ => F64Eq,
1288			F64NE => F64Ne,
1289			F64LT => F64Lt,
1290			F64GT => F64Gt,
1291			F64LE => F64Le,
1292			F64GE => F64Ge,
1293
1294			I32CLZ => I32Clz,
1295			I32CTZ => I32Ctz,
1296			I32POPCNT => I32Popcnt,
1297			I32ADD => I32Add,
1298			I32SUB => I32Sub,
1299			I32MUL => I32Mul,
1300			I32DIVS => I32DivS,
1301			I32DIVU => I32DivU,
1302			I32REMS => I32RemS,
1303			I32REMU => I32RemU,
1304			I32AND => I32And,
1305			I32OR => I32Or,
1306			I32XOR => I32Xor,
1307			I32SHL => I32Shl,
1308			I32SHRS => I32ShrS,
1309			I32SHRU => I32ShrU,
1310			I32ROTL => I32Rotl,
1311			I32ROTR => I32Rotr,
1312
1313			I64CLZ => I64Clz,
1314			I64CTZ => I64Ctz,
1315			I64POPCNT => I64Popcnt,
1316			I64ADD => I64Add,
1317			I64SUB => I64Sub,
1318			I64MUL => I64Mul,
1319			I64DIVS => I64DivS,
1320			I64DIVU => I64DivU,
1321			I64REMS => I64RemS,
1322			I64REMU => I64RemU,
1323			I64AND => I64And,
1324			I64OR => I64Or,
1325			I64XOR => I64Xor,
1326			I64SHL => I64Shl,
1327			I64SHRS => I64ShrS,
1328			I64SHRU => I64ShrU,
1329			I64ROTL => I64Rotl,
1330			I64ROTR => I64Rotr,
1331			F32ABS => F32Abs,
1332			F32NEG => F32Neg,
1333			F32CEIL => F32Ceil,
1334			F32FLOOR => F32Floor,
1335			F32TRUNC => F32Trunc,
1336			F32NEAREST => F32Nearest,
1337			F32SQRT => F32Sqrt,
1338			F32ADD => F32Add,
1339			F32SUB => F32Sub,
1340			F32MUL => F32Mul,
1341			F32DIV => F32Div,
1342			F32MIN => F32Min,
1343			F32MAX => F32Max,
1344			F32COPYSIGN => F32Copysign,
1345			F64ABS => F64Abs,
1346			F64NEG => F64Neg,
1347			F64CEIL => F64Ceil,
1348			F64FLOOR => F64Floor,
1349			F64TRUNC => F64Trunc,
1350			F64NEAREST => F64Nearest,
1351			F64SQRT => F64Sqrt,
1352			F64ADD => F64Add,
1353			F64SUB => F64Sub,
1354			F64MUL => F64Mul,
1355			F64DIV => F64Div,
1356			F64MIN => F64Min,
1357			F64MAX => F64Max,
1358			F64COPYSIGN => F64Copysign,
1359
1360			I32WRAPI64 => I32WrapI64,
1361			I32TRUNCSF32 => I32TruncSF32,
1362			I32TRUNCUF32 => I32TruncUF32,
1363			I32TRUNCSF64 => I32TruncSF64,
1364			I32TRUNCUF64 => I32TruncUF64,
1365			I64EXTENDSI32 => I64ExtendSI32,
1366			I64EXTENDUI32 => I64ExtendUI32,
1367			I64TRUNCSF32 => I64TruncSF32,
1368			I64TRUNCUF32 => I64TruncUF32,
1369			I64TRUNCSF64 => I64TruncSF64,
1370			I64TRUNCUF64 => I64TruncUF64,
1371			F32CONVERTSI32 => F32ConvertSI32,
1372			F32CONVERTUI32 => F32ConvertUI32,
1373			F32CONVERTSI64 => F32ConvertSI64,
1374			F32CONVERTUI64 => F32ConvertUI64,
1375			F32DEMOTEF64 => F32DemoteF64,
1376			F64CONVERTSI32 => F64ConvertSI32,
1377			F64CONVERTUI32 => F64ConvertUI32,
1378			F64CONVERTSI64 => F64ConvertSI64,
1379			F64CONVERTUI64 => F64ConvertUI64,
1380			F64PROMOTEF32 => F64PromoteF32,
1381
1382			I32REINTERPRETF32 => I32ReinterpretF32,
1383			I64REINTERPRETF64 => I64ReinterpretF64,
1384			F32REINTERPRETI32 => F32ReinterpretI32,
1385			F64REINTERPRETI64 => F64ReinterpretI64,
1386
1387			#[cfg(feature = "sign_ext")]
1388			I32_EXTEND8_S | I32_EXTEND16_S | I64_EXTEND8_S | I64_EXTEND16_S | I64_EXTEND32_S => match val {
1389				I32_EXTEND8_S => SignExt(SignExtInstruction::I32Extend8S),
1390				I32_EXTEND16_S => SignExt(SignExtInstruction::I32Extend16S),
1391				I64_EXTEND8_S => SignExt(SignExtInstruction::I64Extend8S),
1392				I64_EXTEND16_S => SignExt(SignExtInstruction::I64Extend16S),
1393				I64_EXTEND32_S => SignExt(SignExtInstruction::I64Extend32S),
1394				_ => return Err(Error::UnknownOpcode(val)),
1395			},
1396
1397			#[cfg(feature = "atomics")]
1398			atomics::ATOMIC_PREFIX => return deserialize_atomic(reader),
1399
1400			#[cfg(feature = "simd")]
1401			simd::SIMD_PREFIX => return deserialize_simd(reader),
1402
1403			#[cfg(feature = "bulk")]
1404			bulk::BULK_PREFIX => return deserialize_bulk(reader),
1405
1406			_ => return Err(Error::UnknownOpcode(val)),
1407		})
1408	}
1409}
1410
1411#[cfg(feature = "atomics")]
1412fn deserialize_atomic<R: io::Read>(reader: &mut R) -> Result<Instruction, Error> {
1413	use self::{opcodes::atomics::*, AtomicsInstruction::*};
1414
1415	let val: u8 = Uint8::deserialize(reader)?.into();
1416	let mem = MemArg::deserialize(reader)?;
1417	Ok(Instruction::Atomics(match val {
1418		ATOMIC_WAKE => AtomicWake(mem),
1419		I32_ATOMIC_WAIT => I32AtomicWait(mem),
1420		I64_ATOMIC_WAIT => I64AtomicWait(mem),
1421
1422		I32_ATOMIC_LOAD => I32AtomicLoad(mem),
1423		I64_ATOMIC_LOAD => I64AtomicLoad(mem),
1424		I32_ATOMIC_LOAD8U => I32AtomicLoad8u(mem),
1425		I32_ATOMIC_LOAD16U => I32AtomicLoad16u(mem),
1426		I64_ATOMIC_LOAD8U => I64AtomicLoad8u(mem),
1427		I64_ATOMIC_LOAD16U => I64AtomicLoad16u(mem),
1428		I64_ATOMIC_LOAD32U => I64AtomicLoad32u(mem),
1429		I32_ATOMIC_STORE => I32AtomicStore(mem),
1430		I64_ATOMIC_STORE => I64AtomicStore(mem),
1431		I32_ATOMIC_STORE8U => I32AtomicStore8u(mem),
1432		I32_ATOMIC_STORE16U => I32AtomicStore16u(mem),
1433		I64_ATOMIC_STORE8U => I64AtomicStore8u(mem),
1434		I64_ATOMIC_STORE16U => I64AtomicStore16u(mem),
1435		I64_ATOMIC_STORE32U => I64AtomicStore32u(mem),
1436
1437		I32_ATOMIC_RMW_ADD => I32AtomicRmwAdd(mem),
1438		I64_ATOMIC_RMW_ADD => I64AtomicRmwAdd(mem),
1439		I32_ATOMIC_RMW_ADD8U => I32AtomicRmwAdd8u(mem),
1440		I32_ATOMIC_RMW_ADD16U => I32AtomicRmwAdd16u(mem),
1441		I64_ATOMIC_RMW_ADD8U => I64AtomicRmwAdd8u(mem),
1442		I64_ATOMIC_RMW_ADD16U => I64AtomicRmwAdd16u(mem),
1443		I64_ATOMIC_RMW_ADD32U => I64AtomicRmwAdd32u(mem),
1444
1445		I32_ATOMIC_RMW_SUB => I32AtomicRmwSub(mem),
1446		I64_ATOMIC_RMW_SUB => I64AtomicRmwSub(mem),
1447		I32_ATOMIC_RMW_SUB8U => I32AtomicRmwSub8u(mem),
1448		I32_ATOMIC_RMW_SUB16U => I32AtomicRmwSub16u(mem),
1449		I64_ATOMIC_RMW_SUB8U => I64AtomicRmwSub8u(mem),
1450		I64_ATOMIC_RMW_SUB16U => I64AtomicRmwSub16u(mem),
1451		I64_ATOMIC_RMW_SUB32U => I64AtomicRmwSub32u(mem),
1452
1453		I32_ATOMIC_RMW_AND => I32AtomicRmwAnd(mem),
1454		I64_ATOMIC_RMW_AND => I64AtomicRmwAnd(mem),
1455		I32_ATOMIC_RMW_AND8U => I32AtomicRmwAnd8u(mem),
1456		I32_ATOMIC_RMW_AND16U => I32AtomicRmwAnd16u(mem),
1457		I64_ATOMIC_RMW_AND8U => I64AtomicRmwAnd8u(mem),
1458		I64_ATOMIC_RMW_AND16U => I64AtomicRmwAnd16u(mem),
1459		I64_ATOMIC_RMW_AND32U => I64AtomicRmwAnd32u(mem),
1460
1461		I32_ATOMIC_RMW_OR => I32AtomicRmwOr(mem),
1462		I64_ATOMIC_RMW_OR => I64AtomicRmwOr(mem),
1463		I32_ATOMIC_RMW_OR8U => I32AtomicRmwOr8u(mem),
1464		I32_ATOMIC_RMW_OR16U => I32AtomicRmwOr16u(mem),
1465		I64_ATOMIC_RMW_OR8U => I64AtomicRmwOr8u(mem),
1466		I64_ATOMIC_RMW_OR16U => I64AtomicRmwOr16u(mem),
1467		I64_ATOMIC_RMW_OR32U => I64AtomicRmwOr32u(mem),
1468
1469		I32_ATOMIC_RMW_XOR => I32AtomicRmwXor(mem),
1470		I64_ATOMIC_RMW_XOR => I64AtomicRmwXor(mem),
1471		I32_ATOMIC_RMW_XOR8U => I32AtomicRmwXor8u(mem),
1472		I32_ATOMIC_RMW_XOR16U => I32AtomicRmwXor16u(mem),
1473		I64_ATOMIC_RMW_XOR8U => I64AtomicRmwXor8u(mem),
1474		I64_ATOMIC_RMW_XOR16U => I64AtomicRmwXor16u(mem),
1475		I64_ATOMIC_RMW_XOR32U => I64AtomicRmwXor32u(mem),
1476
1477		I32_ATOMIC_RMW_XCHG => I32AtomicRmwXchg(mem),
1478		I64_ATOMIC_RMW_XCHG => I64AtomicRmwXchg(mem),
1479		I32_ATOMIC_RMW_XCHG8U => I32AtomicRmwXchg8u(mem),
1480		I32_ATOMIC_RMW_XCHG16U => I32AtomicRmwXchg16u(mem),
1481		I64_ATOMIC_RMW_XCHG8U => I64AtomicRmwXchg8u(mem),
1482		I64_ATOMIC_RMW_XCHG16U => I64AtomicRmwXchg16u(mem),
1483		I64_ATOMIC_RMW_XCHG32U => I64AtomicRmwXchg32u(mem),
1484
1485		I32_ATOMIC_RMW_CMPXCHG => I32AtomicRmwCmpxchg(mem),
1486		I64_ATOMIC_RMW_CMPXCHG => I64AtomicRmwCmpxchg(mem),
1487		I32_ATOMIC_RMW_CMPXCHG8U => I32AtomicRmwCmpxchg8u(mem),
1488		I32_ATOMIC_RMW_CMPXCHG16U => I32AtomicRmwCmpxchg16u(mem),
1489		I64_ATOMIC_RMW_CMPXCHG8U => I64AtomicRmwCmpxchg8u(mem),
1490		I64_ATOMIC_RMW_CMPXCHG16U => I64AtomicRmwCmpxchg16u(mem),
1491		I64_ATOMIC_RMW_CMPXCHG32U => I64AtomicRmwCmpxchg32u(mem),
1492
1493		_ => return Err(Error::UnknownOpcode(val)),
1494	}))
1495}
1496
1497#[cfg(feature = "simd")]
1498fn deserialize_simd<R: io::Read>(reader: &mut R) -> Result<Instruction, Error> {
1499	use self::{opcodes::simd::*, SimdInstruction::*};
1500
1501	let val = VarUint32::deserialize(reader)?.into();
1502	Ok(Instruction::Simd(match val {
1503		V128_CONST => {
1504			let mut buf = [0; 16];
1505			reader.read(&mut buf)?;
1506			V128Const(Box::new(buf))
1507		},
1508		V128_LOAD => V128Load(MemArg::deserialize(reader)?),
1509		V128_STORE => V128Store(MemArg::deserialize(reader)?),
1510		I8X16_SPLAT => I8x16Splat,
1511		I16X8_SPLAT => I16x8Splat,
1512		I32X4_SPLAT => I32x4Splat,
1513		I64X2_SPLAT => I64x2Splat,
1514		F32X4_SPLAT => F32x4Splat,
1515		F64X2_SPLAT => F64x2Splat,
1516		I8X16_EXTRACT_LANE_S => I8x16ExtractLaneS(Uint8::deserialize(reader)?.into()),
1517		I8X16_EXTRACT_LANE_U => I8x16ExtractLaneU(Uint8::deserialize(reader)?.into()),
1518		I16X8_EXTRACT_LANE_S => I16x8ExtractLaneS(Uint8::deserialize(reader)?.into()),
1519		I16X8_EXTRACT_LANE_U => I16x8ExtractLaneU(Uint8::deserialize(reader)?.into()),
1520		I32X4_EXTRACT_LANE => I32x4ExtractLane(Uint8::deserialize(reader)?.into()),
1521		I64X2_EXTRACT_LANE => I64x2ExtractLane(Uint8::deserialize(reader)?.into()),
1522		F32X4_EXTRACT_LANE => F32x4ExtractLane(Uint8::deserialize(reader)?.into()),
1523		F64X2_EXTRACT_LANE => F64x2ExtractLane(Uint8::deserialize(reader)?.into()),
1524		I8X16_REPLACE_LANE => I8x16ReplaceLane(Uint8::deserialize(reader)?.into()),
1525		I16X8_REPLACE_LANE => I16x8ReplaceLane(Uint8::deserialize(reader)?.into()),
1526		I32X4_REPLACE_LANE => I32x4ReplaceLane(Uint8::deserialize(reader)?.into()),
1527		I64X2_REPLACE_LANE => I64x2ReplaceLane(Uint8::deserialize(reader)?.into()),
1528		F32X4_REPLACE_LANE => F32x4ReplaceLane(Uint8::deserialize(reader)?.into()),
1529		F64X2_REPLACE_LANE => F64x2ReplaceLane(Uint8::deserialize(reader)?.into()),
1530		V8X16_SHUFFLE => {
1531			let mut buf = [0; 16];
1532			reader.read(&mut buf)?;
1533			V8x16Shuffle(Box::new(buf))
1534		},
1535		I8X16_ADD => I8x16Add,
1536		I16X8_ADD => I16x8Add,
1537		I32X4_ADD => I32x4Add,
1538		I64X2_ADD => I64x2Add,
1539		I8X16_SUB => I8x16Sub,
1540		I16X8_SUB => I16x8Sub,
1541		I32X4_SUB => I32x4Sub,
1542		I64X2_SUB => I64x2Sub,
1543		I8X16_MUL => I8x16Mul,
1544		I16X8_MUL => I16x8Mul,
1545		I32X4_MUL => I32x4Mul,
1546		// I64X2_MUL => I64x2Mul,
1547		I8X16_NEG => I8x16Neg,
1548		I16X8_NEG => I16x8Neg,
1549		I32X4_NEG => I32x4Neg,
1550		I64X2_NEG => I64x2Neg,
1551
1552		I8X16_ADD_SATURATE_S => I8x16AddSaturateS,
1553		I8X16_ADD_SATURATE_U => I8x16AddSaturateU,
1554		I16X8_ADD_SATURATE_S => I16x8AddSaturateS,
1555		I16X8_ADD_SATURATE_U => I16x8AddSaturateU,
1556		I8X16_SUB_SATURATE_S => I8x16SubSaturateS,
1557		I8X16_SUB_SATURATE_U => I8x16SubSaturateU,
1558		I16X8_SUB_SATURATE_S => I16x8SubSaturateS,
1559		I16X8_SUB_SATURATE_U => I16x8SubSaturateU,
1560		I8X16_SHL => I8x16Shl,
1561		I16X8_SHL => I16x8Shl,
1562		I32X4_SHL => I32x4Shl,
1563		I64X2_SHL => I64x2Shl,
1564		I8X16_SHR_S => I8x16ShrS,
1565		I8X16_SHR_U => I8x16ShrU,
1566		I16X8_SHR_S => I16x8ShrS,
1567		I16X8_SHR_U => I16x8ShrU,
1568		I32X4_SHR_S => I32x4ShrS,
1569		I32X4_SHR_U => I32x4ShrU,
1570		I64X2_SHR_S => I64x2ShrS,
1571		I64X2_SHR_U => I64x2ShrU,
1572		V128_AND => V128And,
1573		V128_OR => V128Or,
1574		V128_XOR => V128Xor,
1575		V128_NOT => V128Not,
1576		V128_BITSELECT => V128Bitselect,
1577		I8X16_ANY_TRUE => I8x16AnyTrue,
1578		I16X8_ANY_TRUE => I16x8AnyTrue,
1579		I32X4_ANY_TRUE => I32x4AnyTrue,
1580		I64X2_ANY_TRUE => I64x2AnyTrue,
1581		I8X16_ALL_TRUE => I8x16AllTrue,
1582		I16X8_ALL_TRUE => I16x8AllTrue,
1583		I32X4_ALL_TRUE => I32x4AllTrue,
1584		I64X2_ALL_TRUE => I64x2AllTrue,
1585		I8X16_EQ => I8x16Eq,
1586		I16X8_EQ => I16x8Eq,
1587		I32X4_EQ => I32x4Eq,
1588		// I64X2_EQ => I64x2Eq,
1589		F32X4_EQ => F32x4Eq,
1590		F64X2_EQ => F64x2Eq,
1591		I8X16_NE => I8x16Ne,
1592		I16X8_NE => I16x8Ne,
1593		I32X4_NE => I32x4Ne,
1594		// I64X2_NE => I64x2Ne,
1595		F32X4_NE => F32x4Ne,
1596		F64X2_NE => F64x2Ne,
1597		I8X16_LT_S => I8x16LtS,
1598		I8X16_LT_U => I8x16LtU,
1599		I16X8_LT_S => I16x8LtS,
1600		I16X8_LT_U => I16x8LtU,
1601		I32X4_LT_S => I32x4LtS,
1602		I32X4_LT_U => I32x4LtU,
1603		// I64X2_LT_S => I64x2LtS,
1604		// I64X2_LT_U => I64x2LtU,
1605		F32X4_LT => F32x4Lt,
1606		F64X2_LT => F64x2Lt,
1607		I8X16_LE_S => I8x16LeS,
1608		I8X16_LE_U => I8x16LeU,
1609		I16X8_LE_S => I16x8LeS,
1610		I16X8_LE_U => I16x8LeU,
1611		I32X4_LE_S => I32x4LeS,
1612		I32X4_LE_U => I32x4LeU,
1613		// I64X2_LE_S => I64x2LeS,
1614		// I64X2_LE_U => I64x2LeU,
1615		F32X4_LE => F32x4Le,
1616		F64X2_LE => F64x2Le,
1617		I8X16_GT_S => I8x16GtS,
1618		I8X16_GT_U => I8x16GtU,
1619		I16X8_GT_S => I16x8GtS,
1620		I16X8_GT_U => I16x8GtU,
1621		I32X4_GT_S => I32x4GtS,
1622		I32X4_GT_U => I32x4GtU,
1623		// I64X2_GT_S => I64x2GtS,
1624		// I64X2_GT_U => I64x2GtU,
1625		F32X4_GT => F32x4Gt,
1626		F64X2_GT => F64x2Gt,
1627		I8X16_GE_S => I8x16GeS,
1628		I8X16_GE_U => I8x16GeU,
1629		I16X8_GE_S => I16x8GeS,
1630		I16X8_GE_U => I16x8GeU,
1631		I32X4_GE_S => I32x4GeS,
1632		I32X4_GE_U => I32x4GeU,
1633		// I64X2_GE_S => I64x2GeS,
1634		// I64X2_GE_U => I64x2GeU,
1635		F32X4_GE => F32x4Ge,
1636		F64X2_GE => F64x2Ge,
1637		F32X4_NEG => F32x4Neg,
1638		F64X2_NEG => F64x2Neg,
1639		F32X4_ABS => F32x4Abs,
1640		F64X2_ABS => F64x2Abs,
1641		F32X4_MIN => F32x4Min,
1642		F64X2_MIN => F64x2Min,
1643		F32X4_MAX => F32x4Max,
1644		F64X2_MAX => F64x2Max,
1645		F32X4_ADD => F32x4Add,
1646		F64X2_ADD => F64x2Add,
1647		F32X4_SUB => F32x4Sub,
1648		F64X2_SUB => F64x2Sub,
1649		F32X4_DIV => F32x4Div,
1650		F64X2_DIV => F64x2Div,
1651		F32X4_MUL => F32x4Mul,
1652		F64X2_MUL => F64x2Mul,
1653		F32X4_SQRT => F32x4Sqrt,
1654		F64X2_SQRT => F64x2Sqrt,
1655		F32X4_CONVERT_S_I32X4 => F32x4ConvertSI32x4,
1656		F32X4_CONVERT_U_I32X4 => F32x4ConvertUI32x4,
1657		F64X2_CONVERT_S_I64X2 => F64x2ConvertSI64x2,
1658		F64X2_CONVERT_U_I64X2 => F64x2ConvertUI64x2,
1659		I32X4_TRUNC_S_F32X4_SAT => I32x4TruncSF32x4Sat,
1660		I32X4_TRUNC_U_F32X4_SAT => I32x4TruncUF32x4Sat,
1661		I64X2_TRUNC_S_F64X2_SAT => I64x2TruncSF64x2Sat,
1662		I64X2_TRUNC_U_F64X2_SAT => I64x2TruncUF64x2Sat,
1663
1664		_ => return Err(Error::UnknownSimdOpcode(val)),
1665	}))
1666}
1667
1668#[cfg(feature = "bulk")]
1669fn deserialize_bulk<R: io::Read>(reader: &mut R) -> Result<Instruction, Error> {
1670	use self::{opcodes::bulk::*, BulkInstruction::*};
1671
1672	let val: u8 = Uint8::deserialize(reader)?.into();
1673	Ok(Instruction::Bulk(match val {
1674		MEMORY_INIT => {
1675			if u8::from(Uint8::deserialize(reader)?) != 0 {
1676				return Err(Error::UnknownOpcode(val));
1677			}
1678			MemoryInit(VarUint32::deserialize(reader)?.into())
1679		},
1680		MEMORY_DROP => MemoryDrop(VarUint32::deserialize(reader)?.into()),
1681		MEMORY_FILL => {
1682			if u8::from(Uint8::deserialize(reader)?) != 0 {
1683				return Err(Error::UnknownOpcode(val));
1684			}
1685			MemoryFill
1686		},
1687		MEMORY_COPY => {
1688			if u8::from(Uint8::deserialize(reader)?) != 0 {
1689				return Err(Error::UnknownOpcode(val));
1690			}
1691			MemoryCopy
1692		},
1693
1694		TABLE_INIT => {
1695			if u8::from(Uint8::deserialize(reader)?) != 0 {
1696				return Err(Error::UnknownOpcode(val));
1697			}
1698			TableInit(VarUint32::deserialize(reader)?.into())
1699		},
1700		TABLE_DROP => TableDrop(VarUint32::deserialize(reader)?.into()),
1701		TABLE_COPY => {
1702			if u8::from(Uint8::deserialize(reader)?) != 0 {
1703				return Err(Error::UnknownOpcode(val));
1704			}
1705			TableCopy
1706		},
1707
1708		_ => return Err(Error::UnknownOpcode(val)),
1709	}))
1710}
1711
1712#[cfg(any(feature = "simd", feature = "atomics"))]
1713impl Deserialize for MemArg {
1714	type Error = Error;
1715
1716	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
1717		let align = Uint8::deserialize(reader)?;
1718		let offset = VarUint32::deserialize(reader)?;
1719		Ok(MemArg { align: align.into(), offset: offset.into() })
1720	}
1721}
1722
1723macro_rules! op {
1724	($writer: expr, $byte: expr) => {{
1725		let b: u8 = $byte;
1726		$writer.write(&[b])?;
1727	}};
1728	($writer: expr, $byte: expr, $s: block) => {{
1729		op!($writer, $byte);
1730		$s;
1731	}};
1732}
1733
1734#[cfg(feature = "atomics")]
1735macro_rules! atomic {
1736	($writer: expr, $byte: expr, $mem:expr) => {{
1737		$writer.write(&[ATOMIC_PREFIX, $byte])?;
1738		MemArg::serialize($mem, $writer)?;
1739	}};
1740}
1741
1742#[cfg(feature = "simd")]
1743macro_rules! simd {
1744	($writer: expr, $byte: expr, $other:expr) => {{
1745		$writer.write(&[SIMD_PREFIX])?;
1746		VarUint32::from($byte).serialize($writer)?;
1747		$other;
1748	}};
1749}
1750
1751#[cfg(feature = "bulk")]
1752macro_rules! bulk {
1753	($writer: expr, $byte: expr) => {{
1754		$writer.write(&[BULK_PREFIX, $byte])?;
1755	}};
1756	($writer: expr, $byte: expr, $remaining:expr) => {{
1757		bulk!($writer, $byte);
1758		$remaining;
1759	}};
1760}
1761
1762impl Serialize for Instruction {
1763	type Error = Error;
1764
1765	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
1766		use self::{opcodes::*, Instruction::*};
1767
1768		match self {
1769			Unreachable => op!(writer, UNREACHABLE),
1770			Nop => op!(writer, NOP),
1771			Block(block_type) => op!(writer, BLOCK, {
1772				block_type.serialize(writer)?;
1773			}),
1774			Loop(block_type) => op!(writer, LOOP, {
1775				block_type.serialize(writer)?;
1776			}),
1777			If(block_type) => op!(writer, IF, {
1778				block_type.serialize(writer)?;
1779			}),
1780			Else => op!(writer, ELSE),
1781			End => op!(writer, END),
1782			Br(idx) => op!(writer, BR, {
1783				VarUint32::from(idx).serialize(writer)?;
1784			}),
1785			BrIf(idx) => op!(writer, BRIF, {
1786				VarUint32::from(idx).serialize(writer)?;
1787			}),
1788			BrTable(ref table) => op!(writer, BRTABLE, {
1789				let list_writer = CountedListWriter::<VarUint32, _>(
1790					table.table.len(),
1791					table.table.iter().map(|x| VarUint32::from(*x)),
1792				);
1793				list_writer.serialize(writer)?;
1794				VarUint32::from(table.default).serialize(writer)?;
1795			}),
1796			Return => op!(writer, RETURN),
1797			Call(index) => op!(writer, CALL, {
1798				VarUint32::from(index).serialize(writer)?;
1799			}),
1800			CallIndirect(index, reserved) => op!(writer, CALLINDIRECT, {
1801				VarUint32::from(index).serialize(writer)?;
1802				VarUint32::from(reserved).serialize(writer)?;
1803			}),
1804			Drop => op!(writer, DROP),
1805			Select => op!(writer, SELECT),
1806			GetLocal(index) => op!(writer, GETLOCAL, {
1807				VarUint32::from(index).serialize(writer)?;
1808			}),
1809			SetLocal(index) => op!(writer, SETLOCAL, {
1810				VarUint32::from(index).serialize(writer)?;
1811			}),
1812			TeeLocal(index) => op!(writer, TEELOCAL, {
1813				VarUint32::from(index).serialize(writer)?;
1814			}),
1815			GetGlobal(index) => op!(writer, GETGLOBAL, {
1816				VarUint32::from(index).serialize(writer)?;
1817			}),
1818			SetGlobal(index) => op!(writer, SETGLOBAL, {
1819				VarUint32::from(index).serialize(writer)?;
1820			}),
1821			I32Load(flags, offset) => op!(writer, I32LOAD, {
1822				VarUint32::from(flags).serialize(writer)?;
1823				VarUint32::from(offset).serialize(writer)?;
1824			}),
1825			I64Load(flags, offset) => op!(writer, I64LOAD, {
1826				VarUint32::from(flags).serialize(writer)?;
1827				VarUint32::from(offset).serialize(writer)?;
1828			}),
1829			F32Load(flags, offset) => op!(writer, F32LOAD, {
1830				VarUint32::from(flags).serialize(writer)?;
1831				VarUint32::from(offset).serialize(writer)?;
1832			}),
1833			F64Load(flags, offset) => op!(writer, F64LOAD, {
1834				VarUint32::from(flags).serialize(writer)?;
1835				VarUint32::from(offset).serialize(writer)?;
1836			}),
1837			I32Load8S(flags, offset) => op!(writer, I32LOAD8S, {
1838				VarUint32::from(flags).serialize(writer)?;
1839				VarUint32::from(offset).serialize(writer)?;
1840			}),
1841			I32Load8U(flags, offset) => op!(writer, I32LOAD8U, {
1842				VarUint32::from(flags).serialize(writer)?;
1843				VarUint32::from(offset).serialize(writer)?;
1844			}),
1845			I32Load16S(flags, offset) => op!(writer, I32LOAD16S, {
1846				VarUint32::from(flags).serialize(writer)?;
1847				VarUint32::from(offset).serialize(writer)?;
1848			}),
1849			I32Load16U(flags, offset) => op!(writer, I32LOAD16U, {
1850				VarUint32::from(flags).serialize(writer)?;
1851				VarUint32::from(offset).serialize(writer)?;
1852			}),
1853			I64Load8S(flags, offset) => op!(writer, I64LOAD8S, {
1854				VarUint32::from(flags).serialize(writer)?;
1855				VarUint32::from(offset).serialize(writer)?;
1856			}),
1857			I64Load8U(flags, offset) => op!(writer, I64LOAD8U, {
1858				VarUint32::from(flags).serialize(writer)?;
1859				VarUint32::from(offset).serialize(writer)?;
1860			}),
1861			I64Load16S(flags, offset) => op!(writer, I64LOAD16S, {
1862				VarUint32::from(flags).serialize(writer)?;
1863				VarUint32::from(offset).serialize(writer)?;
1864			}),
1865			I64Load16U(flags, offset) => op!(writer, I64LOAD16U, {
1866				VarUint32::from(flags).serialize(writer)?;
1867				VarUint32::from(offset).serialize(writer)?;
1868			}),
1869			I64Load32S(flags, offset) => op!(writer, I64LOAD32S, {
1870				VarUint32::from(flags).serialize(writer)?;
1871				VarUint32::from(offset).serialize(writer)?;
1872			}),
1873			I64Load32U(flags, offset) => op!(writer, I64LOAD32U, {
1874				VarUint32::from(flags).serialize(writer)?;
1875				VarUint32::from(offset).serialize(writer)?;
1876			}),
1877			I32Store(flags, offset) => op!(writer, I32STORE, {
1878				VarUint32::from(flags).serialize(writer)?;
1879				VarUint32::from(offset).serialize(writer)?;
1880			}),
1881			I64Store(flags, offset) => op!(writer, I64STORE, {
1882				VarUint32::from(flags).serialize(writer)?;
1883				VarUint32::from(offset).serialize(writer)?;
1884			}),
1885			F32Store(flags, offset) => op!(writer, F32STORE, {
1886				VarUint32::from(flags).serialize(writer)?;
1887				VarUint32::from(offset).serialize(writer)?;
1888			}),
1889			F64Store(flags, offset) => op!(writer, F64STORE, {
1890				VarUint32::from(flags).serialize(writer)?;
1891				VarUint32::from(offset).serialize(writer)?;
1892			}),
1893			I32Store8(flags, offset) => op!(writer, I32STORE8, {
1894				VarUint32::from(flags).serialize(writer)?;
1895				VarUint32::from(offset).serialize(writer)?;
1896			}),
1897			I32Store16(flags, offset) => op!(writer, I32STORE16, {
1898				VarUint32::from(flags).serialize(writer)?;
1899				VarUint32::from(offset).serialize(writer)?;
1900			}),
1901			I64Store8(flags, offset) => op!(writer, I64STORE8, {
1902				VarUint32::from(flags).serialize(writer)?;
1903				VarUint32::from(offset).serialize(writer)?;
1904			}),
1905			I64Store16(flags, offset) => op!(writer, I64STORE16, {
1906				VarUint32::from(flags).serialize(writer)?;
1907				VarUint32::from(offset).serialize(writer)?;
1908			}),
1909			I64Store32(flags, offset) => op!(writer, I64STORE32, {
1910				VarUint32::from(flags).serialize(writer)?;
1911				VarUint32::from(offset).serialize(writer)?;
1912			}),
1913			CurrentMemory(flag) => op!(writer, CURRENTMEMORY, {
1914				Uint8::from(flag).serialize(writer)?;
1915			}),
1916			GrowMemory(flag) => op!(writer, GROWMEMORY, {
1917				Uint8::from(flag).serialize(writer)?;
1918			}),
1919			I32Const(def) => op!(writer, I32CONST, {
1920				VarInt32::from(def).serialize(writer)?;
1921			}),
1922			I64Const(def) => op!(writer, I64CONST, {
1923				VarInt64::from(def).serialize(writer)?;
1924			}),
1925			F32Const(def) => op!(writer, F32CONST, {
1926				Uint32::from(def).serialize(writer)?;
1927			}),
1928			F64Const(def) => op!(writer, F64CONST, {
1929				Uint64::from(def).serialize(writer)?;
1930			}),
1931			I32Eqz => op!(writer, I32EQZ),
1932			I32Eq => op!(writer, I32EQ),
1933			I32Ne => op!(writer, I32NE),
1934			I32LtS => op!(writer, I32LTS),
1935			I32LtU => op!(writer, I32LTU),
1936			I32GtS => op!(writer, I32GTS),
1937			I32GtU => op!(writer, I32GTU),
1938			I32LeS => op!(writer, I32LES),
1939			I32LeU => op!(writer, I32LEU),
1940			I32GeS => op!(writer, I32GES),
1941			I32GeU => op!(writer, I32GEU),
1942
1943			I64Eqz => op!(writer, I64EQZ),
1944			I64Eq => op!(writer, I64EQ),
1945			I64Ne => op!(writer, I64NE),
1946			I64LtS => op!(writer, I64LTS),
1947			I64LtU => op!(writer, I64LTU),
1948			I64GtS => op!(writer, I64GTS),
1949			I64GtU => op!(writer, I64GTU),
1950			I64LeS => op!(writer, I64LES),
1951			I64LeU => op!(writer, I64LEU),
1952			I64GeS => op!(writer, I64GES),
1953			I64GeU => op!(writer, I64GEU),
1954
1955			F32Eq => op!(writer, F32EQ),
1956			F32Ne => op!(writer, F32NE),
1957			F32Lt => op!(writer, F32LT),
1958			F32Gt => op!(writer, F32GT),
1959			F32Le => op!(writer, F32LE),
1960			F32Ge => op!(writer, F32GE),
1961
1962			F64Eq => op!(writer, F64EQ),
1963			F64Ne => op!(writer, F64NE),
1964			F64Lt => op!(writer, F64LT),
1965			F64Gt => op!(writer, F64GT),
1966			F64Le => op!(writer, F64LE),
1967			F64Ge => op!(writer, F64GE),
1968
1969			I32Clz => op!(writer, I32CLZ),
1970			I32Ctz => op!(writer, I32CTZ),
1971			I32Popcnt => op!(writer, I32POPCNT),
1972			I32Add => op!(writer, I32ADD),
1973			I32Sub => op!(writer, I32SUB),
1974			I32Mul => op!(writer, I32MUL),
1975			I32DivS => op!(writer, I32DIVS),
1976			I32DivU => op!(writer, I32DIVU),
1977			I32RemS => op!(writer, I32REMS),
1978			I32RemU => op!(writer, I32REMU),
1979			I32And => op!(writer, I32AND),
1980			I32Or => op!(writer, I32OR),
1981			I32Xor => op!(writer, I32XOR),
1982			I32Shl => op!(writer, I32SHL),
1983			I32ShrS => op!(writer, I32SHRS),
1984			I32ShrU => op!(writer, I32SHRU),
1985			I32Rotl => op!(writer, I32ROTL),
1986			I32Rotr => op!(writer, I32ROTR),
1987
1988			I64Clz => op!(writer, I64CLZ),
1989			I64Ctz => op!(writer, I64CTZ),
1990			I64Popcnt => op!(writer, I64POPCNT),
1991			I64Add => op!(writer, I64ADD),
1992			I64Sub => op!(writer, I64SUB),
1993			I64Mul => op!(writer, I64MUL),
1994			I64DivS => op!(writer, I64DIVS),
1995			I64DivU => op!(writer, I64DIVU),
1996			I64RemS => op!(writer, I64REMS),
1997			I64RemU => op!(writer, I64REMU),
1998			I64And => op!(writer, I64AND),
1999			I64Or => op!(writer, I64OR),
2000			I64Xor => op!(writer, I64XOR),
2001			I64Shl => op!(writer, I64SHL),
2002			I64ShrS => op!(writer, I64SHRS),
2003			I64ShrU => op!(writer, I64SHRU),
2004			I64Rotl => op!(writer, I64ROTL),
2005			I64Rotr => op!(writer, I64ROTR),
2006			F32Abs => op!(writer, F32ABS),
2007			F32Neg => op!(writer, F32NEG),
2008			F32Ceil => op!(writer, F32CEIL),
2009			F32Floor => op!(writer, F32FLOOR),
2010			F32Trunc => op!(writer, F32TRUNC),
2011			F32Nearest => op!(writer, F32NEAREST),
2012			F32Sqrt => op!(writer, F32SQRT),
2013			F32Add => op!(writer, F32ADD),
2014			F32Sub => op!(writer, F32SUB),
2015			F32Mul => op!(writer, F32MUL),
2016			F32Div => op!(writer, F32DIV),
2017			F32Min => op!(writer, F32MIN),
2018			F32Max => op!(writer, F32MAX),
2019			F32Copysign => op!(writer, F32COPYSIGN),
2020			F64Abs => op!(writer, F64ABS),
2021			F64Neg => op!(writer, F64NEG),
2022			F64Ceil => op!(writer, F64CEIL),
2023			F64Floor => op!(writer, F64FLOOR),
2024			F64Trunc => op!(writer, F64TRUNC),
2025			F64Nearest => op!(writer, F64NEAREST),
2026			F64Sqrt => op!(writer, F64SQRT),
2027			F64Add => op!(writer, F64ADD),
2028			F64Sub => op!(writer, F64SUB),
2029			F64Mul => op!(writer, F64MUL),
2030			F64Div => op!(writer, F64DIV),
2031			F64Min => op!(writer, F64MIN),
2032			F64Max => op!(writer, F64MAX),
2033			F64Copysign => op!(writer, F64COPYSIGN),
2034
2035			I32WrapI64 => op!(writer, I32WRAPI64),
2036			I32TruncSF32 => op!(writer, I32TRUNCSF32),
2037			I32TruncUF32 => op!(writer, I32TRUNCUF32),
2038			I32TruncSF64 => op!(writer, I32TRUNCSF64),
2039			I32TruncUF64 => op!(writer, I32TRUNCUF64),
2040			I64ExtendSI32 => op!(writer, I64EXTENDSI32),
2041			I64ExtendUI32 => op!(writer, I64EXTENDUI32),
2042			I64TruncSF32 => op!(writer, I64TRUNCSF32),
2043			I64TruncUF32 => op!(writer, I64TRUNCUF32),
2044			I64TruncSF64 => op!(writer, I64TRUNCSF64),
2045			I64TruncUF64 => op!(writer, I64TRUNCUF64),
2046			F32ConvertSI32 => op!(writer, F32CONVERTSI32),
2047			F32ConvertUI32 => op!(writer, F32CONVERTUI32),
2048			F32ConvertSI64 => op!(writer, F32CONVERTSI64),
2049			F32ConvertUI64 => op!(writer, F32CONVERTUI64),
2050			F32DemoteF64 => op!(writer, F32DEMOTEF64),
2051			F64ConvertSI32 => op!(writer, F64CONVERTSI32),
2052			F64ConvertUI32 => op!(writer, F64CONVERTUI32),
2053			F64ConvertSI64 => op!(writer, F64CONVERTSI64),
2054			F64ConvertUI64 => op!(writer, F64CONVERTUI64),
2055			F64PromoteF32 => op!(writer, F64PROMOTEF32),
2056
2057			I32ReinterpretF32 => op!(writer, I32REINTERPRETF32),
2058			I64ReinterpretF64 => op!(writer, I64REINTERPRETF64),
2059			F32ReinterpretI32 => op!(writer, F32REINTERPRETI32),
2060			F64ReinterpretI64 => op!(writer, F64REINTERPRETI64),
2061
2062			#[cfg(feature = "sign_ext")]
2063			SignExt(ref a) => match *a {
2064				SignExtInstruction::I32Extend8S => op!(writer, sign_ext::I32_EXTEND8_S),
2065				SignExtInstruction::I32Extend16S => op!(writer, sign_ext::I32_EXTEND16_S),
2066				SignExtInstruction::I64Extend8S => op!(writer, sign_ext::I64_EXTEND8_S),
2067				SignExtInstruction::I64Extend16S => op!(writer, sign_ext::I64_EXTEND16_S),
2068				SignExtInstruction::I64Extend32S => op!(writer, sign_ext::I64_EXTEND32_S),
2069			},
2070
2071			#[cfg(feature = "atomics")]
2072			Atomics(a) => return a.serialize(writer),
2073
2074			#[cfg(feature = "simd")]
2075			Simd(a) => return a.serialize(writer),
2076
2077			#[cfg(feature = "bulk")]
2078			Bulk(a) => return a.serialize(writer),
2079		}
2080
2081		Ok(())
2082	}
2083}
2084
2085#[cfg(feature = "atomics")]
2086impl Serialize for AtomicsInstruction {
2087	type Error = Error;
2088
2089	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2090		use self::{opcodes::atomics::*, AtomicsInstruction::*};
2091
2092		match self {
2093			AtomicWake(m) => atomic!(writer, ATOMIC_WAKE, m),
2094			I32AtomicWait(m) => atomic!(writer, I32_ATOMIC_WAIT, m),
2095			I64AtomicWait(m) => atomic!(writer, I64_ATOMIC_WAIT, m),
2096
2097			I32AtomicLoad(m) => atomic!(writer, I32_ATOMIC_LOAD, m),
2098			I64AtomicLoad(m) => atomic!(writer, I64_ATOMIC_LOAD, m),
2099			I32AtomicLoad8u(m) => atomic!(writer, I32_ATOMIC_LOAD8U, m),
2100			I32AtomicLoad16u(m) => atomic!(writer, I32_ATOMIC_LOAD16U, m),
2101			I64AtomicLoad8u(m) => atomic!(writer, I64_ATOMIC_LOAD8U, m),
2102			I64AtomicLoad16u(m) => atomic!(writer, I64_ATOMIC_LOAD16U, m),
2103			I64AtomicLoad32u(m) => atomic!(writer, I64_ATOMIC_LOAD32U, m),
2104			I32AtomicStore(m) => atomic!(writer, I32_ATOMIC_STORE, m),
2105			I64AtomicStore(m) => atomic!(writer, I64_ATOMIC_STORE, m),
2106			I32AtomicStore8u(m) => atomic!(writer, I32_ATOMIC_STORE8U, m),
2107			I32AtomicStore16u(m) => atomic!(writer, I32_ATOMIC_STORE16U, m),
2108			I64AtomicStore8u(m) => atomic!(writer, I64_ATOMIC_STORE8U, m),
2109			I64AtomicStore16u(m) => atomic!(writer, I64_ATOMIC_STORE16U, m),
2110			I64AtomicStore32u(m) => atomic!(writer, I64_ATOMIC_STORE32U, m),
2111
2112			I32AtomicRmwAdd(m) => atomic!(writer, I32_ATOMIC_RMW_ADD, m),
2113			I64AtomicRmwAdd(m) => atomic!(writer, I64_ATOMIC_RMW_ADD, m),
2114			I32AtomicRmwAdd8u(m) => atomic!(writer, I32_ATOMIC_RMW_ADD8U, m),
2115			I32AtomicRmwAdd16u(m) => atomic!(writer, I32_ATOMIC_RMW_ADD16U, m),
2116			I64AtomicRmwAdd8u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD8U, m),
2117			I64AtomicRmwAdd16u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD16U, m),
2118			I64AtomicRmwAdd32u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD32U, m),
2119
2120			I32AtomicRmwSub(m) => atomic!(writer, I32_ATOMIC_RMW_SUB, m),
2121			I64AtomicRmwSub(m) => atomic!(writer, I64_ATOMIC_RMW_SUB, m),
2122			I32AtomicRmwSub8u(m) => atomic!(writer, I32_ATOMIC_RMW_SUB8U, m),
2123			I32AtomicRmwSub16u(m) => atomic!(writer, I32_ATOMIC_RMW_SUB16U, m),
2124			I64AtomicRmwSub8u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB8U, m),
2125			I64AtomicRmwSub16u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB16U, m),
2126			I64AtomicRmwSub32u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB32U, m),
2127
2128			I32AtomicRmwAnd(m) => atomic!(writer, I32_ATOMIC_RMW_AND, m),
2129			I64AtomicRmwAnd(m) => atomic!(writer, I64_ATOMIC_RMW_AND, m),
2130			I32AtomicRmwAnd8u(m) => atomic!(writer, I32_ATOMIC_RMW_AND8U, m),
2131			I32AtomicRmwAnd16u(m) => atomic!(writer, I32_ATOMIC_RMW_AND16U, m),
2132			I64AtomicRmwAnd8u(m) => atomic!(writer, I64_ATOMIC_RMW_AND8U, m),
2133			I64AtomicRmwAnd16u(m) => atomic!(writer, I64_ATOMIC_RMW_AND16U, m),
2134			I64AtomicRmwAnd32u(m) => atomic!(writer, I64_ATOMIC_RMW_AND32U, m),
2135
2136			I32AtomicRmwOr(m) => atomic!(writer, I32_ATOMIC_RMW_OR, m),
2137			I64AtomicRmwOr(m) => atomic!(writer, I64_ATOMIC_RMW_OR, m),
2138			I32AtomicRmwOr8u(m) => atomic!(writer, I32_ATOMIC_RMW_OR8U, m),
2139			I32AtomicRmwOr16u(m) => atomic!(writer, I32_ATOMIC_RMW_OR16U, m),
2140			I64AtomicRmwOr8u(m) => atomic!(writer, I64_ATOMIC_RMW_OR8U, m),
2141			I64AtomicRmwOr16u(m) => atomic!(writer, I64_ATOMIC_RMW_OR16U, m),
2142			I64AtomicRmwOr32u(m) => atomic!(writer, I64_ATOMIC_RMW_OR32U, m),
2143
2144			I32AtomicRmwXor(m) => atomic!(writer, I32_ATOMIC_RMW_XOR, m),
2145			I64AtomicRmwXor(m) => atomic!(writer, I64_ATOMIC_RMW_XOR, m),
2146			I32AtomicRmwXor8u(m) => atomic!(writer, I32_ATOMIC_RMW_XOR8U, m),
2147			I32AtomicRmwXor16u(m) => atomic!(writer, I32_ATOMIC_RMW_XOR16U, m),
2148			I64AtomicRmwXor8u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR8U, m),
2149			I64AtomicRmwXor16u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR16U, m),
2150			I64AtomicRmwXor32u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR32U, m),
2151
2152			I32AtomicRmwXchg(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG, m),
2153			I64AtomicRmwXchg(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG, m),
2154			I32AtomicRmwXchg8u(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG8U, m),
2155			I32AtomicRmwXchg16u(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG16U, m),
2156			I64AtomicRmwXchg8u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG8U, m),
2157			I64AtomicRmwXchg16u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG16U, m),
2158			I64AtomicRmwXchg32u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG32U, m),
2159
2160			I32AtomicRmwCmpxchg(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG, m),
2161			I64AtomicRmwCmpxchg(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG, m),
2162			I32AtomicRmwCmpxchg8u(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG8U, m),
2163			I32AtomicRmwCmpxchg16u(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG16U, m),
2164			I64AtomicRmwCmpxchg8u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG8U, m),
2165			I64AtomicRmwCmpxchg16u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG16U, m),
2166			I64AtomicRmwCmpxchg32u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG32U, m),
2167		}
2168
2169		Ok(())
2170	}
2171}
2172
2173#[cfg(feature = "simd")]
2174impl Serialize for SimdInstruction {
2175	type Error = Error;
2176
2177	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2178		use self::{opcodes::simd::*, SimdInstruction::*};
2179
2180		match self {
2181			V128Const(ref c) => simd!(writer, V128_CONST, writer.write(&c[..])?),
2182			V128Load(m) => simd!(writer, V128_LOAD, MemArg::serialize(m, writer)?),
2183			V128Store(m) => simd!(writer, V128_STORE, MemArg::serialize(m, writer)?),
2184			I8x16Splat => simd!(writer, I8X16_SPLAT, {}),
2185			I16x8Splat => simd!(writer, I16X8_SPLAT, {}),
2186			I32x4Splat => simd!(writer, I32X4_SPLAT, {}),
2187			I64x2Splat => simd!(writer, I64X2_SPLAT, {}),
2188			F32x4Splat => simd!(writer, F32X4_SPLAT, {}),
2189			F64x2Splat => simd!(writer, F64X2_SPLAT, {}),
2190			I8x16ExtractLaneS(i) => simd!(writer, I8X16_EXTRACT_LANE_S, writer.write(&[i])?),
2191			I8x16ExtractLaneU(i) => simd!(writer, I8X16_EXTRACT_LANE_U, writer.write(&[i])?),
2192			I16x8ExtractLaneS(i) => simd!(writer, I16X8_EXTRACT_LANE_S, writer.write(&[i])?),
2193			I16x8ExtractLaneU(i) => simd!(writer, I16X8_EXTRACT_LANE_U, writer.write(&[i])?),
2194			I32x4ExtractLane(i) => simd!(writer, I32X4_EXTRACT_LANE, writer.write(&[i])?),
2195			I64x2ExtractLane(i) => simd!(writer, I64X2_EXTRACT_LANE, writer.write(&[i])?),
2196			F32x4ExtractLane(i) => simd!(writer, F32X4_EXTRACT_LANE, writer.write(&[i])?),
2197			F64x2ExtractLane(i) => simd!(writer, F64X2_EXTRACT_LANE, writer.write(&[i])?),
2198			I8x16ReplaceLane(i) => simd!(writer, I8X16_REPLACE_LANE, writer.write(&[i])?),
2199			I16x8ReplaceLane(i) => simd!(writer, I16X8_REPLACE_LANE, writer.write(&[i])?),
2200			I32x4ReplaceLane(i) => simd!(writer, I32X4_REPLACE_LANE, writer.write(&[i])?),
2201			I64x2ReplaceLane(i) => simd!(writer, I64X2_REPLACE_LANE, writer.write(&[i])?),
2202			F32x4ReplaceLane(i) => simd!(writer, F32X4_REPLACE_LANE, writer.write(&[i])?),
2203			F64x2ReplaceLane(i) => simd!(writer, F64X2_REPLACE_LANE, writer.write(&[i])?),
2204			V8x16Shuffle(ref i) => simd!(writer, V8X16_SHUFFLE, writer.write(&i[..])?),
2205			I8x16Add => simd!(writer, I8X16_ADD, {}),
2206			I16x8Add => simd!(writer, I16X8_ADD, {}),
2207			I32x4Add => simd!(writer, I32X4_ADD, {}),
2208			I64x2Add => simd!(writer, I64X2_ADD, {}),
2209			I8x16Sub => simd!(writer, I8X16_SUB, {}),
2210			I16x8Sub => simd!(writer, I16X8_SUB, {}),
2211			I32x4Sub => simd!(writer, I32X4_SUB, {}),
2212			I64x2Sub => simd!(writer, I64X2_SUB, {}),
2213			I8x16Mul => simd!(writer, I8X16_MUL, {}),
2214			I16x8Mul => simd!(writer, I16X8_MUL, {}),
2215			I32x4Mul => simd!(writer, I32X4_MUL, {}),
2216			// I64x2Mul => simd!(writer, I64X2_MUL, {}),
2217			I8x16Neg => simd!(writer, I8X16_NEG, {}),
2218			I16x8Neg => simd!(writer, I16X8_NEG, {}),
2219			I32x4Neg => simd!(writer, I32X4_NEG, {}),
2220			I64x2Neg => simd!(writer, I64X2_NEG, {}),
2221			I8x16AddSaturateS => simd!(writer, I8X16_ADD_SATURATE_S, {}),
2222			I8x16AddSaturateU => simd!(writer, I8X16_ADD_SATURATE_U, {}),
2223			I16x8AddSaturateS => simd!(writer, I16X8_ADD_SATURATE_S, {}),
2224			I16x8AddSaturateU => simd!(writer, I16X8_ADD_SATURATE_U, {}),
2225			I8x16SubSaturateS => simd!(writer, I8X16_SUB_SATURATE_S, {}),
2226			I8x16SubSaturateU => simd!(writer, I8X16_SUB_SATURATE_U, {}),
2227			I16x8SubSaturateS => simd!(writer, I16X8_SUB_SATURATE_S, {}),
2228			I16x8SubSaturateU => simd!(writer, I16X8_SUB_SATURATE_U, {}),
2229			I8x16Shl => simd!(writer, I8X16_SHL, {}),
2230			I16x8Shl => simd!(writer, I16X8_SHL, {}),
2231			I32x4Shl => simd!(writer, I32X4_SHL, {}),
2232			I64x2Shl => simd!(writer, I64X2_SHL, {}),
2233			I8x16ShrS => simd!(writer, I8X16_SHR_S, {}),
2234			I8x16ShrU => simd!(writer, I8X16_SHR_U, {}),
2235			I16x8ShrS => simd!(writer, I16X8_SHR_S, {}),
2236			I16x8ShrU => simd!(writer, I16X8_SHR_U, {}),
2237			I32x4ShrU => simd!(writer, I32X4_SHR_U, {}),
2238			I32x4ShrS => simd!(writer, I32X4_SHR_S, {}),
2239			I64x2ShrU => simd!(writer, I64X2_SHR_U, {}),
2240			I64x2ShrS => simd!(writer, I64X2_SHR_S, {}),
2241			V128And => simd!(writer, V128_AND, {}),
2242			V128Or => simd!(writer, V128_OR, {}),
2243			V128Xor => simd!(writer, V128_XOR, {}),
2244			V128Not => simd!(writer, V128_NOT, {}),
2245			V128Bitselect => simd!(writer, V128_BITSELECT, {}),
2246			I8x16AnyTrue => simd!(writer, I8X16_ANY_TRUE, {}),
2247			I16x8AnyTrue => simd!(writer, I16X8_ANY_TRUE, {}),
2248			I32x4AnyTrue => simd!(writer, I32X4_ANY_TRUE, {}),
2249			I64x2AnyTrue => simd!(writer, I64X2_ANY_TRUE, {}),
2250			I8x16AllTrue => simd!(writer, I8X16_ALL_TRUE, {}),
2251			I16x8AllTrue => simd!(writer, I16X8_ALL_TRUE, {}),
2252			I32x4AllTrue => simd!(writer, I32X4_ALL_TRUE, {}),
2253			I64x2AllTrue => simd!(writer, I64X2_ALL_TRUE, {}),
2254			I8x16Eq => simd!(writer, I8X16_EQ, {}),
2255			I16x8Eq => simd!(writer, I16X8_EQ, {}),
2256			I32x4Eq => simd!(writer, I32X4_EQ, {}),
2257			// I64x2Eq => simd!(writer, I64X2_EQ, {}),
2258			F32x4Eq => simd!(writer, F32X4_EQ, {}),
2259			F64x2Eq => simd!(writer, F64X2_EQ, {}),
2260			I8x16Ne => simd!(writer, I8X16_NE, {}),
2261			I16x8Ne => simd!(writer, I16X8_NE, {}),
2262			I32x4Ne => simd!(writer, I32X4_NE, {}),
2263			// I64x2Ne => simd!(writer, I64X2_NE, {}),
2264			F32x4Ne => simd!(writer, F32X4_NE, {}),
2265			F64x2Ne => simd!(writer, F64X2_NE, {}),
2266			I8x16LtS => simd!(writer, I8X16_LT_S, {}),
2267			I8x16LtU => simd!(writer, I8X16_LT_U, {}),
2268			I16x8LtS => simd!(writer, I16X8_LT_S, {}),
2269			I16x8LtU => simd!(writer, I16X8_LT_U, {}),
2270			I32x4LtS => simd!(writer, I32X4_LT_S, {}),
2271			I32x4LtU => simd!(writer, I32X4_LT_U, {}),
2272			// I64x2LtS => simd!(writer, I64X2_LT_S, {}),
2273			// I64x2LtU => simd!(writer, I64X2_LT_U, {}),
2274			F32x4Lt => simd!(writer, F32X4_LT, {}),
2275			F64x2Lt => simd!(writer, F64X2_LT, {}),
2276			I8x16LeS => simd!(writer, I8X16_LE_S, {}),
2277			I8x16LeU => simd!(writer, I8X16_LE_U, {}),
2278			I16x8LeS => simd!(writer, I16X8_LE_S, {}),
2279			I16x8LeU => simd!(writer, I16X8_LE_U, {}),
2280			I32x4LeS => simd!(writer, I32X4_LE_S, {}),
2281			I32x4LeU => simd!(writer, I32X4_LE_U, {}),
2282			// I64x2LeS => simd!(writer, I64X2_LE_S, {}),
2283			// I64x2LeU => simd!(writer, I64X2_LE_U, {}),
2284			F32x4Le => simd!(writer, F32X4_LE, {}),
2285			F64x2Le => simd!(writer, F64X2_LE, {}),
2286			I8x16GtS => simd!(writer, I8X16_GT_S, {}),
2287			I8x16GtU => simd!(writer, I8X16_GT_U, {}),
2288			I16x8GtS => simd!(writer, I16X8_GT_S, {}),
2289			I16x8GtU => simd!(writer, I16X8_GT_U, {}),
2290			I32x4GtS => simd!(writer, I32X4_GT_S, {}),
2291			I32x4GtU => simd!(writer, I32X4_GT_U, {}),
2292			// I64x2GtS => simd!(writer, I64X2_GT_S, {}),
2293			// I64x2GtU => simd!(writer, I64X2_GT_U, {}),
2294			F32x4Gt => simd!(writer, F32X4_GT, {}),
2295			F64x2Gt => simd!(writer, F64X2_GT, {}),
2296			I8x16GeS => simd!(writer, I8X16_GE_S, {}),
2297			I8x16GeU => simd!(writer, I8X16_GE_U, {}),
2298			I16x8GeS => simd!(writer, I16X8_GE_S, {}),
2299			I16x8GeU => simd!(writer, I16X8_GE_U, {}),
2300			I32x4GeS => simd!(writer, I32X4_GE_S, {}),
2301			I32x4GeU => simd!(writer, I32X4_GE_U, {}),
2302			// I64x2GeS => simd!(writer, I64X2_GE_S, {}),
2303			// I64x2GeU => simd!(writer, I64X2_GE_U, {}),
2304			F32x4Ge => simd!(writer, F32X4_GE, {}),
2305			F64x2Ge => simd!(writer, F64X2_GE, {}),
2306			F32x4Neg => simd!(writer, F32X4_NEG, {}),
2307			F64x2Neg => simd!(writer, F64X2_NEG, {}),
2308			F32x4Abs => simd!(writer, F32X4_ABS, {}),
2309			F64x2Abs => simd!(writer, F64X2_ABS, {}),
2310			F32x4Min => simd!(writer, F32X4_MIN, {}),
2311			F64x2Min => simd!(writer, F64X2_MIN, {}),
2312			F32x4Max => simd!(writer, F32X4_MAX, {}),
2313			F64x2Max => simd!(writer, F64X2_MAX, {}),
2314			F32x4Add => simd!(writer, F32X4_ADD, {}),
2315			F64x2Add => simd!(writer, F64X2_ADD, {}),
2316			F32x4Sub => simd!(writer, F32X4_SUB, {}),
2317			F64x2Sub => simd!(writer, F64X2_SUB, {}),
2318			F32x4Div => simd!(writer, F32X4_DIV, {}),
2319			F64x2Div => simd!(writer, F64X2_DIV, {}),
2320			F32x4Mul => simd!(writer, F32X4_MUL, {}),
2321			F64x2Mul => simd!(writer, F64X2_MUL, {}),
2322			F32x4Sqrt => simd!(writer, F32X4_SQRT, {}),
2323			F64x2Sqrt => simd!(writer, F64X2_SQRT, {}),
2324			F32x4ConvertSI32x4 => simd!(writer, F32X4_CONVERT_S_I32X4, {}),
2325			F32x4ConvertUI32x4 => simd!(writer, F32X4_CONVERT_U_I32X4, {}),
2326			F64x2ConvertSI64x2 => simd!(writer, F64X2_CONVERT_S_I64X2, {}),
2327			F64x2ConvertUI64x2 => simd!(writer, F64X2_CONVERT_U_I64X2, {}),
2328			I32x4TruncSF32x4Sat => simd!(writer, I32X4_TRUNC_S_F32X4_SAT, {}),
2329			I32x4TruncUF32x4Sat => simd!(writer, I32X4_TRUNC_U_F32X4_SAT, {}),
2330			I64x2TruncSF64x2Sat => simd!(writer, I64X2_TRUNC_S_F64X2_SAT, {}),
2331			I64x2TruncUF64x2Sat => simd!(writer, I64X2_TRUNC_U_F64X2_SAT, {}),
2332		}
2333
2334		Ok(())
2335	}
2336}
2337
2338#[cfg(feature = "bulk")]
2339impl Serialize for BulkInstruction {
2340	type Error = Error;
2341
2342	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2343		use self::{opcodes::bulk::*, BulkInstruction::*};
2344
2345		match self {
2346			MemoryInit(seg) => bulk!(writer, MEMORY_INIT, {
2347				Uint8::from(0).serialize(writer)?;
2348				VarUint32::from(seg).serialize(writer)?;
2349			}),
2350			MemoryDrop(seg) => bulk!(writer, MEMORY_DROP, VarUint32::from(seg).serialize(writer)?),
2351			MemoryFill => bulk!(writer, MEMORY_FILL, Uint8::from(0).serialize(writer)?),
2352			MemoryCopy => bulk!(writer, MEMORY_COPY, Uint8::from(0).serialize(writer)?),
2353			TableInit(seg) => bulk!(writer, TABLE_INIT, {
2354				Uint8::from(0).serialize(writer)?;
2355				VarUint32::from(seg).serialize(writer)?;
2356			}),
2357			TableDrop(seg) => bulk!(writer, TABLE_DROP, VarUint32::from(seg).serialize(writer)?),
2358			TableCopy => bulk!(writer, TABLE_COPY, Uint8::from(0).serialize(writer)?),
2359		}
2360
2361		Ok(())
2362	}
2363}
2364
2365#[cfg(any(feature = "simd", feature = "atomics"))]
2366impl Serialize for MemArg {
2367	type Error = Error;
2368
2369	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2370		Uint8::from(self.align).serialize(writer)?;
2371		VarUint32::from(self.offset).serialize(writer)?;
2372		Ok(())
2373	}
2374}
2375
2376macro_rules! fmt_op {
2377	($f: expr, $mnemonic: expr) => {{
2378		write!($f, "{}", $mnemonic)
2379	}};
2380	($f: expr, $mnemonic: expr, $immediate: expr) => {{
2381		write!($f, "{} {}", $mnemonic, $immediate)
2382	}};
2383	($f: expr, $mnemonic: expr, $immediate1: expr, $immediate2: expr) => {{
2384		write!($f, "{} {} {}", $mnemonic, $immediate1, $immediate2)
2385	}};
2386}
2387
2388impl fmt::Display for Instruction {
2389	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2390		use self::Instruction::*;
2391
2392		match *self {
2393			Unreachable => fmt_op!(f, "unreachable"),
2394			Nop => fmt_op!(f, "nop"),
2395			Block(BlockType::NoResult) => fmt_op!(f, "block"),
2396			Block(BlockType::Value(value_type)) => fmt_op!(f, "block", value_type),
2397			#[cfg(feature = "multi_value")]
2398			Block(BlockType::TypeIndex(idx)) => write!(f, "block type_idx={}", idx),
2399			Loop(BlockType::NoResult) => fmt_op!(f, "loop"),
2400			Loop(BlockType::Value(value_type)) => fmt_op!(f, "loop", value_type),
2401			#[cfg(feature = "multi_value")]
2402			Loop(BlockType::TypeIndex(idx)) => write!(f, "loop type_idx={}", idx),
2403			If(BlockType::NoResult) => fmt_op!(f, "if"),
2404			If(BlockType::Value(value_type)) => fmt_op!(f, "if", value_type),
2405			#[cfg(feature = "multi_value")]
2406			If(BlockType::TypeIndex(idx)) => write!(f, "if type_idx={}", idx),
2407			Else => fmt_op!(f, "else"),
2408			End => fmt_op!(f, "end"),
2409			Br(idx) => fmt_op!(f, "br", idx),
2410			BrIf(idx) => fmt_op!(f, "br_if", idx),
2411			BrTable(ref table) => fmt_op!(f, "br_table", table.default),
2412			Return => fmt_op!(f, "return"),
2413			Call(index) => fmt_op!(f, "call", index),
2414			CallIndirect(index, _) => fmt_op!(f, "call_indirect", index),
2415			Drop => fmt_op!(f, "drop"),
2416			Select => fmt_op!(f, "select"),
2417			GetLocal(index) => fmt_op!(f, "get_local", index),
2418			SetLocal(index) => fmt_op!(f, "set_local", index),
2419			TeeLocal(index) => fmt_op!(f, "tee_local", index),
2420			GetGlobal(index) => fmt_op!(f, "get_global", index),
2421			SetGlobal(index) => fmt_op!(f, "set_global", index),
2422
2423			I32Load(_, 0) => write!(f, "i32.load"),
2424			I32Load(_, offset) => write!(f, "i32.load offset={}", offset),
2425
2426			I64Load(_, 0) => write!(f, "i64.load"),
2427			I64Load(_, offset) => write!(f, "i64.load offset={}", offset),
2428
2429			F32Load(_, 0) => write!(f, "f32.load"),
2430			F32Load(_, offset) => write!(f, "f32.load offset={}", offset),
2431
2432			F64Load(_, 0) => write!(f, "f64.load"),
2433			F64Load(_, offset) => write!(f, "f64.load offset={}", offset),
2434
2435			I32Load8S(_, 0) => write!(f, "i32.load8_s"),
2436			I32Load8S(_, offset) => write!(f, "i32.load8_s offset={}", offset),
2437
2438			I32Load8U(_, 0) => write!(f, "i32.load8_u"),
2439			I32Load8U(_, offset) => write!(f, "i32.load8_u offset={}", offset),
2440
2441			I32Load16S(_, 0) => write!(f, "i32.load16_s"),
2442			I32Load16S(_, offset) => write!(f, "i32.load16_s offset={}", offset),
2443
2444			I32Load16U(_, 0) => write!(f, "i32.load16_u"),
2445			I32Load16U(_, offset) => write!(f, "i32.load16_u offset={}", offset),
2446
2447			I64Load8S(_, 0) => write!(f, "i64.load8_s"),
2448			I64Load8S(_, offset) => write!(f, "i64.load8_s offset={}", offset),
2449
2450			I64Load8U(_, 0) => write!(f, "i64.load8_u"),
2451			I64Load8U(_, offset) => write!(f, "i64.load8_u offset={}", offset),
2452
2453			I64Load16S(_, 0) => write!(f, "i64.load16_s"),
2454			I64Load16S(_, offset) => write!(f, "i64.load16_s offset={}", offset),
2455
2456			I64Load16U(_, 0) => write!(f, "i64.load16_u"),
2457			I64Load16U(_, offset) => write!(f, "i64.load16_u offset={}", offset),
2458
2459			I64Load32S(_, 0) => write!(f, "i64.load32_s"),
2460			I64Load32S(_, offset) => write!(f, "i64.load32_s offset={}", offset),
2461
2462			I64Load32U(_, 0) => write!(f, "i64.load32_u"),
2463			I64Load32U(_, offset) => write!(f, "i64.load32_u offset={}", offset),
2464
2465			I32Store(_, 0) => write!(f, "i32.store"),
2466			I32Store(_, offset) => write!(f, "i32.store offset={}", offset),
2467
2468			I64Store(_, 0) => write!(f, "i64.store"),
2469			I64Store(_, offset) => write!(f, "i64.store offset={}", offset),
2470
2471			F32Store(_, 0) => write!(f, "f32.store"),
2472			F32Store(_, offset) => write!(f, "f32.store offset={}", offset),
2473
2474			F64Store(_, 0) => write!(f, "f64.store"),
2475			F64Store(_, offset) => write!(f, "f64.store offset={}", offset),
2476
2477			I32Store8(_, 0) => write!(f, "i32.store8"),
2478			I32Store8(_, offset) => write!(f, "i32.store8 offset={}", offset),
2479
2480			I32Store16(_, 0) => write!(f, "i32.store16"),
2481			I32Store16(_, offset) => write!(f, "i32.store16 offset={}", offset),
2482
2483			I64Store8(_, 0) => write!(f, "i64.store8"),
2484			I64Store8(_, offset) => write!(f, "i64.store8 offset={}", offset),
2485
2486			I64Store16(_, 0) => write!(f, "i64.store16"),
2487			I64Store16(_, offset) => write!(f, "i64.store16 offset={}", offset),
2488
2489			I64Store32(_, 0) => write!(f, "i64.store32"),
2490			I64Store32(_, offset) => write!(f, "i64.store32 offset={}", offset),
2491
2492			CurrentMemory(_) => fmt_op!(f, "current_memory"),
2493			GrowMemory(_) => fmt_op!(f, "grow_memory"),
2494
2495			I32Const(def) => fmt_op!(f, "i32.const", def),
2496			I64Const(def) => fmt_op!(f, "i64.const", def),
2497			F32Const(def) => fmt_op!(f, "f32.const", def),
2498			F64Const(def) => fmt_op!(f, "f64.const", def),
2499
2500			I32Eq => write!(f, "i32.eq"),
2501			I32Eqz => write!(f, "i32.eqz"),
2502			I32Ne => write!(f, "i32.ne"),
2503			I32LtS => write!(f, "i32.lt_s"),
2504			I32LtU => write!(f, "i32.lt_u"),
2505			I32GtS => write!(f, "i32.gt_s"),
2506			I32GtU => write!(f, "i32.gt_u"),
2507			I32LeS => write!(f, "i32.le_s"),
2508			I32LeU => write!(f, "i32.le_u"),
2509			I32GeS => write!(f, "i32.ge_s"),
2510			I32GeU => write!(f, "i32.ge_u"),
2511
2512			I64Eq => write!(f, "i64.eq"),
2513			I64Eqz => write!(f, "i64.eqz"),
2514			I64Ne => write!(f, "i64.ne"),
2515			I64LtS => write!(f, "i64.lt_s"),
2516			I64LtU => write!(f, "i64.lt_u"),
2517			I64GtS => write!(f, "i64.gt_s"),
2518			I64GtU => write!(f, "i64.gt_u"),
2519			I64LeS => write!(f, "i64.le_s"),
2520			I64LeU => write!(f, "i64.le_u"),
2521			I64GeS => write!(f, "i64.ge_s"),
2522			I64GeU => write!(f, "i64.ge_u"),
2523
2524			F32Eq => write!(f, "f32.eq"),
2525			F32Ne => write!(f, "f32.ne"),
2526			F32Lt => write!(f, "f32.lt"),
2527			F32Gt => write!(f, "f32.gt"),
2528			F32Le => write!(f, "f32.le"),
2529			F32Ge => write!(f, "f32.ge"),
2530
2531			F64Eq => write!(f, "f64.eq"),
2532			F64Ne => write!(f, "f64.ne"),
2533			F64Lt => write!(f, "f64.lt"),
2534			F64Gt => write!(f, "f64.gt"),
2535			F64Le => write!(f, "f64.le"),
2536			F64Ge => write!(f, "f64.ge"),
2537
2538			I32Clz => write!(f, "i32.clz"),
2539			I32Ctz => write!(f, "i32.ctz"),
2540			I32Popcnt => write!(f, "i32.popcnt"),
2541			I32Add => write!(f, "i32.add"),
2542			I32Sub => write!(f, "i32.sub"),
2543			I32Mul => write!(f, "i32.mul"),
2544			I32DivS => write!(f, "i32.div_s"),
2545			I32DivU => write!(f, "i32.div_u"),
2546			I32RemS => write!(f, "i32.rem_s"),
2547			I32RemU => write!(f, "i32.rem_u"),
2548			I32And => write!(f, "i32.and"),
2549			I32Or => write!(f, "i32.or"),
2550			I32Xor => write!(f, "i32.xor"),
2551			I32Shl => write!(f, "i32.shl"),
2552			I32ShrS => write!(f, "i32.shr_s"),
2553			I32ShrU => write!(f, "i32.shr_u"),
2554			I32Rotl => write!(f, "i32.rotl"),
2555			I32Rotr => write!(f, "i32.rotr"),
2556
2557			I64Clz => write!(f, "i64.clz"),
2558			I64Ctz => write!(f, "i64.ctz"),
2559			I64Popcnt => write!(f, "i64.popcnt"),
2560			I64Add => write!(f, "i64.add"),
2561			I64Sub => write!(f, "i64.sub"),
2562			I64Mul => write!(f, "i64.mul"),
2563			I64DivS => write!(f, "i64.div_s"),
2564			I64DivU => write!(f, "i64.div_u"),
2565			I64RemS => write!(f, "i64.rem_s"),
2566			I64RemU => write!(f, "i64.rem_u"),
2567			I64And => write!(f, "i64.and"),
2568			I64Or => write!(f, "i64.or"),
2569			I64Xor => write!(f, "i64.xor"),
2570			I64Shl => write!(f, "i64.shl"),
2571			I64ShrS => write!(f, "i64.shr_s"),
2572			I64ShrU => write!(f, "i64.shr_u"),
2573			I64Rotl => write!(f, "i64.rotl"),
2574			I64Rotr => write!(f, "i64.rotr"),
2575
2576			F32Abs => write!(f, "f32.abs"),
2577			F32Neg => write!(f, "f32.neg"),
2578			F32Ceil => write!(f, "f32.ceil"),
2579			F32Floor => write!(f, "f32.floor"),
2580			F32Trunc => write!(f, "f32.trunc"),
2581			F32Nearest => write!(f, "f32.nearest"),
2582			F32Sqrt => write!(f, "f32.sqrt"),
2583			F32Add => write!(f, "f32.add"),
2584			F32Sub => write!(f, "f32.sub"),
2585			F32Mul => write!(f, "f32.mul"),
2586			F32Div => write!(f, "f32.div"),
2587			F32Min => write!(f, "f32.min"),
2588			F32Max => write!(f, "f32.max"),
2589			F32Copysign => write!(f, "f32.copysign"),
2590
2591			F64Abs => write!(f, "f64.abs"),
2592			F64Neg => write!(f, "f64.neg"),
2593			F64Ceil => write!(f, "f64.ceil"),
2594			F64Floor => write!(f, "f64.floor"),
2595			F64Trunc => write!(f, "f64.trunc"),
2596			F64Nearest => write!(f, "f64.nearest"),
2597			F64Sqrt => write!(f, "f64.sqrt"),
2598			F64Add => write!(f, "f64.add"),
2599			F64Sub => write!(f, "f64.sub"),
2600			F64Mul => write!(f, "f64.mul"),
2601			F64Div => write!(f, "f64.div"),
2602			F64Min => write!(f, "f64.min"),
2603			F64Max => write!(f, "f64.max"),
2604			F64Copysign => write!(f, "f64.copysign"),
2605
2606			I32WrapI64 => write!(f, "i32.wrap/i64"),
2607			I32TruncSF32 => write!(f, "i32.trunc_s/f32"),
2608			I32TruncUF32 => write!(f, "i32.trunc_u/f32"),
2609			I32TruncSF64 => write!(f, "i32.trunc_s/f64"),
2610			I32TruncUF64 => write!(f, "i32.trunc_u/f64"),
2611
2612			I64ExtendSI32 => write!(f, "i64.extend_s/i32"),
2613			I64ExtendUI32 => write!(f, "i64.extend_u/i32"),
2614
2615			I64TruncSF32 => write!(f, "i64.trunc_s/f32"),
2616			I64TruncUF32 => write!(f, "i64.trunc_u/f32"),
2617			I64TruncSF64 => write!(f, "i64.trunc_s/f64"),
2618			I64TruncUF64 => write!(f, "i64.trunc_u/f64"),
2619
2620			F32ConvertSI32 => write!(f, "f32.convert_s/i32"),
2621			F32ConvertUI32 => write!(f, "f32.convert_u/i32"),
2622			F32ConvertSI64 => write!(f, "f32.convert_s/i64"),
2623			F32ConvertUI64 => write!(f, "f32.convert_u/i64"),
2624			F32DemoteF64 => write!(f, "f32.demote/f64"),
2625
2626			F64ConvertSI32 => write!(f, "f64.convert_s/i32"),
2627			F64ConvertUI32 => write!(f, "f64.convert_u/i32"),
2628			F64ConvertSI64 => write!(f, "f64.convert_s/i64"),
2629			F64ConvertUI64 => write!(f, "f64.convert_u/i64"),
2630			F64PromoteF32 => write!(f, "f64.promote/f32"),
2631
2632			I32ReinterpretF32 => write!(f, "i32.reinterpret/f32"),
2633			I64ReinterpretF64 => write!(f, "i64.reinterpret/f64"),
2634			F32ReinterpretI32 => write!(f, "f32.reinterpret/i32"),
2635			F64ReinterpretI64 => write!(f, "f64.reinterpret/i64"),
2636
2637			#[cfg(feature = "sign_ext")]
2638			SignExt(ref i) => match i {
2639				SignExtInstruction::I32Extend8S => write!(f, "i32.extend8_s"),
2640				SignExtInstruction::I32Extend16S => write!(f, "i32.extend16_s"),
2641				SignExtInstruction::I64Extend8S => write!(f, "i64.extend8_s"),
2642				SignExtInstruction::I64Extend16S => write!(f, "i64.extend16_s"),
2643				SignExtInstruction::I64Extend32S => write!(f, "i64.extend32_s"),
2644			},
2645
2646			#[cfg(feature = "atomics")]
2647			Atomics(ref i) => i.fmt(f),
2648
2649			#[cfg(feature = "simd")]
2650			Simd(ref i) => i.fmt(f),
2651
2652			#[cfg(feature = "bulk")]
2653			Bulk(ref i) => i.fmt(f),
2654		}
2655	}
2656}
2657
2658#[cfg(feature = "atomics")]
2659impl fmt::Display for AtomicsInstruction {
2660	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2661		use self::AtomicsInstruction::*;
2662
2663		match *self {
2664			AtomicWake(_) => write!(f, "atomic.wake"),
2665			I32AtomicWait(_) => write!(f, "i32.atomic.wait"),
2666			I64AtomicWait(_) => write!(f, "i64.atomic.wait"),
2667
2668			I32AtomicLoad(_) => write!(f, "i32.atomic.load"),
2669			I64AtomicLoad(_) => write!(f, "i64.atomic.load"),
2670			I32AtomicLoad8u(_) => write!(f, "i32.atomic.load8_u"),
2671			I32AtomicLoad16u(_) => write!(f, "i32.atomic.load16_u"),
2672			I64AtomicLoad8u(_) => write!(f, "i64.atomic.load8_u"),
2673			I64AtomicLoad16u(_) => write!(f, "i64.atomic.load16_u"),
2674			I64AtomicLoad32u(_) => write!(f, "i64.atomic.load32_u"),
2675			I32AtomicStore(_) => write!(f, "i32.atomic.store"),
2676			I64AtomicStore(_) => write!(f, "i64.atomic.store"),
2677			I32AtomicStore8u(_) => write!(f, "i32.atomic.store8_u"),
2678			I32AtomicStore16u(_) => write!(f, "i32.atomic.store16_u"),
2679			I64AtomicStore8u(_) => write!(f, "i64.atomic.store8_u"),
2680			I64AtomicStore16u(_) => write!(f, "i64.atomic.store16_u"),
2681			I64AtomicStore32u(_) => write!(f, "i64.atomic.store32_u"),
2682
2683			I32AtomicRmwAdd(_) => write!(f, "i32.atomic.rmw.add"),
2684			I64AtomicRmwAdd(_) => write!(f, "i64.atomic.rmw.add"),
2685			I32AtomicRmwAdd8u(_) => write!(f, "i32.atomic.rmw8_u.add"),
2686			I32AtomicRmwAdd16u(_) => write!(f, "i32.atomic.rmw16_u.add"),
2687			I64AtomicRmwAdd8u(_) => write!(f, "i64.atomic.rmw8_u.add"),
2688			I64AtomicRmwAdd16u(_) => write!(f, "i64.atomic.rmw16_u.add"),
2689			I64AtomicRmwAdd32u(_) => write!(f, "i64.atomic.rmw32_u.add"),
2690
2691			I32AtomicRmwSub(_) => write!(f, "i32.atomic.rmw.sub"),
2692			I64AtomicRmwSub(_) => write!(f, "i64.atomic.rmw.sub"),
2693			I32AtomicRmwSub8u(_) => write!(f, "i32.atomic.rmw8_u.sub"),
2694			I32AtomicRmwSub16u(_) => write!(f, "i32.atomic.rmw16_u.sub"),
2695			I64AtomicRmwSub8u(_) => write!(f, "i64.atomic.rmw8_u.sub"),
2696			I64AtomicRmwSub16u(_) => write!(f, "i64.atomic.rmw16_u.sub"),
2697			I64AtomicRmwSub32u(_) => write!(f, "i64.atomic.rmw32_u.sub"),
2698
2699			I32AtomicRmwAnd(_) => write!(f, "i32.atomic.rmw.and"),
2700			I64AtomicRmwAnd(_) => write!(f, "i64.atomic.rmw.and"),
2701			I32AtomicRmwAnd8u(_) => write!(f, "i32.atomic.rmw8_u.and"),
2702			I32AtomicRmwAnd16u(_) => write!(f, "i32.atomic.rmw16_u.and"),
2703			I64AtomicRmwAnd8u(_) => write!(f, "i64.atomic.rmw8_u.and"),
2704			I64AtomicRmwAnd16u(_) => write!(f, "i64.atomic.rmw16_u.and"),
2705			I64AtomicRmwAnd32u(_) => write!(f, "i64.atomic.rmw32_u.and"),
2706
2707			I32AtomicRmwOr(_) => write!(f, "i32.atomic.rmw.or"),
2708			I64AtomicRmwOr(_) => write!(f, "i64.atomic.rmw.or"),
2709			I32AtomicRmwOr8u(_) => write!(f, "i32.atomic.rmw8_u.or"),
2710			I32AtomicRmwOr16u(_) => write!(f, "i32.atomic.rmw16_u.or"),
2711			I64AtomicRmwOr8u(_) => write!(f, "i64.atomic.rmw8_u.or"),
2712			I64AtomicRmwOr16u(_) => write!(f, "i64.atomic.rmw16_u.or"),
2713			I64AtomicRmwOr32u(_) => write!(f, "i64.atomic.rmw32_u.or"),
2714
2715			I32AtomicRmwXor(_) => write!(f, "i32.atomic.rmw.xor"),
2716			I64AtomicRmwXor(_) => write!(f, "i64.atomic.rmw.xor"),
2717			I32AtomicRmwXor8u(_) => write!(f, "i32.atomic.rmw8_u.xor"),
2718			I32AtomicRmwXor16u(_) => write!(f, "i32.atomic.rmw16_u.xor"),
2719			I64AtomicRmwXor8u(_) => write!(f, "i64.atomic.rmw8_u.xor"),
2720			I64AtomicRmwXor16u(_) => write!(f, "i64.atomic.rmw16_u.xor"),
2721			I64AtomicRmwXor32u(_) => write!(f, "i64.atomic.rmw32_u.xor"),
2722
2723			I32AtomicRmwXchg(_) => write!(f, "i32.atomic.rmw.xchg"),
2724			I64AtomicRmwXchg(_) => write!(f, "i64.atomic.rmw.xchg"),
2725			I32AtomicRmwXchg8u(_) => write!(f, "i32.atomic.rmw8_u.xchg"),
2726			I32AtomicRmwXchg16u(_) => write!(f, "i32.atomic.rmw16_u.xchg"),
2727			I64AtomicRmwXchg8u(_) => write!(f, "i64.atomic.rmw8_u.xchg"),
2728			I64AtomicRmwXchg16u(_) => write!(f, "i64.atomic.rmw16_u.xchg"),
2729			I64AtomicRmwXchg32u(_) => write!(f, "i64.atomic.rmw32_u.xchg"),
2730
2731			I32AtomicRmwCmpxchg(_) => write!(f, "i32.atomic.rmw.cmpxchg"),
2732			I64AtomicRmwCmpxchg(_) => write!(f, "i64.atomic.rmw.cmpxchg"),
2733			I32AtomicRmwCmpxchg8u(_) => write!(f, "i32.atomic.rmw8_u.cmpxchg"),
2734			I32AtomicRmwCmpxchg16u(_) => write!(f, "i32.atomic.rmw16_u.cmpxchg"),
2735			I64AtomicRmwCmpxchg8u(_) => write!(f, "i64.atomic.rmw8_u.cmpxchg"),
2736			I64AtomicRmwCmpxchg16u(_) => write!(f, "i64.atomic.rmw16_u.cmpxchg"),
2737			I64AtomicRmwCmpxchg32u(_) => write!(f, "i64.atomic.rmw32_u.cmpxchg"),
2738		}
2739	}
2740}
2741
2742#[cfg(feature = "simd")]
2743impl fmt::Display for SimdInstruction {
2744	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2745		use self::SimdInstruction::*;
2746
2747		match *self {
2748			V128Const(_) => write!(f, "v128.const"),
2749			V128Load(_) => write!(f, "v128.load"),
2750			V128Store(_) => write!(f, "v128.store"),
2751			I8x16Splat => write!(f, "i8x16.splat"),
2752			I16x8Splat => write!(f, "i16x8.splat"),
2753			I32x4Splat => write!(f, "i32x4.splat"),
2754			I64x2Splat => write!(f, "i64x2.splat"),
2755			F32x4Splat => write!(f, "f32x4.splat"),
2756			F64x2Splat => write!(f, "f64x2.splat"),
2757			I8x16ExtractLaneS(_) => write!(f, "i8x16.extract_lane_s"),
2758			I8x16ExtractLaneU(_) => write!(f, "i8x16.extract_lane_u"),
2759			I16x8ExtractLaneS(_) => write!(f, "i16x8.extract_lane_s"),
2760			I16x8ExtractLaneU(_) => write!(f, "i16x8.extract_lane_u"),
2761			I32x4ExtractLane(_) => write!(f, "i32x4.extract_lane"),
2762			I64x2ExtractLane(_) => write!(f, "i64x2.extract_lane"),
2763			F32x4ExtractLane(_) => write!(f, "f32x4.extract_lane"),
2764			F64x2ExtractLane(_) => write!(f, "f64x2.extract_lane"),
2765			I8x16ReplaceLane(_) => write!(f, "i8x16.replace_lane"),
2766			I16x8ReplaceLane(_) => write!(f, "i16x8.replace_lane"),
2767			I32x4ReplaceLane(_) => write!(f, "i32x4.replace_lane"),
2768			I64x2ReplaceLane(_) => write!(f, "i64x2.replace_lane"),
2769			F32x4ReplaceLane(_) => write!(f, "f32x4.replace_lane"),
2770			F64x2ReplaceLane(_) => write!(f, "f64x2.replace_lane"),
2771			V8x16Shuffle(_) => write!(f, "v8x16.shuffle"),
2772			I8x16Add => write!(f, "i8x16.add"),
2773			I16x8Add => write!(f, "i16x8.add"),
2774			I32x4Add => write!(f, "i32x4.add"),
2775			I64x2Add => write!(f, "i64x2.add"),
2776			I8x16Sub => write!(f, "i8x16.sub"),
2777			I16x8Sub => write!(f, "i16x8.sub"),
2778			I32x4Sub => write!(f, "i32x4.sub"),
2779			I64x2Sub => write!(f, "i64x2.sub"),
2780			I8x16Mul => write!(f, "i8x16.mul"),
2781			I16x8Mul => write!(f, "i16x8.mul"),
2782			I32x4Mul => write!(f, "i32x4.mul"),
2783			// I64x2Mul => write!(f, "i64x2.mul"),
2784			I8x16Neg => write!(f, "i8x16.neg"),
2785			I16x8Neg => write!(f, "i16x8.neg"),
2786			I32x4Neg => write!(f, "i32x4.neg"),
2787			I64x2Neg => write!(f, "i64x2.neg"),
2788			I8x16AddSaturateS => write!(f, "i8x16.add_saturate_s"),
2789			I8x16AddSaturateU => write!(f, "i8x16.add_saturate_u"),
2790			I16x8AddSaturateS => write!(f, "i16x8.add_saturate_S"),
2791			I16x8AddSaturateU => write!(f, "i16x8.add_saturate_u"),
2792			I8x16SubSaturateS => write!(f, "i8x16.sub_saturate_S"),
2793			I8x16SubSaturateU => write!(f, "i8x16.sub_saturate_u"),
2794			I16x8SubSaturateS => write!(f, "i16x8.sub_saturate_S"),
2795			I16x8SubSaturateU => write!(f, "i16x8.sub_saturate_u"),
2796			I8x16Shl => write!(f, "i8x16.shl"),
2797			I16x8Shl => write!(f, "i16x8.shl"),
2798			I32x4Shl => write!(f, "i32x4.shl"),
2799			I64x2Shl => write!(f, "i64x2.shl"),
2800			I8x16ShrS => write!(f, "i8x16.shr_s"),
2801			I8x16ShrU => write!(f, "i8x16.shr_u"),
2802			I16x8ShrS => write!(f, "i16x8.shr_s"),
2803			I16x8ShrU => write!(f, "i16x8.shr_u"),
2804			I32x4ShrS => write!(f, "i32x4.shr_s"),
2805			I32x4ShrU => write!(f, "i32x4.shr_u"),
2806			I64x2ShrS => write!(f, "i64x2.shr_s"),
2807			I64x2ShrU => write!(f, "i64x2.shr_u"),
2808			V128And => write!(f, "v128.and"),
2809			V128Or => write!(f, "v128.or"),
2810			V128Xor => write!(f, "v128.xor"),
2811			V128Not => write!(f, "v128.not"),
2812			V128Bitselect => write!(f, "v128.bitselect"),
2813			I8x16AnyTrue => write!(f, "i8x16.any_true"),
2814			I16x8AnyTrue => write!(f, "i16x8.any_true"),
2815			I32x4AnyTrue => write!(f, "i32x4.any_true"),
2816			I64x2AnyTrue => write!(f, "i64x2.any_true"),
2817			I8x16AllTrue => write!(f, "i8x16.all_true"),
2818			I16x8AllTrue => write!(f, "i16x8.all_true"),
2819			I32x4AllTrue => write!(f, "i32x4.all_true"),
2820			I64x2AllTrue => write!(f, "i64x2.all_true"),
2821			I8x16Eq => write!(f, "i8x16.eq"),
2822			I16x8Eq => write!(f, "i16x8.eq"),
2823			I32x4Eq => write!(f, "i32x4.eq"),
2824			// I64x2Eq => write!(f, "i64x2.eq"),
2825			F32x4Eq => write!(f, "f32x4.eq"),
2826			F64x2Eq => write!(f, "f64x2.eq"),
2827			I8x16Ne => write!(f, "i8x16.ne"),
2828			I16x8Ne => write!(f, "i16x8.ne"),
2829			I32x4Ne => write!(f, "i32x4.ne"),
2830			// I64x2Ne => write!(f, "i64x2.ne"),
2831			F32x4Ne => write!(f, "f32x4.ne"),
2832			F64x2Ne => write!(f, "f64x2.ne"),
2833			I8x16LtS => write!(f, "i8x16.lt_s"),
2834			I8x16LtU => write!(f, "i8x16.lt_u"),
2835			I16x8LtS => write!(f, "i16x8.lt_s"),
2836			I16x8LtU => write!(f, "i16x8.lt_u"),
2837			I32x4LtS => write!(f, "i32x4.lt_s"),
2838			I32x4LtU => write!(f, "i32x4.lt_u"),
2839			// I64x2LtS => write!(f, "// I64x2.lt_s"),
2840			// I64x2LtU => write!(f, "// I64x2.lt_u"),
2841			F32x4Lt => write!(f, "f32x4.lt"),
2842			F64x2Lt => write!(f, "f64x2.lt"),
2843			I8x16LeS => write!(f, "i8x16.le_s"),
2844			I8x16LeU => write!(f, "i8x16.le_u"),
2845			I16x8LeS => write!(f, "i16x8.le_s"),
2846			I16x8LeU => write!(f, "i16x8.le_u"),
2847			I32x4LeS => write!(f, "i32x4.le_s"),
2848			I32x4LeU => write!(f, "i32x4.le_u"),
2849			// I64x2LeS => write!(f, "// I64x2.le_s"),
2850			// I64x2LeU => write!(f, "// I64x2.le_u"),
2851			F32x4Le => write!(f, "f32x4.le"),
2852			F64x2Le => write!(f, "f64x2.le"),
2853			I8x16GtS => write!(f, "i8x16.gt_s"),
2854			I8x16GtU => write!(f, "i8x16.gt_u"),
2855			I16x8GtS => write!(f, "i16x8.gt_s"),
2856			I16x8GtU => write!(f, "i16x8.gt_u"),
2857			I32x4GtS => write!(f, "i32x4.gt_s"),
2858			I32x4GtU => write!(f, "i32x4.gt_u"),
2859			// I64x2GtS => write!(f, "// I64x2.gt_s"),
2860			// I64x2GtU => write!(f, "// I64x2.gt_u"),
2861			F32x4Gt => write!(f, "f32x4.gt"),
2862			F64x2Gt => write!(f, "f64x2.gt"),
2863			I8x16GeS => write!(f, "i8x16.ge_s"),
2864			I8x16GeU => write!(f, "i8x16.ge_u"),
2865			I16x8GeS => write!(f, "i16x8.ge_s"),
2866			I16x8GeU => write!(f, "i16x8.ge_u"),
2867			I32x4GeS => write!(f, "i32x4.ge_s"),
2868			I32x4GeU => write!(f, "i32x4.ge_u"),
2869			// I64x2GeS => write!(f, "// I64x2.ge_s"),
2870			// I64x2GeU => write!(f, "// I64x2.ge_u"),
2871			F32x4Ge => write!(f, "f32x4.ge"),
2872			F64x2Ge => write!(f, "f64x2.ge"),
2873			F32x4Neg => write!(f, "f32x4.neg"),
2874			F64x2Neg => write!(f, "f64x2.neg"),
2875			F32x4Abs => write!(f, "f32x4.abs"),
2876			F64x2Abs => write!(f, "f64x2.abs"),
2877			F32x4Min => write!(f, "f32x4.min"),
2878			F64x2Min => write!(f, "f64x2.min"),
2879			F32x4Max => write!(f, "f32x4.max"),
2880			F64x2Max => write!(f, "f64x2.max"),
2881			F32x4Add => write!(f, "f32x4.add"),
2882			F64x2Add => write!(f, "f64x2.add"),
2883			F32x4Sub => write!(f, "f32x4.sub"),
2884			F64x2Sub => write!(f, "f64x2.sub"),
2885			F32x4Div => write!(f, "f32x4.div"),
2886			F64x2Div => write!(f, "f64x2.div"),
2887			F32x4Mul => write!(f, "f32x4.mul"),
2888			F64x2Mul => write!(f, "f64x2.mul"),
2889			F32x4Sqrt => write!(f, "f32x4.sqrt"),
2890			F64x2Sqrt => write!(f, "f64x2.sqrt"),
2891			F32x4ConvertSI32x4 => write!(f, "f32x4.convert_s/i32x4"),
2892			F32x4ConvertUI32x4 => write!(f, "f32x4.convert_u/i32x4"),
2893			F64x2ConvertSI64x2 => write!(f, "f64x2.convert_s/i64x2"),
2894			F64x2ConvertUI64x2 => write!(f, "f64x2.convert_u/i64x2"),
2895			I32x4TruncSF32x4Sat => write!(f, "i32x4.trunc_s/f32x4:sat"),
2896			I32x4TruncUF32x4Sat => write!(f, "i32x4.trunc_u/f32x4:sat"),
2897			I64x2TruncSF64x2Sat => write!(f, "i64x2.trunc_s/f64x2:sat"),
2898			I64x2TruncUF64x2Sat => write!(f, "i64x2.trunc_u/f64x2:sat"),
2899		}
2900	}
2901}
2902
2903#[cfg(feature = "bulk")]
2904impl fmt::Display for BulkInstruction {
2905	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2906		use self::BulkInstruction::*;
2907
2908		match *self {
2909			MemoryInit(_) => write!(f, "memory.init"),
2910			MemoryDrop(_) => write!(f, "memory.drop"),
2911			MemoryFill => write!(f, "memory.fill"),
2912			MemoryCopy => write!(f, "memory.copy"),
2913			TableInit(_) => write!(f, "table.init"),
2914			TableDrop(_) => write!(f, "table.drop"),
2915			TableCopy => write!(f, "table.copy"),
2916		}
2917	}
2918}
2919
2920impl Serialize for Instructions {
2921	type Error = Error;
2922
2923	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2924		for op in self.0.into_iter() {
2925			op.serialize(writer)?;
2926		}
2927
2928		Ok(())
2929	}
2930}
2931
2932impl Serialize for InitExpr {
2933	type Error = Error;
2934
2935	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2936		for op in self.0.into_iter() {
2937			op.serialize(writer)?;
2938		}
2939
2940		Ok(())
2941	}
2942}
2943
2944#[cfg(test)]
2945mod tests {
2946	use super::*;
2947	#[test]
2948	fn ifelse() {
2949		// see if-else.wast/if-else.wasm
2950		let instruction_list = crate::elements::deserialize_buffer::<Instructions>(&[
2951			0x04, 0x7F, 0x41, 0x05, 0x05, 0x41, 0x07, 0x0B, 0x0B,
2952		])
2953		.expect("valid hex of if instruction");
2954		let instructions = instruction_list.elements();
2955		match instructions[0] {
2956			Instruction::If(_) => (),
2957			_ => panic!("Should be deserialized as if instruction"),
2958		}
2959		let before_else = instructions
2960			.iter()
2961			.skip(1)
2962			.take_while(|op| !matches!(**op, Instruction::Else))
2963			.count();
2964		let after_else = instructions
2965			.iter()
2966			.skip(1)
2967			.skip_while(|op| !matches!(**op, Instruction::Else))
2968			.take_while(|op| !matches!(**op, Instruction::End))
2969			.count() - 1; // minus Instruction::Else itself
2970		assert_eq!(before_else, after_else);
2971	}
2972
2973	#[test]
2974	fn display() {
2975		let instruction = Instruction::GetLocal(0);
2976		assert_eq!("get_local 0", format!("{}", instruction));
2977
2978		let instruction = Instruction::F64Store(0, 24);
2979		assert_eq!("f64.store offset=24", format!("{}", instruction));
2980
2981		let instruction = Instruction::I64Store(0, 0);
2982		assert_eq!("i64.store", format!("{}", instruction));
2983	}
2984
2985	#[test]
2986	fn size_off() {
2987		assert!(::core::mem::size_of::<Instruction>() <= 24);
2988	}
2989
2990	#[test]
2991	fn instructions_hashset() {
2992		use self::Instruction::{Block, Call, Drop};
2993		use crate::elements::types::{BlockType::Value, ValueType};
2994
2995		let set: hashbrown::HashSet<Instruction> =
2996			vec![Call(1), Block(Value(ValueType::I32)), Drop].into_iter().collect();
2997		assert!(set.contains(&Drop));
2998	}
2999}