1use 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 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 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 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, 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, 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, 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(§ion);
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}