waffle/backend/
mod.rs

1//! Backend: IR to Wasm.
2
3use crate::cfg::CFGInfo;
4use crate::entity::EntityRef;
5use crate::ir::{ExportKind, FuncDecl, FunctionBody, ImportKind, Module, Type, Value, ValueDef};
6use crate::Operator;
7use anyhow::Result;
8use rayon::prelude::*;
9use std::borrow::Cow;
10
11pub mod reducify;
12use reducify::Reducifier;
13pub mod stackify;
14use stackify::{Context as StackifyContext, WasmBlock};
15pub mod treeify;
16use treeify::Trees;
17pub mod localify;
18use localify::Localifier;
19
20pub struct WasmFuncBackend<'a> {
21    body: Cow<'a, FunctionBody>,
22    cfg: CFGInfo,
23}
24
25struct CompileContext<'a> {
26    trees: Trees,
27    ctrl: Vec<WasmBlock<'a>>,
28    locals: Localifier,
29}
30
31macro_rules! op {
32    ($name:tt) => {
33        Some(wasm_encoder::Instruction::$name)
34    };
35}
36
37impl<'a> WasmFuncBackend<'a> {
38    pub fn compile(body: &'a FunctionBody) -> Result<wasm_encoder::Function> {
39        body.validate()?;
40        log::debug!("Backend compiling:\n{}\n", body.display_verbose("| ", None));
41        // For ownership reasons (to avoid a self-referential struct
42        // with the `Cow::Owned` case when the Reducifier modifies the
43        // body), we have to run the Reducifier first, own its result
44        // in this stack frame, then construct the `WasmFuncBackend`
45        // state and run the rest of the compilation in `lower()`.
46        let body = Reducifier::new(body).run();
47        let cfg = CFGInfo::new(&body);
48        let state = WasmFuncBackend { body, cfg };
49        state.lower()
50    }
51
52    pub fn lower(&self) -> Result<wasm_encoder::Function> {
53        log::debug!("CFG:\n{:?}\n", self.cfg);
54        let trees = Trees::compute(&self.body);
55        log::debug!("Trees:\n{:?}\n", trees);
56        let ctrl = StackifyContext::new(&self.body, &self.cfg)?.compute();
57        log::debug!("Ctrl:\n{:?}\n", ctrl);
58        let locals = Localifier::compute(&self.body, &self.cfg, &trees);
59        log::debug!("Locals:\n{:?}\n", locals);
60
61        let ctx = CompileContext {
62            trees,
63            ctrl,
64            locals,
65        };
66
67        let mut func = wasm_encoder::Function::new(
68            ctx.locals
69                .locals
70                .values()
71                .skip(self.body.blocks[self.body.entry].params.len())
72                .map(|&ty| (1, wasm_encoder::ValType::from(ty)))
73                .collect::<Vec<_>>(),
74        );
75
76        for block in &ctx.ctrl {
77            self.lower_block(&ctx, block, &mut func);
78        }
79
80        // If the last block was a Block, Loop or If, then the type
81        // may not match, so end with an Unreachable.
82        match ctx.ctrl.last() {
83            Some(&WasmBlock::Block { .. })
84            | Some(&WasmBlock::Loop { .. })
85            | Some(&WasmBlock::If { .. }) => {
86                func.instruction(&wasm_encoder::Instruction::Unreachable);
87            }
88            _ => {}
89        }
90        func.instruction(&wasm_encoder::Instruction::End);
91
92        log::debug!("Compiled to:\n{:?}\n", func);
93
94        Ok(func)
95    }
96
97    fn lower_block(
98        &self,
99        ctx: &CompileContext<'_>,
100        block: &WasmBlock<'_>,
101        func: &mut wasm_encoder::Function,
102    ) {
103        match block {
104            WasmBlock::Block { body, .. } => {
105                func.instruction(&wasm_encoder::Instruction::Block(
106                    wasm_encoder::BlockType::Empty,
107                ));
108                for sub_block in &body[..] {
109                    self.lower_block(ctx, sub_block, func);
110                }
111                func.instruction(&wasm_encoder::Instruction::End);
112            }
113            WasmBlock::Loop { body, .. } => {
114                func.instruction(&wasm_encoder::Instruction::Loop(
115                    wasm_encoder::BlockType::Empty,
116                ));
117                for sub_block in &body[..] {
118                    self.lower_block(ctx, sub_block, func);
119                }
120                func.instruction(&wasm_encoder::Instruction::End);
121            }
122            WasmBlock::Br { target } => {
123                func.instruction(&wasm_encoder::Instruction::Br(target.index()));
124            }
125            WasmBlock::If {
126                cond,
127                if_true,
128                if_false,
129            } => {
130                self.lower_value(ctx, *cond, func);
131                func.instruction(&wasm_encoder::Instruction::If(
132                    wasm_encoder::BlockType::Empty,
133                ));
134                for sub_block in &if_true[..] {
135                    self.lower_block(ctx, sub_block, func);
136                }
137                if if_false.len() > 0 {
138                    func.instruction(&wasm_encoder::Instruction::Else);
139                    for sub_block in &if_false[..] {
140                        self.lower_block(ctx, sub_block, func);
141                    }
142                }
143                func.instruction(&wasm_encoder::Instruction::End);
144            }
145            WasmBlock::Select {
146                selector,
147                targets,
148                default,
149            } => {
150                self.lower_value(ctx, *selector, func);
151                func.instruction(&wasm_encoder::Instruction::BrTable(
152                    Cow::Owned(
153                        targets
154                            .iter()
155                            .map(|label| label.index())
156                            .collect::<Vec<_>>(),
157                    ),
158                    default.index(),
159                ));
160            }
161            WasmBlock::Leaf { block } => {
162                for &inst in &self.body.blocks[*block].insts {
163                    // If this value is "owned", do nothing: it will be lowered in
164                    // the one place it's used.
165                    if ctx.trees.owner.contains_key(&inst) || ctx.trees.remat.contains(&inst) {
166                        continue;
167                    }
168                    if let &ValueDef::Operator(..) = &self.body.values[inst] {
169                        self.lower_inst(ctx, inst, /* root = */ true, func);
170                    }
171                }
172            }
173            WasmBlock::BlockParams { from, to } => {
174                debug_assert_eq!(from.len(), to.len());
175                for (&from, &(to_ty, to)) in from.iter().zip(to.iter()) {
176                    if ctx.locals.values[to].is_empty() {
177                        continue;
178                    }
179                    let from_ty = self.body.values[self.body.resolve_alias(from)]
180                        .ty(&self.body.type_pool)
181                        .unwrap();
182                    assert_eq!(from_ty, to_ty);
183                    if ctx.locals.values[from].len() == 1 {
184                        assert_eq!(from_ty, ctx.locals.locals[ctx.locals.values[from][0]]);
185                    }
186                    self.lower_value(ctx, from, func);
187                }
188                for &(to_ty, to) in to.iter().rev() {
189                    if ctx.locals.values[to].is_empty() {
190                        continue;
191                    }
192                    if ctx.locals.values[to].len() == 1 {
193                        assert_eq!(to_ty, ctx.locals.locals[ctx.locals.values[to][0]]);
194                    }
195                    self.lower_set_value(ctx, to, func);
196                }
197            }
198            WasmBlock::Return { values } => {
199                for &value in &values[..] {
200                    self.lower_value(ctx, value, func);
201                }
202                func.instruction(&wasm_encoder::Instruction::Return);
203            }
204            WasmBlock::Unreachable => {
205                func.instruction(&wasm_encoder::Instruction::Unreachable);
206            }
207        }
208    }
209
210    fn lower_value(
211        &self,
212        ctx: &CompileContext<'_>,
213        value: Value,
214        func: &mut wasm_encoder::Function,
215    ) {
216        log::trace!("lower_value: value {}", value);
217        let value = self.body.resolve_alias(value);
218        if ctx.trees.remat.contains(&value) {
219            self.lower_inst(ctx, value, /* root = */ false, func);
220        } else {
221            let local = match &self.body.values[value] {
222                &ValueDef::BlockParam(..) | &ValueDef::Operator(..) => ctx.locals.values[value][0],
223                &ValueDef::PickOutput(orig_value, idx, _) => {
224                    ctx.locals.values[orig_value][idx as usize]
225                }
226                val => unreachable!("bad value ({}): {:?}", value, val),
227            };
228            func.instruction(&wasm_encoder::Instruction::LocalGet(local.index() as u32));
229        }
230    }
231
232    fn lower_set_value(
233        &self,
234        ctx: &CompileContext<'a>,
235        value: Value,
236        func: &mut wasm_encoder::Function,
237    ) {
238        debug_assert_eq!(
239            ctx.locals.values[value].len(),
240            1,
241            "Value {} has no local",
242            value
243        );
244        let local = ctx.locals.values[value][0];
245        func.instruction(&wasm_encoder::Instruction::LocalSet(local.index() as u32));
246    }
247
248    fn lower_inst(
249        &self,
250        ctx: &CompileContext<'a>,
251        value: Value,
252        root: bool,
253        func: &mut wasm_encoder::Function,
254    ) {
255        log::trace!("lower_inst: value {} root {}", value, root);
256        match &self.body.values[value] {
257            &ValueDef::Operator(ref op, args, tys) => {
258                for &arg in &self.body.arg_pool[args] {
259                    let arg = self.body.resolve_alias(arg);
260                    if ctx.trees.owner.contains_key(&arg) || ctx.trees.remat.contains(&arg) {
261                        log::trace!(" -> arg {} is owned", arg);
262                        self.lower_inst(ctx, arg, /* root = */ false, func);
263                    } else {
264                        self.lower_value(ctx, arg, func);
265                    }
266                }
267                self.lower_op(op, func);
268                if root {
269                    for &local in &ctx.locals.values[value] {
270                        func.instruction(
271                            &wasm_encoder::Instruction::LocalSet(local.index() as u32),
272                        );
273                    }
274                    let leftovers = tys.len() - ctx.locals.values[value].len();
275                    for _ in 0..leftovers {
276                        func.instruction(&wasm_encoder::Instruction::Drop);
277                    }
278                }
279            }
280            &ValueDef::PickOutput(..) => {
281                self.lower_value(ctx, value, func);
282            }
283            def => unreachable!("Unexpected inst: {:?}", def),
284        }
285    }
286
287    fn lower_op(&self, op: &Operator, func: &mut wasm_encoder::Function) {
288        let inst = match op {
289            Operator::Unreachable => Some(wasm_encoder::Instruction::Unreachable),
290            Operator::Nop => None,
291            Operator::Call { function_index } => Some(wasm_encoder::Instruction::Call(
292                function_index.index() as u32,
293            )),
294            Operator::CallIndirect {
295                sig_index,
296                table_index,
297            } => Some(wasm_encoder::Instruction::CallIndirect {
298                type_index: sig_index.index() as u32,
299                table_index: table_index.index() as u32,
300            }),
301            Operator::Select => Some(wasm_encoder::Instruction::Select),
302            Operator::TypedSelect { ty } => Some(wasm_encoder::Instruction::TypedSelect(
303                wasm_encoder::ValType::from(*ty),
304            )),
305            Operator::GlobalGet { global_index } => Some(wasm_encoder::Instruction::GlobalGet(
306                global_index.index() as u32,
307            )),
308            Operator::GlobalSet { global_index } => Some(wasm_encoder::Instruction::GlobalSet(
309                global_index.index() as u32,
310            )),
311            Operator::I32Load { memory } => Some(wasm_encoder::Instruction::I32Load(
312                wasm_encoder::MemArg::from(*memory),
313            )),
314            Operator::I64Load { memory } => Some(wasm_encoder::Instruction::I64Load(
315                wasm_encoder::MemArg::from(*memory),
316            )),
317            Operator::F32Load { memory } => Some(wasm_encoder::Instruction::F32Load(
318                wasm_encoder::MemArg::from(*memory),
319            )),
320            Operator::F64Load { memory } => Some(wasm_encoder::Instruction::F64Load(
321                wasm_encoder::MemArg::from(*memory),
322            )),
323            Operator::I32Load8S { memory } => Some(wasm_encoder::Instruction::I32Load8S(
324                wasm_encoder::MemArg::from(*memory),
325            )),
326            Operator::I32Load8U { memory } => Some(wasm_encoder::Instruction::I32Load8U(
327                wasm_encoder::MemArg::from(*memory),
328            )),
329            Operator::I32Load16S { memory } => Some(wasm_encoder::Instruction::I32Load16S(
330                wasm_encoder::MemArg::from(*memory),
331            )),
332            Operator::I32Load16U { memory } => Some(wasm_encoder::Instruction::I32Load16U(
333                wasm_encoder::MemArg::from(*memory),
334            )),
335            Operator::I64Load8S { memory } => Some(wasm_encoder::Instruction::I64Load8S(
336                wasm_encoder::MemArg::from(*memory),
337            )),
338            Operator::I64Load8U { memory } => Some(wasm_encoder::Instruction::I64Load8U(
339                wasm_encoder::MemArg::from(*memory),
340            )),
341            Operator::I64Load16S { memory } => Some(wasm_encoder::Instruction::I64Load16S(
342                wasm_encoder::MemArg::from(*memory),
343            )),
344            Operator::I64Load16U { memory } => Some(wasm_encoder::Instruction::I64Load16U(
345                wasm_encoder::MemArg::from(*memory),
346            )),
347            Operator::I64Load32S { memory } => Some(wasm_encoder::Instruction::I64Load32S(
348                wasm_encoder::MemArg::from(*memory),
349            )),
350            Operator::I64Load32U { memory } => Some(wasm_encoder::Instruction::I64Load32U(
351                wasm_encoder::MemArg::from(*memory),
352            )),
353
354            Operator::I32Store { memory } => Some(wasm_encoder::Instruction::I32Store(
355                wasm_encoder::MemArg::from(*memory),
356            )),
357            Operator::I64Store { memory } => Some(wasm_encoder::Instruction::I64Store(
358                wasm_encoder::MemArg::from(*memory),
359            )),
360            Operator::F32Store { memory } => Some(wasm_encoder::Instruction::F32Store(
361                wasm_encoder::MemArg::from(*memory),
362            )),
363            Operator::F64Store { memory } => Some(wasm_encoder::Instruction::F64Store(
364                wasm_encoder::MemArg::from(*memory),
365            )),
366            Operator::I32Store8 { memory } => Some(wasm_encoder::Instruction::I32Store8(
367                wasm_encoder::MemArg::from(*memory),
368            )),
369            Operator::I32Store16 { memory } => Some(wasm_encoder::Instruction::I32Store16(
370                wasm_encoder::MemArg::from(*memory),
371            )),
372            Operator::I64Store8 { memory } => Some(wasm_encoder::Instruction::I64Store8(
373                wasm_encoder::MemArg::from(*memory),
374            )),
375            Operator::I64Store16 { memory } => Some(wasm_encoder::Instruction::I64Store16(
376                wasm_encoder::MemArg::from(*memory),
377            )),
378            Operator::I64Store32 { memory } => Some(wasm_encoder::Instruction::I64Store32(
379                wasm_encoder::MemArg::from(*memory),
380            )),
381
382            Operator::I32Const { value } => {
383                Some(wasm_encoder::Instruction::I32Const(*value as i32))
384            }
385            Operator::I64Const { value } => {
386                Some(wasm_encoder::Instruction::I64Const(*value as i64))
387            }
388            Operator::F32Const { value } => {
389                Some(wasm_encoder::Instruction::F32Const(f32::from_bits(*value)))
390            }
391            Operator::F64Const { value } => {
392                Some(wasm_encoder::Instruction::F64Const(f64::from_bits(*value)))
393            }
394
395            Operator::I32Eqz => op!(I32Eqz),
396            Operator::I32Eq => op!(I32Eq),
397            Operator::I32Ne => op!(I32Ne),
398            Operator::I32LtS => op!(I32LtS),
399            Operator::I32LtU => op!(I32LtU),
400            Operator::I32GtS => op!(I32GtS),
401            Operator::I32GtU => op!(I32GtU),
402            Operator::I32LeS => op!(I32LeS),
403            Operator::I32LeU => op!(I32LeU),
404            Operator::I32GeS => op!(I32GeS),
405            Operator::I32GeU => op!(I32GeU),
406
407            Operator::I64Eqz => op!(I64Eqz),
408
409            Operator::I64Eq => op!(I64Eq),
410            Operator::I64Ne => op!(I64Ne),
411            Operator::I64LtS => op!(I64LtS),
412            Operator::I64LtU => op!(I64LtU),
413            Operator::I64GtU => op!(I64GtU),
414            Operator::I64GtS => op!(I64GtS),
415            Operator::I64LeS => op!(I64LeS),
416            Operator::I64LeU => op!(I64LeU),
417            Operator::I64GeS => op!(I64GeS),
418            Operator::I64GeU => op!(I64GeU),
419
420            Operator::F32Eq => op!(F32Eq),
421            Operator::F32Ne => op!(F32Ne),
422            Operator::F32Lt => op!(F32Lt),
423            Operator::F32Gt => op!(F32Gt),
424            Operator::F32Le => op!(F32Le),
425            Operator::F32Ge => op!(F32Ge),
426
427            Operator::F64Eq => op!(F64Eq),
428            Operator::F64Ne => op!(F64Ne),
429            Operator::F64Lt => op!(F64Lt),
430            Operator::F64Gt => op!(F64Gt),
431            Operator::F64Le => op!(F64Le),
432            Operator::F64Ge => op!(F64Ge),
433
434            Operator::I32Clz => op!(I32Clz),
435            Operator::I32Ctz => op!(I32Ctz),
436            Operator::I32Popcnt => op!(I32Popcnt),
437
438            Operator::I32Add => op!(I32Add),
439            Operator::I32Sub => op!(I32Sub),
440            Operator::I32Mul => op!(I32Mul),
441            Operator::I32DivS => op!(I32DivS),
442            Operator::I32DivU => op!(I32DivU),
443            Operator::I32RemS => op!(I32RemS),
444            Operator::I32RemU => op!(I32RemU),
445            Operator::I32And => op!(I32And),
446            Operator::I32Or => op!(I32Or),
447            Operator::I32Xor => op!(I32Xor),
448            Operator::I32Shl => op!(I32Shl),
449            Operator::I32ShrS => op!(I32ShrS),
450            Operator::I32ShrU => op!(I32ShrU),
451            Operator::I32Rotl => op!(I32Rotl),
452            Operator::I32Rotr => op!(I32Rotr),
453
454            Operator::I64Clz => op!(I64Clz),
455            Operator::I64Ctz => op!(I64Ctz),
456            Operator::I64Popcnt => op!(I64Popcnt),
457
458            Operator::I64Add => op!(I64Add),
459            Operator::I64Sub => op!(I64Sub),
460            Operator::I64Mul => op!(I64Mul),
461            Operator::I64DivS => op!(I64DivS),
462            Operator::I64DivU => op!(I64DivU),
463            Operator::I64RemS => op!(I64RemS),
464            Operator::I64RemU => op!(I64RemU),
465            Operator::I64And => op!(I64And),
466            Operator::I64Or => op!(I64Or),
467            Operator::I64Xor => op!(I64Xor),
468            Operator::I64Shl => op!(I64Shl),
469            Operator::I64ShrS => op!(I64ShrS),
470            Operator::I64ShrU => op!(I64ShrU),
471            Operator::I64Rotl => op!(I64Rotl),
472            Operator::I64Rotr => op!(I64Rotr),
473
474            Operator::F32Abs => op!(F32Abs),
475            Operator::F32Neg => op!(F32Neg),
476            Operator::F32Ceil => op!(F32Ceil),
477            Operator::F32Floor => op!(F32Floor),
478            Operator::F32Trunc => op!(F32Trunc),
479            Operator::F32Nearest => op!(F32Nearest),
480            Operator::F32Sqrt => op!(F32Sqrt),
481
482            Operator::F32Add => op!(F32Add),
483            Operator::F32Sub => op!(F32Sub),
484            Operator::F32Mul => op!(F32Mul),
485            Operator::F32Div => op!(F32Div),
486            Operator::F32Min => op!(F32Min),
487            Operator::F32Max => op!(F32Max),
488            Operator::F32Copysign => op!(F32Copysign),
489
490            Operator::F64Abs => op!(F64Abs),
491            Operator::F64Neg => op!(F64Neg),
492            Operator::F64Ceil => op!(F64Ceil),
493            Operator::F64Floor => op!(F64Floor),
494            Operator::F64Trunc => op!(F64Trunc),
495            Operator::F64Nearest => op!(F64Nearest),
496            Operator::F64Sqrt => op!(F64Sqrt),
497
498            Operator::F64Add => op!(F64Add),
499            Operator::F64Sub => op!(F64Sub),
500            Operator::F64Mul => op!(F64Mul),
501            Operator::F64Div => op!(F64Div),
502            Operator::F64Min => op!(F64Min),
503            Operator::F64Max => op!(F64Max),
504            Operator::F64Copysign => op!(F64Copysign),
505
506            Operator::I32WrapI64 => op!(I32WrapI64),
507            Operator::I32TruncF32S => op!(I32TruncF32S),
508            Operator::I32TruncF32U => op!(I32TruncF32U),
509            Operator::I32TruncF64S => op!(I32TruncF64S),
510            Operator::I32TruncF64U => op!(I32TruncF64U),
511            Operator::I64ExtendI32S => op!(I64ExtendI32S),
512            Operator::I64ExtendI32U => op!(I64ExtendI32U),
513            Operator::I64TruncF32S => op!(I64TruncF32S),
514            Operator::I64TruncF32U => op!(I64TruncF32U),
515            Operator::I64TruncF64S => op!(I64TruncF64S),
516            Operator::I64TruncF64U => op!(I64TruncF64U),
517            Operator::F32ConvertI32S => op!(F32ConvertI32S),
518            Operator::F32ConvertI32U => op!(F32ConvertI32U),
519            Operator::F32ConvertI64S => op!(F32ConvertI64S),
520            Operator::F32ConvertI64U => op!(F32ConvertI64U),
521            Operator::F32DemoteF64 => op!(F32DemoteF64),
522            Operator::F64ConvertI32S => op!(F64ConvertI32S),
523            Operator::F64ConvertI32U => op!(F64ConvertI32U),
524            Operator::F64ConvertI64S => op!(F64ConvertI64S),
525            Operator::F64ConvertI64U => op!(F64ConvertI64U),
526            Operator::F64PromoteF32 => op!(F64PromoteF32),
527            Operator::I32Extend8S => op!(I32Extend8S),
528            Operator::I32Extend16S => op!(I32Extend16S),
529            Operator::I64Extend8S => op!(I64Extend8S),
530            Operator::I64Extend16S => op!(I64Extend16S),
531            Operator::I64Extend32S => op!(I64Extend32S),
532            Operator::I32TruncSatF32S => op!(I32TruncSatF32S),
533            Operator::I32TruncSatF32U => op!(I32TruncSatF32U),
534            Operator::I32TruncSatF64S => op!(I32TruncSatF64S),
535            Operator::I32TruncSatF64U => op!(I32TruncSatF64U),
536            Operator::I64TruncSatF32S => op!(I64TruncSatF32S),
537            Operator::I64TruncSatF32U => op!(I64TruncSatF32U),
538            Operator::I64TruncSatF64S => op!(I64TruncSatF64S),
539            Operator::I64TruncSatF64U => op!(I64TruncSatF64U),
540            Operator::F32ReinterpretI32 => op!(F32ReinterpretI32),
541            Operator::F64ReinterpretI64 => op!(F64ReinterpretI64),
542            Operator::I32ReinterpretF32 => op!(I32ReinterpretF32),
543            Operator::I64ReinterpretF64 => op!(I64ReinterpretF64),
544
545            Operator::TableGet { table_index } => Some(wasm_encoder::Instruction::TableGet(
546                table_index.index() as u32,
547            )),
548            Operator::TableSet { table_index } => Some(wasm_encoder::Instruction::TableSet(
549                table_index.index() as u32,
550            )),
551            Operator::TableGrow { table_index } => Some(wasm_encoder::Instruction::TableGrow(
552                table_index.index() as u32,
553            )),
554            Operator::TableSize { table_index } => Some(wasm_encoder::Instruction::TableSize(
555                table_index.index() as u32,
556            )),
557            Operator::MemorySize { mem } => {
558                Some(wasm_encoder::Instruction::MemorySize(mem.index() as u32))
559            }
560            Operator::MemoryGrow { mem } => {
561                Some(wasm_encoder::Instruction::MemoryGrow(mem.index() as u32))
562            }
563            Operator::MemoryCopy { dst_mem, src_mem } => {
564                Some(wasm_encoder::Instruction::MemoryCopy {
565                    src_mem: src_mem.index() as u32,
566                    dst_mem: dst_mem.index() as u32,
567                })
568            }
569            Operator::MemoryFill { mem } => {
570                Some(wasm_encoder::Instruction::MemoryFill(mem.index() as u32))
571            }
572
573            Operator::V128Load { memory } => Some(wasm_encoder::Instruction::V128Load(
574                wasm_encoder::MemArg::from(*memory),
575            )),
576            Operator::V128Load8x8S { memory } => Some(wasm_encoder::Instruction::V128Load8x8S(
577                wasm_encoder::MemArg::from(*memory),
578            )),
579            Operator::V128Load8x8U { memory } => Some(wasm_encoder::Instruction::V128Load8x8U(
580                wasm_encoder::MemArg::from(*memory),
581            )),
582            Operator::V128Load16x4S { memory } => Some(wasm_encoder::Instruction::V128Load16x4S(
583                wasm_encoder::MemArg::from(*memory),
584            )),
585            Operator::V128Load16x4U { memory } => Some(wasm_encoder::Instruction::V128Load16x4U(
586                wasm_encoder::MemArg::from(*memory),
587            )),
588            Operator::V128Load32x2S { memory } => Some(wasm_encoder::Instruction::V128Load32x2S(
589                wasm_encoder::MemArg::from(*memory),
590            )),
591            Operator::V128Load32x2U { memory } => Some(wasm_encoder::Instruction::V128Load32x2U(
592                wasm_encoder::MemArg::from(*memory),
593            )),
594            Operator::V128Load8Splat { memory } => Some(wasm_encoder::Instruction::V128Load8Splat(
595                wasm_encoder::MemArg::from(*memory),
596            )),
597            Operator::V128Load16Splat { memory } => Some(
598                wasm_encoder::Instruction::V128Load16Splat(wasm_encoder::MemArg::from(*memory)),
599            ),
600            Operator::V128Load32Splat { memory } => Some(
601                wasm_encoder::Instruction::V128Load32Splat(wasm_encoder::MemArg::from(*memory)),
602            ),
603            Operator::V128Load64Splat { memory } => Some(
604                wasm_encoder::Instruction::V128Load64Splat(wasm_encoder::MemArg::from(*memory)),
605            ),
606            Operator::V128Load32Zero { memory } => Some(wasm_encoder::Instruction::V128Load32Zero(
607                wasm_encoder::MemArg::from(*memory),
608            )),
609            Operator::V128Load64Zero { memory } => Some(wasm_encoder::Instruction::V128Load64Zero(
610                wasm_encoder::MemArg::from(*memory),
611            )),
612            Operator::V128Store { memory } => Some(wasm_encoder::Instruction::V128Store(
613                wasm_encoder::MemArg::from(*memory),
614            )),
615            Operator::V128Load8Lane { memory, lane } => {
616                Some(wasm_encoder::Instruction::V128Load8Lane {
617                    memarg: wasm_encoder::MemArg::from(*memory),
618                    lane: *lane,
619                })
620            }
621            Operator::V128Load16Lane { memory, lane } => {
622                Some(wasm_encoder::Instruction::V128Load16Lane {
623                    memarg: wasm_encoder::MemArg::from(*memory),
624                    lane: *lane,
625                })
626            }
627            Operator::V128Load32Lane { memory, lane } => {
628                Some(wasm_encoder::Instruction::V128Load32Lane {
629                    memarg: wasm_encoder::MemArg::from(*memory),
630                    lane: *lane,
631                })
632            }
633            Operator::V128Load64Lane { memory, lane } => {
634                Some(wasm_encoder::Instruction::V128Load64Lane {
635                    memarg: wasm_encoder::MemArg::from(*memory),
636                    lane: *lane,
637                })
638            }
639            Operator::V128Store8Lane { memory, lane } => {
640                Some(wasm_encoder::Instruction::V128Store8Lane {
641                    memarg: wasm_encoder::MemArg::from(*memory),
642                    lane: *lane,
643                })
644            }
645            Operator::V128Store16Lane { memory, lane } => {
646                Some(wasm_encoder::Instruction::V128Store16Lane {
647                    memarg: wasm_encoder::MemArg::from(*memory),
648                    lane: *lane,
649                })
650            }
651            Operator::V128Store32Lane { memory, lane } => {
652                Some(wasm_encoder::Instruction::V128Store32Lane {
653                    memarg: wasm_encoder::MemArg::from(*memory),
654                    lane: *lane,
655                })
656            }
657            Operator::V128Store64Lane { memory, lane } => {
658                Some(wasm_encoder::Instruction::V128Store64Lane {
659                    memarg: wasm_encoder::MemArg::from(*memory),
660                    lane: *lane,
661                })
662            }
663            Operator::V128Const { value } => {
664                Some(wasm_encoder::Instruction::V128Const(*value as i128))
665            }
666
667            Operator::I8x16Shuffle { lanes } => {
668                Some(wasm_encoder::Instruction::I8x16Shuffle(lanes.clone()))
669            }
670
671            Operator::I8x16ExtractLaneS { lane } => {
672                Some(wasm_encoder::Instruction::I8x16ExtractLaneS(*lane))
673            }
674            Operator::I8x16ExtractLaneU { lane } => {
675                Some(wasm_encoder::Instruction::I8x16ExtractLaneU(*lane))
676            }
677            Operator::I8x16ReplaceLane { lane } => {
678                Some(wasm_encoder::Instruction::I8x16ReplaceLane(*lane))
679            }
680            Operator::I16x8ExtractLaneS { lane } => {
681                Some(wasm_encoder::Instruction::I16x8ExtractLaneS(*lane))
682            }
683            Operator::I16x8ExtractLaneU { lane } => {
684                Some(wasm_encoder::Instruction::I16x8ExtractLaneU(*lane))
685            }
686            Operator::I16x8ReplaceLane { lane } => {
687                Some(wasm_encoder::Instruction::I16x8ReplaceLane(*lane))
688            }
689            Operator::I32x4ExtractLane { lane } => {
690                Some(wasm_encoder::Instruction::I32x4ExtractLane(*lane))
691            }
692            Operator::I32x4ReplaceLane { lane } => {
693                Some(wasm_encoder::Instruction::I32x4ReplaceLane(*lane))
694            }
695            Operator::I64x2ExtractLane { lane } => {
696                Some(wasm_encoder::Instruction::I64x2ExtractLane(*lane))
697            }
698            Operator::I64x2ReplaceLane { lane } => {
699                Some(wasm_encoder::Instruction::I64x2ReplaceLane(*lane))
700            }
701            Operator::F32x4ExtractLane { lane } => {
702                Some(wasm_encoder::Instruction::F32x4ExtractLane(*lane))
703            }
704            Operator::F32x4ReplaceLane { lane } => {
705                Some(wasm_encoder::Instruction::F32x4ReplaceLane(*lane))
706            }
707            Operator::F64x2ExtractLane { lane } => {
708                Some(wasm_encoder::Instruction::F64x2ExtractLane(*lane))
709            }
710            Operator::F64x2ReplaceLane { lane } => {
711                Some(wasm_encoder::Instruction::F64x2ReplaceLane(*lane))
712            }
713
714            Operator::I8x16Swizzle => Some(wasm_encoder::Instruction::I8x16Swizzle),
715            Operator::I8x16Splat => Some(wasm_encoder::Instruction::I8x16Splat),
716            Operator::I16x8Splat => Some(wasm_encoder::Instruction::I16x8Splat),
717            Operator::I32x4Splat => Some(wasm_encoder::Instruction::I32x4Splat),
718            Operator::I64x2Splat => Some(wasm_encoder::Instruction::I64x2Splat),
719            Operator::F32x4Splat => Some(wasm_encoder::Instruction::F32x4Splat),
720            Operator::F64x2Splat => Some(wasm_encoder::Instruction::F64x2Splat),
721
722            Operator::I8x16Eq => Some(wasm_encoder::Instruction::I8x16Eq),
723            Operator::I8x16Ne => Some(wasm_encoder::Instruction::I8x16Ne),
724            Operator::I8x16LtS => Some(wasm_encoder::Instruction::I8x16LtS),
725            Operator::I8x16LtU => Some(wasm_encoder::Instruction::I8x16LtU),
726            Operator::I8x16GtS => Some(wasm_encoder::Instruction::I8x16GtS),
727            Operator::I8x16GtU => Some(wasm_encoder::Instruction::I8x16GtU),
728            Operator::I8x16LeS => Some(wasm_encoder::Instruction::I8x16LeS),
729            Operator::I8x16LeU => Some(wasm_encoder::Instruction::I8x16LeU),
730            Operator::I8x16GeS => Some(wasm_encoder::Instruction::I8x16GeS),
731            Operator::I8x16GeU => Some(wasm_encoder::Instruction::I8x16GeU),
732
733            Operator::I16x8Eq => Some(wasm_encoder::Instruction::I16x8Eq),
734            Operator::I16x8Ne => Some(wasm_encoder::Instruction::I16x8Ne),
735            Operator::I16x8LtS => Some(wasm_encoder::Instruction::I16x8LtS),
736            Operator::I16x8LtU => Some(wasm_encoder::Instruction::I16x8LtU),
737            Operator::I16x8GtS => Some(wasm_encoder::Instruction::I16x8GtS),
738            Operator::I16x8GtU => Some(wasm_encoder::Instruction::I16x8GtU),
739            Operator::I16x8LeS => Some(wasm_encoder::Instruction::I16x8LeS),
740            Operator::I16x8LeU => Some(wasm_encoder::Instruction::I16x8LeU),
741            Operator::I16x8GeS => Some(wasm_encoder::Instruction::I16x8GeS),
742            Operator::I16x8GeU => Some(wasm_encoder::Instruction::I16x8GeU),
743
744            Operator::I32x4Eq => Some(wasm_encoder::Instruction::I32x4Eq),
745            Operator::I32x4Ne => Some(wasm_encoder::Instruction::I32x4Ne),
746            Operator::I32x4LtS => Some(wasm_encoder::Instruction::I32x4LtS),
747            Operator::I32x4LtU => Some(wasm_encoder::Instruction::I32x4LtU),
748            Operator::I32x4GtS => Some(wasm_encoder::Instruction::I32x4GtS),
749            Operator::I32x4GtU => Some(wasm_encoder::Instruction::I32x4GtU),
750            Operator::I32x4LeS => Some(wasm_encoder::Instruction::I32x4LeS),
751            Operator::I32x4LeU => Some(wasm_encoder::Instruction::I32x4LeU),
752            Operator::I32x4GeS => Some(wasm_encoder::Instruction::I32x4GeS),
753            Operator::I32x4GeU => Some(wasm_encoder::Instruction::I32x4GeU),
754
755            Operator::I64x2Eq => Some(wasm_encoder::Instruction::I64x2Eq),
756            Operator::I64x2Ne => Some(wasm_encoder::Instruction::I64x2Ne),
757            Operator::I64x2LtS => Some(wasm_encoder::Instruction::I64x2LtS),
758            Operator::I64x2GtS => Some(wasm_encoder::Instruction::I64x2GtS),
759            Operator::I64x2LeS => Some(wasm_encoder::Instruction::I64x2LeS),
760            Operator::I64x2GeS => Some(wasm_encoder::Instruction::I64x2GeS),
761
762            Operator::F32x4Eq => Some(wasm_encoder::Instruction::F32x4Eq),
763            Operator::F32x4Ne => Some(wasm_encoder::Instruction::F32x4Ne),
764            Operator::F32x4Lt => Some(wasm_encoder::Instruction::F32x4Lt),
765            Operator::F32x4Gt => Some(wasm_encoder::Instruction::F32x4Gt),
766            Operator::F32x4Le => Some(wasm_encoder::Instruction::F32x4Le),
767            Operator::F32x4Ge => Some(wasm_encoder::Instruction::F32x4Ge),
768
769            Operator::F64x2Eq => Some(wasm_encoder::Instruction::F64x2Eq),
770            Operator::F64x2Ne => Some(wasm_encoder::Instruction::F64x2Ne),
771            Operator::F64x2Lt => Some(wasm_encoder::Instruction::F64x2Lt),
772            Operator::F64x2Gt => Some(wasm_encoder::Instruction::F64x2Gt),
773            Operator::F64x2Le => Some(wasm_encoder::Instruction::F64x2Le),
774            Operator::F64x2Ge => Some(wasm_encoder::Instruction::F64x2Ge),
775
776            Operator::V128Not => Some(wasm_encoder::Instruction::V128Not),
777            Operator::V128And => Some(wasm_encoder::Instruction::V128And),
778            Operator::V128AndNot => Some(wasm_encoder::Instruction::V128AndNot),
779            Operator::V128Or => Some(wasm_encoder::Instruction::V128Or),
780            Operator::V128Xor => Some(wasm_encoder::Instruction::V128Xor),
781            Operator::V128Bitselect => Some(wasm_encoder::Instruction::V128Bitselect),
782            Operator::V128AnyTrue => Some(wasm_encoder::Instruction::V128AnyTrue),
783
784            Operator::I8x16Abs => Some(wasm_encoder::Instruction::I8x16Abs),
785            Operator::I8x16Neg => Some(wasm_encoder::Instruction::I8x16Neg),
786            Operator::I8x16Popcnt => Some(wasm_encoder::Instruction::I8x16Popcnt),
787            Operator::I8x16AllTrue => Some(wasm_encoder::Instruction::I8x16AllTrue),
788            Operator::I8x16Bitmask => Some(wasm_encoder::Instruction::I8x16Bitmask),
789            Operator::I8x16NarrowI16x8S => Some(wasm_encoder::Instruction::I8x16NarrowI16x8S),
790            Operator::I8x16NarrowI16x8U => Some(wasm_encoder::Instruction::I8x16NarrowI16x8U),
791            Operator::I8x16Shl => Some(wasm_encoder::Instruction::I8x16Shl),
792            Operator::I8x16ShrS => Some(wasm_encoder::Instruction::I8x16ShrS),
793            Operator::I8x16ShrU => Some(wasm_encoder::Instruction::I8x16ShrU),
794            Operator::I8x16Add => Some(wasm_encoder::Instruction::I8x16Add),
795            Operator::I8x16AddSatS => Some(wasm_encoder::Instruction::I8x16AddSatS),
796            Operator::I8x16AddSatU => Some(wasm_encoder::Instruction::I8x16AddSatU),
797            Operator::I8x16Sub => Some(wasm_encoder::Instruction::I8x16Sub),
798            Operator::I8x16SubSatS => Some(wasm_encoder::Instruction::I8x16SubSatS),
799            Operator::I8x16SubSatU => Some(wasm_encoder::Instruction::I8x16SubSatU),
800            Operator::I8x16MinS => Some(wasm_encoder::Instruction::I8x16MinS),
801            Operator::I8x16MinU => Some(wasm_encoder::Instruction::I8x16MinU),
802            Operator::I8x16MaxS => Some(wasm_encoder::Instruction::I8x16MaxS),
803            Operator::I8x16MaxU => Some(wasm_encoder::Instruction::I8x16MaxU),
804            Operator::I8x16AvgrU => Some(wasm_encoder::Instruction::I8x16AvgrU),
805
806            Operator::I16x8ExtAddPairwiseI8x16S => {
807                Some(wasm_encoder::Instruction::I16x8ExtAddPairwiseI8x16S)
808            }
809            Operator::I16x8ExtAddPairwiseI8x16U => {
810                Some(wasm_encoder::Instruction::I16x8ExtAddPairwiseI8x16U)
811            }
812            Operator::I16x8Abs => Some(wasm_encoder::Instruction::I16x8Abs),
813            Operator::I16x8Neg => Some(wasm_encoder::Instruction::I16x8Neg),
814            Operator::I16x8Q15MulrSatS => Some(wasm_encoder::Instruction::I16x8Q15MulrSatS),
815            Operator::I16x8AllTrue => Some(wasm_encoder::Instruction::I16x8AllTrue),
816            Operator::I16x8Bitmask => Some(wasm_encoder::Instruction::I16x8Bitmask),
817            Operator::I16x8NarrowI32x4S => Some(wasm_encoder::Instruction::I16x8NarrowI32x4S),
818            Operator::I16x8NarrowI32x4U => Some(wasm_encoder::Instruction::I16x8NarrowI32x4U),
819            Operator::I16x8ExtendLowI8x16S => Some(wasm_encoder::Instruction::I16x8ExtendLowI8x16S),
820            Operator::I16x8ExtendHighI8x16S => {
821                Some(wasm_encoder::Instruction::I16x8ExtendHighI8x16S)
822            }
823            Operator::I16x8ExtendLowI8x16U => Some(wasm_encoder::Instruction::I16x8ExtendLowI8x16U),
824            Operator::I16x8ExtendHighI8x16U => {
825                Some(wasm_encoder::Instruction::I16x8ExtendHighI8x16U)
826            }
827            Operator::I16x8Shl => Some(wasm_encoder::Instruction::I16x8Shl),
828            Operator::I16x8ShrS => Some(wasm_encoder::Instruction::I16x8ShrS),
829            Operator::I16x8ShrU => Some(wasm_encoder::Instruction::I16x8ShrU),
830            Operator::I16x8Add => Some(wasm_encoder::Instruction::I16x8Add),
831            Operator::I16x8AddSatS => Some(wasm_encoder::Instruction::I16x8AddSatS),
832            Operator::I16x8AddSatU => Some(wasm_encoder::Instruction::I16x8AddSatU),
833            Operator::I16x8Sub => Some(wasm_encoder::Instruction::I16x8Sub),
834            Operator::I16x8SubSatS => Some(wasm_encoder::Instruction::I16x8SubSatS),
835            Operator::I16x8SubSatU => Some(wasm_encoder::Instruction::I16x8SubSatU),
836            Operator::I16x8Mul => Some(wasm_encoder::Instruction::I16x8Mul),
837            Operator::I16x8MinS => Some(wasm_encoder::Instruction::I16x8MinS),
838            Operator::I16x8MinU => Some(wasm_encoder::Instruction::I16x8MinU),
839            Operator::I16x8MaxS => Some(wasm_encoder::Instruction::I16x8MaxS),
840            Operator::I16x8MaxU => Some(wasm_encoder::Instruction::I16x8MaxU),
841            Operator::I16x8AvgrU => Some(wasm_encoder::Instruction::I16x8AvgrU),
842            Operator::I16x8ExtMulLowI8x16S => Some(wasm_encoder::Instruction::I16x8ExtMulLowI8x16S),
843            Operator::I16x8ExtMulHighI8x16S => {
844                Some(wasm_encoder::Instruction::I16x8ExtMulHighI8x16S)
845            }
846            Operator::I16x8ExtMulLowI8x16U => Some(wasm_encoder::Instruction::I16x8ExtMulLowI8x16U),
847            Operator::I16x8ExtMulHighI8x16U => {
848                Some(wasm_encoder::Instruction::I16x8ExtMulHighI8x16U)
849            }
850
851            Operator::I32x4ExtAddPairwiseI16x8S => {
852                Some(wasm_encoder::Instruction::I32x4ExtAddPairwiseI16x8S)
853            }
854            Operator::I32x4ExtAddPairwiseI16x8U => {
855                Some(wasm_encoder::Instruction::I32x4ExtAddPairwiseI16x8U)
856            }
857            Operator::I32x4Abs => Some(wasm_encoder::Instruction::I32x4Abs),
858            Operator::I32x4Neg => Some(wasm_encoder::Instruction::I32x4Neg),
859            Operator::I32x4AllTrue => Some(wasm_encoder::Instruction::I32x4AllTrue),
860            Operator::I32x4Bitmask => Some(wasm_encoder::Instruction::I32x4Bitmask),
861            Operator::I32x4ExtendLowI16x8S => Some(wasm_encoder::Instruction::I32x4ExtendLowI16x8S),
862            Operator::I32x4ExtendHighI16x8S => {
863                Some(wasm_encoder::Instruction::I32x4ExtendHighI16x8S)
864            }
865            Operator::I32x4ExtendLowI16x8U => Some(wasm_encoder::Instruction::I32x4ExtendLowI16x8U),
866            Operator::I32x4ExtendHighI16x8U => {
867                Some(wasm_encoder::Instruction::I32x4ExtendHighI16x8U)
868            }
869            Operator::I32x4Shl => Some(wasm_encoder::Instruction::I32x4Shl),
870            Operator::I32x4ShrS => Some(wasm_encoder::Instruction::I32x4ShrS),
871            Operator::I32x4ShrU => Some(wasm_encoder::Instruction::I32x4ShrU),
872            Operator::I32x4Add => Some(wasm_encoder::Instruction::I32x4Add),
873            Operator::I32x4Sub => Some(wasm_encoder::Instruction::I32x4Sub),
874            Operator::I32x4Mul => Some(wasm_encoder::Instruction::I32x4Mul),
875            Operator::I32x4MinS => Some(wasm_encoder::Instruction::I32x4MinS),
876            Operator::I32x4MinU => Some(wasm_encoder::Instruction::I32x4MinU),
877            Operator::I32x4MaxS => Some(wasm_encoder::Instruction::I32x4MaxS),
878            Operator::I32x4MaxU => Some(wasm_encoder::Instruction::I32x4MaxU),
879            Operator::I32x4DotI16x8S => Some(wasm_encoder::Instruction::I32x4DotI16x8S),
880            Operator::I32x4ExtMulLowI16x8S => Some(wasm_encoder::Instruction::I32x4ExtMulLowI16x8S),
881            Operator::I32x4ExtMulHighI16x8S => {
882                Some(wasm_encoder::Instruction::I32x4ExtMulHighI16x8S)
883            }
884            Operator::I32x4ExtMulLowI16x8U => Some(wasm_encoder::Instruction::I32x4ExtMulLowI16x8U),
885            Operator::I32x4ExtMulHighI16x8U => {
886                Some(wasm_encoder::Instruction::I32x4ExtMulHighI16x8U)
887            }
888
889            Operator::I64x2Abs => Some(wasm_encoder::Instruction::I64x2Abs),
890            Operator::I64x2Neg => Some(wasm_encoder::Instruction::I64x2Neg),
891            Operator::I64x2AllTrue => Some(wasm_encoder::Instruction::I64x2AllTrue),
892            Operator::I64x2Bitmask => Some(wasm_encoder::Instruction::I64x2Bitmask),
893            Operator::I64x2ExtendLowI32x4S => Some(wasm_encoder::Instruction::I64x2ExtendLowI32x4S),
894            Operator::I64x2ExtendHighI32x4S => {
895                Some(wasm_encoder::Instruction::I64x2ExtendHighI32x4S)
896            }
897            Operator::I64x2ExtendLowI32x4U => Some(wasm_encoder::Instruction::I64x2ExtendLowI32x4U),
898            Operator::I64x2ExtendHighI32x4U => {
899                Some(wasm_encoder::Instruction::I64x2ExtendHighI32x4U)
900            }
901            Operator::I64x2Shl => Some(wasm_encoder::Instruction::I64x2Shl),
902            Operator::I64x2ShrS => Some(wasm_encoder::Instruction::I64x2ShrS),
903            Operator::I64x2ShrU => Some(wasm_encoder::Instruction::I64x2ShrU),
904            Operator::I64x2Add => Some(wasm_encoder::Instruction::I64x2Add),
905            Operator::I64x2Sub => Some(wasm_encoder::Instruction::I64x2Sub),
906            Operator::I64x2Mul => Some(wasm_encoder::Instruction::I64x2Mul),
907            Operator::I64x2ExtMulLowI32x4S => Some(wasm_encoder::Instruction::I64x2ExtMulLowI32x4S),
908            Operator::I64x2ExtMulHighI32x4S => {
909                Some(wasm_encoder::Instruction::I64x2ExtMulHighI32x4S)
910            }
911            Operator::I64x2ExtMulLowI32x4U => Some(wasm_encoder::Instruction::I64x2ExtMulLowI32x4U),
912            Operator::I64x2ExtMulHighI32x4U => {
913                Some(wasm_encoder::Instruction::I64x2ExtMulHighI32x4U)
914            }
915
916            Operator::F32x4Ceil => Some(wasm_encoder::Instruction::F32x4Ceil),
917            Operator::F32x4Floor => Some(wasm_encoder::Instruction::F32x4Floor),
918            Operator::F32x4Trunc => Some(wasm_encoder::Instruction::F32x4Trunc),
919            Operator::F32x4Nearest => Some(wasm_encoder::Instruction::F32x4Nearest),
920            Operator::F32x4Abs => Some(wasm_encoder::Instruction::F32x4Abs),
921            Operator::F32x4Neg => Some(wasm_encoder::Instruction::F32x4Neg),
922            Operator::F32x4Sqrt => Some(wasm_encoder::Instruction::F32x4Sqrt),
923            Operator::F32x4Add => Some(wasm_encoder::Instruction::F32x4Add),
924            Operator::F32x4Sub => Some(wasm_encoder::Instruction::F32x4Sub),
925            Operator::F32x4Mul => Some(wasm_encoder::Instruction::F32x4Mul),
926            Operator::F32x4Div => Some(wasm_encoder::Instruction::F32x4Div),
927            Operator::F32x4Min => Some(wasm_encoder::Instruction::F32x4Min),
928            Operator::F32x4Max => Some(wasm_encoder::Instruction::F32x4Max),
929            Operator::F32x4PMin => Some(wasm_encoder::Instruction::F32x4PMin),
930            Operator::F32x4PMax => Some(wasm_encoder::Instruction::F32x4PMax),
931
932            Operator::F64x2Ceil => Some(wasm_encoder::Instruction::F64x2Ceil),
933            Operator::F64x2Floor => Some(wasm_encoder::Instruction::F64x2Floor),
934            Operator::F64x2Trunc => Some(wasm_encoder::Instruction::F64x2Trunc),
935            Operator::F64x2Nearest => Some(wasm_encoder::Instruction::F64x2Nearest),
936            Operator::F64x2Abs => Some(wasm_encoder::Instruction::F64x2Abs),
937            Operator::F64x2Neg => Some(wasm_encoder::Instruction::F64x2Neg),
938            Operator::F64x2Sqrt => Some(wasm_encoder::Instruction::F64x2Sqrt),
939            Operator::F64x2Add => Some(wasm_encoder::Instruction::F64x2Add),
940            Operator::F64x2Sub => Some(wasm_encoder::Instruction::F64x2Sub),
941            Operator::F64x2Mul => Some(wasm_encoder::Instruction::F64x2Mul),
942            Operator::F64x2Div => Some(wasm_encoder::Instruction::F64x2Div),
943            Operator::F64x2Min => Some(wasm_encoder::Instruction::F64x2Min),
944            Operator::F64x2Max => Some(wasm_encoder::Instruction::F64x2Max),
945            Operator::F64x2PMin => Some(wasm_encoder::Instruction::F64x2PMin),
946            Operator::F64x2PMax => Some(wasm_encoder::Instruction::F64x2PMax),
947
948            Operator::I32x4TruncSatF32x4S => Some(wasm_encoder::Instruction::I32x4TruncSatF32x4S),
949            Operator::I32x4TruncSatF32x4U => Some(wasm_encoder::Instruction::I32x4TruncSatF32x4U),
950
951            Operator::F32x4ConvertI32x4S => Some(wasm_encoder::Instruction::F32x4ConvertI32x4S),
952            Operator::F32x4ConvertI32x4U => Some(wasm_encoder::Instruction::F32x4ConvertI32x4U),
953            Operator::I32x4TruncSatF64x2SZero => {
954                Some(wasm_encoder::Instruction::I32x4TruncSatF64x2SZero)
955            }
956            Operator::I32x4TruncSatF64x2UZero => {
957                Some(wasm_encoder::Instruction::I32x4TruncSatF64x2UZero)
958            }
959            Operator::F64x2ConvertLowI32x4S => {
960                Some(wasm_encoder::Instruction::F64x2ConvertLowI32x4S)
961            }
962            Operator::F64x2ConvertLowI32x4U => {
963                Some(wasm_encoder::Instruction::F64x2ConvertLowI32x4U)
964            }
965            Operator::F32x4DemoteF64x2Zero => Some(wasm_encoder::Instruction::F32x4DemoteF64x2Zero),
966            Operator::F64x2PromoteLowF32x4 => Some(wasm_encoder::Instruction::F64x2PromoteLowF32x4),
967
968            Operator::CallRef { sig_index } => {
969                Some(wasm_encoder::Instruction::CallRef(sig_index.index() as u32))
970            }
971            Operator::RefIsNull => Some(wasm_encoder::Instruction::RefIsNull),
972            Operator::RefNull { sig_index } => Some(wasm_encoder::Instruction::RefNull(
973                wasm_encoder::HeapType::Concrete(sig_index.index() as u32),
974            )),
975            Operator::RefFunc { func_index } => {
976                Some(wasm_encoder::Instruction::RefFunc(func_index.index() as u32))
977            }
978        };
979
980        if let Some(inst) = inst {
981            func.instruction(&inst);
982        }
983    }
984}
985
986pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
987    let mut into_mod = wasm_encoder::Module::new();
988
989    let mut types = wasm_encoder::TypeSection::new();
990    for sig_data in module.signatures.values() {
991        let params = sig_data
992            .params
993            .iter()
994            .map(|&ty| wasm_encoder::ValType::from(ty));
995        let returns = sig_data
996            .returns
997            .iter()
998            .map(|&ty| wasm_encoder::ValType::from(ty));
999        types.function(params, returns);
1000    }
1001    into_mod.section(&types);
1002
1003    let mut imports = wasm_encoder::ImportSection::new();
1004    let mut num_func_imports = 0;
1005    let mut num_table_imports = 0;
1006    let mut num_global_imports = 0;
1007    let mut num_mem_imports = 0;
1008    for import in &module.imports {
1009        let entity = match &import.kind {
1010            &ImportKind::Func(func) => {
1011                num_func_imports += 1;
1012                let func = &module.funcs[func];
1013                wasm_encoder::EntityType::Function(func.sig().index() as u32)
1014            }
1015            &ImportKind::Table(table) => {
1016                num_table_imports += 1;
1017                let table = &module.tables[table];
1018                wasm_encoder::EntityType::Table(wasm_encoder::TableType {
1019                    element_type: wasm_encoder::RefType::from(table.ty),
1020                    minimum: table.initial,
1021                    maximum: table.max,
1022                    table64: false,
1023                })
1024            }
1025            &ImportKind::Global(global) => {
1026                num_global_imports += 1;
1027                let global = &module.globals[global];
1028                wasm_encoder::EntityType::Global(wasm_encoder::GlobalType {
1029                    val_type: wasm_encoder::ValType::from(global.ty),
1030                    mutable: global.mutable,
1031                    shared: false,
1032                })
1033            }
1034            &ImportKind::Memory(mem) => {
1035                num_mem_imports += 1;
1036                let mem = &module.memories[mem];
1037                wasm_encoder::EntityType::Memory(wasm_encoder::MemoryType {
1038                    memory64: false,
1039                    shared: false,
1040                    minimum: mem.initial_pages as u64,
1041                    maximum: mem.maximum_pages.map(|val| val as u64),
1042                    page_size_log2: None,
1043                })
1044            }
1045        };
1046        imports.import(&import.module[..], &import.name[..], entity);
1047    }
1048
1049    into_mod.section(&imports);
1050
1051    let mut funcs = wasm_encoder::FunctionSection::new();
1052    for (func, func_decl) in module.funcs.entries().skip(num_func_imports) {
1053        match func_decl {
1054            FuncDecl::Import(_, _) => anyhow::bail!("Import comes after func with body: {}", func),
1055            FuncDecl::Lazy(sig, _, _)
1056            | FuncDecl::Body(sig, _, _)
1057            | FuncDecl::Compiled(sig, _, _) => {
1058                funcs.function(sig.index() as u32);
1059            }
1060            FuncDecl::None => panic!("FuncDecl::None at compilation time"),
1061        }
1062    }
1063    into_mod.section(&funcs);
1064
1065    let mut tables = wasm_encoder::TableSection::new();
1066    for table_data in module.tables.values().skip(num_table_imports) {
1067        tables.table(wasm_encoder::TableType {
1068            element_type: wasm_encoder::RefType::from(table_data.ty),
1069            minimum: table_data.initial,
1070            maximum: table_data.max,
1071            table64: false,
1072        });
1073    }
1074    into_mod.section(&tables);
1075
1076    let mut memories = wasm_encoder::MemorySection::new();
1077    for mem_data in module.memories.values().skip(num_mem_imports) {
1078        memories.memory(wasm_encoder::MemoryType {
1079            minimum: mem_data.initial_pages as u64,
1080            maximum: mem_data.maximum_pages.map(|val| val as u64),
1081            memory64: false,
1082            shared: false,
1083            page_size_log2: None,
1084        });
1085    }
1086    into_mod.section(&memories);
1087
1088    let mut globals = wasm_encoder::GlobalSection::new();
1089    for global_data in module.globals.values().skip(num_global_imports) {
1090        globals.global(
1091            wasm_encoder::GlobalType {
1092                val_type: wasm_encoder::ValType::from(global_data.ty),
1093                mutable: global_data.mutable,
1094                shared: false,
1095            },
1096            &const_init(global_data.ty, global_data.value),
1097        );
1098    }
1099    into_mod.section(&globals);
1100
1101    let mut exports = wasm_encoder::ExportSection::new();
1102    for export in &module.exports {
1103        match &export.kind {
1104            &ExportKind::Table(table) => {
1105                exports.export(
1106                    &export.name[..],
1107                    wasm_encoder::ExportKind::Table,
1108                    table.index() as u32,
1109                );
1110            }
1111            &ExportKind::Func(func) => {
1112                exports.export(
1113                    &export.name[..],
1114                    wasm_encoder::ExportKind::Func,
1115                    func.index() as u32,
1116                );
1117            }
1118            &ExportKind::Memory(mem) => {
1119                exports.export(
1120                    &export.name[..],
1121                    wasm_encoder::ExportKind::Memory,
1122                    mem.index() as u32,
1123                );
1124            }
1125            &ExportKind::Global(global) => {
1126                exports.export(
1127                    &export.name[..],
1128                    wasm_encoder::ExportKind::Global,
1129                    global.index() as u32,
1130                );
1131            }
1132        }
1133    }
1134    into_mod.section(&exports);
1135
1136    if let Some(start) = module.start_func {
1137        let start = wasm_encoder::StartSection {
1138            function_index: start.index() as u32,
1139        };
1140        into_mod.section(&start);
1141    }
1142
1143    let mut elem = wasm_encoder::ElementSection::new();
1144    for (table, table_data) in module.tables.entries() {
1145        if let Some(elts) = &table_data.func_elements {
1146            for (i, &elt) in elts.iter().enumerate() {
1147                if elt.is_valid() {
1148                    match table_data.ty {
1149                        Type::FuncRef => {
1150                            elem.active(
1151                                Some(table.index() as u32),
1152                                &wasm_encoder::ConstExpr::i32_const(i as i32),
1153                                wasm_encoder::Elements::Functions(&[elt.index() as u32]),
1154                            );
1155                        }
1156                        Type::TypedFuncRef(..) => {
1157                            elem.active(
1158                                Some(table.index() as u32),
1159                                &wasm_encoder::ConstExpr::i32_const(i as i32),
1160                                wasm_encoder::Elements::Expressions(
1161                                    table_data.ty.into(),
1162                                    &[wasm_encoder::ConstExpr::ref_func(elt.index() as u32)],
1163                                ),
1164                            );
1165                        }
1166                        _ => unreachable!(),
1167                    }
1168                }
1169            }
1170        }
1171    }
1172    into_mod.section(&elem);
1173
1174    let mut code = wasm_encoder::CodeSection::new();
1175
1176    let bodies = module
1177        .funcs
1178        .entries()
1179        .skip(num_func_imports)
1180        .collect::<Vec<_>>()
1181        .par_iter()
1182        .map(|(func, func_decl)| -> Result<_> {
1183            match func_decl {
1184                FuncDecl::Lazy(_, _name, reader) => {
1185                    let data = &module.orig_bytes.unwrap()[reader.range()];
1186                    Ok(Cow::Borrowed(data))
1187                }
1188                FuncDecl::Compiled(_, _name, bytes) => Ok(Cow::Borrowed(&bytes[..])),
1189                FuncDecl::Body(_, name, body) => {
1190                    log::debug!("Compiling {} \"{}\"", func, name);
1191                    WasmFuncBackend::compile(body).map(|func| Cow::Owned(func.into_raw_body()))
1192                }
1193                FuncDecl::Import(_, _) => unreachable!("Should have skipped imports"),
1194                FuncDecl::None => panic!("FuncDecl::None at compilation time"),
1195            }
1196        })
1197        .collect::<Result<Vec<_>>>()?;
1198
1199    for body in bodies {
1200        code.raw(&body);
1201    }
1202    into_mod.section(&code);
1203
1204    let mut data = wasm_encoder::DataSection::new();
1205    for (mem, mem_data) in module.memories.entries() {
1206        for segment in &mem_data.segments {
1207            data.active(
1208                mem.index() as u32,
1209                &wasm_encoder::ConstExpr::i32_const(segment.offset as i32),
1210                segment.data.iter().copied(),
1211            );
1212        }
1213    }
1214    into_mod.section(&data);
1215
1216    let mut names = wasm_encoder::NameSection::new();
1217    let mut func_names = wasm_encoder::NameMap::new();
1218    for (func, decl) in module.funcs.entries() {
1219        func_names.append(func.index() as u32, decl.name());
1220    }
1221    names.functions(&func_names);
1222    into_mod.section(&names);
1223
1224    for (custom_name, &custom_data) in &module.custom_sections {
1225        let section = wasm_encoder::CustomSection {
1226            name: custom_name.into(),
1227            data: custom_data.into(),
1228        };
1229        into_mod.section(&section);
1230    }
1231
1232    Ok(into_mod.finish())
1233}
1234
1235fn const_init(ty: Type, value: Option<u64>) -> wasm_encoder::ConstExpr {
1236    let bits = value.unwrap_or(0);
1237    match ty {
1238        Type::I32 => wasm_encoder::ConstExpr::i32_const(bits as u32 as i32),
1239        Type::I64 => wasm_encoder::ConstExpr::i64_const(bits as i64),
1240        Type::F32 => wasm_encoder::ConstExpr::f32_const(f32::from_bits(bits as u32)),
1241        Type::F64 => wasm_encoder::ConstExpr::f64_const(f64::from_bits(bits as u64)),
1242        Type::TypedFuncRef(true, sig) if bits == 0 => {
1243            let hty = wasm_encoder::HeapType::Concrete(sig);
1244            wasm_encoder::ConstExpr::ref_null(hty)
1245        }
1246        _ => unimplemented!(),
1247    }
1248}