linera_parity_wasm/elements/
ops.rs

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