web_assembler/
ops.rs

1use types::*;
2use util::*;
3use Dump;
4
5#[derive(Debug, Clone)]
6pub enum Op {
7    Unreachable,
8    Nop,
9    Block { sig: BlockType },
10    Loop { sig: BlockType },
11    If { sig: BlockType },
12    Else,
13    End,
14    // TODO: use relative block index
15    Br { depth: u32 },
16    BrIf { depth: u32 },
17    BrTable(BrTarget),
18    Return,
19    Call { index: FunctionSpaceIndex },
20    // TODO: use table index
21    CallIndirect { index: TypeIndex, reserved: bool },
22    Drop,
23    Select,
24    GetLocal(LocalIndex),
25    SetLocal(LocalIndex),
26    TeeLocal(LocalIndex),
27    GetGlobal(GlobalIndex),
28    SetGlobal(GlobalIndex),
29    I32Load { imm: MemoryImmediate },
30    I64Load { imm: MemoryImmediate },
31    F32Load { imm: MemoryImmediate },
32    F64Load { imm: MemoryImmediate },
33    I32Load8S { imm: MemoryImmediate },
34    I32Load8U { imm: MemoryImmediate },
35    I32Load16S { imm: MemoryImmediate },
36    I32Load16U { imm: MemoryImmediate },
37    I64Load8S { imm: MemoryImmediate },
38    I64Load8U { imm: MemoryImmediate },
39    I64Load16S { imm: MemoryImmediate },
40    I64Load16U { imm: MemoryImmediate },
41    I64load32S { imm: MemoryImmediate },
42    I64load32U { imm: MemoryImmediate },
43    I32Store { imm: MemoryImmediate },
44    I64Store { imm: MemoryImmediate },
45    F32Store { imm: MemoryImmediate },
46    F64Store { imm: MemoryImmediate },
47    I32Store8 { imm: MemoryImmediate },
48    I32Store16 { imm: MemoryImmediate },
49    I64Store8 { imm: MemoryImmediate },
50    I64Store16 { imm: MemoryImmediate },
51    I64Store32 { imm: MemoryImmediate },
52    CurrentMemory { reserved: bool },
53    GrowMemory { reserved: bool },
54    I32Const(i32),
55    I64Const(i64),
56    F32Const(f32),
57    F64Const(f64),
58    I32Eqz,
59    I32Eq,
60    I32NE,
61    I32LtS,
62    I32LtU,
63    I32GtS,
64    I32GtU,
65    I32LeS,
66    I32LeU,
67    I32GeS,
68    I32GeU,
69    I64Eqz,
70    I64Eq,
71    I64Ne,
72    I64LtS,
73    I64LtU,
74    I64GtS,
75    I64GtU,
76    I64LeS,
77    I64LeU,
78    I64GeS,
79    I64GeU,
80    F32Eq,
81    F32Ne,
82    F32Lt,
83    F32Gt,
84    F32Le,
85    F32Ge,
86    F64Eq,
87    F64Ne,
88    F64Lt,
89    F64Gt,
90    F64Le,
91    F64Ge,
92    I32Clz,
93    I32Ctz,
94    I32Popcnt,
95    I32Add,
96    I32Sub,
97    I32Mul,
98    I32DivS,
99    I32DivU,
100    I32RemS,
101    I32RemU,
102    I32And,
103    I32Or,
104    I32Xor,
105    I32Shl,
106    I32ShrS,
107    I32ShrU,
108    I32Rotl,
109    I32Rotr,
110    I64Clz,
111    I64Ctz,
112    I64Popcnt,
113    I64Add,
114    I64Sub,
115    I64Mul,
116    I64DivS,
117    I64DivU,
118    I64RemS,
119    I64RemU,
120    I64And,
121    I64Or,
122    I64Xor,
123    I64Shl,
124    I64ShrS,
125    I64ShrU,
126    I64Rotl,
127    I64Rotr,
128    F32Abs,
129    F32Neg,
130    F32Ceil,
131    F32Floor,
132    F32Trunc,
133    F32Nearest,
134    F32Sqrt,
135    F32Add,
136    F32Sub,
137    F32Mul,
138    F32Div,
139    F32Min,
140    F32Max,
141    F32Copysign,
142    F64Abs,
143    F64Neg,
144    F64Ceil,
145    F64Floor,
146    F64Trunc,
147    F64Nearest,
148    F64Sqrt,
149    F64Add,
150    F64Sub,
151    F64Mul,
152    F64Div,
153    F64Min,
154    F64Max,
155    F64Copysign,
156    I32wrapI64,
157    I32TruncSF32,
158    I32TruncUF32,
159    I32TruncSF64,
160    I32TruncUF64,
161    I64ExtendSI32,
162    I64ExtendUI32,
163    I64TruncSF32,
164    I64TruncUF32,
165    I64TruncSF64,
166    I64TruncUF64,
167    F32ConvertSI32,
168    F32ConvertUI32,
169    F32ConvertSI64,
170    F32ConvertUI64,
171    F32DemoteF64,
172    F64ConvertSI32,
173    F64ConvertUI32,
174    F64ConvertSI64,
175    F64ConvertUI64,
176    F64PromoteF32,
177    I32ReinterpretF32,
178    I64ReinterpretF64,
179    F32ReinterpretI32,
180    F64ReinterpretI64,
181}
182
183impl Op {
184    pub fn resolve_functions(&mut self, nimports: u32) {
185        match *self {
186            Op::Call { ref mut index } => {
187                use InnerFunctionSpaceIndex::*;
188                match index.0 {
189                    Function(ref mut f) => {
190                        f.0 += nimports;
191                    }
192                    _ => (),
193                }
194            }
195            _ => (),
196        }
197    }
198}
199
200impl Dump for Op {
201    fn dump(&self, buf: &mut Vec<u8>) -> usize {
202        use self::Op::*;
203        fn do_imm(buf: &mut Vec<u8>, imm: &MemoryImmediate, code: u8) -> usize {
204            let mut size = 0;
205
206            size += write_uint8(buf, code);
207            size += imm.dump(buf);
208
209            size
210        }
211        let mut size = 0;
212
213        match self {
214            &Unreachable => size += write_uint8(buf, 0x00),
215            &Nop => size += write_uint8(buf, 0x01),
216            &Block { ref sig } => {
217                size += write_uint8(buf, 0x02);
218                size += sig.dump(buf);
219            }
220            &Loop { ref sig } => {
221                size += write_uint8(buf, 0x03);
222                size += sig.dump(buf);
223            }
224            &If { ref sig } => {
225                size += write_uint8(buf, 0x04);
226                size += sig.dump(buf);
227            }
228            &Else => size += write_uint8(buf, 0x05),
229            &End => size += write_uint8(buf, 0x0b),
230            &Br { ref depth } => {
231                size += write_uint8(buf, 0x0c);
232                size += write_varuint32(buf, *depth);
233            }
234            &BrIf { ref depth } => {
235                size += write_uint8(buf, 0x0d);
236                size += write_varuint32(buf, *depth);
237            }
238            &BrTable(ref br_target) => {
239                size += write_uint8(buf, 0x0e);
240                size += br_target.dump(buf);
241            }
242            &Return => size += write_uint8(buf, 0x0f),
243            &Call { ref index } => {
244                size += write_uint8(buf, 0x10);
245                size += write_varuint32(buf, **index);
246            }
247
248            &CallIndirect {
249                ref index,
250                ref reserved,
251            } => {
252                size += write_uint8(buf, 0x11);
253                size += write_varuint32(buf, **index);
254                size += write_varuint1(buf, *reserved as u8);
255            }
256            &Drop => size += write_uint8(buf, 0x1a),
257            &Select => size += write_uint8(buf, 0x1b),
258            &GetLocal(ref i) => {
259                size += write_uint8(buf, 0x20);
260                size += write_varuint32(buf, **i);
261            }
262            &SetLocal(ref i) => {
263                size += write_uint8(buf, 0x21);
264                size += write_varuint32(buf, **i);
265            }
266            &TeeLocal(ref i) => {
267                size += write_uint8(buf, 0x22);
268                size += write_varuint32(buf, **i);
269            }
270            &GetGlobal(ref i) => {
271                size += write_uint8(buf, 0x023);
272                size += write_varuint32(buf, **i);
273            }
274            &SetGlobal(ref i) => {
275                size += write_uint8(buf, 0x24);
276                size += write_varuint32(buf, **i);
277            }
278            &I32Load { ref imm } => size += do_imm(buf, imm, 0x28),
279            &I64Load { ref imm } => size += do_imm(buf, imm, 0x29),
280            &F32Load { ref imm } => size += do_imm(buf, imm, 0x2a),
281            &F64Load { ref imm } => size += do_imm(buf, imm, 0x2b),
282            &I32Load8S { ref imm } => size += do_imm(buf, imm, 0x2c),
283            &I32Load8U { ref imm } => size += do_imm(buf, imm, 0x2d),
284            &I32Load16S { ref imm } => size += do_imm(buf, imm, 0x2e),
285            &I32Load16U { ref imm } => size += do_imm(buf, imm, 0x2f),
286            &I64Load8S { ref imm } => size += do_imm(buf, imm, 0x30),
287            &I64Load8U { ref imm } => size += do_imm(buf, imm, 0x31),
288            &I64Load16S { ref imm } => size += do_imm(buf, imm, 0x32),
289            &I64Load16U { ref imm } => size += do_imm(buf, imm, 0x33),
290            &I64load32S { ref imm } => size += do_imm(buf, imm, 0x34),
291            &I64load32U { ref imm } => size += do_imm(buf, imm, 0x35),
292            &I32Store { ref imm } => size += do_imm(buf, imm, 0x36),
293            &I64Store { ref imm } => size += do_imm(buf, imm, 0x37),
294            &F32Store { ref imm } => size += do_imm(buf, imm, 0x38),
295            &F64Store { ref imm } => size += do_imm(buf, imm, 0x39),
296            &I32Store8 { ref imm } => size += do_imm(buf, imm, 0x3a),
297            &I32Store16 { ref imm } => size += do_imm(buf, imm, 0x3b),
298            &I64Store8 { ref imm } => size += do_imm(buf, imm, 0x3c),
299            &I64Store16 { ref imm } => size += do_imm(buf, imm, 0x3d),
300            &I64Store32 { ref imm } => size += do_imm(buf, imm, 0x3e),
301            &CurrentMemory { ref reserved } => {
302                size += write_uint8(buf, 0x3f);
303                size += write_varuint1(buf, *reserved as u8);
304            }
305            &GrowMemory { ref reserved } => {
306                size += write_uint8(buf, 0x40);
307                size += write_varuint1(buf, *reserved as u8);
308            }
309            &I32Const(ref i) => {
310                size += write_uint8(buf, 0x41);
311                size += write_varint32(buf, *i);
312            }
313            &I64Const(ref i) => {
314                size += write_uint8(buf, 0x42);
315                size += write_varint64(buf, *i);
316            }
317            &F32Const(ref f) => {
318                size += write_uint8(buf, 0x43);
319                unsafe {
320                    size += write_uint32(buf, ::std::mem::transmute::<f32, u32>(*f));
321                }
322            }
323            &F64Const(ref f) => {
324                size += write_uint8(buf, 0x44);
325                unsafe {
326                    size += write_uint64(buf, ::std::mem::transmute::<f64, u64>(*f));
327                }
328            }
329            &I32Eqz => size += write_uint8(buf, 0x45),
330            &I32Eq => size += write_uint8(buf, 0x46),
331            &I32NE => size += write_uint8(buf, 0x47),
332            &I32LtS => size += write_uint8(buf, 0x48),
333            &I32LtU => size += write_uint8(buf, 0x49),
334            &I32GtS => size += write_uint8(buf, 0x4a),
335            &I32GtU => size += write_uint8(buf, 0x4b),
336            &I32LeS => size += write_uint8(buf, 0x4c),
337            &I32LeU => size += write_uint8(buf, 0x4d),
338            &I32GeS => size += write_uint8(buf, 0x4e),
339            &I32GeU => size += write_uint8(buf, 0x4f),
340            &I64Eqz => size += write_uint8(buf, 0x50),
341            &I64Eq => size += write_uint8(buf, 0x51),
342            &I64Ne => size += write_uint8(buf, 0x52),
343            &I64LtS => size += write_uint8(buf, 0x53),
344            &I64LtU => size += write_uint8(buf, 0x54),
345            &I64GtS => size += write_uint8(buf, 0x55),
346            &I64GtU => size += write_uint8(buf, 0x56),
347            &I64LeS => size += write_uint8(buf, 0x57),
348            &I64LeU => size += write_uint8(buf, 0x58),
349            &I64GeS => size += write_uint8(buf, 0x59),
350            &I64GeU => size += write_uint8(buf, 0x5a),
351            &F32Eq => size += write_uint8(buf, 0x5b),
352            &F32Ne => size += write_uint8(buf, 0x5c),
353            &F32Lt => size += write_uint8(buf, 0x5d),
354            &F32Gt => size += write_uint8(buf, 0x5e),
355            &F32Le => size += write_uint8(buf, 0x5f),
356            &F32Ge => size += write_uint8(buf, 0x60),
357            &F64Eq => size += write_uint8(buf, 0x61),
358            &F64Ne => size += write_uint8(buf, 0x62),
359            &F64Lt => size += write_uint8(buf, 0x63),
360            &F64Gt => size += write_uint8(buf, 0x64),
361            &F64Le => size += write_uint8(buf, 0x65),
362            &F64Ge => size += write_uint8(buf, 0x66),
363            &I32Clz => size += write_uint8(buf, 0x67),
364            &I32Ctz => size += write_uint8(buf, 0x68),
365            &I32Popcnt => size += write_uint8(buf, 0x69),
366            &I32Add => size += write_uint8(buf, 0x6a),
367            &I32Sub => size += write_uint8(buf, 0x6b),
368            &I32Mul => size += write_uint8(buf, 0x6c),
369            &I32DivS => size += write_uint8(buf, 0x6d),
370            &I32DivU => size += write_uint8(buf, 0x6e),
371            &I32RemS => size += write_uint8(buf, 0x6f),
372            &I32RemU => size += write_uint8(buf, 0x70),
373            &I32And => size += write_uint8(buf, 0x71),
374            &I32Or => size += write_uint8(buf, 0x72),
375            &I32Xor => size += write_uint8(buf, 0x73),
376            &I32Shl => size += write_uint8(buf, 0x74),
377            &I32ShrS => size += write_uint8(buf, 0x75),
378            &I32ShrU => size += write_uint8(buf, 0x76),
379            &I32Rotl => size += write_uint8(buf, 0x77),
380            &I32Rotr => size += write_uint8(buf, 0x78),
381            &I64Clz => size += write_uint8(buf, 0x79),
382            &I64Ctz => size += write_uint8(buf, 0x7a),
383            &I64Popcnt => size += write_uint8(buf, 0x7b),
384            &I64Add => size += write_uint8(buf, 0x7c),
385            &I64Sub => size += write_uint8(buf, 0x7d),
386            &I64Mul => size += write_uint8(buf, 0x7e),
387            &I64DivS => size += write_uint8(buf, 0x7f),
388            &I64DivU => size += write_uint8(buf, 0x80),
389            &I64RemS => size += write_uint8(buf, 0x81),
390            &I64RemU => size += write_uint8(buf, 0x82),
391            &I64And => size += write_uint8(buf, 0x83),
392            &I64Or => size += write_uint8(buf, 0x84),
393            &I64Xor => size += write_uint8(buf, 0x85),
394            &I64Shl => size += write_uint8(buf, 0x86),
395            &I64ShrS => size += write_uint8(buf, 0x87),
396            &I64ShrU => size += write_uint8(buf, 0x88),
397            &I64Rotl => size += write_uint8(buf, 0x89),
398            &I64Rotr => size += write_uint8(buf, 0x8a),
399            &F32Abs => size += write_uint8(buf, 0x8b),
400            &F32Neg => size += write_uint8(buf, 0x8c),
401            &F32Ceil => size += write_uint8(buf, 0x8d),
402            &F32Floor => size += write_uint8(buf, 0x8e),
403            &F32Trunc => size += write_uint8(buf, 0x8f),
404            &F32Nearest => size += write_uint8(buf, 0x90),
405            &F32Sqrt => size += write_uint8(buf, 0x91),
406            &F32Add => size += write_uint8(buf, 0x92),
407            &F32Sub => size += write_uint8(buf, 0x93),
408            &F32Mul => size += write_uint8(buf, 0x94),
409            &F32Div => size += write_uint8(buf, 0x95),
410            &F32Min => size += write_uint8(buf, 0x96),
411            &F32Max => size += write_uint8(buf, 0x97),
412            &F32Copysign => size += write_uint8(buf, 0x98),
413            &F64Abs => size += write_uint8(buf, 0x99),
414            &F64Neg => size += write_uint8(buf, 0x9a),
415            &F64Ceil => size += write_uint8(buf, 0x9b),
416            &F64Floor => size += write_uint8(buf, 0x9c),
417            &F64Trunc => size += write_uint8(buf, 0x9d),
418            &F64Nearest => size += write_uint8(buf, 0x9e),
419            &F64Sqrt => size += write_uint8(buf, 0x9f),
420            &F64Add => size += write_uint8(buf, 0xa0),
421            &F64Sub => size += write_uint8(buf, 0xa1),
422            &F64Mul => size += write_uint8(buf, 0xa2),
423            &F64Div => size += write_uint8(buf, 0xa3),
424            &F64Min => size += write_uint8(buf, 0xa4),
425            &F64Max => size += write_uint8(buf, 0xa5),
426            &F64Copysign => size += write_uint8(buf, 0xa6),
427            &I32wrapI64 => size += write_uint8(buf, 0xa7),
428            &I32TruncSF32 => size += write_uint8(buf, 0xa8),
429            &I32TruncUF32 => size += write_uint8(buf, 0xa9),
430            &I32TruncSF64 => size += write_uint8(buf, 0xaa),
431            &I32TruncUF64 => size += write_uint8(buf, 0xab),
432            &I64ExtendSI32 => size += write_uint8(buf, 0xac),
433            &I64ExtendUI32 => size += write_uint8(buf, 0xad),
434            &I64TruncSF32 => size += write_uint8(buf, 0xae),
435            &I64TruncUF32 => size += write_uint8(buf, 0xaf),
436            &I64TruncSF64 => size += write_uint8(buf, 0xb0),
437            &I64TruncUF64 => size += write_uint8(buf, 0xb1),
438            &F32ConvertSI32 => size += write_uint8(buf, 0xb2),
439            &F32ConvertUI32 => size += write_uint8(buf, 0xb3),
440            &F32ConvertSI64 => size += write_uint8(buf, 0xb4),
441            &F32ConvertUI64 => size += write_uint8(buf, 0xb5),
442            &F32DemoteF64 => size += write_uint8(buf, 0xb6),
443            &F64ConvertSI32 => size += write_uint8(buf, 0xb7),
444            &F64ConvertUI32 => size += write_uint8(buf, 0xb8),
445            &F64ConvertSI64 => size += write_uint8(buf, 0xb9),
446            &F64ConvertUI64 => size += write_uint8(buf, 0xba),
447            &F64PromoteF32 => size += write_uint8(buf, 0xbb),
448            &I32ReinterpretF32 => size += write_uint8(buf, 0xbc),
449            &I64ReinterpretF64 => size += write_uint8(buf, 0xbd),
450            &F32ReinterpretI32 => size += write_uint8(buf, 0xbe),
451            &F64ReinterpretI64 => size += write_uint8(buf, 0xbf),
452        };
453        size
454    }
455}
456
457impl From<i32> for Op {
458    fn from(i: i32) -> Self {
459        Op::I32Const(i)
460    }
461}
462impl From<i64> for Op {
463    fn from(i: i64) -> Self {
464        Op::I64Const(i)
465    }
466}
467impl From<f32> for Op {
468    fn from(f: f32) -> Self {
469        Op::F32Const(f)
470    }
471}
472impl From<f64> for Op {
473    fn from(f: f64) -> Self {
474        Op::F64Const(f)
475    }
476}
477
478#[derive(Debug, Clone)]
479pub struct MemoryImmediate {
480    pub flags: u32,
481    pub offset: u32,
482}
483
484impl Dump for MemoryImmediate {
485    fn dump(&self, buf: &mut Vec<u8>) -> usize {
486        let mut size = 0;
487
488        size += write_varuint32(buf, self.flags);
489        size += write_varuint32(buf, self.offset);
490
491        size
492    }
493}
494
495#[derive(Debug, Clone)]
496pub struct BrTarget {
497    // TODO: use relative block index
498    pub table: Vec<u32>,
499    pub default_target: u32,
500}
501
502impl Dump for BrTarget {
503    fn dump(&self, buf: &mut Vec<u8>) -> usize {
504        let mut size = 0;
505        let table = &self.table;
506
507        size += write_varuint32(buf, table.len() as u32);
508        for t in table {
509            size += write_varuint32(buf, *t);
510        }
511
512        size += write_varuint32(buf, self.default_target);
513
514        size
515    }
516}