1mod bounds_checks;
78
79use super::func_environ::{FuncEnvironment, GlobalVariable};
80use super::func_state::{ControlStackFrame, ElseData, FuncTranslationState};
81use super::translation_utils::{block_with_params, f32_translation, f64_translation};
82use crate::{HashMap, hash_map};
83use core::convert::TryFrom;
84use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
85use cranelift_codegen::ir::immediates::Offset32;
86use cranelift_codegen::ir::types::*;
87use cranelift_codegen::ir::{
88 self, AtomicRmwOp, BlockArg, ConstantData, InstBuilder, JumpTableData, MemFlags, Value,
89 ValueLabel,
90};
91use cranelift_codegen::packed_option::ReservedValue;
92use cranelift_frontend::{FunctionBuilder, Variable};
93use itertools::Itertools;
94use smallvec::SmallVec;
95use std::vec::Vec;
96
97use wasmer_compiler::wasmparser::{MemArg, Operator};
98use wasmer_compiler::{ModuleTranslationState, from_binaryreadererror_wasmerror, wasm_unsupported};
99use wasmer_types::{
100 FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex, WasmResult,
101};
102
103macro_rules! unwrap_or_return_unreachable_state {
110 ($state:ident, $value:expr_2021) => {
111 match $value {
112 Reachability::Reachable(x) => x,
113 Reachability::Unreachable => {
114 $state.reachable = false;
115 return Ok(());
116 }
117 }
118 };
119}
120
121#[allow(clippy::unneeded_field_pattern, clippy::cognitive_complexity)]
123pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
126 module_translation_state: &ModuleTranslationState,
127 op: &Operator,
128 builder: &mut FunctionBuilder,
129 state: &mut FuncTranslationState,
130 environ: &mut FE,
131) -> WasmResult<()> {
132 if !state.reachable {
133 translate_unreachable_operator(module_translation_state, op, builder, state, environ)?;
134 return Ok(());
135 }
136
137 match op {
139 Operator::LocalGet { local_index } => {
144 let val = builder.use_var(Variable::from_u32(*local_index));
145 state.push1(val);
146 let label = ValueLabel::from_u32(*local_index);
147 builder.set_val_label(val, label);
148 }
149 Operator::LocalSet { local_index } => {
150 let mut val = state.pop1();
151
152 let ty = builder.func.dfg.value_type(val);
154 if ty.is_vector() {
155 val = optionally_bitcast_vector(val, I8X16, builder);
156 }
157
158 builder.def_var(Variable::from_u32(*local_index), val);
159 let label = ValueLabel::from_u32(*local_index);
160 builder.set_val_label(val, label);
161 }
162 Operator::LocalTee { local_index } => {
163 let mut val = state.peek1();
164
165 let ty = builder.func.dfg.value_type(val);
167 if ty.is_vector() {
168 val = optionally_bitcast_vector(val, I8X16, builder);
169 }
170
171 builder.def_var(Variable::from_u32(*local_index), val);
172 let label = ValueLabel::from_u32(*local_index);
173 builder.set_val_label(val, label);
174 }
175 Operator::GlobalGet { global_index } => {
179 let val = match state.get_global(builder.func, *global_index, environ)? {
180 GlobalVariable::Const(val) => val,
181 GlobalVariable::Memory { gv, offset, ty } => {
182 let addr = builder.ins().global_value(environ.pointer_type(), gv);
183 let mut flags = ir::MemFlags::trusted();
184 flags.set_alias_region(Some(ir::AliasRegion::Table));
186 builder.ins().load(ty, flags, addr, offset)
187 }
188 GlobalVariable::Custom => environ.translate_custom_global_get(
189 builder.cursor(),
190 GlobalIndex::from_u32(*global_index),
191 )?,
192 };
193 state.push1(val);
194 }
195 Operator::GlobalSet { global_index } => {
196 match state.get_global(builder.func, *global_index, environ)? {
197 GlobalVariable::Const(_) => panic!("global #{} is a constant", *global_index),
198 GlobalVariable::Memory { gv, offset, ty } => {
199 let addr = builder.ins().global_value(environ.pointer_type(), gv);
200 let mut flags = ir::MemFlags::trusted();
201 flags.set_alias_region(Some(ir::AliasRegion::Table));
203 let mut val = state.pop1();
204 if ty.is_vector() {
206 val = optionally_bitcast_vector(val, I8X16, builder);
207 }
208 debug_assert_eq!(ty, builder.func.dfg.value_type(val));
209 builder.ins().store(flags, val, addr, offset);
210 environ.update_global(builder, *global_index, val);
211 }
212 GlobalVariable::Custom => {
213 let val = state.pop1();
214 environ.translate_custom_global_set(
215 builder.cursor(),
216 GlobalIndex::from_u32(*global_index),
217 val,
218 )?;
219 }
220 }
221 }
222 Operator::Drop => {
226 state.pop1();
227 }
228 Operator::Select => {
229 let (mut arg1, mut arg2, cond) = state.pop3();
231 if builder.func.dfg.value_type(arg1).is_vector() {
232 arg1 = optionally_bitcast_vector(arg1, I8X16, builder);
233 }
234 if builder.func.dfg.value_type(arg2).is_vector() {
235 arg2 = optionally_bitcast_vector(arg2, I8X16, builder);
236 }
237 state.push1(builder.ins().select(cond, arg1, arg2));
238 }
239 Operator::TypedSelect { ty: _ } => {
240 let (mut arg1, mut arg2, cond) = state.pop3();
244 if builder.func.dfg.value_type(arg1).is_vector() {
245 arg1 = optionally_bitcast_vector(arg1, I8X16, builder);
246 }
247 if builder.func.dfg.value_type(arg2).is_vector() {
248 arg2 = optionally_bitcast_vector(arg2, I8X16, builder);
249 }
250 state.push1(builder.ins().select(cond, arg1, arg2));
251 }
252 Operator::Nop => {
253 }
255 Operator::Unreachable => {
256 builder.ins().trap(crate::TRAP_UNREACHABLE);
257 state.reachable = false;
258 }
259 Operator::Block { blockty } => {
271 let (params, results) = module_translation_state.blocktype_params_results(blockty)?;
272 let next = block_with_params(builder, results.iter(), environ)?;
273 state.push_block(next, params.len(), results.len());
274 }
275 Operator::Loop { blockty } => {
276 let (params, results) = module_translation_state.blocktype_params_results(blockty)?;
277 let loop_body = block_with_params(builder, params.iter(), environ)?;
278 let next = block_with_params(builder, results.iter(), environ)?;
279 canonicalise_then_jump(builder, loop_body, state.peekn(params.len()));
280 state.push_loop(loop_body, next, params.len(), results.len());
281
282 state.popn(params.len());
285 state
286 .stack
287 .extend_from_slice(builder.block_params(loop_body));
288
289 builder.switch_to_block(loop_body);
290 environ.translate_loop_header(builder.cursor())?;
291 }
292 Operator::If { blockty } => {
293 let val = state.pop1();
294
295 let next_block = builder.create_block();
296 let (params, results) = module_translation_state.blocktype_params_results(blockty)?;
297 let results: Vec<_> = results.iter().copied().collect();
298 let (destination, else_data) = if params == results {
299 let destination = block_with_params(builder, results.iter(), environ)?;
306 let branch_inst = canonicalise_brif(
307 builder,
308 val,
309 next_block,
310 &[],
311 destination,
312 state.peekn(params.len()),
313 );
314 (
315 destination,
316 ElseData::NoElse {
317 branch_inst,
318 placeholder: destination,
319 },
320 )
321 } else {
322 let destination = block_with_params(builder, results.iter(), environ)?;
325 let else_block = block_with_params(builder, params.iter(), environ)?;
326 canonicalise_brif(
327 builder,
328 val,
329 next_block,
330 &[],
331 else_block,
332 state.peekn(params.len()),
333 );
334 builder.seal_block(else_block);
335 (destination, ElseData::WithElse { else_block })
336 };
337
338 builder.seal_block(next_block); builder.switch_to_block(next_block);
340
341 state.push_if(
348 destination,
349 else_data,
350 params.len(),
351 results.len(),
352 *blockty,
353 );
354 }
355 Operator::Else => {
356 let i = state.control_stack.len() - 1;
357 match state.control_stack[i] {
358 ControlStackFrame::If {
359 ref else_data,
360 head_is_reachable,
361 ref mut consequent_ends_reachable,
362 num_return_values,
363 blocktype,
364 destination,
365 ..
366 } => {
367 debug_assert!(consequent_ends_reachable.is_none());
370 *consequent_ends_reachable = Some(state.reachable);
371
372 if head_is_reachable {
373 state.reachable = true;
375
376 let else_block = match *else_data {
379 ElseData::NoElse {
380 branch_inst,
381 placeholder,
382 } => {
383 let (params, _results) = module_translation_state
384 .blocktype_params_results(&blocktype)?;
385 debug_assert_eq!(params.len(), num_return_values);
386 let else_block =
387 block_with_params(builder, params.iter(), environ)?;
388 canonicalise_then_jump(
389 builder,
390 destination,
391 state.peekn(params.len()),
392 );
393 state.popn(params.len());
394
395 builder.change_jump_destination(
396 branch_inst,
397 placeholder,
398 else_block,
399 );
400 builder.seal_block(else_block);
401 else_block
402 }
403 ElseData::WithElse { else_block } => {
404 canonicalise_then_jump(
405 builder,
406 destination,
407 state.peekn(num_return_values),
408 );
409 state.popn(num_return_values);
410 else_block
411 }
412 };
413
414 builder.switch_to_block(else_block);
425
426 }
429 }
430 _ => unreachable!(),
431 }
432 }
433 Operator::End => {
434 let frame = state.control_stack.pop().unwrap();
435 let next_block = frame.following_code();
436 let return_count = frame.num_return_values();
437 let return_args = state.peekn_mut(return_count);
438
439 canonicalise_then_jump(builder, next_block, return_args);
440 builder.switch_to_block(next_block);
448 builder.seal_block(next_block);
449
450 if let ControlStackFrame::Loop { header, .. } = frame {
452 builder.seal_block(header)
453 }
454
455 frame.truncate_value_stack_to_original_size(&mut state.stack);
456 state
457 .stack
458 .extend_from_slice(builder.block_params(next_block));
459 }
460 Operator::Br { relative_depth } => {
482 let i = state.control_stack.len() - 1 - (*relative_depth as usize);
483 let (return_count, br_destination) = {
484 let frame = &mut state.control_stack[i];
485 frame.set_branched_to_exit();
487 let return_count = if frame.is_loop() {
488 frame.num_param_values()
489 } else {
490 frame.num_return_values()
491 };
492 (return_count, frame.br_destination())
493 };
494 let destination_args = state.peekn(return_count);
495 canonicalise_then_jump(builder, br_destination, destination_args);
496 state.popn(return_count);
497 state.reachable = false;
498 }
499 Operator::BrIf { relative_depth } => translate_br_if(*relative_depth, builder, state),
500 Operator::BrTable { targets } => {
501 let default = targets.default();
502 let mut min_depth = default;
503 for depth in targets.targets() {
504 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
505 if depth < min_depth {
506 min_depth = depth;
507 }
508 }
509 let jump_args_count = {
510 let i = state.control_stack.len() - 1 - (min_depth as usize);
511 let min_depth_frame = &state.control_stack[i];
512 if min_depth_frame.is_loop() {
513 min_depth_frame.num_param_values()
514 } else {
515 min_depth_frame.num_return_values()
516 }
517 };
518 let val = state.pop1();
519 let mut data = Vec::with_capacity(targets.len() as usize);
520 if jump_args_count == 0 {
521 for depth in targets.targets() {
523 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
524 let block = {
525 let i = state.control_stack.len() - 1 - (depth as usize);
526 let frame = &mut state.control_stack[i];
527 frame.set_branched_to_exit();
528 frame.br_destination()
529 };
530 data.push(builder.func.dfg.block_call(block, &[]));
531 }
532 let block = {
533 let i = state.control_stack.len() - 1 - (default as usize);
534 let frame = &mut state.control_stack[i];
535 frame.set_branched_to_exit();
536 frame.br_destination()
537 };
538 let block = builder.func.dfg.block_call(block, &[]);
539 let jt = builder.create_jump_table(JumpTableData::new(block, &data));
540 builder.ins().br_table(val, jt);
541 } else {
542 let return_count = jump_args_count;
545 let mut dest_block_sequence = vec![];
546 let mut dest_block_map = HashMap::new();
547 for depth in targets.targets() {
548 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
549 let branch_block = match dest_block_map.entry(depth as usize) {
550 hash_map::Entry::Occupied(entry) => *entry.get(),
551 hash_map::Entry::Vacant(entry) => {
552 let block = builder.create_block();
553 dest_block_sequence.push((depth as usize, block));
554 *entry.insert(block)
555 }
556 };
557 data.push(builder.func.dfg.block_call(branch_block, &[]));
558 }
559 let default_branch_block = match dest_block_map.entry(default as usize) {
560 hash_map::Entry::Occupied(entry) => *entry.get(),
561 hash_map::Entry::Vacant(entry) => {
562 let block = builder.create_block();
563 dest_block_sequence.push((default as usize, block));
564 *entry.insert(block)
565 }
566 };
567 let default_branch_block = builder.func.dfg.block_call(default_branch_block, &[]);
568 let jt = builder.create_jump_table(JumpTableData::new(default_branch_block, &data));
569 builder.ins().br_table(val, jt);
570 for (depth, dest_block) in dest_block_sequence {
571 builder.switch_to_block(dest_block);
572 builder.seal_block(dest_block);
573 let real_dest_block = {
574 let i = state.control_stack.len() - 1 - depth;
575 let frame = &mut state.control_stack[i];
576 frame.set_branched_to_exit();
577 frame.br_destination()
578 };
579 let destination_args = state.peekn_mut(return_count);
580 canonicalise_then_jump(builder, real_dest_block, destination_args);
581 }
582 state.popn(return_count);
583 }
584 state.reachable = false;
585 }
586 Operator::Return => {
587 let return_count = {
588 let frame = &mut state.control_stack[0];
589 frame.num_return_values()
590 };
591 {
592 let return_args = state.peekn_mut(return_count);
593 environ.handle_before_return(return_args, builder);
594 bitcast_wasm_returns(environ, return_args, builder);
595 builder.ins().return_(return_args);
596 }
597 state.popn(return_count);
598 state.reachable = false;
599 }
600
601 Operator::Try { .. }
603 | Operator::Catch { .. }
604 | Operator::Throw { .. }
605 | Operator::Rethrow { .. }
606 | Operator::Delegate { .. }
607 | Operator::CatchAll => {
608 return Err(wasm_unsupported!(
609 "proposed exception handling operator {:?}",
610 op
611 ));
612 }
613 Operator::Call { function_index } => {
619 let (fref, num_args) = state.get_direct_func(builder.func, *function_index, environ)?;
620
621 let args = state.peekn_mut(num_args);
623 bitcast_wasm_params(
624 environ,
625 builder.func.dfg.ext_funcs[fref].signature,
626 args,
627 builder,
628 );
629
630 let call = environ.translate_call(
631 builder,
632 FunctionIndex::from_u32(*function_index),
633 fref,
634 args,
635 )?;
636 let inst_results = builder.inst_results(call);
637 debug_assert_eq!(
638 inst_results.len(),
639 builder.func.dfg.signatures[builder.func.dfg.ext_funcs[fref].signature]
640 .returns
641 .len(),
642 "translate_call results should match the call signature"
643 );
644 state.popn(num_args);
645 state.pushn(inst_results);
646 }
647 Operator::CallIndirect {
648 type_index,
649 table_index,
650 ..
651 } => {
652 let (sigref, num_args) = state.get_indirect_sig(builder.func, *type_index, environ)?;
656 let callee = state.pop1();
657
658 let args = state.peekn_mut(num_args);
660 bitcast_wasm_params(environ, sigref, args, builder);
661
662 let call = environ.translate_call_indirect(
663 builder,
664 TableIndex::from_u32(*table_index),
665 SignatureIndex::from_u32(*type_index),
666 sigref,
667 callee,
668 state.peekn(num_args),
669 )?;
670 let inst_results = builder.inst_results(call);
671 debug_assert_eq!(
672 inst_results.len(),
673 builder.func.dfg.signatures[sigref].returns.len(),
674 "translate_call_indirect results should match the call signature"
675 );
676 state.popn(num_args);
677 state.pushn(inst_results);
678 }
679 Operator::MemoryGrow { mem } => {
684 let heap_index = MemoryIndex::from_u32(*mem);
687 let heap = state.get_heap(builder.func, *mem, environ)?;
688 let val = state.pop1();
689 state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?)
690 }
691 Operator::MemorySize { mem } => {
692 let heap_index = MemoryIndex::from_u32(*mem);
693 let heap = state.get_heap(builder.func, *mem, environ)?;
694 state.push1(environ.translate_memory_size(builder.cursor(), heap_index, heap)?);
695 }
696 Operator::I32Load8U { memarg } => {
701 unwrap_or_return_unreachable_state!(
702 state,
703 translate_load(memarg, ir::Opcode::Uload8, I32, builder, state, environ)?
704 );
705 }
706 Operator::I32Load16U { memarg } => {
707 unwrap_or_return_unreachable_state!(
708 state,
709 translate_load(memarg, ir::Opcode::Uload16, I32, builder, state, environ)?
710 );
711 }
712 Operator::I32Load8S { memarg } => {
713 unwrap_or_return_unreachable_state!(
714 state,
715 translate_load(memarg, ir::Opcode::Sload8, I32, builder, state, environ)?
716 );
717 }
718 Operator::I32Load16S { memarg } => {
719 unwrap_or_return_unreachable_state!(
720 state,
721 translate_load(memarg, ir::Opcode::Sload16, I32, builder, state, environ)?
722 );
723 }
724 Operator::I64Load8U { memarg } => {
725 unwrap_or_return_unreachable_state!(
726 state,
727 translate_load(memarg, ir::Opcode::Uload8, I64, builder, state, environ)?
728 );
729 }
730 Operator::I64Load16U { memarg } => {
731 unwrap_or_return_unreachable_state!(
732 state,
733 translate_load(memarg, ir::Opcode::Uload16, I64, builder, state, environ)?
734 );
735 }
736 Operator::I64Load8S { memarg } => {
737 unwrap_or_return_unreachable_state!(
738 state,
739 translate_load(memarg, ir::Opcode::Sload8, I64, builder, state, environ)?
740 );
741 }
742 Operator::I64Load16S { memarg } => {
743 unwrap_or_return_unreachable_state!(
744 state,
745 translate_load(memarg, ir::Opcode::Sload16, I64, builder, state, environ)?
746 );
747 }
748 Operator::I64Load32S { memarg } => {
749 unwrap_or_return_unreachable_state!(
750 state,
751 translate_load(memarg, ir::Opcode::Sload32, I64, builder, state, environ)?
752 );
753 }
754 Operator::I64Load32U { memarg } => {
755 unwrap_or_return_unreachable_state!(
756 state,
757 translate_load(memarg, ir::Opcode::Uload32, I64, builder, state, environ)?
758 );
759 }
760 Operator::I32Load { memarg } => {
761 unwrap_or_return_unreachable_state!(
762 state,
763 translate_load(memarg, ir::Opcode::Load, I32, builder, state, environ)?
764 );
765 }
766 Operator::F32Load { memarg } => {
767 unwrap_or_return_unreachable_state!(
768 state,
769 translate_load(memarg, ir::Opcode::Load, F32, builder, state, environ)?
770 );
771 }
772 Operator::I64Load { memarg } => {
773 unwrap_or_return_unreachable_state!(
774 state,
775 translate_load(memarg, ir::Opcode::Load, I64, builder, state, environ)?
776 );
777 }
778 Operator::F64Load { memarg } => {
779 unwrap_or_return_unreachable_state!(
780 state,
781 translate_load(memarg, ir::Opcode::Load, F64, builder, state, environ)?
782 );
783 }
784 Operator::V128Load { memarg } => {
785 unwrap_or_return_unreachable_state!(
786 state,
787 translate_load(memarg, ir::Opcode::Load, I8X16, builder, state, environ)?
788 );
789 }
790 Operator::V128Load8x8S { memarg } => {
791 let (flags, _, base) = unwrap_or_return_unreachable_state!(
793 state,
794 prepare_addr(memarg, 8, builder, state, environ)?
795 );
796 let loaded = builder.ins().sload8x8(flags, base, 0);
797 state.push1(loaded);
798 }
799 Operator::V128Load8x8U { memarg } => {
800 let (flags, _, base) = unwrap_or_return_unreachable_state!(
801 state,
802 prepare_addr(memarg, 8, builder, state, environ)?
803 );
804 let loaded = builder.ins().uload8x8(flags, base, 0);
805 state.push1(loaded);
806 }
807 Operator::V128Load16x4S { memarg } => {
808 let (flags, _, base) = unwrap_or_return_unreachable_state!(
809 state,
810 prepare_addr(memarg, 8, builder, state, environ)?
811 );
812 let loaded = builder.ins().sload16x4(flags, base, 0);
813 state.push1(loaded);
814 }
815 Operator::V128Load16x4U { memarg } => {
816 let (flags, _, base) = unwrap_or_return_unreachable_state!(
817 state,
818 prepare_addr(memarg, 8, builder, state, environ)?
819 );
820 let loaded = builder.ins().uload16x4(flags, base, 0);
821 state.push1(loaded);
822 }
823 Operator::V128Load32x2S { memarg } => {
824 let (flags, _, base) = unwrap_or_return_unreachable_state!(
825 state,
826 prepare_addr(memarg, 8, builder, state, environ)?
827 );
828 let loaded = builder.ins().sload32x2(flags, base, 0);
829 state.push1(loaded);
830 }
831 Operator::V128Load32x2U { memarg } => {
832 let (flags, _, base) = unwrap_or_return_unreachable_state!(
833 state,
834 prepare_addr(memarg, 8, builder, state, environ)?
835 );
836 let loaded = builder.ins().uload32x2(flags, base, 0);
837 state.push1(loaded);
838 }
839 Operator::I32Store { memarg }
844 | Operator::I64Store { memarg }
845 | Operator::F32Store { memarg }
846 | Operator::F64Store { memarg } => {
847 translate_store(memarg, ir::Opcode::Store, builder, state, environ)?;
848 }
849 Operator::I32Store8 { memarg } | Operator::I64Store8 { memarg } => {
850 translate_store(memarg, ir::Opcode::Istore8, builder, state, environ)?;
851 }
852 Operator::I32Store16 { memarg } | Operator::I64Store16 { memarg } => {
853 translate_store(memarg, ir::Opcode::Istore16, builder, state, environ)?;
854 }
855 Operator::I64Store32 { memarg } => {
856 translate_store(memarg, ir::Opcode::Istore32, builder, state, environ)?;
857 }
858 Operator::V128Store { memarg } => {
859 translate_store(memarg, ir::Opcode::Store, builder, state, environ)?;
860 }
861 Operator::I32Const { value } => {
863 state.push1(builder.ins().iconst(I32, *value as u32 as i64))
864 }
865 Operator::I64Const { value } => state.push1(builder.ins().iconst(I64, *value)),
866 Operator::F32Const { value } => {
867 state.push1(builder.ins().f32const(f32_translation(*value)));
868 }
869 Operator::F64Const { value } => {
870 state.push1(builder.ins().f64const(f64_translation(*value)));
871 }
872 Operator::I32Clz | Operator::I64Clz => {
874 let arg = state.pop1();
875 state.push1(builder.ins().clz(arg));
876 }
877 Operator::I32Ctz | Operator::I64Ctz => {
878 let arg = state.pop1();
879 state.push1(builder.ins().ctz(arg));
880 }
881 Operator::I32Popcnt | Operator::I64Popcnt => {
882 let arg = state.pop1();
883 state.push1(builder.ins().popcnt(arg));
884 }
885 Operator::I64ExtendI32S => {
886 let val = state.pop1();
887 state.push1(builder.ins().sextend(I64, val));
888 }
889 Operator::I64ExtendI32U => {
890 let val = state.pop1();
891 state.push1(builder.ins().uextend(I64, val));
892 }
893 Operator::I32WrapI64 => {
894 let val = state.pop1();
895 state.push1(builder.ins().ireduce(I32, val));
896 }
897 Operator::F32Sqrt | Operator::F64Sqrt => {
898 let arg = state.pop1();
899 state.push1(builder.ins().sqrt(arg));
900 }
901 Operator::F32Ceil | Operator::F64Ceil => {
902 let arg = state.pop1();
903 state.push1(builder.ins().ceil(arg));
904 }
905 Operator::F32Floor | Operator::F64Floor => {
906 let arg = state.pop1();
907 state.push1(builder.ins().floor(arg));
908 }
909 Operator::F32Trunc | Operator::F64Trunc => {
910 let arg = state.pop1();
911 state.push1(builder.ins().trunc(arg));
912 }
913 Operator::F32Nearest | Operator::F64Nearest => {
914 let arg = state.pop1();
915 state.push1(builder.ins().nearest(arg));
916 }
917 Operator::F32Abs | Operator::F64Abs => {
918 let val = state.pop1();
919 state.push1(builder.ins().fabs(val));
920 }
921 Operator::F32Neg | Operator::F64Neg => {
922 let arg = state.pop1();
923 state.push1(builder.ins().fneg(arg));
924 }
925 Operator::F64ConvertI64U | Operator::F64ConvertI32U => {
926 let val = state.pop1();
927 state.push1(builder.ins().fcvt_from_uint(F64, val));
928 }
929 Operator::F64ConvertI64S | Operator::F64ConvertI32S => {
930 let val = state.pop1();
931 state.push1(builder.ins().fcvt_from_sint(F64, val));
932 }
933 Operator::F32ConvertI64S | Operator::F32ConvertI32S => {
934 let val = state.pop1();
935 state.push1(builder.ins().fcvt_from_sint(F32, val));
936 }
937 Operator::F32ConvertI64U | Operator::F32ConvertI32U => {
938 let val = state.pop1();
939 state.push1(builder.ins().fcvt_from_uint(F32, val));
940 }
941 Operator::F64PromoteF32 => {
942 let val = state.pop1();
943 state.push1(builder.ins().fpromote(F64, val));
944 }
945 Operator::F32DemoteF64 => {
946 let val = state.pop1();
947 state.push1(builder.ins().fdemote(F32, val));
948 }
949 Operator::I64TruncF64S | Operator::I64TruncF32S => {
950 let val = state.pop1();
951 state.push1(builder.ins().fcvt_to_sint(I64, val));
952 }
953 Operator::I32TruncF64S | Operator::I32TruncF32S => {
954 let val = state.pop1();
955 state.push1(builder.ins().fcvt_to_sint(I32, val));
956 }
957 Operator::I64TruncF64U | Operator::I64TruncF32U => {
958 let val = state.pop1();
959 state.push1(builder.ins().fcvt_to_uint(I64, val));
960 }
961 Operator::I32TruncF64U | Operator::I32TruncF32U => {
962 let val = state.pop1();
963 state.push1(builder.ins().fcvt_to_uint(I32, val));
964 }
965 Operator::I64TruncSatF64S | Operator::I64TruncSatF32S => {
966 let val = state.pop1();
967 state.push1(builder.ins().fcvt_to_sint_sat(I64, val));
968 }
969 Operator::I32TruncSatF64S | Operator::I32TruncSatF32S => {
970 let val = state.pop1();
971 state.push1(builder.ins().fcvt_to_sint_sat(I32, val));
972 }
973 Operator::I64TruncSatF64U | Operator::I64TruncSatF32U => {
974 let val = state.pop1();
975 state.push1(builder.ins().fcvt_to_uint_sat(I64, val));
976 }
977 Operator::I32TruncSatF64U | Operator::I32TruncSatF32U => {
978 let val = state.pop1();
979 state.push1(builder.ins().fcvt_to_uint_sat(I32, val));
980 }
981 Operator::F32ReinterpretI32 => {
982 let val = state.pop1();
983 state.push1(builder.ins().bitcast(F32, MemFlags::new(), val));
984 }
985 Operator::F64ReinterpretI64 => {
986 let val = state.pop1();
987 state.push1(builder.ins().bitcast(F64, MemFlags::new(), val));
988 }
989 Operator::I32ReinterpretF32 => {
990 let val = state.pop1();
991 state.push1(builder.ins().bitcast(I32, MemFlags::new(), val));
992 }
993 Operator::I64ReinterpretF64 => {
994 let val = state.pop1();
995 state.push1(builder.ins().bitcast(I64, MemFlags::new(), val));
996 }
997 Operator::I32Extend8S => {
998 let val = state.pop1();
999 state.push1(builder.ins().ireduce(I8, val));
1000 let val = state.pop1();
1001 state.push1(builder.ins().sextend(I32, val));
1002 }
1003 Operator::I32Extend16S => {
1004 let val = state.pop1();
1005 state.push1(builder.ins().ireduce(I16, val));
1006 let val = state.pop1();
1007 state.push1(builder.ins().sextend(I32, val));
1008 }
1009 Operator::I64Extend8S => {
1010 let val = state.pop1();
1011 state.push1(builder.ins().ireduce(I8, val));
1012 let val = state.pop1();
1013 state.push1(builder.ins().sextend(I64, val));
1014 }
1015 Operator::I64Extend16S => {
1016 let val = state.pop1();
1017 state.push1(builder.ins().ireduce(I16, val));
1018 let val = state.pop1();
1019 state.push1(builder.ins().sextend(I64, val));
1020 }
1021 Operator::I64Extend32S => {
1022 let val = state.pop1();
1023 state.push1(builder.ins().ireduce(I32, val));
1024 let val = state.pop1();
1025 state.push1(builder.ins().sextend(I64, val));
1026 }
1027 Operator::I32Add | Operator::I64Add => {
1029 let (arg1, arg2) = state.pop2();
1030 state.push1(builder.ins().iadd(arg1, arg2));
1031 }
1032 Operator::I32And | Operator::I64And => {
1033 let (arg1, arg2) = state.pop2();
1034 state.push1(builder.ins().band(arg1, arg2));
1035 }
1036 Operator::I32Or | Operator::I64Or => {
1037 let (arg1, arg2) = state.pop2();
1038 state.push1(builder.ins().bor(arg1, arg2));
1039 }
1040 Operator::I32Xor | Operator::I64Xor => {
1041 let (arg1, arg2) = state.pop2();
1042 state.push1(builder.ins().bxor(arg1, arg2));
1043 }
1044 Operator::I32Shl | Operator::I64Shl => {
1045 let (arg1, arg2) = state.pop2();
1046 state.push1(builder.ins().ishl(arg1, arg2));
1047 }
1048 Operator::I32ShrS | Operator::I64ShrS => {
1049 let (arg1, arg2) = state.pop2();
1050 state.push1(builder.ins().sshr(arg1, arg2));
1051 }
1052 Operator::I32ShrU | Operator::I64ShrU => {
1053 let (arg1, arg2) = state.pop2();
1054 state.push1(builder.ins().ushr(arg1, arg2));
1055 }
1056 Operator::I32Rotl | Operator::I64Rotl => {
1057 let (arg1, arg2) = state.pop2();
1058 state.push1(builder.ins().rotl(arg1, arg2));
1059 }
1060 Operator::I32Rotr | Operator::I64Rotr => {
1061 let (arg1, arg2) = state.pop2();
1062 state.push1(builder.ins().rotr(arg1, arg2));
1063 }
1064 Operator::F32Add | Operator::F64Add => {
1065 let (arg1, arg2) = state.pop2();
1066 state.push1(builder.ins().fadd(arg1, arg2));
1067 }
1068 Operator::I32Sub | Operator::I64Sub => {
1069 let (arg1, arg2) = state.pop2();
1070 state.push1(builder.ins().isub(arg1, arg2));
1071 }
1072 Operator::F32Sub | Operator::F64Sub => {
1073 let (arg1, arg2) = state.pop2();
1074 state.push1(builder.ins().fsub(arg1, arg2));
1075 }
1076 Operator::I32Mul | Operator::I64Mul => {
1077 let (arg1, arg2) = state.pop2();
1078 state.push1(builder.ins().imul(arg1, arg2));
1079 }
1080 Operator::F32Mul | Operator::F64Mul => {
1081 let (arg1, arg2) = state.pop2();
1082 state.push1(builder.ins().fmul(arg1, arg2));
1083 }
1084 Operator::F32Div | Operator::F64Div => {
1085 let (arg1, arg2) = state.pop2();
1086 state.push1(builder.ins().fdiv(arg1, arg2));
1087 }
1088 Operator::I32DivS | Operator::I64DivS => {
1089 let (arg1, arg2) = state.pop2();
1090 state.push1(builder.ins().sdiv(arg1, arg2));
1091 }
1092 Operator::I32DivU | Operator::I64DivU => {
1093 let (arg1, arg2) = state.pop2();
1094 state.push1(builder.ins().udiv(arg1, arg2));
1095 }
1096 Operator::I32RemS | Operator::I64RemS => {
1097 let (arg1, arg2) = state.pop2();
1098 state.push1(builder.ins().srem(arg1, arg2));
1099 }
1100 Operator::I32RemU | Operator::I64RemU => {
1101 let (arg1, arg2) = state.pop2();
1102 state.push1(builder.ins().urem(arg1, arg2));
1103 }
1104 Operator::F32Min | Operator::F64Min => {
1105 let (arg1, arg2) = state.pop2();
1106 state.push1(builder.ins().fmin(arg1, arg2));
1107 }
1108 Operator::F32Max | Operator::F64Max => {
1109 let (arg1, arg2) = state.pop2();
1110 state.push1(builder.ins().fmax(arg1, arg2));
1111 }
1112 Operator::F32Copysign | Operator::F64Copysign => {
1113 let (arg1, arg2) = state.pop2();
1114 state.push1(builder.ins().fcopysign(arg1, arg2));
1115 }
1116 Operator::I32LtS | Operator::I64LtS => {
1118 translate_icmp(IntCC::SignedLessThan, builder, state)
1119 }
1120 Operator::I32LtU | Operator::I64LtU => {
1121 translate_icmp(IntCC::UnsignedLessThan, builder, state)
1122 }
1123 Operator::I32LeS | Operator::I64LeS => {
1124 translate_icmp(IntCC::SignedLessThanOrEqual, builder, state)
1125 }
1126 Operator::I32LeU | Operator::I64LeU => {
1127 translate_icmp(IntCC::UnsignedLessThanOrEqual, builder, state)
1128 }
1129 Operator::I32GtS | Operator::I64GtS => {
1130 translate_icmp(IntCC::SignedGreaterThan, builder, state)
1131 }
1132 Operator::I32GtU | Operator::I64GtU => {
1133 translate_icmp(IntCC::UnsignedGreaterThan, builder, state)
1134 }
1135 Operator::I32GeS | Operator::I64GeS => {
1136 translate_icmp(IntCC::SignedGreaterThanOrEqual, builder, state)
1137 }
1138 Operator::I32GeU | Operator::I64GeU => {
1139 translate_icmp(IntCC::UnsignedGreaterThanOrEqual, builder, state)
1140 }
1141 Operator::I32Eqz | Operator::I64Eqz => {
1142 let arg = state.pop1();
1143 let val = builder.ins().icmp_imm(IntCC::Equal, arg, 0);
1144 state.push1(builder.ins().uextend(I32, val));
1145 }
1146 Operator::I32Eq | Operator::I64Eq => translate_icmp(IntCC::Equal, builder, state),
1147 Operator::F32Eq | Operator::F64Eq => translate_fcmp(FloatCC::Equal, builder, state),
1148 Operator::I32Ne | Operator::I64Ne => translate_icmp(IntCC::NotEqual, builder, state),
1149 Operator::F32Ne | Operator::F64Ne => translate_fcmp(FloatCC::NotEqual, builder, state),
1150 Operator::F32Gt | Operator::F64Gt => translate_fcmp(FloatCC::GreaterThan, builder, state),
1151 Operator::F32Ge | Operator::F64Ge => {
1152 translate_fcmp(FloatCC::GreaterThanOrEqual, builder, state)
1153 }
1154 Operator::F32Lt | Operator::F64Lt => translate_fcmp(FloatCC::LessThan, builder, state),
1155 Operator::F32Le | Operator::F64Le => {
1156 translate_fcmp(FloatCC::LessThanOrEqual, builder, state)
1157 }
1158 Operator::RefNull { hty } => {
1159 state.push1(environ.translate_ref_null(builder.cursor(), *hty)?)
1160 }
1161 Operator::RefIsNull => {
1162 let value = state.pop1();
1163 state.push1(environ.translate_ref_is_null(builder.cursor(), value)?);
1164 }
1165 Operator::RefFunc { function_index } => {
1166 let index = FunctionIndex::from_u32(*function_index);
1167 state.push1(environ.translate_ref_func(builder.cursor(), index)?);
1168 }
1169 Operator::MemoryAtomicWait32 { memarg } | Operator::MemoryAtomicWait64 { memarg } => {
1170 let implied_ty = match op {
1174 Operator::MemoryAtomicWait64 { .. } => I64,
1175 Operator::MemoryAtomicWait32 { .. } => I32,
1176 _ => unreachable!(),
1177 };
1178 let heap_index = MemoryIndex::from_u32(memarg.memory);
1179 let heap = state.get_heap(builder.func, memarg.memory, environ)?;
1180 let timeout = state.pop1(); let expected = state.pop1(); let addr = state.pop1(); let addr = fold_atomic_mem_addr(addr, memarg, implied_ty, builder);
1184 assert!(builder.func.dfg.value_type(expected) == implied_ty);
1185 match environ.translate_atomic_wait(
1188 builder.cursor(),
1189 heap_index,
1190 heap,
1191 addr,
1192 expected,
1193 timeout,
1194 ) {
1195 Ok(res) => {
1196 state.push1(res);
1197 }
1198 Err(wasmer_types::WasmError::Unsupported(_err)) => {
1199 builder.ins().trap(crate::TRAP_UNREACHABLE);
1201 state.reachable = false;
1202 }
1203 Err(err) => {
1204 return Err(err);
1205 }
1206 };
1207 }
1208 Operator::MemoryAtomicNotify { memarg } => {
1209 let heap_index = MemoryIndex::from_u32(memarg.memory);
1210 let heap = state.get_heap(builder.func, memarg.memory, environ)?;
1211 let count = state.pop1(); let addr = state.pop1(); let addr = fold_atomic_mem_addr(addr, memarg, I32, builder);
1214 match environ.translate_atomic_notify(builder.cursor(), heap_index, heap, addr, count) {
1215 Ok(res) => {
1216 state.push1(res);
1217 }
1218 Err(wasmer_types::WasmError::Unsupported(_err)) => {
1219 state.push1(builder.ins().iconst(I32, i64::from(0)));
1223 }
1224 Err(err) => {
1225 return Err(err);
1226 }
1227 };
1228 }
1229 Operator::I32AtomicLoad { memarg } => {
1230 translate_atomic_load(I32, I32, memarg, builder, state, environ)?
1231 }
1232 Operator::I64AtomicLoad { memarg } => {
1233 translate_atomic_load(I64, I64, memarg, builder, state, environ)?
1234 }
1235 Operator::I32AtomicLoad8U { memarg } => {
1236 translate_atomic_load(I32, I8, memarg, builder, state, environ)?
1237 }
1238 Operator::I32AtomicLoad16U { memarg } => {
1239 translate_atomic_load(I32, I16, memarg, builder, state, environ)?
1240 }
1241 Operator::I64AtomicLoad8U { memarg } => {
1242 translate_atomic_load(I64, I8, memarg, builder, state, environ)?
1243 }
1244 Operator::I64AtomicLoad16U { memarg } => {
1245 translate_atomic_load(I64, I16, memarg, builder, state, environ)?
1246 }
1247 Operator::I64AtomicLoad32U { memarg } => {
1248 translate_atomic_load(I64, I32, memarg, builder, state, environ)?
1249 }
1250
1251 Operator::I32AtomicStore { memarg } => {
1252 translate_atomic_store(I32, memarg, builder, state, environ)?
1253 }
1254 Operator::I64AtomicStore { memarg } => {
1255 translate_atomic_store(I64, memarg, builder, state, environ)?
1256 }
1257 Operator::I32AtomicStore8 { memarg } => {
1258 translate_atomic_store(I8, memarg, builder, state, environ)?
1259 }
1260 Operator::I32AtomicStore16 { memarg } => {
1261 translate_atomic_store(I16, memarg, builder, state, environ)?
1262 }
1263 Operator::I64AtomicStore8 { memarg } => {
1264 translate_atomic_store(I8, memarg, builder, state, environ)?
1265 }
1266 Operator::I64AtomicStore16 { memarg } => {
1267 translate_atomic_store(I16, memarg, builder, state, environ)?
1268 }
1269 Operator::I64AtomicStore32 { memarg } => {
1270 translate_atomic_store(I32, memarg, builder, state, environ)?
1271 }
1272
1273 Operator::I32AtomicRmwAdd { memarg } => {
1274 translate_atomic_rmw(I32, I32, AtomicRmwOp::Add, memarg, builder, state, environ)?
1275 }
1276 Operator::I64AtomicRmwAdd { memarg } => {
1277 translate_atomic_rmw(I64, I64, AtomicRmwOp::Add, memarg, builder, state, environ)?
1278 }
1279 Operator::I32AtomicRmw8AddU { memarg } => {
1280 translate_atomic_rmw(I32, I8, AtomicRmwOp::Add, memarg, builder, state, environ)?
1281 }
1282 Operator::I32AtomicRmw16AddU { memarg } => {
1283 translate_atomic_rmw(I32, I16, AtomicRmwOp::Add, memarg, builder, state, environ)?
1284 }
1285 Operator::I64AtomicRmw8AddU { memarg } => {
1286 translate_atomic_rmw(I64, I8, AtomicRmwOp::Add, memarg, builder, state, environ)?
1287 }
1288 Operator::I64AtomicRmw16AddU { memarg } => {
1289 translate_atomic_rmw(I64, I16, AtomicRmwOp::Add, memarg, builder, state, environ)?
1290 }
1291 Operator::I64AtomicRmw32AddU { memarg } => {
1292 translate_atomic_rmw(I64, I32, AtomicRmwOp::Add, memarg, builder, state, environ)?
1293 }
1294
1295 Operator::I32AtomicRmwSub { memarg } => {
1296 translate_atomic_rmw(I32, I32, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1297 }
1298 Operator::I64AtomicRmwSub { memarg } => {
1299 translate_atomic_rmw(I64, I64, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1300 }
1301 Operator::I32AtomicRmw8SubU { memarg } => {
1302 translate_atomic_rmw(I32, I8, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1303 }
1304 Operator::I32AtomicRmw16SubU { memarg } => {
1305 translate_atomic_rmw(I32, I16, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1306 }
1307 Operator::I64AtomicRmw8SubU { memarg } => {
1308 translate_atomic_rmw(I64, I8, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1309 }
1310 Operator::I64AtomicRmw16SubU { memarg } => {
1311 translate_atomic_rmw(I64, I16, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1312 }
1313 Operator::I64AtomicRmw32SubU { memarg } => {
1314 translate_atomic_rmw(I64, I32, AtomicRmwOp::Sub, memarg, builder, state, environ)?
1315 }
1316
1317 Operator::I32AtomicRmwAnd { memarg } => {
1318 translate_atomic_rmw(I32, I32, AtomicRmwOp::And, memarg, builder, state, environ)?
1319 }
1320 Operator::I64AtomicRmwAnd { memarg } => {
1321 translate_atomic_rmw(I64, I64, AtomicRmwOp::And, memarg, builder, state, environ)?
1322 }
1323 Operator::I32AtomicRmw8AndU { memarg } => {
1324 translate_atomic_rmw(I32, I8, AtomicRmwOp::And, memarg, builder, state, environ)?
1325 }
1326 Operator::I32AtomicRmw16AndU { memarg } => {
1327 translate_atomic_rmw(I32, I16, AtomicRmwOp::And, memarg, builder, state, environ)?
1328 }
1329 Operator::I64AtomicRmw8AndU { memarg } => {
1330 translate_atomic_rmw(I64, I8, AtomicRmwOp::And, memarg, builder, state, environ)?
1331 }
1332 Operator::I64AtomicRmw16AndU { memarg } => {
1333 translate_atomic_rmw(I64, I16, AtomicRmwOp::And, memarg, builder, state, environ)?
1334 }
1335 Operator::I64AtomicRmw32AndU { memarg } => {
1336 translate_atomic_rmw(I64, I32, AtomicRmwOp::And, memarg, builder, state, environ)?
1337 }
1338
1339 Operator::I32AtomicRmwOr { memarg } => {
1340 translate_atomic_rmw(I32, I32, AtomicRmwOp::Or, memarg, builder, state, environ)?
1341 }
1342 Operator::I64AtomicRmwOr { memarg } => {
1343 translate_atomic_rmw(I64, I64, AtomicRmwOp::Or, memarg, builder, state, environ)?
1344 }
1345 Operator::I32AtomicRmw8OrU { memarg } => {
1346 translate_atomic_rmw(I32, I8, AtomicRmwOp::Or, memarg, builder, state, environ)?
1347 }
1348 Operator::I32AtomicRmw16OrU { memarg } => {
1349 translate_atomic_rmw(I32, I16, AtomicRmwOp::Or, memarg, builder, state, environ)?
1350 }
1351 Operator::I64AtomicRmw8OrU { memarg } => {
1352 translate_atomic_rmw(I64, I8, AtomicRmwOp::Or, memarg, builder, state, environ)?
1353 }
1354 Operator::I64AtomicRmw16OrU { memarg } => {
1355 translate_atomic_rmw(I64, I16, AtomicRmwOp::Or, memarg, builder, state, environ)?
1356 }
1357 Operator::I64AtomicRmw32OrU { memarg } => {
1358 translate_atomic_rmw(I64, I32, AtomicRmwOp::Or, memarg, builder, state, environ)?
1359 }
1360
1361 Operator::I32AtomicRmwXor { memarg } => {
1362 translate_atomic_rmw(I32, I32, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1363 }
1364 Operator::I64AtomicRmwXor { memarg } => {
1365 translate_atomic_rmw(I64, I64, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1366 }
1367 Operator::I32AtomicRmw8XorU { memarg } => {
1368 translate_atomic_rmw(I32, I8, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1369 }
1370 Operator::I32AtomicRmw16XorU { memarg } => {
1371 translate_atomic_rmw(I32, I16, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1372 }
1373 Operator::I64AtomicRmw8XorU { memarg } => {
1374 translate_atomic_rmw(I64, I8, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1375 }
1376 Operator::I64AtomicRmw16XorU { memarg } => {
1377 translate_atomic_rmw(I64, I16, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1378 }
1379 Operator::I64AtomicRmw32XorU { memarg } => {
1380 translate_atomic_rmw(I64, I32, AtomicRmwOp::Xor, memarg, builder, state, environ)?
1381 }
1382
1383 Operator::I32AtomicRmwXchg { memarg } => {
1384 translate_atomic_rmw(I32, I32, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1385 }
1386 Operator::I64AtomicRmwXchg { memarg } => {
1387 translate_atomic_rmw(I64, I64, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1388 }
1389 Operator::I32AtomicRmw8XchgU { memarg } => {
1390 translate_atomic_rmw(I32, I8, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1391 }
1392 Operator::I32AtomicRmw16XchgU { memarg } => {
1393 translate_atomic_rmw(I32, I16, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1394 }
1395 Operator::I64AtomicRmw8XchgU { memarg } => {
1396 translate_atomic_rmw(I64, I8, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1397 }
1398 Operator::I64AtomicRmw16XchgU { memarg } => {
1399 translate_atomic_rmw(I64, I16, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1400 }
1401 Operator::I64AtomicRmw32XchgU { memarg } => {
1402 translate_atomic_rmw(I64, I32, AtomicRmwOp::Xchg, memarg, builder, state, environ)?
1403 }
1404
1405 Operator::I32AtomicRmwCmpxchg { memarg } => {
1406 translate_atomic_cas(I32, I32, memarg, builder, state, environ)?
1407 }
1408 Operator::I64AtomicRmwCmpxchg { memarg } => {
1409 translate_atomic_cas(I64, I64, memarg, builder, state, environ)?
1410 }
1411 Operator::I32AtomicRmw8CmpxchgU { memarg } => {
1412 translate_atomic_cas(I32, I8, memarg, builder, state, environ)?
1413 }
1414 Operator::I32AtomicRmw16CmpxchgU { memarg } => {
1415 translate_atomic_cas(I32, I16, memarg, builder, state, environ)?
1416 }
1417 Operator::I64AtomicRmw8CmpxchgU { memarg } => {
1418 translate_atomic_cas(I64, I8, memarg, builder, state, environ)?
1419 }
1420 Operator::I64AtomicRmw16CmpxchgU { memarg } => {
1421 translate_atomic_cas(I64, I16, memarg, builder, state, environ)?
1422 }
1423 Operator::I64AtomicRmw32CmpxchgU { memarg } => {
1424 translate_atomic_cas(I64, I32, memarg, builder, state, environ)?
1425 }
1426
1427 Operator::AtomicFence { .. } => {
1428 builder.ins().fence();
1429 }
1430 Operator::MemoryCopy { dst_mem, src_mem } => {
1431 let src_index = MemoryIndex::from_u32(*src_mem);
1432 let dst_index = MemoryIndex::from_u32(*dst_mem);
1433 let src_heap = state.get_heap(builder.func, *src_mem, environ)?;
1434 let dst_heap = state.get_heap(builder.func, *dst_mem, environ)?;
1435 let len = state.pop1();
1436 let src_pos = state.pop1();
1437 let dst_pos = state.pop1();
1438 environ.translate_memory_copy(
1439 builder.cursor(),
1440 src_index,
1441 src_heap,
1442 dst_index,
1443 dst_heap,
1444 dst_pos,
1445 src_pos,
1446 len,
1447 )?;
1448 }
1449 Operator::MemoryFill { mem } => {
1450 let heap_index = MemoryIndex::from_u32(*mem);
1451 let heap = state.get_heap(builder.func, *mem, environ)?;
1452 let len = state.pop1();
1453 let val = state.pop1();
1454 let dest = state.pop1();
1455 environ.translate_memory_fill(builder.cursor(), heap_index, heap, dest, val, len)?;
1456 }
1457 Operator::MemoryInit { data_index, mem } => {
1458 let heap_index = MemoryIndex::from_u32(*mem);
1459 let heap = state.get_heap(builder.func, *mem, environ)?;
1460 let len = state.pop1();
1461 let src = state.pop1();
1462 let dest = state.pop1();
1463 environ.translate_memory_init(
1464 builder.cursor(),
1465 heap_index,
1466 heap,
1467 *data_index,
1468 dest,
1469 src,
1470 len,
1471 )?;
1472 }
1473 Operator::DataDrop { data_index } => {
1474 environ.translate_data_drop(builder.cursor(), *data_index)?;
1475 }
1476 Operator::TableSize { table: index } => {
1477 state.push1(
1478 environ.translate_table_size(builder.cursor(), TableIndex::from_u32(*index))?,
1479 );
1480 }
1481 Operator::TableGrow { table: index } => {
1482 let table_index = TableIndex::from_u32(*index);
1483 let delta = state.pop1();
1484 let init_value = state.pop1();
1485 state.push1(environ.translate_table_grow(
1486 builder.cursor(),
1487 table_index,
1488 delta,
1489 init_value,
1490 )?);
1491 }
1492 Operator::TableGet { table: index } => {
1493 let table_index = TableIndex::from_u32(*index);
1494 let index = state.pop1();
1495 state.push1(environ.translate_table_get(builder, table_index, index)?);
1496 }
1497 Operator::TableSet { table: index } => {
1498 let table_index = TableIndex::from_u32(*index);
1499 let value = state.pop1();
1500 let index = state.pop1();
1501 environ.translate_table_set(builder, table_index, value, index)?;
1502 }
1503 Operator::TableCopy {
1504 dst_table: dst_table_index,
1505 src_table: src_table_index,
1506 } => {
1507 let len = state.pop1();
1508 let src = state.pop1();
1509 let dest = state.pop1();
1510 environ.translate_table_copy(
1511 builder.cursor(),
1512 TableIndex::from_u32(*dst_table_index),
1513 TableIndex::from_u32(*src_table_index),
1514 dest,
1515 src,
1516 len,
1517 )?;
1518 }
1519 Operator::TableFill { table } => {
1520 let table_index = TableIndex::from_u32(*table);
1521 let len = state.pop1();
1522 let val = state.pop1();
1523 let dest = state.pop1();
1524 environ.translate_table_fill(builder.cursor(), table_index, dest, val, len)?;
1525 }
1526 Operator::TableInit {
1527 elem_index,
1528 table: table_index,
1529 } => {
1530 let len = state.pop1();
1531 let src = state.pop1();
1532 let dest = state.pop1();
1533 environ.translate_table_init(
1534 builder.cursor(),
1535 *elem_index,
1536 TableIndex::from_u32(*table_index),
1537 dest,
1538 src,
1539 len,
1540 )?;
1541 }
1542 Operator::ElemDrop { elem_index } => {
1543 environ.translate_elem_drop(builder.cursor(), *elem_index)?;
1544 }
1545 Operator::V128Const { value } => {
1546 let data = value.bytes().to_vec().into();
1547 let handle = builder.func.dfg.constants.insert(data);
1548 let value = builder.ins().vconst(I8X16, handle);
1549 state.push1(value)
1552 }
1553 Operator::I8x16Splat | Operator::I16x8Splat => {
1554 let reduced = builder.ins().ireduce(type_of(op).lane_type(), state.pop1());
1555 let splatted = builder.ins().splat(type_of(op), reduced);
1556 state.push1(splatted)
1557 }
1558 Operator::I32x4Splat
1559 | Operator::I64x2Splat
1560 | Operator::F32x4Splat
1561 | Operator::F64x2Splat => {
1562 let splatted = builder.ins().splat(type_of(op), state.pop1());
1563 state.push1(splatted)
1564 }
1565 Operator::V128Load8Splat { memarg }
1566 | Operator::V128Load16Splat { memarg }
1567 | Operator::V128Load32Splat { memarg }
1568 | Operator::V128Load64Splat { memarg } => {
1569 unwrap_or_return_unreachable_state!(
1570 state,
1571 translate_load(
1572 memarg,
1573 ir::Opcode::Load,
1574 type_of(op).lane_type(),
1575 builder,
1576 state,
1577 environ,
1578 )?
1579 );
1580 let splatted = builder.ins().splat(type_of(op), state.pop1());
1581 state.push1(splatted)
1582 }
1583 Operator::V128Load32Zero { memarg } | Operator::V128Load64Zero { memarg } => {
1584 unwrap_or_return_unreachable_state!(
1585 state,
1586 translate_load(
1587 memarg,
1588 ir::Opcode::Load,
1589 type_of(op).lane_type(),
1590 builder,
1591 state,
1592 environ,
1593 )?
1594 );
1595 let as_vector = builder.ins().scalar_to_vector(type_of(op), state.pop1());
1596 state.push1(as_vector)
1597 }
1598 Operator::V128Load8Lane { memarg, lane }
1599 | Operator::V128Load16Lane { memarg, lane }
1600 | Operator::V128Load32Lane { memarg, lane }
1601 | Operator::V128Load64Lane { memarg, lane } => {
1602 let vector = pop1_with_bitcast(state, type_of(op), builder);
1603 unwrap_or_return_unreachable_state!(
1604 state,
1605 translate_load(
1606 memarg,
1607 ir::Opcode::Load,
1608 type_of(op).lane_type(),
1609 builder,
1610 state,
1611 environ,
1612 )?
1613 );
1614 let replacement = state.pop1();
1615 state.push1(builder.ins().insertlane(vector, replacement, *lane))
1616 }
1617 Operator::V128Store8Lane { memarg, lane }
1618 | Operator::V128Store16Lane { memarg, lane }
1619 | Operator::V128Store32Lane { memarg, lane }
1620 | Operator::V128Store64Lane { memarg, lane } => {
1621 let vector = pop1_with_bitcast(state, type_of(op), builder);
1622 state.push1(builder.ins().extractlane(vector, *lane));
1623 translate_store(memarg, ir::Opcode::Store, builder, state, environ)?;
1624 }
1625 Operator::I8x16ExtractLaneS { lane } | Operator::I16x8ExtractLaneS { lane } => {
1626 let vector = pop1_with_bitcast(state, type_of(op), builder);
1627 let extracted = builder.ins().extractlane(vector, *lane);
1628 state.push1(builder.ins().sextend(I32, extracted))
1629 }
1630 Operator::I8x16ExtractLaneU { lane } | Operator::I16x8ExtractLaneU { lane } => {
1631 let vector = pop1_with_bitcast(state, type_of(op), builder);
1632 let extracted = builder.ins().extractlane(vector, *lane);
1633 state.push1(builder.ins().uextend(I32, extracted));
1634 }
1638 Operator::I32x4ExtractLane { lane }
1639 | Operator::I64x2ExtractLane { lane }
1640 | Operator::F32x4ExtractLane { lane }
1641 | Operator::F64x2ExtractLane { lane } => {
1642 let vector = pop1_with_bitcast(state, type_of(op), builder);
1643 state.push1(builder.ins().extractlane(vector, *lane))
1644 }
1645 Operator::I8x16ReplaceLane { lane } | Operator::I16x8ReplaceLane { lane } => {
1646 let (vector, replacement) = state.pop2();
1647 let ty = type_of(op);
1648 let reduced = builder.ins().ireduce(ty.lane_type(), replacement);
1649 let vector = optionally_bitcast_vector(vector, ty, builder);
1650 state.push1(builder.ins().insertlane(vector, reduced, *lane))
1651 }
1652 Operator::I32x4ReplaceLane { lane }
1653 | Operator::I64x2ReplaceLane { lane }
1654 | Operator::F32x4ReplaceLane { lane }
1655 | Operator::F64x2ReplaceLane { lane } => {
1656 let (vector, replacement) = state.pop2();
1657 let vector = optionally_bitcast_vector(vector, type_of(op), builder);
1658 state.push1(builder.ins().insertlane(vector, replacement, *lane))
1659 }
1660 Operator::I8x16Shuffle { lanes, .. } => {
1661 let (a, b) = pop2_with_bitcast(state, I8X16, builder);
1662 let lanes = ConstantData::from(lanes.as_ref());
1663 let mask = builder.func.dfg.immediates.push(lanes);
1664 let shuffled = builder.ins().shuffle(a, b, mask);
1665 state.push1(shuffled)
1666 }
1671 Operator::I8x16Swizzle => {
1672 let (a, b) = pop2_with_bitcast(state, I8X16, builder);
1673 state.push1(builder.ins().swizzle(a, b))
1674 }
1675 Operator::I8x16Add | Operator::I16x8Add | Operator::I32x4Add | Operator::I64x2Add => {
1676 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1677 state.push1(builder.ins().iadd(a, b))
1678 }
1679 Operator::I8x16AddSatS | Operator::I16x8AddSatS => {
1680 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1681 state.push1(builder.ins().sadd_sat(a, b))
1682 }
1683 Operator::I8x16AddSatU | Operator::I16x8AddSatU => {
1684 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1685 state.push1(builder.ins().uadd_sat(a, b))
1686 }
1687 Operator::I8x16Sub | Operator::I16x8Sub | Operator::I32x4Sub | Operator::I64x2Sub => {
1688 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1689 state.push1(builder.ins().isub(a, b))
1690 }
1691 Operator::I8x16SubSatS | Operator::I16x8SubSatS => {
1692 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1693 state.push1(builder.ins().ssub_sat(a, b))
1694 }
1695 Operator::I8x16SubSatU | Operator::I16x8SubSatU => {
1696 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1697 state.push1(builder.ins().usub_sat(a, b))
1698 }
1699 Operator::I8x16MinS | Operator::I16x8MinS | Operator::I32x4MinS => {
1700 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1701 state.push1(builder.ins().smin(a, b))
1702 }
1703 Operator::I8x16MinU | Operator::I16x8MinU | Operator::I32x4MinU => {
1704 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1705 state.push1(builder.ins().umin(a, b))
1706 }
1707 Operator::I8x16MaxS | Operator::I16x8MaxS | Operator::I32x4MaxS => {
1708 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1709 state.push1(builder.ins().smax(a, b))
1710 }
1711 Operator::I8x16MaxU | Operator::I16x8MaxU | Operator::I32x4MaxU => {
1712 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1713 state.push1(builder.ins().umax(a, b))
1714 }
1715 Operator::I8x16AvgrU | Operator::I16x8AvgrU => {
1716 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1717 state.push1(builder.ins().avg_round(a, b))
1718 }
1719 Operator::I8x16Neg | Operator::I16x8Neg | Operator::I32x4Neg | Operator::I64x2Neg => {
1720 let a = pop1_with_bitcast(state, type_of(op), builder);
1721 state.push1(builder.ins().ineg(a))
1722 }
1723 Operator::I8x16Abs | Operator::I16x8Abs | Operator::I32x4Abs | Operator::I64x2Abs => {
1724 let a = pop1_with_bitcast(state, type_of(op), builder);
1725 state.push1(builder.ins().iabs(a))
1726 }
1727 Operator::I16x8Mul | Operator::I32x4Mul | Operator::I64x2Mul => {
1728 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1729 state.push1(builder.ins().imul(a, b))
1730 }
1731 Operator::V128Or => {
1732 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1733 state.push1(builder.ins().bor(a, b))
1734 }
1735 Operator::V128Xor => {
1736 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1737 state.push1(builder.ins().bxor(a, b))
1738 }
1739 Operator::V128And => {
1740 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1741 state.push1(builder.ins().band(a, b))
1742 }
1743 Operator::V128AndNot => {
1744 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1745 state.push1(builder.ins().band_not(a, b))
1746 }
1747 Operator::V128Not => {
1748 let a = state.pop1();
1749 state.push1(builder.ins().bnot(a));
1750 }
1751 Operator::I8x16Shl | Operator::I16x8Shl | Operator::I32x4Shl | Operator::I64x2Shl => {
1752 let (a, b) = state.pop2();
1753 let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder);
1754 let bitwidth = i64::from(type_of(op).lane_bits());
1755 let b_mod_bitwidth = builder.ins().band_imm(b, bitwidth - 1);
1758 state.push1(builder.ins().ishl(bitcast_a, b_mod_bitwidth))
1759 }
1760 Operator::I8x16ShrU | Operator::I16x8ShrU | Operator::I32x4ShrU | Operator::I64x2ShrU => {
1761 let (a, b) = state.pop2();
1762 let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder);
1763 let bitwidth = i64::from(type_of(op).lane_bits());
1764 let b_mod_bitwidth = builder.ins().band_imm(b, bitwidth - 1);
1767 state.push1(builder.ins().ushr(bitcast_a, b_mod_bitwidth))
1768 }
1769 Operator::I8x16ShrS | Operator::I16x8ShrS | Operator::I32x4ShrS | Operator::I64x2ShrS => {
1770 let (a, b) = state.pop2();
1771 let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder);
1772 let bitwidth = i64::from(type_of(op).lane_bits());
1773 let b_mod_bitwidth = builder.ins().band_imm(b, bitwidth - 1);
1776 state.push1(builder.ins().sshr(bitcast_a, b_mod_bitwidth))
1777 }
1778 Operator::V128Bitselect => {
1779 let (a, b, c) = state.pop3();
1780 let bitcast_a = optionally_bitcast_vector(a, I8X16, builder);
1781 let bitcast_b = optionally_bitcast_vector(b, I8X16, builder);
1782 let bitcast_c = optionally_bitcast_vector(c, I8X16, builder);
1783 state.push1(builder.ins().bitselect(bitcast_c, bitcast_a, bitcast_b))
1786 }
1787 Operator::V128AnyTrue => {
1788 let a = pop1_with_bitcast(state, type_of(op), builder);
1789 let bool_result = builder.ins().vany_true(a);
1790 state.push1(builder.ins().uextend(I32, bool_result))
1791 }
1792 Operator::I8x16AllTrue
1793 | Operator::I16x8AllTrue
1794 | Operator::I32x4AllTrue
1795 | Operator::I64x2AllTrue => {
1796 let a = pop1_with_bitcast(state, type_of(op), builder);
1797 let bool_result = builder.ins().vall_true(a);
1798 state.push1(builder.ins().uextend(I32, bool_result))
1799 }
1800 Operator::I8x16Bitmask
1801 | Operator::I16x8Bitmask
1802 | Operator::I32x4Bitmask
1803 | Operator::I64x2Bitmask => {
1804 let a = pop1_with_bitcast(state, type_of(op), builder);
1805 state.push1(builder.ins().vhigh_bits(I32, a));
1806 }
1807 Operator::I8x16Eq | Operator::I16x8Eq | Operator::I32x4Eq | Operator::I64x2Eq => {
1808 translate_vector_icmp(IntCC::Equal, type_of(op), builder, state)
1809 }
1810 Operator::I8x16Ne | Operator::I16x8Ne | Operator::I32x4Ne | Operator::I64x2Ne => {
1811 translate_vector_icmp(IntCC::NotEqual, type_of(op), builder, state)
1812 }
1813 Operator::I8x16GtS | Operator::I16x8GtS | Operator::I32x4GtS | Operator::I64x2GtS => {
1814 translate_vector_icmp(IntCC::SignedGreaterThan, type_of(op), builder, state)
1815 }
1816 Operator::I8x16LtS | Operator::I16x8LtS | Operator::I32x4LtS | Operator::I64x2LtS => {
1817 translate_vector_icmp(IntCC::SignedLessThan, type_of(op), builder, state)
1818 }
1819 Operator::I8x16GtU | Operator::I16x8GtU | Operator::I32x4GtU => {
1820 translate_vector_icmp(IntCC::UnsignedGreaterThan, type_of(op), builder, state)
1821 }
1822 Operator::I8x16LtU | Operator::I16x8LtU | Operator::I32x4LtU => {
1823 translate_vector_icmp(IntCC::UnsignedLessThan, type_of(op), builder, state)
1824 }
1825 Operator::I8x16GeS | Operator::I16x8GeS | Operator::I32x4GeS | Operator::I64x2GeS => {
1826 translate_vector_icmp(IntCC::SignedGreaterThanOrEqual, type_of(op), builder, state)
1827 }
1828 Operator::I8x16LeS | Operator::I16x8LeS | Operator::I32x4LeS | Operator::I64x2LeS => {
1829 translate_vector_icmp(IntCC::SignedLessThanOrEqual, type_of(op), builder, state)
1830 }
1831 Operator::I8x16GeU | Operator::I16x8GeU | Operator::I32x4GeU => translate_vector_icmp(
1832 IntCC::UnsignedGreaterThanOrEqual,
1833 type_of(op),
1834 builder,
1835 state,
1836 ),
1837 Operator::I8x16LeU | Operator::I16x8LeU | Operator::I32x4LeU => {
1838 translate_vector_icmp(IntCC::UnsignedLessThanOrEqual, type_of(op), builder, state)
1839 }
1840 Operator::F32x4Eq | Operator::F64x2Eq => {
1841 translate_vector_fcmp(FloatCC::Equal, type_of(op), builder, state)
1842 }
1843 Operator::F32x4Ne | Operator::F64x2Ne => {
1844 translate_vector_fcmp(FloatCC::NotEqual, type_of(op), builder, state)
1845 }
1846 Operator::F32x4Lt | Operator::F64x2Lt => {
1847 translate_vector_fcmp(FloatCC::LessThan, type_of(op), builder, state)
1848 }
1849 Operator::F32x4Gt | Operator::F64x2Gt => {
1850 translate_vector_fcmp(FloatCC::GreaterThan, type_of(op), builder, state)
1851 }
1852 Operator::F32x4Le | Operator::F64x2Le => {
1853 translate_vector_fcmp(FloatCC::LessThanOrEqual, type_of(op), builder, state)
1854 }
1855 Operator::F32x4Ge | Operator::F64x2Ge => {
1856 translate_vector_fcmp(FloatCC::GreaterThanOrEqual, type_of(op), builder, state)
1857 }
1858 Operator::F32x4Add | Operator::F64x2Add => {
1859 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1860 state.push1(builder.ins().fadd(a, b))
1861 }
1862 Operator::F32x4Sub | Operator::F64x2Sub => {
1863 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1864 state.push1(builder.ins().fsub(a, b))
1865 }
1866 Operator::F32x4Mul | Operator::F64x2Mul => {
1867 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1868 state.push1(builder.ins().fmul(a, b))
1869 }
1870 Operator::F32x4Div | Operator::F64x2Div => {
1871 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1872 state.push1(builder.ins().fdiv(a, b))
1873 }
1874 Operator::F32x4Max | Operator::F64x2Max => {
1875 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1876 state.push1(builder.ins().fmax(a, b))
1877 }
1878 Operator::F32x4Min | Operator::F64x2Min => {
1879 let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
1880 state.push1(builder.ins().fmin(a, b))
1881 }
1882 Operator::F32x4PMax | Operator::F64x2PMax => {
1883 let ty = type_of(op);
1890 let (a, b) = pop2_with_bitcast(state, ty, builder);
1891 let cmp = builder.ins().fcmp(FloatCC::LessThan, a, b);
1892 let cmp = optionally_bitcast_vector(cmp, ty, builder);
1893 state.push1(builder.ins().bitselect(cmp, b, a))
1894 }
1895 Operator::F32x4PMin | Operator::F64x2PMin => {
1896 let ty = type_of(op);
1902 let (a, b) = pop2_with_bitcast(state, ty, builder);
1903 let cmp = builder.ins().fcmp(FloatCC::LessThan, b, a);
1904 let cmp = optionally_bitcast_vector(cmp, ty, builder);
1905 state.push1(builder.ins().bitselect(cmp, b, a))
1906 }
1907 Operator::F32x4Sqrt | Operator::F64x2Sqrt => {
1908 let a = pop1_with_bitcast(state, type_of(op), builder);
1909 state.push1(builder.ins().sqrt(a))
1910 }
1911 Operator::F32x4Neg | Operator::F64x2Neg => {
1912 let a = pop1_with_bitcast(state, type_of(op), builder);
1913 state.push1(builder.ins().fneg(a))
1914 }
1915 Operator::F32x4Abs | Operator::F64x2Abs => {
1916 let a = pop1_with_bitcast(state, type_of(op), builder);
1917 state.push1(builder.ins().fabs(a))
1918 }
1919 Operator::F32x4ConvertI32x4S => {
1920 let a = pop1_with_bitcast(state, I32X4, builder);
1921 state.push1(builder.ins().fcvt_from_sint(F32X4, a))
1922 }
1923 Operator::F32x4ConvertI32x4U => {
1924 let a = pop1_with_bitcast(state, I32X4, builder);
1925 state.push1(builder.ins().fcvt_from_uint(F32X4, a))
1926 }
1927 Operator::F64x2ConvertLowI32x4S => {
1928 let a = pop1_with_bitcast(state, I32X4, builder);
1929 let widened_a = builder.ins().swiden_low(a);
1930 state.push1(builder.ins().fcvt_from_sint(F64X2, widened_a));
1931 }
1932 Operator::F64x2ConvertLowI32x4U => {
1933 let a = pop1_with_bitcast(state, I32X4, builder);
1934 let widened_a = builder.ins().uwiden_low(a);
1935 state.push1(builder.ins().fcvt_from_uint(F64X2, widened_a));
1936 }
1937 Operator::F64x2PromoteLowF32x4 => {
1938 let a = pop1_with_bitcast(state, F32X4, builder);
1939 state.push1(builder.ins().fvpromote_low(a));
1940 }
1941 Operator::F32x4DemoteF64x2Zero => {
1942 let a = pop1_with_bitcast(state, F64X2, builder);
1943 state.push1(builder.ins().fvdemote(a));
1944 }
1945 Operator::I32x4TruncSatF32x4S => {
1946 let a = pop1_with_bitcast(state, F32X4, builder);
1947 state.push1(builder.ins().fcvt_to_sint_sat(I32X4, a))
1948 }
1949 Operator::I32x4TruncSatF64x2SZero => {
1950 let a = pop1_with_bitcast(state, F64X2, builder);
1951 let converted_a = builder.ins().fcvt_to_sint_sat(I64X2, a);
1952 let handle = builder.func.dfg.constants.insert(vec![0u8; 16].into());
1953 let zero = builder.ins().vconst(I64X2, handle);
1954
1955 state.push1(builder.ins().snarrow(converted_a, zero));
1956 }
1957 Operator::I32x4TruncSatF32x4U => {
1958 let a = pop1_with_bitcast(state, F32X4, builder);
1959 state.push1(builder.ins().fcvt_to_uint_sat(I32X4, a))
1960 }
1961 Operator::I32x4TruncSatF64x2UZero => {
1962 let a = pop1_with_bitcast(state, F64X2, builder);
1963 let converted_a = builder.ins().fcvt_to_uint_sat(I64X2, a);
1964 let handle = builder.func.dfg.constants.insert(vec![0u8; 16].into());
1965 let zero = builder.ins().vconst(I64X2, handle);
1966
1967 state.push1(builder.ins().uunarrow(converted_a, zero));
1968 }
1969 Operator::I8x16NarrowI16x8S => {
1970 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
1971 state.push1(builder.ins().snarrow(a, b))
1972 }
1973 Operator::I16x8NarrowI32x4S => {
1974 let (a, b) = pop2_with_bitcast(state, I32X4, builder);
1975 state.push1(builder.ins().snarrow(a, b))
1976 }
1977 Operator::I8x16NarrowI16x8U => {
1978 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
1979 state.push1(builder.ins().unarrow(a, b))
1980 }
1981 Operator::I16x8NarrowI32x4U => {
1982 let (a, b) = pop2_with_bitcast(state, I32X4, builder);
1983 state.push1(builder.ins().unarrow(a, b))
1984 }
1985 Operator::I16x8ExtendLowI8x16S => {
1986 let a = pop1_with_bitcast(state, I8X16, builder);
1987 state.push1(builder.ins().swiden_low(a))
1988 }
1989 Operator::I16x8ExtendHighI8x16S => {
1990 let a = pop1_with_bitcast(state, I8X16, builder);
1991 state.push1(builder.ins().swiden_high(a))
1992 }
1993 Operator::I16x8ExtendLowI8x16U => {
1994 let a = pop1_with_bitcast(state, I8X16, builder);
1995 state.push1(builder.ins().uwiden_low(a))
1996 }
1997 Operator::I16x8ExtendHighI8x16U => {
1998 let a = pop1_with_bitcast(state, I8X16, builder);
1999 state.push1(builder.ins().uwiden_high(a))
2000 }
2001 Operator::I32x4ExtendLowI16x8S => {
2002 let a = pop1_with_bitcast(state, I16X8, builder);
2003 state.push1(builder.ins().swiden_low(a))
2004 }
2005 Operator::I32x4ExtendHighI16x8S => {
2006 let a = pop1_with_bitcast(state, I16X8, builder);
2007 state.push1(builder.ins().swiden_high(a))
2008 }
2009 Operator::I32x4ExtendLowI16x8U => {
2010 let a = pop1_with_bitcast(state, I16X8, builder);
2011 state.push1(builder.ins().uwiden_low(a))
2012 }
2013 Operator::I32x4ExtendHighI16x8U => {
2014 let a = pop1_with_bitcast(state, I16X8, builder);
2015 state.push1(builder.ins().uwiden_high(a))
2016 }
2017
2018 Operator::I64x2ExtendLowI32x4S => {
2019 let a = pop1_with_bitcast(state, I32X4, builder);
2020 state.push1(builder.ins().swiden_low(a))
2021 }
2022 Operator::I64x2ExtendHighI32x4S => {
2023 let a = pop1_with_bitcast(state, I32X4, builder);
2024 state.push1(builder.ins().swiden_high(a))
2025 }
2026 Operator::I64x2ExtendLowI32x4U => {
2027 let a = pop1_with_bitcast(state, I32X4, builder);
2028 state.push1(builder.ins().uwiden_low(a))
2029 }
2030 Operator::I64x2ExtendHighI32x4U => {
2031 let a = pop1_with_bitcast(state, I32X4, builder);
2032 state.push1(builder.ins().uwiden_high(a))
2033 }
2034 Operator::I16x8ExtAddPairwiseI8x16S => {
2035 let a = pop1_with_bitcast(state, I8X16, builder);
2036 let widen_low = builder.ins().swiden_low(a);
2037 let widen_high = builder.ins().swiden_high(a);
2038 state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
2039 }
2040 Operator::I32x4ExtAddPairwiseI16x8S => {
2041 let a = pop1_with_bitcast(state, I16X8, builder);
2042 let widen_low = builder.ins().swiden_low(a);
2043 let widen_high = builder.ins().swiden_high(a);
2044 state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
2045 }
2046 Operator::I16x8ExtAddPairwiseI8x16U => {
2047 let a = pop1_with_bitcast(state, I8X16, builder);
2048 let widen_low = builder.ins().uwiden_low(a);
2049 let widen_high = builder.ins().uwiden_high(a);
2050 state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
2051 }
2052 Operator::I32x4ExtAddPairwiseI16x8U => {
2053 let a = pop1_with_bitcast(state, I16X8, builder);
2054 let widen_low = builder.ins().uwiden_low(a);
2055 let widen_high = builder.ins().uwiden_high(a);
2056 state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
2057 }
2058 Operator::F32x4Ceil | Operator::F64x2Ceil => {
2059 let arg = pop1_with_bitcast(state, type_of(op), builder);
2063 state.push1(builder.ins().ceil(arg));
2064 }
2065 Operator::F32x4Floor | Operator::F64x2Floor => {
2066 let arg = pop1_with_bitcast(state, type_of(op), builder);
2067 state.push1(builder.ins().floor(arg));
2068 }
2069 Operator::F32x4Trunc | Operator::F64x2Trunc => {
2070 let arg = pop1_with_bitcast(state, type_of(op), builder);
2071 state.push1(builder.ins().trunc(arg));
2072 }
2073 Operator::F32x4Nearest | Operator::F64x2Nearest => {
2074 let arg = pop1_with_bitcast(state, type_of(op), builder);
2075 state.push1(builder.ins().nearest(arg));
2076 }
2077 Operator::I32x4DotI16x8S => {
2078 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
2079 let alow = builder.ins().swiden_low(a);
2080 let blow = builder.ins().swiden_low(b);
2081 let low = builder.ins().imul(alow, blow);
2082 let ahigh = builder.ins().swiden_high(a);
2083 let bhigh = builder.ins().swiden_high(b);
2084 let high = builder.ins().imul(ahigh, bhigh);
2085 state.push1(builder.ins().iadd_pairwise(low, high));
2086 }
2087 Operator::I8x16Popcnt => {
2088 let arg = pop1_with_bitcast(state, type_of(op), builder);
2089 state.push1(builder.ins().popcnt(arg));
2090 }
2091 Operator::I16x8Q15MulrSatS => {
2092 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
2093 state.push1(builder.ins().sqmul_round_sat(a, b))
2094 }
2095 Operator::I16x8ExtMulLowI8x16S => {
2096 let (a, b) = pop2_with_bitcast(state, I8X16, builder);
2097 let a_low = builder.ins().swiden_low(a);
2098 let b_low = builder.ins().swiden_low(b);
2099 state.push1(builder.ins().imul(a_low, b_low));
2100 }
2101 Operator::I16x8ExtMulHighI8x16S => {
2102 let (a, b) = pop2_with_bitcast(state, I8X16, builder);
2103 let a_high = builder.ins().swiden_high(a);
2104 let b_high = builder.ins().swiden_high(b);
2105 state.push1(builder.ins().imul(a_high, b_high));
2106 }
2107 Operator::I16x8ExtMulLowI8x16U => {
2108 let (a, b) = pop2_with_bitcast(state, I8X16, builder);
2109 let a_low = builder.ins().uwiden_low(a);
2110 let b_low = builder.ins().uwiden_low(b);
2111 state.push1(builder.ins().imul(a_low, b_low));
2112 }
2113 Operator::I16x8ExtMulHighI8x16U => {
2114 let (a, b) = pop2_with_bitcast(state, I8X16, builder);
2115 let a_high = builder.ins().uwiden_high(a);
2116 let b_high = builder.ins().uwiden_high(b);
2117 state.push1(builder.ins().imul(a_high, b_high));
2118 }
2119 Operator::I32x4ExtMulLowI16x8S => {
2120 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
2121 let a_low = builder.ins().swiden_low(a);
2122 let b_low = builder.ins().swiden_low(b);
2123 state.push1(builder.ins().imul(a_low, b_low));
2124 }
2125 Operator::I32x4ExtMulHighI16x8S => {
2126 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
2127 let a_high = builder.ins().swiden_high(a);
2128 let b_high = builder.ins().swiden_high(b);
2129 state.push1(builder.ins().imul(a_high, b_high));
2130 }
2131 Operator::I32x4ExtMulLowI16x8U => {
2132 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
2133 let a_low = builder.ins().uwiden_low(a);
2134 let b_low = builder.ins().uwiden_low(b);
2135 state.push1(builder.ins().imul(a_low, b_low));
2136 }
2137 Operator::I32x4ExtMulHighI16x8U => {
2138 let (a, b) = pop2_with_bitcast(state, I16X8, builder);
2139 let a_high = builder.ins().uwiden_high(a);
2140 let b_high = builder.ins().uwiden_high(b);
2141 state.push1(builder.ins().imul(a_high, b_high));
2142 }
2143 Operator::I64x2ExtMulLowI32x4S => {
2144 let (a, b) = pop2_with_bitcast(state, I32X4, builder);
2145 let a_low = builder.ins().swiden_low(a);
2146 let b_low = builder.ins().swiden_low(b);
2147 state.push1(builder.ins().imul(a_low, b_low));
2148 }
2149 Operator::I64x2ExtMulHighI32x4S => {
2150 let (a, b) = pop2_with_bitcast(state, I32X4, builder);
2151 let a_high = builder.ins().swiden_high(a);
2152 let b_high = builder.ins().swiden_high(b);
2153 state.push1(builder.ins().imul(a_high, b_high));
2154 }
2155 Operator::I64x2ExtMulLowI32x4U => {
2156 let (a, b) = pop2_with_bitcast(state, I32X4, builder);
2157 let a_low = builder.ins().uwiden_low(a);
2158 let b_low = builder.ins().uwiden_low(b);
2159 state.push1(builder.ins().imul(a_low, b_low));
2160 }
2161 Operator::I64x2ExtMulHighI32x4U => {
2162 let (a, b) = pop2_with_bitcast(state, I32X4, builder);
2163 let a_high = builder.ins().uwiden_high(a);
2164 let b_high = builder.ins().uwiden_high(b);
2165 state.push1(builder.ins().imul(a_high, b_high));
2166 }
2167 Operator::ReturnCall { .. } | Operator::ReturnCallIndirect { .. } => {
2168 return Err(wasm_unsupported!("proposed tail-call operator {:?}", op));
2169 }
2170 Operator::I8x16RelaxedSwizzle
2171 | Operator::I32x4RelaxedTruncF32x4S
2172 | Operator::I32x4RelaxedTruncF32x4U
2173 | Operator::I32x4RelaxedTruncF64x2SZero
2174 | Operator::I32x4RelaxedTruncF64x2UZero
2175 | Operator::F32x4RelaxedNmadd
2176 | Operator::F32x4RelaxedMadd
2177 | Operator::I8x16RelaxedLaneselect
2178 | Operator::I16x8RelaxedLaneselect
2179 | Operator::I32x4RelaxedLaneselect
2180 | Operator::I64x2RelaxedLaneselect
2181 | Operator::F32x4RelaxedMin
2182 | Operator::F32x4RelaxedMax
2183 | Operator::F64x2RelaxedMin
2184 | Operator::F64x2RelaxedMax
2185 | Operator::F64x2RelaxedMadd
2186 | Operator::F64x2RelaxedNmadd
2187 | Operator::I16x8RelaxedDotI8x16I7x16S
2188 | Operator::I32x4RelaxedDotI8x16I7x16AddS
2189 | Operator::I16x8RelaxedQ15mulrS => {
2190 return Err(wasm_unsupported!("proposed relaxed-simd operator {:?}", op));
2191 }
2192 Operator::TryTable { .. } | Operator::ThrowRef => {
2193 return Err(wasm_unsupported!(
2194 "exceptions are not supported (operator: {op:?})"
2195 ));
2196 }
2197 Operator::RefEq
2198 | Operator::StructNew { .. }
2199 | Operator::StructNewDefault { .. }
2200 | Operator::StructGet { .. }
2201 | Operator::StructGetS { .. }
2202 | Operator::StructGetU { .. }
2203 | Operator::StructSet { .. }
2204 | Operator::ArrayNew { .. }
2205 | Operator::ArrayNewDefault { .. }
2206 | Operator::ArrayNewFixed { .. }
2207 | Operator::ArrayNewData { .. }
2208 | Operator::ArrayNewElem { .. }
2209 | Operator::ArrayGet { .. }
2210 | Operator::ArrayGetS { .. }
2211 | Operator::ArrayGetU { .. }
2212 | Operator::ArraySet { .. }
2213 | Operator::ArrayLen
2214 | Operator::ArrayFill { .. }
2215 | Operator::ArrayCopy { .. }
2216 | Operator::ArrayInitData { .. }
2217 | Operator::ArrayInitElem { .. }
2218 | Operator::RefTestNonNull { .. } => {}
2219 Operator::RefTestNullable { .. }
2220 | Operator::RefCastNonNull { .. }
2221 | Operator::RefCastNullable { .. }
2222 | Operator::BrOnCast { .. }
2223 | Operator::BrOnCastFail { .. }
2224 | Operator::AnyConvertExtern
2225 | Operator::ExternConvertAny
2226 | Operator::RefI31
2227 | Operator::RefI31Shared => todo!(),
2228 Operator::I31GetS
2229 | Operator::I31GetU
2230 | Operator::MemoryDiscard { .. }
2231 | Operator::CallRef { .. }
2232 | Operator::ReturnCallRef { .. }
2233 | Operator::RefAsNonNull
2234 | Operator::BrOnNull { .. }
2235 | Operator::BrOnNonNull { .. } => {
2236 return Err(wasm_unsupported!("GC proposal not (operator: {:?})", op));
2237 }
2238 Operator::GlobalAtomicGet { .. }
2239 | Operator::GlobalAtomicSet { .. }
2240 | Operator::GlobalAtomicRmwAdd { .. }
2241 | Operator::GlobalAtomicRmwSub { .. }
2242 | Operator::GlobalAtomicRmwAnd { .. }
2243 | Operator::GlobalAtomicRmwOr { .. }
2244 | Operator::GlobalAtomicRmwXor { .. }
2245 | Operator::GlobalAtomicRmwXchg { .. }
2246 | Operator::GlobalAtomicRmwCmpxchg { .. } => {
2247 return Err(wasm_unsupported!("Global atomics not supported yet!"));
2248 }
2249 Operator::TableAtomicGet { .. }
2250 | Operator::TableAtomicSet { .. }
2251 | Operator::TableAtomicRmwXchg { .. }
2252 | Operator::TableAtomicRmwCmpxchg { .. } => {
2253 return Err(wasm_unsupported!("Table atomics not supported yet!"));
2254 }
2255 Operator::StructAtomicGet { .. }
2256 | Operator::StructAtomicGetS { .. }
2257 | Operator::StructAtomicGetU { .. }
2258 | Operator::StructAtomicSet { .. }
2259 | Operator::StructAtomicRmwAdd { .. }
2260 | Operator::StructAtomicRmwSub { .. }
2261 | Operator::StructAtomicRmwAnd { .. }
2262 | Operator::StructAtomicRmwOr { .. }
2263 | Operator::StructAtomicRmwXor { .. }
2264 | Operator::StructAtomicRmwXchg { .. }
2265 | Operator::StructAtomicRmwCmpxchg { .. } => {
2266 return Err(wasm_unsupported!("Table atomics not supported yet!"));
2267 }
2268 Operator::ArrayAtomicGet { .. }
2269 | Operator::ArrayAtomicGetS { .. }
2270 | Operator::ArrayAtomicGetU { .. }
2271 | Operator::ArrayAtomicSet { .. }
2272 | Operator::ArrayAtomicRmwAdd { .. }
2273 | Operator::ArrayAtomicRmwSub { .. }
2274 | Operator::ArrayAtomicRmwAnd { .. }
2275 | Operator::ArrayAtomicRmwOr { .. }
2276 | Operator::ArrayAtomicRmwXor { .. }
2277 | Operator::ArrayAtomicRmwXchg { .. }
2278 | Operator::ArrayAtomicRmwCmpxchg { .. } => {
2279 return Err(wasm_unsupported!("Array atomics not supported yet!"));
2280 }
2281 Operator::ContNew { .. } => todo!(),
2282 Operator::ContBind { .. } => todo!(),
2283 Operator::Suspend { .. } => todo!(),
2284 Operator::Resume { .. } => todo!(),
2285 Operator::ResumeThrow { .. } => todo!(),
2286 Operator::Switch { .. } => todo!(),
2287 Operator::I64Add128 => todo!(),
2288 Operator::I64Sub128 => todo!(),
2289 Operator::I64MulWideS => todo!(),
2290 Operator::I64MulWideU => todo!(),
2291 _ => todo!(),
2292 };
2293 Ok(())
2294}
2295
2296#[allow(clippy::unneeded_field_pattern)]
2298fn translate_unreachable_operator<FE: FuncEnvironment + ?Sized>(
2302 module_translation_state: &ModuleTranslationState,
2303 op: &Operator,
2304 builder: &mut FunctionBuilder,
2305 state: &mut FuncTranslationState,
2306 environ: &mut FE,
2307) -> WasmResult<()> {
2308 debug_assert!(!state.reachable);
2309 match *op {
2310 Operator::If { blockty } => {
2311 state.push_if(
2314 ir::Block::reserved_value(),
2315 ElseData::NoElse {
2316 branch_inst: ir::Inst::reserved_value(),
2317 placeholder: ir::Block::reserved_value(),
2318 },
2319 0,
2320 0,
2321 blockty,
2322 );
2323 }
2324 Operator::Loop { blockty: _ } | Operator::Block { blockty: _ } => {
2325 state.push_block(ir::Block::reserved_value(), 0, 0);
2326 }
2327 Operator::Else => {
2328 let i = state.control_stack.len() - 1;
2329 match state.control_stack[i] {
2330 ControlStackFrame::If {
2331 ref else_data,
2332 head_is_reachable,
2333 ref mut consequent_ends_reachable,
2334 blocktype,
2335 ..
2336 } => {
2337 debug_assert!(consequent_ends_reachable.is_none());
2338 *consequent_ends_reachable = Some(state.reachable);
2339
2340 if head_is_reachable {
2341 state.reachable = true;
2343
2344 let else_block = match *else_data {
2345 ElseData::NoElse {
2346 branch_inst,
2347 placeholder,
2348 } => {
2349 let (params, _results) = module_translation_state
2350 .blocktype_params_results(&blocktype)?;
2351 let else_block =
2352 block_with_params(builder, params.iter(), environ)?;
2353 let frame = state.control_stack.last().unwrap();
2354 frame.truncate_value_stack_to_else_params(&mut state.stack);
2355
2356 builder.change_jump_destination(
2358 branch_inst,
2359 placeholder,
2360 else_block,
2361 );
2362 builder.seal_block(else_block);
2363 else_block
2364 }
2365 ElseData::WithElse { else_block } => {
2366 let frame = state.control_stack.last().unwrap();
2367 frame.truncate_value_stack_to_else_params(&mut state.stack);
2368 else_block
2369 }
2370 };
2371
2372 builder.switch_to_block(else_block);
2373
2374 }
2379 }
2380 _ => unreachable!(),
2381 }
2382 }
2383 Operator::End => {
2384 let stack = &mut state.stack;
2385 let control_stack = &mut state.control_stack;
2386 let frame = control_stack.pop().unwrap();
2387
2388 frame.truncate_value_stack_to_original_size(stack);
2390
2391 let reachable_anyway = match frame {
2392 ControlStackFrame::Loop { header, .. } => {
2394 builder.seal_block(header);
2395 false
2397 }
2398 ControlStackFrame::If {
2403 head_is_reachable,
2404 consequent_ends_reachable: None,
2405 ..
2406 } => head_is_reachable,
2407 ControlStackFrame::If {
2412 head_is_reachable,
2413 consequent_ends_reachable: Some(consequent_ends_reachable),
2414 ..
2415 } => head_is_reachable && consequent_ends_reachable,
2416 _ => false,
2418 };
2419
2420 if frame.exit_is_branched_to() || reachable_anyway {
2421 builder.switch_to_block(frame.following_code());
2422 builder.seal_block(frame.following_code());
2423
2424 stack.extend_from_slice(builder.block_params(frame.following_code()));
2427 state.reachable = true;
2428 }
2429 }
2430 _ => {
2431 }
2433 }
2434
2435 Ok(())
2436}
2437
2438fn prepare_addr<FE>(
2451 memarg: &MemArg,
2452 access_size: u8,
2453 builder: &mut FunctionBuilder,
2454 state: &mut FuncTranslationState,
2455 environ: &mut FE,
2456) -> WasmResult<Reachability<(MemFlags, Value, Value)>>
2457where
2458 FE: FuncEnvironment + ?Sized,
2459{
2460 let index = state.pop1();
2461 let heap = state.get_heap(builder.func, memarg.memory, environ)?;
2462
2463 let heap = environ.heaps()[heap].clone();
2534 let addr = match u32::try_from(memarg.offset) {
2535 Ok(offset) => bounds_checks::bounds_check_and_compute_addr(
2538 builder,
2539 environ,
2540 &heap,
2541 index,
2542 offset,
2543 access_size,
2544 )?,
2545
2546 Err(_) => {
2573 let offset = builder.ins().iconst(heap.index_type, memarg.offset as i64);
2574 let adjusted_index =
2575 builder
2576 .ins()
2577 .uadd_overflow_trap(index, offset, ir::TrapCode::HEAP_OUT_OF_BOUNDS);
2578 bounds_checks::bounds_check_and_compute_addr(
2579 builder,
2580 environ,
2581 &heap,
2582 adjusted_index,
2583 0,
2584 access_size,
2585 )?
2586 }
2587 };
2588 let addr = match addr {
2589 Reachability::Unreachable => return Ok(Reachability::Unreachable),
2590 Reachability::Reachable(a) => a,
2591 };
2592
2593 let mut flags = MemFlags::new();
2598 flags.set_endianness(ir::Endianness::Little);
2599
2600 if heap.memory_type.is_some() {
2601 flags.set_checked();
2603 }
2604
2605 flags.set_alias_region(Some(ir::AliasRegion::Heap));
2610
2611 Ok(Reachability::Reachable((flags, index, addr)))
2612}
2613
2614fn align_atomic_addr(
2615 memarg: &MemArg,
2616 loaded_bytes: u8,
2617 builder: &mut FunctionBuilder,
2618 state: &mut FuncTranslationState,
2619) {
2620 if loaded_bytes > 1 {
2631 let addr = state.pop1(); state.push1(addr);
2633 let effective_addr = if memarg.offset == 0 {
2634 addr
2635 } else {
2636 builder
2637 .ins()
2638 .iadd_imm(addr, i64::from(memarg.offset as i32))
2639 };
2640 debug_assert!(loaded_bytes.is_power_of_two());
2641 let misalignment = builder
2642 .ins()
2643 .band_imm(effective_addr, i64::from(loaded_bytes - 1));
2644 let f = builder.ins().icmp_imm(IntCC::NotEqual, misalignment, 0);
2645 builder.ins().trapnz(f, crate::TRAP_HEAP_MISALIGNED);
2646 }
2647}
2648
2649fn prepare_atomic_addr<FE: FuncEnvironment + ?Sized>(
2653 memarg: &MemArg,
2654 loaded_bytes: u8,
2655 builder: &mut FunctionBuilder,
2656 state: &mut FuncTranslationState,
2657 environ: &mut FE,
2658) -> WasmResult<Reachability<(MemFlags, Value, Value)>> {
2659 align_atomic_addr(memarg, loaded_bytes, builder, state);
2660 prepare_addr(memarg, loaded_bytes, builder, state, environ)
2661}
2662
2663#[derive(PartialEq, Eq)]
2669#[must_use]
2670pub enum Reachability<T> {
2671 Reachable(T),
2673 Unreachable,
2677}
2678
2679fn translate_load<FE: FuncEnvironment + ?Sized>(
2683 memarg: &MemArg,
2684 opcode: ir::Opcode,
2685 result_ty: Type,
2686 builder: &mut FunctionBuilder,
2687 state: &mut FuncTranslationState,
2688 environ: &mut FE,
2689) -> WasmResult<Reachability<()>> {
2690 let mem_op_size = mem_op_size(opcode, result_ty);
2691 let (flags, wasm_index, base) =
2692 match prepare_addr(memarg, mem_op_size, builder, state, environ)? {
2693 Reachability::Unreachable => return Ok(Reachability::Unreachable),
2694 Reachability::Reachable((f, i, b)) => (f, i, b),
2695 };
2696
2697 environ.before_load(builder, mem_op_size, wasm_index, memarg.offset);
2698
2699 let (load, dfg) = builder
2700 .ins()
2701 .Load(opcode, result_ty, flags, Offset32::new(0), base);
2702 state.push1(dfg.first_result(load));
2703 Ok(Reachability::Reachable(()))
2704}
2705
2706fn translate_store<FE: FuncEnvironment + ?Sized>(
2708 memarg: &MemArg,
2709 opcode: ir::Opcode,
2710 builder: &mut FunctionBuilder,
2711 state: &mut FuncTranslationState,
2712 environ: &mut FE,
2713) -> WasmResult<()> {
2714 let val = state.pop1();
2715 let val_ty = builder.func.dfg.value_type(val);
2716 let mem_op_size = mem_op_size(opcode, val_ty);
2717
2718 let (flags, wasm_index, base) = unwrap_or_return_unreachable_state!(
2719 state,
2720 prepare_addr(memarg, mem_op_size, builder, state, environ)?
2721 );
2722
2723 environ.before_store(builder, mem_op_size, wasm_index, memarg.offset);
2724
2725 builder
2726 .ins()
2727 .Store(opcode, val_ty, flags, Offset32::new(0), val, base);
2728 Ok(())
2729}
2730
2731fn mem_op_size(opcode: ir::Opcode, ty: Type) -> u8 {
2732 match opcode {
2733 ir::Opcode::Istore8 | ir::Opcode::Sload8 | ir::Opcode::Uload8 => 1,
2734 ir::Opcode::Istore16 | ir::Opcode::Sload16 | ir::Opcode::Uload16 => 2,
2735 ir::Opcode::Istore32 | ir::Opcode::Sload32 | ir::Opcode::Uload32 => 4,
2736 ir::Opcode::Store | ir::Opcode::Load => u8::try_from(ty.bytes()).unwrap(),
2737 _ => panic!("unknown size of mem op for {opcode:?}"),
2738 }
2739}
2740
2741fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) {
2742 let (arg0, arg1) = state.pop2();
2743 let val = builder.ins().icmp(cc, arg0, arg1);
2744 state.push1(builder.ins().uextend(I32, val));
2745}
2746
2747fn fold_atomic_mem_addr(
2748 linear_mem_addr: Value,
2749 memarg: &MemArg,
2750 access_ty: Type,
2751 builder: &mut FunctionBuilder,
2752) -> Value {
2753 let access_ty_bytes = access_ty.bytes();
2754 let final_lma = if memarg.offset > 0 {
2755 assert!(builder.func.dfg.value_type(linear_mem_addr) == I32);
2756 let linear_mem_addr = builder.ins().uextend(I64, linear_mem_addr);
2757 let a = builder
2758 .ins()
2759 .iadd_imm(linear_mem_addr, memarg.offset as i64);
2760 let r = builder
2761 .ins()
2762 .icmp_imm(IntCC::UnsignedGreaterThanOrEqual, a, 0x1_0000_0000i64);
2763 builder.ins().trapnz(r, ir::TrapCode::HEAP_OUT_OF_BOUNDS);
2764 builder.ins().ireduce(I32, a)
2765 } else {
2766 linear_mem_addr
2767 };
2768 assert!(access_ty_bytes == 4 || access_ty_bytes == 8);
2769 let final_lma_misalignment = builder
2770 .ins()
2771 .band_imm(final_lma, i64::from(access_ty_bytes - 1));
2772 let f = builder
2773 .ins()
2774 .icmp_imm(IntCC::Equal, final_lma_misalignment, i64::from(0));
2775 builder.ins().trapz(f, crate::TRAP_HEAP_MISALIGNED);
2776 final_lma
2777}
2778
2779fn translate_atomic_rmw<FE: FuncEnvironment + ?Sized>(
2780 widened_ty: Type,
2781 access_ty: Type,
2782 op: AtomicRmwOp,
2783 memarg: &MemArg,
2784 builder: &mut FunctionBuilder,
2785 state: &mut FuncTranslationState,
2786 environ: &mut FE,
2787) -> WasmResult<()> {
2788 let mut arg2 = state.pop1();
2789 let arg2_ty = builder.func.dfg.value_type(arg2);
2790
2791 match access_ty {
2794 I8 | I16 | I32 | I64 => {}
2795 _ => {
2796 return Err(wasm_unsupported!(
2797 "atomic_rmw: unsupported access type {:?}",
2798 access_ty
2799 ));
2800 }
2801 };
2802 let w_ty_ok = matches!(widened_ty, I32 | I64);
2803 assert!(w_ty_ok && widened_ty.bytes() >= access_ty.bytes());
2804
2805 assert!(arg2_ty.bytes() >= access_ty.bytes());
2806 if arg2_ty.bytes() > access_ty.bytes() {
2807 arg2 = builder.ins().ireduce(access_ty, arg2);
2808 }
2809
2810 let (flags, _, addr) = unwrap_or_return_unreachable_state!(
2811 state,
2812 prepare_atomic_addr(
2813 memarg,
2814 u8::try_from(access_ty.bytes()).unwrap(),
2815 builder,
2816 state,
2817 environ,
2818 )?
2819 );
2820
2821 let mut res = builder.ins().atomic_rmw(access_ty, flags, op, addr, arg2);
2822 if access_ty != widened_ty {
2823 res = builder.ins().uextend(widened_ty, res);
2824 }
2825 state.push1(res);
2826 Ok(())
2827}
2828fn translate_atomic_cas<FE: FuncEnvironment + ?Sized>(
2829 widened_ty: Type,
2830 access_ty: Type,
2831 memarg: &MemArg,
2832 builder: &mut FunctionBuilder,
2833 state: &mut FuncTranslationState,
2834 environ: &mut FE,
2835) -> WasmResult<()> {
2836 let (mut expected, mut replacement) = state.pop2();
2837 let expected_ty = builder.func.dfg.value_type(expected);
2838 let replacement_ty = builder.func.dfg.value_type(replacement);
2839
2840 match access_ty {
2843 I8 | I16 | I32 | I64 => {}
2844 _ => {
2845 return Err(wasm_unsupported!(
2846 "atomic_cas: unsupported access type {:?}",
2847 access_ty
2848 ));
2849 }
2850 };
2851 let w_ty_ok = matches!(widened_ty, I32 | I64);
2852 assert!(w_ty_ok && widened_ty.bytes() >= access_ty.bytes());
2853
2854 assert!(expected_ty.bytes() >= access_ty.bytes());
2855 if expected_ty.bytes() > access_ty.bytes() {
2856 expected = builder.ins().ireduce(access_ty, expected);
2857 }
2858 assert!(replacement_ty.bytes() >= access_ty.bytes());
2859 if replacement_ty.bytes() > access_ty.bytes() {
2860 replacement = builder.ins().ireduce(access_ty, replacement);
2861 }
2862
2863 let (flags, _, addr) = unwrap_or_return_unreachable_state!(
2864 state,
2865 prepare_atomic_addr(
2866 memarg,
2867 u8::try_from(access_ty.bytes()).unwrap(),
2868 builder,
2869 state,
2870 environ,
2871 )?
2872 );
2873 let mut res = builder.ins().atomic_cas(flags, addr, expected, replacement);
2874 if access_ty != widened_ty {
2875 res = builder.ins().uextend(widened_ty, res);
2876 }
2877 state.push1(res);
2878 Ok(())
2879}
2880
2881fn translate_atomic_load<FE: FuncEnvironment + ?Sized>(
2882 widened_ty: Type,
2883 access_ty: Type,
2884 memarg: &MemArg,
2885 builder: &mut FunctionBuilder,
2886 state: &mut FuncTranslationState,
2887 environ: &mut FE,
2888) -> WasmResult<()> {
2889 match access_ty {
2892 I8 | I16 | I32 | I64 => {}
2893 _ => {
2894 return Err(wasm_unsupported!(
2895 "atomic_load: unsupported access type {:?}",
2896 access_ty
2897 ));
2898 }
2899 };
2900 let w_ty_ok = matches!(widened_ty, I32 | I64);
2901 assert!(w_ty_ok && widened_ty.bytes() >= access_ty.bytes());
2902
2903 let (flags, _, addr) = unwrap_or_return_unreachable_state!(
2904 state,
2905 prepare_atomic_addr(
2906 memarg,
2907 u8::try_from(access_ty.bytes()).unwrap(),
2908 builder,
2909 state,
2910 environ,
2911 )?
2912 );
2913 let mut res = builder.ins().atomic_load(access_ty, flags, addr);
2914 if access_ty != widened_ty {
2915 res = builder.ins().uextend(widened_ty, res);
2916 }
2917 state.push1(res);
2918 Ok(())
2919}
2920
2921fn translate_atomic_store<FE: FuncEnvironment + ?Sized>(
2922 access_ty: Type,
2923 memarg: &MemArg,
2924 builder: &mut FunctionBuilder,
2925 state: &mut FuncTranslationState,
2926 environ: &mut FE,
2927) -> WasmResult<()> {
2928 let mut data = state.pop1();
2929 let data_ty = builder.func.dfg.value_type(data);
2930
2931 match access_ty {
2934 I8 | I16 | I32 | I64 => {}
2935 _ => {
2936 return Err(wasm_unsupported!(
2937 "atomic_store: unsupported access type {:?}",
2938 access_ty
2939 ));
2940 }
2941 };
2942 let d_ty_ok = matches!(data_ty, I32 | I64);
2943 assert!(d_ty_ok && data_ty.bytes() >= access_ty.bytes());
2944
2945 if data_ty.bytes() > access_ty.bytes() {
2946 data = builder.ins().ireduce(access_ty, data);
2947 }
2948
2949 let (flags, _, addr) = unwrap_or_return_unreachable_state!(
2950 state,
2951 prepare_atomic_addr(
2952 memarg,
2953 u8::try_from(access_ty.bytes()).unwrap(),
2954 builder,
2955 state,
2956 environ,
2957 )?
2958 );
2959 builder.ins().atomic_store(flags, data, addr);
2960 Ok(())
2961}
2962
2963fn translate_vector_icmp(
2964 cc: IntCC,
2965 needed_type: Type,
2966 builder: &mut FunctionBuilder,
2967 state: &mut FuncTranslationState,
2968) {
2969 let (a, b) = state.pop2();
2970 let bitcast_a = optionally_bitcast_vector(a, needed_type, builder);
2971 let bitcast_b = optionally_bitcast_vector(b, needed_type, builder);
2972 state.push1(builder.ins().icmp(cc, bitcast_a, bitcast_b))
2973}
2974
2975fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) {
2976 let (arg0, arg1) = state.pop2();
2977 let val = builder.ins().fcmp(cc, arg0, arg1);
2978 state.push1(builder.ins().uextend(I32, val));
2979}
2980
2981fn translate_vector_fcmp(
2982 cc: FloatCC,
2983 needed_type: Type,
2984 builder: &mut FunctionBuilder,
2985 state: &mut FuncTranslationState,
2986) {
2987 let (a, b) = state.pop2();
2988 let bitcast_a = optionally_bitcast_vector(a, needed_type, builder);
2989 let bitcast_b = optionally_bitcast_vector(b, needed_type, builder);
2990 state.push1(builder.ins().fcmp(cc, bitcast_a, bitcast_b))
2991}
2992
2993fn translate_br_if(
2994 relative_depth: u32,
2995 builder: &mut FunctionBuilder,
2996 state: &mut FuncTranslationState,
2997) {
2998 let val = state.pop1();
2999 let (br_destination, inputs) = translate_br_if_args(relative_depth, state);
3000 let next_block = builder.create_block();
3001 canonicalise_brif(builder, val, br_destination, inputs, next_block, &[]);
3002
3003 builder.seal_block(next_block); builder.switch_to_block(next_block);
3005}
3006
3007fn translate_br_if_args(
3008 relative_depth: u32,
3009 state: &mut FuncTranslationState,
3010) -> (ir::Block, &mut [ir::Value]) {
3011 let i = state.control_stack.len() - 1 - (relative_depth as usize);
3012 let (return_count, br_destination) = {
3013 let frame = &mut state.control_stack[i];
3014 frame.set_branched_to_exit();
3017 let return_count = if frame.is_loop() {
3018 frame.num_param_values()
3019 } else {
3020 frame.num_return_values()
3021 };
3022 (return_count, frame.br_destination())
3023 };
3024 let inputs = state.peekn_mut(return_count);
3025 (br_destination, inputs)
3026}
3027
3028fn type_of(operator: &Operator) -> Type {
3030 match operator {
3031 Operator::V128Load { .. }
3032 | Operator::V128Store { .. }
3033 | Operator::V128Const { .. }
3034 | Operator::V128Not
3035 | Operator::V128And
3036 | Operator::V128AndNot
3037 | Operator::V128Or
3038 | Operator::V128Xor
3039 | Operator::V128AnyTrue
3040 | Operator::V128Bitselect => I8X16, Operator::I8x16Shuffle { .. }
3043 | Operator::I8x16Splat
3044 | Operator::V128Load8Splat { .. }
3045 | Operator::V128Load8Lane { .. }
3046 | Operator::V128Store8Lane { .. }
3047 | Operator::I8x16ExtractLaneS { .. }
3048 | Operator::I8x16ExtractLaneU { .. }
3049 | Operator::I8x16ReplaceLane { .. }
3050 | Operator::I8x16Eq
3051 | Operator::I8x16Ne
3052 | Operator::I8x16LtS
3053 | Operator::I8x16LtU
3054 | Operator::I8x16GtS
3055 | Operator::I8x16GtU
3056 | Operator::I8x16LeS
3057 | Operator::I8x16LeU
3058 | Operator::I8x16GeS
3059 | Operator::I8x16GeU
3060 | Operator::I8x16Neg
3061 | Operator::I8x16Abs
3062 | Operator::I8x16AllTrue
3063 | Operator::I8x16Shl
3064 | Operator::I8x16ShrS
3065 | Operator::I8x16ShrU
3066 | Operator::I8x16Add
3067 | Operator::I8x16AddSatS
3068 | Operator::I8x16AddSatU
3069 | Operator::I8x16Sub
3070 | Operator::I8x16SubSatS
3071 | Operator::I8x16SubSatU
3072 | Operator::I8x16MinS
3073 | Operator::I8x16MinU
3074 | Operator::I8x16MaxS
3075 | Operator::I8x16MaxU
3076 | Operator::I8x16AvgrU
3077 | Operator::I8x16Bitmask
3078 | Operator::I8x16Popcnt => I8X16,
3079
3080 Operator::I16x8Splat
3081 | Operator::V128Load16Splat { .. }
3082 | Operator::V128Load16Lane { .. }
3083 | Operator::V128Store16Lane { .. }
3084 | Operator::I16x8ExtractLaneS { .. }
3085 | Operator::I16x8ExtractLaneU { .. }
3086 | Operator::I16x8ReplaceLane { .. }
3087 | Operator::I16x8Eq
3088 | Operator::I16x8Ne
3089 | Operator::I16x8LtS
3090 | Operator::I16x8LtU
3091 | Operator::I16x8GtS
3092 | Operator::I16x8GtU
3093 | Operator::I16x8LeS
3094 | Operator::I16x8LeU
3095 | Operator::I16x8GeS
3096 | Operator::I16x8GeU
3097 | Operator::I16x8Neg
3098 | Operator::I16x8Abs
3099 | Operator::I16x8AllTrue
3100 | Operator::I16x8Shl
3101 | Operator::I16x8ShrS
3102 | Operator::I16x8ShrU
3103 | Operator::I16x8Add
3104 | Operator::I16x8AddSatS
3105 | Operator::I16x8AddSatU
3106 | Operator::I16x8Sub
3107 | Operator::I16x8SubSatS
3108 | Operator::I16x8SubSatU
3109 | Operator::I16x8MinS
3110 | Operator::I16x8MinU
3111 | Operator::I16x8MaxS
3112 | Operator::I16x8MaxU
3113 | Operator::I16x8AvgrU
3114 | Operator::I16x8Mul
3115 | Operator::I16x8Bitmask => I16X8,
3116
3117 Operator::I32x4Splat
3118 | Operator::V128Load32Splat { .. }
3119 | Operator::V128Load32Lane { .. }
3120 | Operator::V128Store32Lane { .. }
3121 | Operator::I32x4ExtractLane { .. }
3122 | Operator::I32x4ReplaceLane { .. }
3123 | Operator::I32x4Eq
3124 | Operator::I32x4Ne
3125 | Operator::I32x4LtS
3126 | Operator::I32x4LtU
3127 | Operator::I32x4GtS
3128 | Operator::I32x4GtU
3129 | Operator::I32x4LeS
3130 | Operator::I32x4LeU
3131 | Operator::I32x4GeS
3132 | Operator::I32x4GeU
3133 | Operator::I32x4Neg
3134 | Operator::I32x4Abs
3135 | Operator::I32x4AllTrue
3136 | Operator::I32x4Shl
3137 | Operator::I32x4ShrS
3138 | Operator::I32x4ShrU
3139 | Operator::I32x4Add
3140 | Operator::I32x4Sub
3141 | Operator::I32x4Mul
3142 | Operator::I32x4MinS
3143 | Operator::I32x4MinU
3144 | Operator::I32x4MaxS
3145 | Operator::I32x4MaxU
3146 | Operator::I32x4Bitmask
3147 | Operator::I32x4TruncSatF32x4S
3148 | Operator::I32x4TruncSatF32x4U
3149 | Operator::V128Load32Zero { .. } => I32X4,
3150
3151 Operator::I64x2Splat
3152 | Operator::V128Load64Splat { .. }
3153 | Operator::V128Load64Lane { .. }
3154 | Operator::V128Store64Lane { .. }
3155 | Operator::I64x2ExtractLane { .. }
3156 | Operator::I64x2ReplaceLane { .. }
3157 | Operator::I64x2Eq
3158 | Operator::I64x2Ne
3159 | Operator::I64x2LtS
3160 | Operator::I64x2GtS
3161 | Operator::I64x2LeS
3162 | Operator::I64x2GeS
3163 | Operator::I64x2Neg
3164 | Operator::I64x2Abs
3165 | Operator::I64x2AllTrue
3166 | Operator::I64x2Shl
3167 | Operator::I64x2ShrS
3168 | Operator::I64x2ShrU
3169 | Operator::I64x2Add
3170 | Operator::I64x2Sub
3171 | Operator::I64x2Mul
3172 | Operator::I64x2Bitmask
3173 | Operator::V128Load64Zero { .. } => I64X2,
3174
3175 Operator::F32x4Splat
3176 | Operator::F32x4ExtractLane { .. }
3177 | Operator::F32x4ReplaceLane { .. }
3178 | Operator::F32x4Eq
3179 | Operator::F32x4Ne
3180 | Operator::F32x4Lt
3181 | Operator::F32x4Gt
3182 | Operator::F32x4Le
3183 | Operator::F32x4Ge
3184 | Operator::F32x4Abs
3185 | Operator::F32x4Neg
3186 | Operator::F32x4Sqrt
3187 | Operator::F32x4Add
3188 | Operator::F32x4Sub
3189 | Operator::F32x4Mul
3190 | Operator::F32x4Div
3191 | Operator::F32x4Min
3192 | Operator::F32x4Max
3193 | Operator::F32x4PMin
3194 | Operator::F32x4PMax
3195 | Operator::F32x4ConvertI32x4S
3196 | Operator::F32x4ConvertI32x4U
3197 | Operator::F32x4Ceil
3198 | Operator::F32x4Floor
3199 | Operator::F32x4Trunc
3200 | Operator::F32x4Nearest => F32X4,
3201
3202 Operator::F64x2Splat
3203 | Operator::F64x2ExtractLane { .. }
3204 | Operator::F64x2ReplaceLane { .. }
3205 | Operator::F64x2Eq
3206 | Operator::F64x2Ne
3207 | Operator::F64x2Lt
3208 | Operator::F64x2Gt
3209 | Operator::F64x2Le
3210 | Operator::F64x2Ge
3211 | Operator::F64x2Abs
3212 | Operator::F64x2Neg
3213 | Operator::F64x2Sqrt
3214 | Operator::F64x2Add
3215 | Operator::F64x2Sub
3216 | Operator::F64x2Mul
3217 | Operator::F64x2Div
3218 | Operator::F64x2Min
3219 | Operator::F64x2Max
3220 | Operator::F64x2PMin
3221 | Operator::F64x2PMax
3222 | Operator::F64x2Ceil
3223 | Operator::F64x2Floor
3224 | Operator::F64x2Trunc
3225 | Operator::F64x2Nearest => F64X2,
3226
3227 _ => unimplemented!(
3228 "Currently only SIMD instructions are mapped to their return type; the \
3229 following instruction is not mapped: {:?}",
3230 operator
3231 ),
3232 }
3233}
3234
3235fn optionally_bitcast_vector(
3238 value: Value,
3239 needed_type: Type,
3240 builder: &mut FunctionBuilder,
3241) -> Value {
3242 if builder.func.dfg.value_type(value) != needed_type {
3243 builder.ins().bitcast(
3244 needed_type,
3245 MemFlags::new().with_endianness(ir::Endianness::Little),
3246 value,
3247 )
3248 } else {
3249 value
3250 }
3251}
3252
3253#[inline(always)]
3254fn is_non_canonical_v128(ty: ir::Type) -> bool {
3255 matches!(ty, I64X2 | I32X4 | I16X8 | F32X4 | F64X2)
3256}
3257
3258fn canonicalise_v128_values<'a>(
3263 tmp_canonicalised: &'a mut SmallVec<[ir::BlockArg; 16]>,
3264 builder: &mut FunctionBuilder,
3265 values: &'a [ir::Value],
3266) -> &'a [ir::BlockArg] {
3267 debug_assert!(tmp_canonicalised.is_empty());
3268 for v in values {
3269 let value = if is_non_canonical_v128(builder.func.dfg.value_type(*v)) {
3270 builder.ins().bitcast(
3271 I8X16,
3272 MemFlags::new().with_endianness(ir::Endianness::Little),
3273 *v,
3274 )
3275 } else {
3276 *v
3277 };
3278 tmp_canonicalised.push(BlockArg::from(value));
3279 }
3280 tmp_canonicalised.as_slice()
3281}
3282
3283fn canonicalise_then_jump(
3287 builder: &mut FunctionBuilder,
3288 destination: ir::Block,
3289 params: &[ir::Value],
3290) -> ir::Inst {
3291 let mut tmp_canonicalised = SmallVec::<[_; 16]>::new();
3292 let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params);
3293 builder.ins().jump(destination, canonicalised)
3294}
3295
3296fn canonicalise_brif(
3298 builder: &mut FunctionBuilder,
3299 cond: ir::Value,
3300 block_then: ir::Block,
3301 params_then: &[ir::Value],
3302 block_else: ir::Block,
3303 params_else: &[ir::Value],
3304) -> ir::Inst {
3305 let mut tmp_canonicalised_then = SmallVec::<[_; 16]>::new();
3306 let canonicalised_then =
3307 canonicalise_v128_values(&mut tmp_canonicalised_then, builder, params_then);
3308 let mut tmp_canonicalised_else = SmallVec::<[_; 16]>::new();
3309 let canonicalised_else =
3310 canonicalise_v128_values(&mut tmp_canonicalised_else, builder, params_else);
3311 builder.ins().brif(
3312 cond,
3313 block_then,
3314 canonicalised_then,
3315 block_else,
3316 canonicalised_else,
3317 )
3318}
3319
3320fn pop1_with_bitcast(
3324 state: &mut FuncTranslationState,
3325 needed_type: Type,
3326 builder: &mut FunctionBuilder,
3327) -> Value {
3328 optionally_bitcast_vector(state.pop1(), needed_type, builder)
3329}
3330
3331fn pop2_with_bitcast(
3335 state: &mut FuncTranslationState,
3336 needed_type: Type,
3337 builder: &mut FunctionBuilder,
3338) -> (Value, Value) {
3339 let (a, b) = state.pop2();
3340 let bitcast_a = optionally_bitcast_vector(a, needed_type, builder);
3341 let bitcast_b = optionally_bitcast_vector(b, needed_type, builder);
3342 (bitcast_a, bitcast_b)
3343}
3344
3345pub fn bitcast_arguments<'a>(
3346 builder: &FunctionBuilder,
3347 arguments: &'a mut [Value],
3348 params: &[ir::AbiParam],
3349 param_predicate: impl Fn(usize) -> bool,
3350) -> Vec<(Type, &'a mut Value)> {
3351 let filtered_param_types = params
3352 .iter()
3353 .enumerate()
3354 .filter(|(i, _)| param_predicate(*i))
3355 .map(|(_, param)| param.value_type);
3356
3357 let pairs = filtered_param_types.zip_eq(arguments.iter_mut());
3361
3362 pairs
3365 .filter(|(param_type, _)| param_type.is_vector())
3366 .filter(|(param_type, arg)| {
3367 let arg_type = builder.func.dfg.value_type(**arg);
3368 assert!(
3369 arg_type.is_vector(),
3370 "unexpected type mismatch: expected {}, argument {} was actually of type {}",
3371 param_type,
3372 *arg,
3373 arg_type
3374 );
3375
3376 arg_type != *param_type
3380 })
3381 .collect()
3382}
3383
3384pub fn bitcast_wasm_returns<FE: FuncEnvironment + ?Sized>(
3390 environ: &mut FE,
3391 arguments: &mut [Value],
3392 builder: &mut FunctionBuilder,
3393) {
3394 let changes = bitcast_arguments(builder, arguments, &builder.func.signature.returns, |i| {
3395 environ.is_wasm_return(&builder.func.signature, i)
3396 });
3397 for (t, arg) in changes {
3398 let mut flags = MemFlags::new();
3399 flags.set_endianness(ir::Endianness::Little);
3400 *arg = builder.ins().bitcast(t, flags, *arg);
3401 }
3402}
3403
3404pub fn bitcast_wasm_params<FE: FuncEnvironment + ?Sized>(
3406 environ: &mut FE,
3407 callee_signature: ir::SigRef,
3408 arguments: &mut [Value],
3409 builder: &mut FunctionBuilder,
3410) {
3411 let callee_signature = &builder.func.dfg.signatures[callee_signature];
3412 let changes = bitcast_arguments(builder, arguments, &callee_signature.params, |i| {
3413 environ.is_wasm_parameter(callee_signature, i)
3414 });
3415 for (t, arg) in changes {
3416 let mut flags = MemFlags::new();
3417 flags.set_endianness(ir::Endianness::Little);
3418 *arg = builder.ins().bitcast(t, flags, *arg);
3419 }
3420}