tetsy_wasm/elements/
ops.rs

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