1use std::collections::HashMap;
2
3use super::{
4 intrinsics::{
5 CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
6 },
7 state::{ControlFrame, ExtraInfo, IfElseState, State, TagCatchInfo},
9};
10use crate::compiler::ModuleBasedSymbolRegistry;
11use enumset::EnumSet;
12use inkwell::{
13 AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
14 attributes::{Attribute, AttributeLoc},
15 builder::Builder,
16 context::Context,
17 module::{Linkage, Module},
18 passes::PassBuilderOptions,
19 targets::{FileType, TargetMachine},
20 types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
21 values::{
22 BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
23 FunctionValue, InstructionOpcode, InstructionValue, IntValue, PhiValue, PointerValue,
24 VectorValue,
25 },
26};
27use itertools::Itertools;
28use smallvec::SmallVec;
29use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
30use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
31
32use crate::{
33 abi::{Abi, get_abi},
34 config::LLVM,
35 error::{err, err_nt},
36 object_file::{CompiledFunction, load_object_file},
37};
38use wasmer_compiler::{
39 CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
40 GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
41 GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
42 LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
43 LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
44 from_binaryreadererror_wasmerror,
45 misc::CompiledKind,
46 types::{
47 relocation::RelocationTarget,
48 symbols::{Symbol, SymbolRegistry},
49 },
50 wasmparser::{Catch, MemArg, Operator},
51 wpheaptype_to_type, wptype_to_type,
52};
53use wasmer_types::{
54 CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
55 ModuleInfo, SignatureIndex, TableIndex, Type, target::CpuFeature,
56};
57use wasmer_types::{TagIndex, entity::PrimaryMap};
58use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
59
60const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
61const FUNCTION_SECTION_MACHO: &str = "__TEXT";
62const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
63
64const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
70
71pub struct FuncTranslator {
72 ctx: Context,
73 target_triple: Triple,
74 target_machine: TargetMachine,
75 target_machine_no_opt: Option<TargetMachine>,
76 abi: Box<dyn Abi>,
77 binary_fmt: BinaryFormat,
78 func_section: String,
79 pointer_width: u8,
80 cpu_features: EnumSet<CpuFeature>,
81 non_volatile_memory_ops: bool,
82}
83
84impl wasmer_compiler::FuncTranslator for FuncTranslator {}
85
86impl FuncTranslator {
87 pub fn new(
88 target_triple: Triple,
89 target_machine: TargetMachine,
90 target_machine_no_opt: Option<TargetMachine>,
91 binary_fmt: BinaryFormat,
92 pointer_width: u8,
93 cpu_features: EnumSet<CpuFeature>,
94 non_volatile_memory_ops: bool,
95 ) -> Result<Self, CompileError> {
96 let abi = get_abi(&target_machine);
97 Ok(Self {
98 ctx: Context::create(),
99 target_triple,
100 target_machine,
101 target_machine_no_opt,
102 abi,
103 func_section: match binary_fmt {
104 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
105 BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
106 _ => {
107 return Err(CompileError::UnsupportedTarget(format!(
108 "Unsupported binary format: {binary_fmt:?}"
109 )));
110 }
111 },
112 binary_fmt,
113 pointer_width,
114 cpu_features,
115 non_volatile_memory_ops,
116 })
117 }
118
119 #[allow(clippy::too_many_arguments)]
120 pub fn translate_to_module(
121 &self,
122 wasm_module: &ModuleInfo,
123 module_translation: &ModuleTranslationState,
124 local_func_index: &LocalFunctionIndex,
125 function_body: &FunctionBodyData,
126 config: &LLVM,
127 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
128 _table_styles: &PrimaryMap<TableIndex, TableStyle>,
129 symbol_registry: &dyn SymbolRegistry,
130 target: &Triple,
131 ) -> Result<Module<'_>, CompileError> {
132 let func_index = wasm_module.func_index(*local_func_index);
134 let function =
135 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
136 let function_name =
137 symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
138
139 let m0_is_enabled = memory_styles
142 .get(MemoryIndex::from_u32(0))
143 .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
144
145 let module_name = match wasm_module.name.as_ref() {
146 None => format!("<anonymous module> function {function_name}"),
147 Some(module_name) => format!("module {module_name} function {function_name}"),
148 };
149 let module = self.ctx.create_module(module_name.as_str());
150
151 let target_machine = &self.target_machine;
152 let target_triple = target_machine.get_triple();
153 let target_data = target_machine.get_target_data();
154 module.set_triple(&target_triple);
155 module.set_data_layout(&target_data.get_data_layout());
156 let wasm_fn_type = wasm_module
157 .signatures
158 .get(wasm_module.functions[func_index])
159 .unwrap();
160
161 let offsets = VMOffsets::new(self.pointer_width, wasm_module);
162 let intrinsics = Intrinsics::declare(
163 &module,
164 &self.ctx,
165 &target_data,
166 &self.target_triple,
167 &self.binary_fmt,
168 );
169 let (func_type, func_attrs) = self.abi.func_type_to_llvm(
170 &self.ctx,
171 &intrinsics,
172 Some(&offsets),
173 wasm_fn_type,
174 m0_is_enabled,
175 )?;
176
177 let func = module.add_function(&function_name, func_type, Some(Linkage::External));
178 for (attr, attr_loc) in &func_attrs {
179 func.add_attribute(*attr_loc, *attr);
180 }
181
182 if !matches!(target.operating_system, OperatingSystem::Windows) {
183 func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
184 }
185
186 func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
187 func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
188
189 let section = match self.binary_fmt {
190 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
191 BinaryFormat::Macho => {
192 format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
193 }
194 _ => {
195 return Err(CompileError::UnsupportedTarget(format!(
196 "Unsupported binary format: {:?}",
197 self.binary_fmt
198 )));
199 }
200 };
201
202 func.set_personality_function(intrinsics.personality);
203 func.as_global_value().set_section(Some(§ion));
204
205 func.set_linkage(Linkage::DLLExport);
206 func.as_global_value()
207 .set_dll_storage_class(DLLStorageClass::Export);
208
209 let entry = self.ctx.append_basic_block(func, "entry");
210 let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
211 let return_ = self.ctx.append_basic_block(func, "return");
212 let alloca_builder = self.ctx.create_builder();
213 let cache_builder = self.ctx.create_builder();
214 let builder = self.ctx.create_builder();
215 cache_builder.position_at_end(entry);
216 let br = err!(cache_builder.build_unconditional_branch(start_of_code));
217 alloca_builder.position_before(&br);
218 cache_builder.position_before(&br);
219 builder.position_at_end(start_of_code);
220
221 let mut state = State::new();
222 builder.position_at_end(return_);
223 let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
224 .results()
225 .iter()
226 .map(|&wasm_ty| {
227 type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
228 })
229 .collect::<Result<_, _>>()?;
230 state.push_block(return_, phis, 0);
231 builder.position_at_end(start_of_code);
232
233 let mut reader = MiddlewareBinaryReader::new_with_offset(
234 function_body.data,
235 function_body.module_offset,
236 );
237 reader.set_middleware_chain(
238 config
239 .middlewares
240 .generate_function_middleware_chain(*local_func_index),
241 );
242
243 let mut params = vec![];
244 let first_param =
245 if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
246 if m0_is_enabled { 3 } else { 2 }
247 } else if m0_is_enabled {
248 2
249 } else {
250 1
251 };
252 let mut is_first_alloca = true;
253 let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
254 let alloca = err!(alloca_builder.build_alloca(ty, &name));
255 if is_first_alloca {
256 alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
257 is_first_alloca = false;
258 }
259 Ok(alloca)
260 };
261
262 for idx in 0..wasm_fn_type.params().len() {
280 let ty = wasm_fn_type.params()[idx];
281 let ty = type_to_llvm(&intrinsics, ty)?;
282 let value = func
283 .get_nth_param((idx as u32).checked_add(first_param).unwrap())
284 .unwrap();
285 let alloca = insert_alloca(ty, format!("param_{idx}"))?;
286 err!(cache_builder.build_store(alloca, value));
287 params.push((ty, alloca));
288 }
289
290 let mut locals = vec![];
291 let num_locals = reader.read_local_count()?;
292 for idx in 0..num_locals {
293 let (count, ty) = reader.read_local_decl()?;
294 let ty = err!(wptype_to_type(ty));
295 let ty = type_to_llvm(&intrinsics, ty)?;
296 for _ in 0..count {
297 let alloca = insert_alloca(ty, format!("local_{idx}"))?;
298 err!(cache_builder.build_store(alloca, ty.const_zero()));
299 locals.push((ty, alloca));
300 }
301 }
302
303 let mut params_locals = params.clone();
304 params_locals.extend(locals.iter().cloned());
305
306 let mut m0_param = None;
307
308 if m0_is_enabled {
309 let m0 = self.abi.get_m0_ptr_param(&func);
310 m0.set_name("m0_base_ptr");
311 m0_param = Some(m0);
312 }
313
314 let mut fcg = LLVMFunctionCodeGenerator {
315 m0_param,
316 context: &self.ctx,
317 builder,
318 alloca_builder,
319 intrinsics: &intrinsics,
320 state,
321 function: func,
322 locals: params_locals,
323 ctx: CtxType::new(
324 wasm_module,
325 &func,
326 &cache_builder,
327 &*self.abi,
328 self.pointer_width,
329 m0_param,
330 ),
331 unreachable_depth: 0,
332 memory_styles,
333 _table_styles,
334 module: &module,
335 module_translation,
336 wasm_module,
337 symbol_registry,
338 abi: &*self.abi,
339 config,
340 target_triple: self.target_triple.clone(),
341 tags_cache: HashMap::new(),
342 binary_fmt: self.binary_fmt,
343 cpu_features: self.cpu_features,
344 non_volatile_memory_ops: self.non_volatile_memory_ops,
345 };
346
347 fcg.ctx.add_func(
348 func_index,
349 func.as_global_value().as_pointer_value(),
350 func_type,
351 fcg.ctx.basic(),
352 &func_attrs,
353 );
354
355 while fcg.state.has_control_frames() {
356 let pos = reader.current_position() as u32;
357 let op = reader.read_operator()?;
358 fcg.translate_operator(op, pos)?;
359 }
360
361 fcg.finalize(wasm_fn_type)?;
362
363 if let Some(ref callbacks) = config.callbacks {
364 callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
365 }
366
367 let mut passes = vec![];
368
369 if config.enable_verifier {
370 passes.push("verify");
371 }
372
373 passes.push("sccp");
374 passes.push("early-cse");
375 passes.push("adce");
377 passes.push("sroa");
378 passes.push("aggressive-instcombine");
379 passes.push("jump-threading");
380 passes.push("simplifycfg");
382 passes.push("reassociate");
383 passes.push("loop-rotate");
384 passes.push("indvars");
385 passes.push("sccp");
389 passes.push("reassociate");
390 passes.push("simplifycfg");
391 passes.push("gvn");
392 passes.push("memcpyopt");
393 passes.push("dse");
394 passes.push("dce");
395 passes.push("reassociate");
397 passes.push("simplifycfg");
398 passes.push("mem2reg");
399
400 module
401 .run_passes(
402 passes.join(",").as_str(),
403 target_machine,
404 PassBuilderOptions::create(),
405 )
406 .unwrap();
407
408 if let Some(ref callbacks) = config.callbacks {
409 callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
410 }
411
412 Ok(module)
413 }
414
415 #[allow(clippy::too_many_arguments)]
416 pub fn translate(
417 &self,
418 wasm_module: &ModuleInfo,
419 module_translation: &ModuleTranslationState,
420 local_func_index: &LocalFunctionIndex,
421 function_body: &FunctionBodyData,
422 config: &LLVM,
423 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
424 table_styles: &PrimaryMap<TableIndex, TableStyle>,
425 symbol_registry: &ModuleBasedSymbolRegistry,
426 target: &Triple,
427 ) -> Result<CompiledFunction, CompileError> {
428 let module = self.translate_to_module(
429 wasm_module,
430 module_translation,
431 local_func_index,
432 function_body,
433 config,
434 memory_styles,
435 table_styles,
436 symbol_registry,
437 target,
438 )?;
439 let function = CompiledKind::Local(
440 *local_func_index,
441 wasm_module.get_function_name(wasm_module.func_index(*local_func_index)),
442 );
443
444 let target_machine = if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
445 self.target_machine_no_opt
446 .as_ref()
447 .unwrap_or(&self.target_machine)
448 } else {
449 &self.target_machine
450 };
451 let memory_buffer = target_machine
452 .write_to_memory_buffer(&module, FileType::Object)
453 .unwrap();
454
455 if let Some(ref callbacks) = config.callbacks {
456 let module_hash = wasm_module.hash().map(|m| m.to_string());
457 callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
458 let asm_buffer = target_machine
459 .write_to_memory_buffer(&module, FileType::Assembly)
460 .unwrap();
461 callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
462 }
463
464 let mem_buf_slice = memory_buffer.as_slice();
465
466 load_object_file(
467 mem_buf_slice,
468 &self.func_section,
469 RelocationTarget::LocalFunc(*local_func_index),
470 |name: &str| {
471 Ok({
472 let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
473 if name.starts_with("_") {
474 name.replacen("_", "", 1)
475 } else {
476 name.to_string()
477 }
478 } else {
479 name.to_string()
480 };
481 if let Some(Symbol::LocalFunction(local_func_index)) =
482 symbol_registry.name_to_symbol(&name)
483 {
484 Some(RelocationTarget::LocalFunc(local_func_index))
485 } else {
486 None
487 }
488 })
489 },
490 self.binary_fmt,
491 )
492 }
493}
494
495impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
496 fn splat_vector(
498 &self,
499 value: BasicValueEnum<'ctx>,
500 vec_ty: VectorType<'ctx>,
501 ) -> Result<VectorValue<'ctx>, CompileError> {
502 err_nt!(
505 self.builder.build_shuffle_vector(
506 err!(self.builder.build_insert_element(
507 vec_ty.get_undef(),
508 value,
509 self.intrinsics.i32_zero,
510 "",
511 )),
512 vec_ty.get_undef(),
513 self.intrinsics
514 .i32_ty
515 .vec_type(vec_ty.get_size())
516 .const_zero(),
517 "",
518 )
519 )
520 }
521
522 #[allow(clippy::too_many_arguments)]
525 fn trunc_sat<T: FloatMathType<'ctx>>(
526 &self,
527 fvec_ty: T,
528 ivec_ty: T::MathConvType,
529 lower_bound: u64, upper_bound: u64, int_min_value: u64,
532 int_max_value: u64,
533 value: IntValue<'ctx>,
534 ) -> Result<VectorValue<'ctx>, CompileError> {
535 let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
549 let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
550 let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
551 let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
552
553 let is_signed = int_min_value != 0;
554 let int_min_value = self.splat_vector(
555 ivec_element_ty
556 .const_int(int_min_value, is_signed)
557 .as_basic_value_enum(),
558 ivec_ty,
559 )?;
560 let int_max_value = self.splat_vector(
561 ivec_element_ty
562 .const_int(int_max_value, is_signed)
563 .as_basic_value_enum(),
564 ivec_ty,
565 )?;
566 let lower_bound = if is_signed {
567 err!(self.builder.build_signed_int_to_float(
568 ivec_element_ty.const_int(lower_bound, is_signed),
569 fvec_element_ty,
570 "",
571 ))
572 } else {
573 err!(self.builder.build_unsigned_int_to_float(
574 ivec_element_ty.const_int(lower_bound, is_signed),
575 fvec_element_ty,
576 "",
577 ))
578 };
579 let upper_bound = if is_signed {
580 err!(self.builder.build_signed_int_to_float(
581 ivec_element_ty.const_int(upper_bound, is_signed),
582 fvec_element_ty,
583 "",
584 ))
585 } else {
586 err!(self.builder.build_unsigned_int_to_float(
587 ivec_element_ty.const_int(upper_bound, is_signed),
588 fvec_element_ty,
589 "",
590 ))
591 };
592
593 let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
594 let zero = fvec_ty.const_zero();
595 let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
596 let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
597 let nan_cmp =
598 err!(
599 self.builder
600 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
601 );
602 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
603 FloatPredicate::OGT,
604 value,
605 upper_bound,
606 "above_upper_bound",
607 ));
608 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
609 FloatPredicate::OLT,
610 value,
611 lower_bound,
612 "below_lower_bound",
613 ));
614 let not_representable = err!(self.builder.build_or(
615 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
616 below_lower_bound_cmp,
617 "not_representable_as_int",
618 ));
619 let value =
620 err!(
621 self.builder
622 .build_select(not_representable, zero, value, "safe_to_convert")
623 )
624 .into_vector_value();
625 let value = if is_signed {
626 self.builder
627 .build_float_to_signed_int(value, ivec_ty, "as_int")
628 } else {
629 self.builder
630 .build_float_to_unsigned_int(value, ivec_ty, "as_int")
631 };
632
633 let value = err!(value);
634 let value =
635 err!(
636 self.builder
637 .build_select(above_upper_bound_cmp, int_max_value, value, "")
638 )
639 .into_vector_value();
640 err_nt!(
641 self.builder
642 .build_select(below_lower_bound_cmp, int_min_value, value, "")
643 .map(|v| v.into_vector_value())
644 )
645 }
646
647 #[allow(clippy::too_many_arguments)]
650 fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
651 &self,
652 fvec_ty: T,
653 ivec_ty: T::MathConvType,
654 lower_bound: u64, upper_bound: u64, int_min_value: u64,
657 int_max_value: u64,
658 value: IntValue<'ctx>,
659 ) -> Result<IntValue<'ctx>, CompileError> {
660 let res = self.trunc_sat(
661 fvec_ty,
662 ivec_ty,
663 lower_bound,
664 upper_bound,
665 int_min_value,
666 int_max_value,
667 value,
668 )?;
669 err_nt!(
670 self.builder
671 .build_bit_cast(res, self.intrinsics.i128_ty, "")
672 .map(|v| v.into_int_value())
673 )
674 }
675
676 fn trunc_sat_scalar(
679 &self,
680 int_ty: IntType<'ctx>,
681 lower_bound: u64, upper_bound: u64, int_min_value: u64,
684 int_max_value: u64,
685 value: FloatValue<'ctx>,
686 ) -> Result<IntValue<'ctx>, CompileError> {
687 let is_signed = int_min_value != 0;
703 let int_min_value = int_ty.const_int(int_min_value, is_signed);
704 let int_max_value = int_ty.const_int(int_max_value, is_signed);
705
706 let lower_bound = if is_signed {
707 err!(self.builder.build_signed_int_to_float(
708 int_ty.const_int(lower_bound, is_signed),
709 value.get_type(),
710 "",
711 ))
712 } else {
713 err!(self.builder.build_unsigned_int_to_float(
714 int_ty.const_int(lower_bound, is_signed),
715 value.get_type(),
716 "",
717 ))
718 };
719 let upper_bound = if is_signed {
720 err!(self.builder.build_signed_int_to_float(
721 int_ty.const_int(upper_bound, is_signed),
722 value.get_type(),
723 "",
724 ))
725 } else {
726 err!(self.builder.build_unsigned_int_to_float(
727 int_ty.const_int(upper_bound, is_signed),
728 value.get_type(),
729 "",
730 ))
731 };
732
733 let zero = value.get_type().const_zero();
734
735 let nan_cmp =
736 err!(
737 self.builder
738 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
739 );
740 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
741 FloatPredicate::OGT,
742 value,
743 upper_bound,
744 "above_upper_bound",
745 ));
746 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
747 FloatPredicate::OLT,
748 value,
749 lower_bound,
750 "below_lower_bound",
751 ));
752 let not_representable = err!(self.builder.build_or(
753 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
754 below_lower_bound_cmp,
755 "not_representable_as_int",
756 ));
757 let value =
758 err!(
759 self.builder
760 .build_select(not_representable, zero, value, "safe_to_convert")
761 )
762 .into_float_value();
763 let value = if is_signed {
764 err!(
765 self.builder
766 .build_float_to_signed_int(value, int_ty, "as_int")
767 )
768 } else {
769 err!(
770 self.builder
771 .build_float_to_unsigned_int(value, int_ty, "as_int")
772 )
773 };
774 let value =
775 err!(
776 self.builder
777 .build_select(above_upper_bound_cmp, int_max_value, value, "")
778 )
779 .into_int_value();
780 let value =
781 err!(
782 self.builder
783 .build_select(below_lower_bound_cmp, int_min_value, value, "")
784 )
785 .into_int_value();
786
787 err_nt!(
788 self.builder
789 .build_bit_cast(value, int_ty, "")
790 .map(|v| v.into_int_value())
791 )
792 }
793
794 fn trap_if_not_representable_as_int(
795 &self,
796 lower_bound: u64, upper_bound: u64, value: FloatValue<'ctx>,
799 ) -> Result<(), CompileError> {
800 let float_ty = value.get_type();
801 let int_ty = if float_ty == self.intrinsics.f32_ty {
802 self.intrinsics.i32_ty
803 } else {
804 self.intrinsics.i64_ty
805 };
806
807 let lower_bound = err!(self.builder.build_bit_cast(
808 int_ty.const_int(lower_bound, false),
809 float_ty,
810 ""
811 ))
812 .into_float_value();
813 let upper_bound = err!(self.builder.build_bit_cast(
814 int_ty.const_int(upper_bound, false),
815 float_ty,
816 ""
817 ))
818 .into_float_value();
819
820 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
824 FloatPredicate::UGT,
825 value,
826 upper_bound,
827 "above_upper_bound",
828 ));
829 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
830 FloatPredicate::ULT,
831 value,
832 lower_bound,
833 "below_lower_bound",
834 ));
835 let out_of_bounds = err!(self.builder.build_or(
836 above_upper_bound_cmp,
837 below_lower_bound_cmp,
838 "out_of_bounds",
839 ));
840
841 let failure_block = self
842 .context
843 .append_basic_block(self.function, "conversion_failure_block");
844 let continue_block = self
845 .context
846 .append_basic_block(self.function, "conversion_success_block");
847
848 err!(
849 self.builder
850 .build_conditional_branch(out_of_bounds, failure_block, continue_block)
851 );
852 self.builder.position_at_end(failure_block);
853 let is_nan =
854 err!(
855 self.builder
856 .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
857 );
858 let trap_code = err!(self.builder.build_select(
859 is_nan,
860 self.intrinsics.trap_bad_conversion_to_integer,
861 self.intrinsics.trap_illegal_arithmetic,
862 "",
863 ));
864 self.build_call_with_param_attributes(
865 self.intrinsics.throw_trap,
866 &[trap_code.into()],
867 "throw",
868 )?;
869 err!(self.builder.build_unreachable());
870 self.builder.position_at_end(continue_block);
871
872 Ok(())
873 }
874
875 fn trap_if_zero_or_overflow(
876 &self,
877 left: IntValue<'ctx>,
878 right: IntValue<'ctx>,
879 ) -> Result<(), CompileError> {
880 let int_type = left.get_type();
881
882 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
883 let min_value = int_type.const_int(i32::MIN as u64, false);
884 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
885 (min_value, neg_one_value)
886 } else if int_type == self.intrinsics.i64_ty {
887 let min_value = int_type.const_int(i64::MIN as u64, false);
888 let neg_one_value = int_type.const_int(-1i64 as u64, false);
889 (min_value, neg_one_value)
890 } else {
891 unreachable!()
892 };
893
894 let divisor_is_zero = err!(self.builder.build_int_compare(
895 IntPredicate::EQ,
896 right,
897 int_type.const_zero(),
898 "divisor_is_zero",
899 ));
900 let should_trap = err!(self.builder.build_or(
901 divisor_is_zero,
902 err!(self.builder.build_and(
903 err!(self.builder.build_int_compare(
904 IntPredicate::EQ,
905 left,
906 min_value,
907 "left_is_min"
908 )),
909 err!(self.builder.build_int_compare(
910 IntPredicate::EQ,
911 right,
912 neg_one_value,
913 "right_is_neg_one",
914 )),
915 "div_will_overflow",
916 )),
917 "div_should_trap",
918 ));
919
920 let should_trap = self
921 .build_call_with_param_attributes(
922 self.intrinsics.expect_i1,
923 &[
924 should_trap.into(),
925 self.intrinsics.i1_ty.const_zero().into(),
926 ],
927 "should_trap_expect",
928 )?
929 .try_as_basic_value()
930 .unwrap_basic()
931 .into_int_value();
932
933 let shouldnt_trap_block = self
934 .context
935 .append_basic_block(self.function, "shouldnt_trap_block");
936 let should_trap_block = self
937 .context
938 .append_basic_block(self.function, "should_trap_block");
939 err!(self.builder.build_conditional_branch(
940 should_trap,
941 should_trap_block,
942 shouldnt_trap_block
943 ));
944 self.builder.position_at_end(should_trap_block);
945 let trap_code = err!(self.builder.build_select(
946 divisor_is_zero,
947 self.intrinsics.trap_integer_division_by_zero,
948 self.intrinsics.trap_illegal_arithmetic,
949 "",
950 ));
951 err!(
952 self.builder
953 .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
954 );
955 err!(self.builder.build_unreachable());
956 self.builder.position_at_end(shouldnt_trap_block);
957
958 Ok(())
959 }
960
961 fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
962 let int_type = value.get_type();
963 let should_trap = err!(self.builder.build_int_compare(
964 IntPredicate::EQ,
965 value,
966 int_type.const_zero(),
967 "divisor_is_zero",
968 ));
969
970 let should_trap = self
971 .build_call_with_param_attributes(
972 self.intrinsics.expect_i1,
973 &[
974 should_trap.into(),
975 self.intrinsics.i1_ty.const_zero().into(),
976 ],
977 "should_trap_expect",
978 )?
979 .try_as_basic_value()
980 .unwrap_basic()
981 .into_int_value();
982
983 let shouldnt_trap_block = self
984 .context
985 .append_basic_block(self.function, "shouldnt_trap_block");
986 let should_trap_block = self
987 .context
988 .append_basic_block(self.function, "should_trap_block");
989 err!(self.builder.build_conditional_branch(
990 should_trap,
991 should_trap_block,
992 shouldnt_trap_block
993 ));
994 self.builder.position_at_end(should_trap_block);
995 self.build_call_with_param_attributes(
996 self.intrinsics.throw_trap,
997 &[self.intrinsics.trap_integer_division_by_zero.into()],
998 "throw",
999 )?;
1000 err!(self.builder.build_unreachable());
1001 self.builder.position_at_end(shouldnt_trap_block);
1002
1003 Ok(())
1004 }
1005
1006 fn v128_into_int_vec(
1007 &self,
1008 value: BasicValueEnum<'ctx>,
1009 info: ExtraInfo,
1010 int_vec_ty: VectorType<'ctx>,
1011 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1012 let (value, info) = if self.config.enable_nan_canonicalization {
1013 if info.has_pending_f32_nan() {
1014 let value = err!(
1015 self.builder
1016 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1017 );
1018 (self.canonicalize_nans(value)?, info.strip_pending())
1019 } else if info.has_pending_f64_nan() {
1020 let value = err!(
1021 self.builder
1022 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1023 );
1024 (self.canonicalize_nans(value)?, info.strip_pending())
1025 } else {
1026 (value, info)
1027 }
1028 } else {
1029 (value, info)
1030 };
1031 Ok((
1032 err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1033 info,
1034 ))
1035 }
1036
1037 fn v128_into_i8x16(
1038 &self,
1039 value: BasicValueEnum<'ctx>,
1040 info: ExtraInfo,
1041 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1042 self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1043 }
1044
1045 fn v128_into_i16x8(
1046 &self,
1047 value: BasicValueEnum<'ctx>,
1048 info: ExtraInfo,
1049 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1050 self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1051 }
1052
1053 fn v128_into_i32x4(
1054 &self,
1055 value: BasicValueEnum<'ctx>,
1056 info: ExtraInfo,
1057 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1058 self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1059 }
1060
1061 fn v128_into_i64x2(
1062 &self,
1063 value: BasicValueEnum<'ctx>,
1064 info: ExtraInfo,
1065 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1066 self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1067 }
1068
1069 fn v128_into_f32x4(
1072 &self,
1073 value: BasicValueEnum<'ctx>,
1074 info: ExtraInfo,
1075 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1076 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1077 {
1078 let value = err!(
1079 self.builder
1080 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1081 );
1082 (self.canonicalize_nans(value)?, info.strip_pending())
1083 } else {
1084 (value, info)
1085 };
1086 Ok((
1087 err!(
1088 self.builder
1089 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1090 )
1091 .into_vector_value(),
1092 info,
1093 ))
1094 }
1095
1096 fn v128_into_f64x2(
1099 &self,
1100 value: BasicValueEnum<'ctx>,
1101 info: ExtraInfo,
1102 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1103 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1104 {
1105 let value = err!(
1106 self.builder
1107 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1108 );
1109 (self.canonicalize_nans(value)?, info.strip_pending())
1110 } else {
1111 (value, info)
1112 };
1113 Ok((
1114 err!(
1115 self.builder
1116 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1117 )
1118 .into_vector_value(),
1119 info,
1120 ))
1121 }
1122
1123 fn apply_pending_canonicalization(
1124 &self,
1125 value: BasicValueEnum<'ctx>,
1126 info: ExtraInfo,
1127 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1128 if !self.config.enable_nan_canonicalization {
1129 return Ok(value);
1130 }
1131
1132 if info.has_pending_f32_nan() {
1133 if value.get_type().is_vector_type()
1134 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1135 {
1136 let ty = value.get_type();
1137 let value = err!(
1138 self.builder
1139 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1140 );
1141 let value = self.canonicalize_nans(value)?;
1142 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1143 } else {
1144 self.canonicalize_nans(value)
1145 }
1146 } else if info.has_pending_f64_nan() {
1147 if value.get_type().is_vector_type()
1148 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1149 {
1150 let ty = value.get_type();
1151 let value = err!(
1152 self.builder
1153 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1154 );
1155 let value = self.canonicalize_nans(value)?;
1156 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1157 } else {
1158 self.canonicalize_nans(value)
1159 }
1160 } else {
1161 Ok(value)
1162 }
1163 }
1164
1165 fn canonicalize_nans(
1167 &self,
1168 value: BasicValueEnum<'ctx>,
1169 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1170 if !self.config.enable_nan_canonicalization {
1171 return Ok(value);
1172 }
1173
1174 let f_ty = value.get_type();
1175 if f_ty.is_vector_type() {
1176 let value = value.into_vector_value();
1177 let f_ty = f_ty.into_vector_type();
1178 let zero = f_ty.const_zero();
1179 let nan_cmp =
1180 err!(
1181 self.builder
1182 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1183 );
1184 let canonical_qnan = f_ty
1185 .get_element_type()
1186 .into_float_type()
1187 .const_float(f64::NAN);
1188 let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1189 err_nt!(
1190 self.builder
1191 .build_select(nan_cmp, canonical_qnan, value, "")
1192 .map(|v| v.as_basic_value_enum())
1193 )
1194 } else {
1195 let value = value.into_float_value();
1196 let f_ty = f_ty.into_float_type();
1197 let zero = f_ty.const_zero();
1198 let nan_cmp =
1199 err!(
1200 self.builder
1201 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1202 );
1203 let canonical_qnan = f_ty.const_float(f64::NAN);
1204 err_nt!(
1205 self.builder
1206 .build_select(nan_cmp, canonical_qnan, value, "")
1207 .map(|v| v.as_basic_value_enum())
1208 )
1209 }
1210 }
1211
1212 fn mark_memaccess_nodelete(
1216 &mut self,
1217 memory_index: MemoryIndex,
1218 memaccess: InstructionValue<'ctx>,
1219 ) -> Result<(), CompileError> {
1220 if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1221 memory_index,
1222 self.intrinsics,
1223 self.module,
1224 self.memory_styles,
1225 )? {
1226 memaccess.set_volatile(true).map_err(|err| {
1228 CompileError::Codegen(format!("could not set volatile on memory operation: {err}"))
1229 })
1230 } else {
1231 Ok(())
1232 }
1233 }
1234
1235 fn annotate_user_memaccess(
1236 &mut self,
1237 memory_index: MemoryIndex,
1238 _memarg: &MemArg,
1239 alignment: u32,
1240 memaccess: InstructionValue<'ctx>,
1241 ) -> Result<(), CompileError> {
1242 match memaccess.get_opcode() {
1243 InstructionOpcode::Load | InstructionOpcode::Store => {
1244 memaccess.set_alignment(alignment).unwrap();
1245 }
1246 _ => {}
1247 };
1248 if !self.non_volatile_memory_ops {
1249 self.mark_memaccess_nodelete(memory_index, memaccess)?;
1250 }
1251 tbaa_label(
1252 self.module,
1253 self.intrinsics,
1254 format!("memory {}", memory_index.as_u32()),
1255 memaccess,
1256 );
1257 Ok(())
1258 }
1259
1260 fn resolve_memory_ptr(
1261 &mut self,
1262 memory_index: MemoryIndex,
1263 memarg: &MemArg,
1264 ptr_ty: PointerType<'ctx>,
1265 var_offset: IntValue<'ctx>,
1266 value_size: usize,
1267 ) -> Result<PointerValue<'ctx>, CompileError> {
1268 let builder = &self.builder;
1269 let intrinsics = &self.intrinsics;
1270 let context = &self.context;
1271 let function = &self.function;
1272
1273 let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1275 let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1276 let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1277
1278 let base_ptr = if let Some(m0) = self.m0_param {
1280 m0
1281 } else {
1282 match self
1283 .ctx
1284 .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1285 {
1286 MemoryCache::Dynamic {
1287 ptr_to_base_ptr,
1288 ptr_to_current_length,
1289 } => {
1290 let minimum = self.wasm_module.memories[memory_index].minimum;
1292 let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1293 let ptr_in_bounds = if offset.is_const() {
1294 let load_offset_end =
1297 offset.const_add(value_size_v).get_zero_extended_constant();
1298 if load_offset_end.is_some_and(|load_offset_end| {
1299 load_offset_end <= minimum.bytes().0 as u64
1300 }) {
1301 Some(intrinsics.i64_ty.const_int(1, false))
1302 } else {
1303 None
1304 }
1305 } else {
1306 None
1307 };
1308
1309 let ptr_in_bounds = match ptr_in_bounds {
1310 Some(ptr) => ptr,
1311 None => {
1312 let load_offset_end = err!(builder.build_int_add(
1313 offset,
1314 value_size_v,
1315 "load_offset_end"
1316 ));
1317
1318 let current_length = err!(builder.build_load(
1319 self.intrinsics.i32_ty,
1320 ptr_to_current_length,
1321 "current_length"
1322 ))
1323 .into_int_value();
1324 tbaa_label(
1325 self.module,
1326 self.intrinsics,
1327 format!("memory {} length", memory_index.as_u32()),
1328 current_length.as_instruction_value().unwrap(),
1329 );
1330 let current_length = err!(builder.build_int_z_extend(
1331 current_length,
1332 intrinsics.i64_ty,
1333 "current_length_zextd"
1334 ));
1335
1336 err!(builder.build_int_compare(
1337 IntPredicate::ULE,
1338 load_offset_end,
1339 current_length,
1340 "ptr_in_bounds",
1341 ))
1342 }
1343 };
1344
1345 if !ptr_in_bounds.is_constant_int()
1346 || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1347 {
1348 let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1354 intrinsics.expect_i1,
1355 &[
1356 ptr_in_bounds.into(),
1357 intrinsics.i1_ty.const_int(1, true).into(),
1358 ],
1359 "ptr_in_bounds_expect",
1360 ))
1361 .try_as_basic_value()
1362 .unwrap_basic()
1363 .into_int_value();
1364
1365 let in_bounds_continue_block =
1366 context.append_basic_block(*function, "in_bounds_continue_block");
1367 let not_in_bounds_block =
1368 context.append_basic_block(*function, "not_in_bounds_block");
1369 err!(builder.build_conditional_branch(
1370 ptr_in_bounds,
1371 in_bounds_continue_block,
1372 not_in_bounds_block,
1373 ));
1374 builder.position_at_end(not_in_bounds_block);
1375 err!(self.build_call_with_param_attributes(
1376 intrinsics.throw_trap,
1377 &[intrinsics.trap_memory_oob.into()],
1378 "throw",
1379 ));
1380 err!(builder.build_unreachable());
1381 builder.position_at_end(in_bounds_continue_block);
1382 }
1383 let ptr_to_base =
1384 err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1385 .into_pointer_value();
1386 tbaa_label(
1387 self.module,
1388 self.intrinsics,
1389 format!("memory base_ptr {}", memory_index.as_u32()),
1390 ptr_to_base.as_instruction_value().unwrap(),
1391 );
1392 ptr_to_base
1393 }
1394 MemoryCache::Static { base_ptr } => base_ptr,
1395 }
1396 };
1397 let value_ptr = unsafe {
1398 err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1399 };
1400 err_nt!(
1401 builder
1402 .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1403 .map(|v| v.into_pointer_value())
1404 )
1405 }
1406
1407 fn trap_if_misaligned(
1408 &self,
1409 _memarg: &MemArg,
1410 ptr: PointerValue<'ctx>,
1411 align: u8,
1412 ) -> Result<(), CompileError> {
1413 if align <= 1 {
1414 return Ok(());
1415 }
1416 let value = err!(self.builder.build_ptr_to_int(
1417 ptr,
1418 self.intrinsics.i64_ty,
1419 "mischeck_value"
1420 ));
1421 let and = err!(self.builder.build_and(
1422 value,
1423 self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1424 "misaligncheck",
1425 ));
1426 let aligned = err!(self.builder.build_int_compare(
1427 IntPredicate::EQ,
1428 and,
1429 self.intrinsics.i64_zero,
1430 "is_aligned"
1431 ));
1432 let aligned = self
1433 .build_call_with_param_attributes(
1434 self.intrinsics.expect_i1,
1435 &[
1436 aligned.into(),
1437 self.intrinsics.i1_ty.const_int(1, false).into(),
1438 ],
1439 "is_aligned_expect",
1440 )?
1441 .try_as_basic_value()
1442 .unwrap_basic()
1443 .into_int_value();
1444
1445 let continue_block = self
1446 .context
1447 .append_basic_block(self.function, "aligned_access_continue_block");
1448 let not_aligned_block = self
1449 .context
1450 .append_basic_block(self.function, "misaligned_trap_block");
1451 err!(
1452 self.builder
1453 .build_conditional_branch(aligned, continue_block, not_aligned_block)
1454 );
1455
1456 self.builder.position_at_end(not_aligned_block);
1457 self.build_call_with_param_attributes(
1458 self.intrinsics.throw_trap,
1459 &[self.intrinsics.trap_unaligned_atomic.into()],
1460 "throw",
1461 )?;
1462 err!(self.builder.build_unreachable());
1463
1464 self.builder.position_at_end(continue_block);
1465 Ok(())
1466 }
1467
1468 fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1469 let func_type = self.function.get_type();
1470
1471 let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1472 let results = err!(
1473 results
1474 .into_iter()
1475 .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1476 .collect::<Result<Vec<_>, _>>()
1477 );
1478
1479 if wasm_fn_type.results().is_empty() {
1480 err!(self.builder.build_return(None));
1481 } else if self.abi.is_sret(wasm_fn_type)? {
1482 let sret = self
1483 .function
1484 .get_first_param()
1485 .unwrap()
1486 .into_pointer_value();
1487 let llvm_params: Vec<_> = wasm_fn_type
1488 .results()
1489 .iter()
1490 .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1491 .collect();
1492 let mut struct_value = self
1493 .context
1494 .struct_type(llvm_params.as_slice(), false)
1495 .get_undef();
1496 for (idx, value) in results.into_iter().enumerate() {
1497 let value = err!(self.builder.build_bit_cast(
1498 value,
1499 type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1500 "",
1501 ));
1502 struct_value =
1503 err!(
1504 self.builder
1505 .build_insert_value(struct_value, value, idx as u32, "")
1506 )
1507 .into_struct_value();
1508 }
1509 err!(self.builder.build_store(sret, struct_value));
1510 err!(self.builder.build_return(None));
1511 } else {
1512 err!(
1513 self.builder
1514 .build_return(Some(&self.abi.pack_values_for_register_return(
1515 self.intrinsics,
1516 &self.builder,
1517 &results,
1518 &func_type,
1519 )?))
1520 );
1521 }
1522 Ok(())
1523 }
1524
1525 fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1528 if let Some(tag) = self.tags_cache.get(&tag) {
1529 return *tag;
1530 }
1531
1532 let tag_ty = self
1533 .context
1534 .struct_type(&[self.intrinsics.i32_ty.into()], false);
1535 let tag_glbl = self.module.add_global(
1536 tag_ty,
1537 Some(AddressSpace::default()),
1538 &format!("__wasmer_eh_type_info_{tag}"),
1539 );
1540 tag_glbl.set_initializer(
1541 &tag_ty
1542 .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1543 .as_basic_value_enum(),
1544 );
1545
1546 tag_glbl.set_linkage(Linkage::External);
1547 tag_glbl.set_constant(true);
1548 if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1556 tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1557 }
1558
1559 let tag_glbl = tag_glbl.as_basic_value_enum();
1560
1561 self.tags_cache.insert(tag, tag_glbl);
1562 tag_glbl
1563 }
1564
1565 fn build_m0_indirect_call(
1566 &mut self,
1567 table_index: u32,
1568 ctx_ptr: PointerValue<'ctx>,
1569 func_type: &FunctionType,
1570 func_ptr: PointerValue<'ctx>,
1571 func_index: IntValue<'ctx>,
1572 ) -> Result<(), CompileError> {
1573 let Some(m0) = self.m0_param else {
1574 return Err(CompileError::Codegen(
1575 "Call to build_m0_indirect_call without m0 parameter!".to_string(),
1576 ));
1577 };
1578
1579 let mut local_func_indices = vec![];
1580 let mut foreign_func_indices = vec![];
1581
1582 for t in &self.wasm_module.table_initializers {
1583 if t.table_index.as_u32() == table_index {
1584 for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
1585 if self.wasm_module.local_func_index(*func_idx).is_some() {
1586 local_func_indices.push(func_in_table_idx)
1587 } else {
1588 foreign_func_indices.push(func_in_table_idx)
1589 }
1590 }
1591 break;
1592 }
1593 }
1594
1595 let needs_switch = self.m0_param.is_some()
1596 && !local_func_indices.is_empty()
1597 && !foreign_func_indices.is_empty();
1598
1599 if needs_switch {
1600 let foreign_idx_block = self
1601 .context
1602 .append_basic_block(self.function, "foreign_call_block");
1603 let local_idx_block = self
1604 .context
1605 .append_basic_block(self.function, "local_call_block");
1606 let unreachable_indirect_call_branch_block = self
1607 .context
1608 .append_basic_block(self.function, "unreachable_indirect_call_branch");
1609
1610 let cont = self.context.append_basic_block(self.function, "cont");
1611
1612 err!(
1613 self.builder.build_switch(
1614 func_index,
1615 unreachable_indirect_call_branch_block,
1616 &local_func_indices
1617 .into_iter()
1618 .map(|v| (
1619 self.intrinsics.i32_ty.const_int(v as _, false),
1620 local_idx_block
1621 ))
1622 .chain(foreign_func_indices.into_iter().map(|v| (
1623 self.intrinsics.i32_ty.const_int(v as _, false),
1624 foreign_idx_block
1625 )))
1626 .collect::<Vec<_>>()
1627 )
1628 );
1629
1630 self.builder
1631 .position_at_end(unreachable_indirect_call_branch_block);
1632 err!(self.builder.build_unreachable());
1633
1634 self.builder.position_at_end(local_idx_block);
1636 let local_call_site =
1637 self.build_indirect_call(ctx_ptr, func_type, func_ptr, Some(m0))?;
1638
1639 let local_rets = self.abi.rets_from_call(
1640 &self.builder,
1641 self.intrinsics,
1642 local_call_site,
1643 func_type,
1644 )?;
1645
1646 err!(self.builder.build_unconditional_branch(cont));
1647
1648 self.builder.position_at_end(foreign_idx_block);
1649 let foreign_call_site = self.build_indirect_call(ctx_ptr, func_type, func_ptr, None)?;
1650
1651 let foreign_rets = self.abi.rets_from_call(
1652 &self.builder,
1653 self.intrinsics,
1654 foreign_call_site,
1655 func_type,
1656 )?;
1657
1658 err!(self.builder.build_unconditional_branch(cont));
1659
1660 self.builder.position_at_end(cont);
1661
1662 for i in 0..foreign_rets.len() {
1663 let f_i = foreign_rets[i];
1664 let l_i = local_rets[i];
1665 let ty = f_i.get_type();
1666 let v = err!(self.builder.build_phi(ty, ""));
1667 v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
1668 self.state.push1(v.as_basic_value());
1669 }
1670 } else if foreign_func_indices.is_empty() {
1671 let call_site = self.build_indirect_call(ctx_ptr, func_type, func_ptr, Some(m0))?;
1672
1673 self.abi
1674 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1675 .iter()
1676 .for_each(|ret| self.state.push1(*ret));
1677 } else {
1678 let call_site = self.build_indirect_call(ctx_ptr, func_type, func_ptr, None)?;
1679 self.abi
1680 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1681 .iter()
1682 .for_each(|ret| self.state.push1(*ret));
1683 }
1684
1685 Ok(())
1686 }
1687
1688 fn build_indirect_call(
1689 &mut self,
1690 ctx_ptr: PointerValue<'ctx>,
1691 func_type: &FunctionType,
1692 func_ptr: PointerValue<'ctx>,
1693 m0_param: Option<PointerValue<'ctx>>,
1694 ) -> Result<CallSiteValue<'ctx>, CompileError> {
1695 let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
1696 self.context,
1697 self.intrinsics,
1698 Some(self.ctx.get_offsets()),
1699 func_type,
1700 m0_param.is_some(),
1701 )?;
1702
1703 let params = self.state.popn_save_extra(func_type.params().len())?;
1704
1705 let params = params
1707 .iter()
1708 .zip(func_type.params().iter())
1709 .map(|((v, info), wasm_ty)| match wasm_ty {
1710 Type::F32 => err_nt!(self.builder.build_bit_cast(
1711 self.apply_pending_canonicalization(*v, *info)?,
1712 self.intrinsics.f32_ty,
1713 "",
1714 )),
1715 Type::F64 => err_nt!(self.builder.build_bit_cast(
1716 self.apply_pending_canonicalization(*v, *info)?,
1717 self.intrinsics.f64_ty,
1718 "",
1719 )),
1720 Type::V128 => self.apply_pending_canonicalization(*v, *info),
1721 _ => Ok(*v),
1722 })
1723 .collect::<Result<Vec<_>, _>>()?;
1724
1725 let params = self.abi.args_to_call(
1726 &self.alloca_builder,
1727 func_type,
1728 &llvm_func_type,
1729 ctx_ptr,
1730 params.as_slice(),
1731 self.intrinsics,
1732 m0_param,
1733 )?;
1734
1735 let typed_func_ptr = err!(self.builder.build_pointer_cast(
1736 func_ptr,
1737 self.context.ptr_type(AddressSpace::default()),
1738 "typed_func_ptr",
1739 ));
1740
1741 let call_site_local = self.build_indirect_call_or_invoke(
1742 llvm_func_type,
1743 typed_func_ptr,
1744 params.as_slice(),
1745 "then_block",
1746 )?;
1747 for (attr, attr_loc) in llvm_func_attrs {
1748 call_site_local.add_attribute(attr_loc, attr);
1749 }
1750
1751 Ok(call_site_local)
1752 }
1753
1754 fn build_indirect_call_or_invoke(
1755 &mut self,
1756 llvm_func_type: inkwell::types::FunctionType<'ctx>,
1757 func_ptr: PointerValue<'ctx>,
1758 params: &[BasicValueEnum<'ctx>],
1759 then_block_name: &str,
1760 ) -> Result<CallSiteValue<'ctx>, CompileError> {
1761 if let Some(lpad) = self.state.get_innermost_landingpad() {
1762 let then_block = self
1763 .context
1764 .append_basic_block(self.function, then_block_name);
1765
1766 let ret = err!(self.builder.build_indirect_invoke(
1767 llvm_func_type,
1768 func_ptr,
1769 params,
1770 then_block,
1771 lpad,
1772 "",
1773 ));
1774
1775 self.builder.position_at_end(then_block);
1776 Ok(ret)
1777 } else {
1778 let call_params = params
1779 .iter()
1780 .copied()
1781 .map(Into::into)
1782 .collect::<Vec<BasicMetadataValueEnum>>();
1783 Ok(err!(self.builder.build_indirect_call(
1784 llvm_func_type,
1785 func_ptr,
1786 call_params.as_slice(),
1787 ""
1788 )))
1789 }
1790 }
1791}
1792
1793pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
1794 m0_param: Option<PointerValue<'ctx>>,
1795 context: &'ctx Context,
1796 builder: Builder<'ctx>,
1797 alloca_builder: Builder<'ctx>,
1798 intrinsics: &'a Intrinsics<'ctx>,
1799 state: State<'ctx>,
1800 function: FunctionValue<'ctx>,
1801 locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, ctx: CtxType<'ctx, 'a>,
1803 unreachable_depth: usize,
1804 memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
1805 _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
1806 module: &'a Module<'ctx>,
1807 module_translation: &'a ModuleTranslationState,
1808 wasm_module: &'a ModuleInfo,
1809 symbol_registry: &'a dyn SymbolRegistry,
1810 abi: &'a dyn Abi,
1811 config: &'a LLVM,
1812 target_triple: Triple,
1813 tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
1814 binary_fmt: target_lexicon::BinaryFormat,
1815 cpu_features: EnumSet<CpuFeature>,
1816 non_volatile_memory_ops: bool,
1817}
1818
1819impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
1820 fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
1821 let intrinsic = if value
1822 .get_type()
1823 .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
1824 {
1825 Some(self.intrinsics.add_f32)
1826 } else if value
1827 .get_type()
1828 .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
1829 {
1830 Some(self.intrinsics.add_f64)
1831 } else if value
1832 .get_type()
1833 .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
1834 {
1835 Some(self.intrinsics.add_f32x4)
1836 } else if value
1837 .get_type()
1838 .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
1839 {
1840 Some(self.intrinsics.add_f64x2)
1841 } else {
1842 None
1843 };
1844
1845 match intrinsic {
1846 Some(intrinsic) => err_nt!(
1847 self.builder
1848 .build_call(
1849 intrinsic,
1850 &[
1851 value.into(),
1852 value.get_type().const_zero().into(),
1853 self.intrinsics.fp_rounding_md,
1854 self.intrinsics.fp_exception_md,
1855 ],
1856 "",
1857 )
1858 .map(|v| v.try_as_basic_value().unwrap_basic())
1859 ),
1860 None => Ok(value),
1861 }
1862 }
1863
1864 fn finalize_minmax_result(
1865 &self,
1866 value: BasicValueEnum<'ctx>,
1867 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1868 let ty = value.get_type();
1869 if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
1870 || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
1871 {
1872 let value = value.into_float_value();
1873 let is_nan = err!(self.builder.build_float_compare(
1874 FloatPredicate::UNO,
1875 value,
1876 value,
1877 "res_is_nan"
1878 ));
1879 let quiet = self.quiet_nan(value.as_basic_value_enum())?;
1880 let result =
1881 err!(
1882 self.builder
1883 .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
1884 );
1885 Ok(result.as_basic_value_enum())
1886 } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
1887 let value = value.into_vector_value();
1888 let is_nan = self
1889 .build_call_with_param_attributes(
1890 self.intrinsics.cmp_f32x4,
1891 &[
1892 value.into(),
1893 value.into(),
1894 self.intrinsics.fp_uno_md,
1895 self.intrinsics.fp_exception_md,
1896 ],
1897 "",
1898 )?
1899 .try_as_basic_value()
1900 .unwrap_basic()
1901 .into_vector_value();
1902 let quiet = self
1903 .quiet_nan(value.as_basic_value_enum())?
1904 .into_vector_value();
1905 let result = err!(self.builder.build_select(
1906 is_nan,
1907 quiet.as_basic_value_enum(),
1908 value.as_basic_value_enum(),
1909 "",
1910 ));
1911 Ok(result.as_basic_value_enum())
1912 } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
1913 let value = value.into_vector_value();
1914 let is_nan = self
1915 .build_call_with_param_attributes(
1916 self.intrinsics.cmp_f64x2,
1917 &[
1918 value.into(),
1919 value.into(),
1920 self.intrinsics.fp_uno_md,
1921 self.intrinsics.fp_exception_md,
1922 ],
1923 "",
1924 )?
1925 .try_as_basic_value()
1926 .unwrap_basic()
1927 .into_vector_value();
1928 let quiet = self
1929 .quiet_nan(value.as_basic_value_enum())?
1930 .into_vector_value();
1931 let result = err!(self.builder.build_select(
1932 is_nan,
1933 quiet.as_basic_value_enum(),
1934 value.as_basic_value_enum(),
1935 "",
1936 ));
1937 Ok(result.as_basic_value_enum())
1938 } else {
1939 Ok(value)
1940 }
1941 }
1942
1943 fn finalize_rounding_result(
1944 &self,
1945 value: BasicValueEnum<'ctx>,
1946 info: ExtraInfo,
1947 ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
1948 let ty = value.get_type();
1949 let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
1950 let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
1951 let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
1952 let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
1953 debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
1954
1955 if matches!(
1956 self.target_triple.architecture,
1957 Architecture::Riscv32(..) | Architecture::Riscv64(..)
1958 ) {
1959 if is_f32 || is_f64 {
1960 let input = value.into_float_value();
1961 let is_nan = err!(self.builder.build_float_compare(
1962 FloatPredicate::UNO,
1963 input,
1964 input,
1965 "res_is_nan",
1966 ));
1967 let canonical_nan_bits = if is_f32 {
1968 self.intrinsics
1969 .i32_ty
1970 .const_int(CANONICAL_NAN_F32 as _, false)
1971 } else {
1972 self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
1973 };
1974 let canonical_nan = err!(self.builder.build_bit_cast(
1975 canonical_nan_bits,
1976 ty,
1977 "canonical_nan",
1978 ));
1979 let res =
1980 err!(
1981 self.builder
1982 .build_select(is_nan, canonical_nan, value, "canonical_nan",)
1983 );
1984 Ok((res, info))
1985 } else if is_f32x4 {
1986 let value = value.into_vector_value();
1987 let is_nan = err!(self.builder.build_call(
1988 self.intrinsics.cmp_f32x4,
1989 &[
1990 value.into(),
1991 value.into(),
1992 self.intrinsics.fp_uno_md,
1993 self.intrinsics.fp_exception_md,
1994 ],
1995 "",
1996 ))
1997 .try_as_basic_value()
1998 .unwrap_basic()
1999 .into_vector_value();
2000 let canonical_nan_bits = self
2001 .intrinsics
2002 .i32_ty
2003 .const_int(CANONICAL_NAN_F32 as _, false);
2004 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2005 let canonical_nan = err!(self.builder.build_bit_cast(
2006 canonical_nan_bits,
2007 self.intrinsics.f32x4_ty,
2008 "canonical_nan",
2009 ));
2010 let res = err!(self.builder.build_select(
2011 is_nan,
2012 canonical_nan.as_basic_value_enum(),
2013 value.as_basic_value_enum(),
2014 "canonical_nan",
2015 ));
2016 Ok((res, info))
2017 } else {
2018 let value = value.into_vector_value();
2019 let is_nan = err!(self.builder.build_call(
2020 self.intrinsics.cmp_f64x2,
2021 &[
2022 value.into(),
2023 value.into(),
2024 self.intrinsics.fp_uno_md,
2025 self.intrinsics.fp_exception_md,
2026 ],
2027 "",
2028 ))
2029 .try_as_basic_value()
2030 .unwrap_basic()
2031 .into_vector_value();
2032 let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2033 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2034 let canonical_nan = err!(self.builder.build_bit_cast(
2035 canonical_nan_bits,
2036 self.intrinsics.f64x2_ty,
2037 "canonical_nan",
2038 ));
2039 let res = err!(self.builder.build_select(
2040 is_nan,
2041 canonical_nan.as_basic_value_enum(),
2042 value.as_basic_value_enum(),
2043 "canonical_nan",
2044 ));
2045 Ok((res, info))
2046 }
2047 } else {
2048 Ok((
2049 value,
2050 (info
2051 | if is_f32 || is_f32x4 {
2052 ExtraInfo::pending_f32_nan()
2053 } else {
2054 ExtraInfo::pending_f64_nan()
2055 })?,
2056 ))
2057 }
2058 }
2059
2060 fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
2061 let vmctx = &self.ctx.basic().into_pointer_value();
2064
2065 if !self.state.reachable {
2068 match op {
2069 Operator::Block { blockty: _ }
2070 | Operator::Loop { blockty: _ }
2071 | Operator::If { blockty: _ }
2072 | Operator::TryTable { .. } => {
2073 self.unreachable_depth += 1;
2074 return Ok(());
2075 }
2076 Operator::Else => {
2077 if self.unreachable_depth != 0 {
2078 return Ok(());
2079 }
2080 }
2081 Operator::End => {
2082 if self.unreachable_depth != 0 {
2083 self.unreachable_depth -= 1;
2084 return Ok(());
2085 }
2086 }
2087 _ => {
2088 return Ok(());
2089 }
2090 }
2091 }
2092
2093 match op {
2094 Operator::Block { blockty } => {
2099 let current_block = self
2100 .builder
2101 .get_insert_block()
2102 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2103
2104 let end_block = self.context.append_basic_block(self.function, "end");
2105 self.builder.position_at_end(end_block);
2106
2107 let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2108 .module_translation
2109 .blocktype_params_results(&blockty)?
2110 .1
2111 .iter()
2112 .map(|&wp_ty| {
2113 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2114 type_to_llvm(self.intrinsics, wasm_ty)
2115 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2116 })
2117 })
2118 .collect::<Result<_, _>>()?;
2119
2120 self.state.push_block(
2121 end_block,
2122 phis,
2123 self.module_translation
2124 .blocktype_params_results(&blockty)?
2125 .0
2126 .len(),
2127 );
2128 self.builder.position_at_end(current_block);
2129 }
2130 Operator::Loop { blockty } => {
2131 let loop_body = self.context.append_basic_block(self.function, "loop_body");
2132 let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2133 let pre_loop_block = self.builder.get_insert_block().unwrap();
2134
2135 err!(self.builder.build_unconditional_branch(loop_body));
2136
2137 self.builder.position_at_end(loop_next);
2138 let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2139 let phis = blocktypes
2140 .1
2141 .iter()
2142 .map(|&wp_ty| {
2143 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2144 type_to_llvm(self.intrinsics, wasm_ty)
2145 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2146 })
2147 })
2148 .collect::<Result<_, _>>()?;
2149 self.builder.position_at_end(loop_body);
2150 let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2151 .0
2152 .iter()
2153 .map(|&wp_ty| {
2154 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2155 type_to_llvm(self.intrinsics, wasm_ty)
2156 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2157 })
2158 })
2159 .collect::<Result<_, _>>()?;
2160 for phi in loop_phis.iter().rev() {
2161 let (value, info) = self.state.pop1_extra()?;
2162 let value = self.apply_pending_canonicalization(value, info)?;
2163 phi.add_incoming(&[(&value, pre_loop_block)]);
2164 }
2165 for phi in &loop_phis {
2166 self.state.push1(phi.as_basic_value());
2167 }
2168
2169 let num_inputs = loop_phis.len();
2170 self.state
2171 .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2172 }
2173 Operator::Br { relative_depth } => {
2174 let frame = self.state.frame_at_depth(relative_depth)?;
2175
2176 let current_block = self
2177 .builder
2178 .get_insert_block()
2179 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2180
2181 let phis = if frame.is_loop() {
2182 frame.loop_body_phis()
2183 } else {
2184 frame.phis()
2185 };
2186
2187 let len = phis.len();
2188 let values = self.state.peekn_extra(len)?;
2189 let values = values
2190 .iter()
2191 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2192 .collect::<Result<Vec<_>, _>>()?;
2193
2194 for (phi, value) in phis.iter().zip(values) {
2198 phi.add_incoming(&[(&value, current_block)]);
2199 }
2200
2201 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2202
2203 self.state.popn(len)?;
2204 self.state.reachable = false;
2205 }
2206 Operator::BrIf { relative_depth } => {
2207 let cond = self.state.pop1()?;
2208 let frame = self.state.frame_at_depth(relative_depth)?;
2209
2210 let current_block = self
2211 .builder
2212 .get_insert_block()
2213 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2214
2215 let phis = if frame.is_loop() {
2216 frame.loop_body_phis()
2217 } else {
2218 frame.phis()
2219 };
2220
2221 let param_stack = self.state.peekn_extra(phis.len())?;
2222 let param_stack = param_stack
2223 .iter()
2224 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2225 .collect::<Result<Vec<_>, _>>()?;
2226
2227 for (phi, value) in phis.iter().zip(param_stack) {
2228 phi.add_incoming(&[(&value, current_block)]);
2229 }
2230
2231 let else_block = self.context.append_basic_block(self.function, "else");
2232
2233 let cond_value = err!(self.builder.build_int_compare(
2234 IntPredicate::NE,
2235 cond.into_int_value(),
2236 self.intrinsics.i32_zero,
2237 "",
2238 ));
2239 err!(self.builder.build_conditional_branch(
2240 cond_value,
2241 *frame.br_dest(),
2242 else_block
2243 ));
2244 self.builder.position_at_end(else_block);
2245 }
2246 Operator::BrTable { ref targets } => {
2247 let current_block = self
2248 .builder
2249 .get_insert_block()
2250 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2251
2252 let index = self.state.pop1()?;
2253
2254 let default_frame = self.state.frame_at_depth(targets.default())?;
2255
2256 let phis = if default_frame.is_loop() {
2257 default_frame.loop_body_phis()
2258 } else {
2259 default_frame.phis()
2260 };
2261 let args = self.state.peekn(phis.len())?;
2262
2263 for (phi, value) in phis.iter().zip(args.iter()) {
2264 phi.add_incoming(&[(value, current_block)]);
2265 }
2266
2267 let cases: Vec<_> = targets
2268 .targets()
2269 .enumerate()
2270 .map(|(case_index, depth)| {
2271 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2272 let frame_result: Result<&ControlFrame, CompileError> =
2273 self.state.frame_at_depth(depth);
2274 let frame = match frame_result {
2275 Ok(v) => v,
2276 Err(e) => return Err(e),
2277 };
2278 let case_index_literal =
2279 self.context.i32_type().const_int(case_index as u64, false);
2280 let phis = if frame.is_loop() {
2281 frame.loop_body_phis()
2282 } else {
2283 frame.phis()
2284 };
2285 for (phi, value) in phis.iter().zip(args.iter()) {
2286 phi.add_incoming(&[(value, current_block)]);
2287 }
2288
2289 Ok((case_index_literal, *frame.br_dest()))
2290 })
2291 .collect::<Result<_, _>>()?;
2292
2293 err!(self.builder.build_switch(
2294 index.into_int_value(),
2295 *default_frame.br_dest(),
2296 &cases[..],
2297 ));
2298
2299 let args_len = args.len();
2300 self.state.popn(args_len)?;
2301 self.state.reachable = false;
2302 }
2303 Operator::If { blockty } => {
2304 let current_block = self
2305 .builder
2306 .get_insert_block()
2307 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2308 let if_then_block = self.context.append_basic_block(self.function, "if_then");
2309 let if_else_block = self.context.append_basic_block(self.function, "if_else");
2310 let end_block = self.context.append_basic_block(self.function, "if_end");
2311
2312 let end_phis = {
2313 self.builder.position_at_end(end_block);
2314
2315 let phis = self
2316 .module_translation
2317 .blocktype_params_results(&blockty)?
2318 .1
2319 .iter()
2320 .map(|&wp_ty| {
2321 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2322 type_to_llvm(self.intrinsics, wasm_ty)
2323 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2324 })
2325 })
2326 .collect::<Result<_, _>>()?;
2327
2328 self.builder.position_at_end(current_block);
2329 phis
2330 };
2331
2332 let cond = self.state.pop1()?;
2333
2334 let cond_value = err!(self.builder.build_int_compare(
2335 IntPredicate::NE,
2336 cond.into_int_value(),
2337 self.intrinsics.i32_zero,
2338 "",
2339 ));
2340
2341 err!(self.builder.build_conditional_branch(
2342 cond_value,
2343 if_then_block,
2344 if_else_block
2345 ));
2346 self.builder.position_at_end(if_else_block);
2347 let block_param_types = self
2348 .module_translation
2349 .blocktype_params_results(&blockty)?
2350 .0
2351 .iter()
2352 .map(|&wp_ty| {
2353 err_nt!(wptype_to_type(wp_ty))
2354 .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2355 })
2356 .collect::<Result<Vec<_>, _>>()?;
2357 let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2358 .iter()
2359 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2360 .collect::<Result<SmallVec<_>, _>>()?;
2361 self.builder.position_at_end(if_then_block);
2362 let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2363 .iter()
2364 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2365 .collect::<Result<SmallVec<_>, _>>()?;
2366 for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2367 let (value, info) = self.state.pop1_extra()?;
2368 let value = self.apply_pending_canonicalization(value, info)?;
2369 else_phi.add_incoming(&[(&value, current_block)]);
2370 then_phi.add_incoming(&[(&value, current_block)]);
2371 }
2372 for phi in then_phis.iter() {
2373 self.state.push1(phi.as_basic_value());
2374 }
2375
2376 self.state.push_if(
2377 if_then_block,
2378 if_else_block,
2379 end_block,
2380 then_phis,
2381 else_phis,
2382 end_phis,
2383 block_param_types.len(),
2384 );
2385 }
2386 Operator::Else => {
2387 if self.state.reachable {
2388 let frame = self.state.frame_at_depth(0)?;
2389 let current_block = self.builder.get_insert_block().ok_or_else(|| {
2390 CompileError::Codegen("not currently in a block".to_string())
2391 })?;
2392
2393 for phi in frame.phis().to_vec().iter().rev() {
2394 let (value, info) = self.state.pop1_extra()?;
2395 let value = self.apply_pending_canonicalization(value, info)?;
2396 phi.add_incoming(&[(&value, current_block)])
2397 }
2398
2399 let frame = self.state.frame_at_depth(0)?;
2400 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2401 }
2402
2403 let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2404 if_else,
2405 if_else_state,
2406 ..
2407 } = self.state.frame_at_depth_mut(0)?
2408 {
2409 (if_else, if_else_state)
2410 } else {
2411 unreachable!()
2412 };
2413
2414 *if_else_state = IfElseState::Else;
2415
2416 self.builder.position_at_end(*if_else_block);
2417 self.state.reachable = true;
2418
2419 if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2420 for phi in else_phis.clone().iter() {
2422 self.state.push1(phi.as_basic_value());
2423 }
2424 };
2425 }
2426
2427 Operator::End => {
2428 let frame = self.state.pop_frame()?;
2429 let current_block = self
2430 .builder
2431 .get_insert_block()
2432 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2433
2434 if self.state.reachable {
2435 for phi in frame.phis().iter().rev() {
2436 let (value, info) = self.state.pop1_extra()?;
2437 let value = self.apply_pending_canonicalization(value, info)?;
2438 phi.add_incoming(&[(&value, current_block)]);
2439 }
2440
2441 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2442 }
2443
2444 if let ControlFrame::IfElse {
2445 if_else,
2446 next,
2447 if_else_state: IfElseState::If,
2448 else_phis,
2449 ..
2450 } = &frame
2451 {
2452 for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
2453 phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
2454 }
2455 self.builder.position_at_end(*if_else);
2456 err!(self.builder.build_unconditional_branch(*next));
2457 } else if let ControlFrame::Landingpad { .. } = &frame {
2458 self.state.pop_landingpad();
2459 };
2460
2461 self.builder.position_at_end(*frame.code_after());
2462 self.state.reset_stack(&frame);
2463
2464 self.state.reachable = true;
2465
2466 for phi in frame.phis() {
2468 if phi.count_incoming() != 0 {
2469 self.state.push1(phi.as_basic_value());
2470 } else {
2471 let basic_ty = phi.as_basic_value().get_type();
2478 let placeholder_value = basic_ty.const_zero();
2479 self.state.push1(placeholder_value);
2480 phi.as_instruction().erase_from_basic_block();
2481 }
2482 }
2483 }
2484 Operator::Return => {
2485 let current_block = self
2486 .builder
2487 .get_insert_block()
2488 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2489
2490 let frame = self.state.outermost_frame()?;
2491 for phi in frame.phis().to_vec().iter().rev() {
2492 let (arg, info) = self.state.pop1_extra()?;
2493 let arg = self.apply_pending_canonicalization(arg, info)?;
2494 phi.add_incoming(&[(&arg, current_block)]);
2495 }
2496 let frame = self.state.outermost_frame()?;
2497 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2498
2499 self.state.reachable = false;
2500 }
2501
2502 Operator::Unreachable => {
2503 self.build_call_with_param_attributes(
2504 self.intrinsics.throw_trap,
2505 &[self.intrinsics.trap_unreachable.into()],
2506 "throw",
2507 )?;
2508 err!(self.builder.build_unreachable());
2509
2510 self.state.reachable = false;
2511 }
2512
2513 Operator::Nop => {
2518 }
2520 Operator::Drop => {
2521 self.state.pop1()?;
2522 }
2523
2524 Operator::I32Const { value } => {
2526 let i = self.intrinsics.i32_ty.const_int(value as u64, false);
2527 let info = if is_f32_arithmetic(value as u32) {
2528 ExtraInfo::arithmetic_f32()
2529 } else {
2530 Default::default()
2531 };
2532 self.state.push1_extra(i, info);
2533 }
2534 Operator::I64Const { value } => {
2535 let i = self.intrinsics.i64_ty.const_int(value as u64, false);
2536 let info = if is_f64_arithmetic(value as u64) {
2537 ExtraInfo::arithmetic_f64()
2538 } else {
2539 Default::default()
2540 };
2541 self.state.push1_extra(i, info);
2542 }
2543 Operator::F32Const { value } => {
2544 let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
2545 let info = if is_f32_arithmetic(value.bits()) {
2546 ExtraInfo::arithmetic_f32()
2547 } else {
2548 Default::default()
2549 };
2550 let f = err!(
2551 self.builder
2552 .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
2553 );
2554 self.state.push1_extra(f, info);
2555 }
2556 Operator::F64Const { value } => {
2557 let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
2558 let info = if is_f64_arithmetic(value.bits()) {
2559 ExtraInfo::arithmetic_f64()
2560 } else {
2561 Default::default()
2562 };
2563 let f = err!(
2564 self.builder
2565 .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
2566 );
2567 self.state.push1_extra(f, info);
2568 }
2569 Operator::V128Const { value } => {
2570 let mut hi: [u8; 8] = Default::default();
2571 let mut lo: [u8; 8] = Default::default();
2572 hi.copy_from_slice(&value.bytes()[0..8]);
2573 lo.copy_from_slice(&value.bytes()[8..16]);
2574 let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
2575 let i = self
2576 .intrinsics
2577 .i128_ty
2578 .const_int_arbitrary_precision(&packed);
2579 let mut quad1: [u8; 4] = Default::default();
2580 let mut quad2: [u8; 4] = Default::default();
2581 let mut quad3: [u8; 4] = Default::default();
2582 let mut quad4: [u8; 4] = Default::default();
2583 quad1.copy_from_slice(&value.bytes()[0..4]);
2584 quad2.copy_from_slice(&value.bytes()[4..8]);
2585 quad3.copy_from_slice(&value.bytes()[8..12]);
2586 quad4.copy_from_slice(&value.bytes()[12..16]);
2587 let mut info: ExtraInfo = Default::default();
2588 if is_f32_arithmetic(u32::from_le_bytes(quad1))
2589 && is_f32_arithmetic(u32::from_le_bytes(quad2))
2590 && is_f32_arithmetic(u32::from_le_bytes(quad3))
2591 && is_f32_arithmetic(u32::from_le_bytes(quad4))
2592 {
2593 info |= ExtraInfo::arithmetic_f32();
2594 }
2595 if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
2596 info |= ExtraInfo::arithmetic_f64();
2597 }
2598 self.state.push1_extra(i, info);
2599 }
2600
2601 Operator::I8x16Splat => {
2602 let (v, i) = self.state.pop1_extra()?;
2603 let v = v.into_int_value();
2604 let v = err!(
2605 self.builder
2606 .build_int_truncate(v, self.intrinsics.i8_ty, "")
2607 );
2608 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
2609 let res = err!(
2610 self.builder
2611 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2612 );
2613 self.state.push1_extra(res, i);
2614 }
2615 Operator::I16x8Splat => {
2616 let (v, i) = self.state.pop1_extra()?;
2617 let v = v.into_int_value();
2618 let v = err!(
2619 self.builder
2620 .build_int_truncate(v, self.intrinsics.i16_ty, "")
2621 );
2622 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
2623 let res = err!(
2624 self.builder
2625 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2626 );
2627 self.state.push1_extra(res, i);
2628 }
2629 Operator::I32x4Splat => {
2630 let (v, i) = self.state.pop1_extra()?;
2631 let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
2632 let res = err!(
2633 self.builder
2634 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2635 );
2636 self.state.push1_extra(res, i);
2637 }
2638 Operator::I64x2Splat => {
2639 let (v, i) = self.state.pop1_extra()?;
2640 let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
2641 let res = err!(
2642 self.builder
2643 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2644 );
2645 self.state.push1_extra(res, i);
2646 }
2647 Operator::F32x4Splat => {
2648 let (v, i) = self.state.pop1_extra()?;
2649 let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
2650 let res = err!(
2651 self.builder
2652 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2653 );
2654 self.state.push1_extra(res, i);
2657 }
2658 Operator::F64x2Splat => {
2659 let (v, i) = self.state.pop1_extra()?;
2660 let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
2661 let res = err!(
2662 self.builder
2663 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2664 );
2665 self.state.push1_extra(res, i);
2668 }
2669
2670 Operator::LocalGet { local_index } => {
2672 let (type_value, pointer_value) = self.locals[local_index as usize];
2673 let v = err!(self.builder.build_load(
2674 type_value,
2675 pointer_value,
2676 &format!("local_{local_index}_get")
2677 ));
2678 tbaa_label(
2679 self.module,
2680 self.intrinsics,
2681 format!("local {local_index}"),
2682 v.as_instruction_value().unwrap(),
2683 );
2684 self.state.push1(v);
2685 }
2686 Operator::LocalSet { local_index } => {
2687 let pointer_value = self.locals[local_index as usize].1;
2688 let (v, i) = self.state.pop1_extra()?;
2689 let v = self.apply_pending_canonicalization(v, i)?;
2690 let store = err!(self.builder.build_store(pointer_value, v));
2691 tbaa_label(
2692 self.module,
2693 self.intrinsics,
2694 format!("local {local_index}"),
2695 store,
2696 );
2697 }
2698 Operator::LocalTee { local_index } => {
2699 let pointer_value = self.locals[local_index as usize].1;
2700 let (v, i) = self.state.peek1_extra()?;
2701 let v = self.apply_pending_canonicalization(v, i)?;
2702 let store = err!(self.builder.build_store(pointer_value, v));
2703 tbaa_label(
2704 self.module,
2705 self.intrinsics,
2706 format!("local {local_index}"),
2707 store,
2708 );
2709 }
2710
2711 Operator::GlobalGet { global_index } => {
2712 let global_index = GlobalIndex::from_u32(global_index);
2713 match self
2714 .ctx
2715 .global(global_index, self.intrinsics, self.module)?
2716 {
2717 GlobalCache::Const { value } => {
2718 self.state.push1(*value);
2719 }
2720 GlobalCache::Mut {
2721 ptr_to_value,
2722 value_type,
2723 } => {
2724 let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
2725 tbaa_label(
2726 self.module,
2727 self.intrinsics,
2728 format!("global {}", global_index.as_u32()),
2729 value.as_instruction_value().unwrap(),
2730 );
2731 self.state.push1(value);
2732 }
2733 }
2734 }
2735 Operator::GlobalSet { global_index } => {
2736 let global_index = GlobalIndex::from_u32(global_index);
2737 match self
2738 .ctx
2739 .global(global_index, self.intrinsics, self.module)?
2740 {
2741 GlobalCache::Const { value: _ } => {
2742 return Err(CompileError::Codegen(format!(
2743 "global.set on immutable global index {}",
2744 global_index.as_u32()
2745 )));
2746 }
2747 GlobalCache::Mut { ptr_to_value, .. } => {
2748 let ptr_to_value = *ptr_to_value;
2749 let (value, info) = self.state.pop1_extra()?;
2750 let value = self.apply_pending_canonicalization(value, info)?;
2751 let store = err!(self.builder.build_store(ptr_to_value, value));
2752 tbaa_label(
2753 self.module,
2754 self.intrinsics,
2755 format!("global {}", global_index.as_u32()),
2756 store,
2757 );
2758 }
2759 }
2760 }
2761
2762 Operator::TypedSelect { .. } | Operator::Select => {
2765 let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
2766 let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
2774 || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
2775 {
2776 (
2777 self.apply_pending_canonicalization(v1, i1)?,
2778 i1.strip_pending(),
2779 self.apply_pending_canonicalization(v2, i2)?,
2780 i2.strip_pending(),
2781 )
2782 } else {
2783 (v1, i1, v2, i2)
2784 };
2785 let cond_value = err!(self.builder.build_int_compare(
2786 IntPredicate::NE,
2787 cond.into_int_value(),
2788 self.intrinsics.i32_zero,
2789 "",
2790 ));
2791 let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
2792 let info = {
2793 let mut info = (i1.strip_pending() & i2.strip_pending())?;
2794 if i1.has_pending_f32_nan() {
2795 debug_assert!(i2.has_pending_f32_nan());
2796 info = (info | ExtraInfo::pending_f32_nan())?;
2797 }
2798 if i1.has_pending_f64_nan() {
2799 debug_assert!(i2.has_pending_f64_nan());
2800 info = (info | ExtraInfo::pending_f64_nan())?;
2801 }
2802 info
2803 };
2804 self.state.push1_extra(res, info);
2805 }
2806 Operator::Call { function_index } => {
2807 let func_index = FunctionIndex::from_u32(function_index);
2808 let sigindex = &self.wasm_module.functions[func_index];
2809 let func_type = &self.wasm_module.signatures[*sigindex];
2810
2811 let FunctionCache {
2812 func,
2813 llvm_func_type,
2814 vmctx: callee_vmctx,
2815 imported_include_m0_param,
2816 attrs,
2817 } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
2818 let function_name = self
2819 .symbol_registry
2820 .symbol_to_name(Symbol::LocalFunction(local_func_index));
2821
2822 self.ctx.local_func(
2823 local_func_index,
2824 func_index,
2825 self.intrinsics,
2826 self.module,
2827 self.context,
2828 func_type,
2829 &function_name,
2830 )?
2831 } else {
2832 self.ctx
2833 .imported_func(func_index, self.intrinsics, self.context, func_type)?
2834 };
2835 let llvm_func_type = *llvm_func_type;
2836 let func = *func;
2837 let callee_vmctx = *callee_vmctx;
2838 let imported_include_m0_param = *imported_include_m0_param;
2839 let attrs = attrs.clone();
2840
2841 let params = self.state.popn_save_extra(func_type.params().len())?;
2847
2848 let params = params
2850 .iter()
2851 .zip(func_type.params().iter())
2852 .map(|((v, info), wasm_ty)| match wasm_ty {
2853 Type::F32 => err_nt!(self.builder.build_bit_cast(
2854 self.apply_pending_canonicalization(*v, *info)?,
2855 self.intrinsics.f32_ty,
2856 "",
2857 )),
2858 Type::F64 => err_nt!(self.builder.build_bit_cast(
2859 self.apply_pending_canonicalization(*v, *info)?,
2860 self.intrinsics.f64_ty,
2861 "",
2862 )),
2863 Type::V128 => self.apply_pending_canonicalization(*v, *info),
2864 _ => Ok(*v),
2865 })
2866 .collect::<Result<Vec<_>, _>>()?;
2867
2868 if let (Some(m0_param), Some(include_m0_param)) =
2869 (self.m0_param, imported_include_m0_param)
2870 {
2871 let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
2875 self.abi.func_type_to_llvm(
2876 self.context,
2877 self.intrinsics,
2878 Some(self.ctx.get_offsets()),
2879 func_type,
2880 false,
2881 )?;
2882 let params_with_m0 = self.abi.args_to_call(
2883 &self.alloca_builder,
2884 func_type,
2885 &llvm_func_type,
2886 callee_vmctx.into_pointer_value(),
2887 params.as_slice(),
2888 self.intrinsics,
2889 Some(m0_param),
2890 )?;
2891 let params_no_m0 = self.abi.args_to_call(
2892 &self.alloca_builder,
2893 func_type,
2894 &llvm_func_type_no_m0,
2895 callee_vmctx.into_pointer_value(),
2896 params.as_slice(),
2897 self.intrinsics,
2898 None,
2899 )?;
2900
2901 let include_m0_call_block = self
2902 .context
2903 .append_basic_block(self.function, "call_block_with_m0");
2904 let skip_m0_call_block =
2905 self.context.append_basic_block(self.function, "call_block");
2906 let call_cont = self.context.append_basic_block(self.function, "call_cont");
2907 err!(self.builder.build_conditional_branch(
2908 include_m0_param,
2909 include_m0_call_block,
2910 skip_m0_call_block,
2911 ));
2912
2913 self.builder.position_at_end(include_m0_call_block);
2914 let call_site_with_m0 = self.build_indirect_call_or_invoke(
2915 llvm_func_type,
2916 func,
2917 params_with_m0.as_slice(),
2918 "then_block_with_m0",
2919 )?;
2920 for (attr, attr_loc) in &attrs {
2921 call_site_with_m0.add_attribute(*attr_loc, *attr);
2922 }
2923 let rets_with_m0 = self.abi.rets_from_call(
2924 &self.builder,
2925 self.intrinsics,
2926 call_site_with_m0,
2927 func_type,
2928 )?;
2929 let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
2930 CompileError::Codegen(
2931 "missing insertion block after call with m0".to_string(),
2932 )
2933 })?;
2934 err!(self.builder.build_unconditional_branch(call_cont));
2935
2936 self.builder.position_at_end(skip_m0_call_block);
2937 let call_site_no_m0 = self.build_indirect_call_or_invoke(
2938 llvm_func_type_no_m0,
2939 func,
2940 params_no_m0.as_slice(),
2941 "then_block",
2942 )?;
2943 for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
2944 call_site_no_m0.add_attribute(*attr_loc, *attr);
2945 }
2946 let rets_no_m0 = self.abi.rets_from_call(
2947 &self.builder,
2948 self.intrinsics,
2949 call_site_no_m0,
2950 func_type,
2951 )?;
2952 let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
2953 CompileError::Codegen(
2954 "missing insertion block after call without m0".to_string(),
2955 )
2956 })?;
2957 err!(self.builder.build_unconditional_branch(call_cont));
2958
2959 self.builder.position_at_end(call_cont);
2960 for i in 0..rets_with_m0.len() {
2961 let with_m0 = rets_with_m0[i];
2962 let no_m0 = rets_no_m0[i];
2963 let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
2964 phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
2965 self.state.push1(phi.as_basic_value());
2966 }
2967 } else {
2968 let params = self.abi.args_to_call(
2969 &self.alloca_builder,
2970 func_type,
2971 &llvm_func_type,
2972 callee_vmctx.into_pointer_value(),
2973 params.as_slice(),
2974 self.intrinsics,
2975 self.m0_param,
2976 )?;
2977
2978 let call_site = self.build_indirect_call_or_invoke(
2979 llvm_func_type,
2980 func,
2981 params.as_slice(),
2982 "then_block",
2983 )?;
2984 for (attr, attr_loc) in attrs {
2985 call_site.add_attribute(attr_loc, attr);
2986 }
2987
2988 self.abi
2989 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2990 .iter()
2991 .for_each(|ret| self.state.push1(*ret));
2992 }
2993 }
2994 Operator::CallIndirect {
2995 type_index,
2996 table_index,
2997 } => {
2998 let sigindex = SignatureIndex::from_u32(type_index);
2999 let func_type = &self.wasm_module.signatures[sigindex];
3000 let expected_dynamic_sigindex =
3001 self.ctx
3002 .dynamic_sigindex(sigindex, self.intrinsics, self.module)?;
3003 let (table_base, table_bound) = self.ctx.table(
3004 TableIndex::from_u32(table_index),
3005 self.intrinsics,
3006 self.module,
3007 &self.builder,
3008 )?;
3009 let func_index = self.state.pop1()?.into_int_value();
3010
3011 let truncated_table_bounds = err!(self.builder.build_int_truncate(
3012 table_bound,
3013 self.intrinsics.i32_ty,
3014 "truncated_table_bounds",
3015 ));
3016
3017 let index_in_bounds = err!(self.builder.build_int_compare(
3019 IntPredicate::ULT,
3020 func_index,
3021 truncated_table_bounds,
3022 "index_in_bounds",
3023 ));
3024
3025 let index_in_bounds = self
3026 .build_call_with_param_attributes(
3027 self.intrinsics.expect_i1,
3028 &[
3029 index_in_bounds.into(),
3030 self.intrinsics.i1_ty.const_int(1, false).into(),
3031 ],
3032 "index_in_bounds_expect",
3033 )?
3034 .try_as_basic_value()
3035 .unwrap_basic()
3036 .into_int_value();
3037
3038 let in_bounds_continue_block = self
3039 .context
3040 .append_basic_block(self.function, "in_bounds_continue_block");
3041 let not_in_bounds_block = self
3042 .context
3043 .append_basic_block(self.function, "not_in_bounds_block");
3044 err!(self.builder.build_conditional_branch(
3045 index_in_bounds,
3046 in_bounds_continue_block,
3047 not_in_bounds_block,
3048 ));
3049 self.builder.position_at_end(not_in_bounds_block);
3050 self.build_call_with_param_attributes(
3051 self.intrinsics.throw_trap,
3052 &[self.intrinsics.trap_table_access_oob.into()],
3053 "throw",
3054 )?;
3055 err!(self.builder.build_unreachable());
3056 self.builder.position_at_end(in_bounds_continue_block);
3057
3058 let casted_table_base = err!(self.builder.build_pointer_cast(
3061 table_base,
3062 self.context.ptr_type(AddressSpace::default()),
3063 "casted_table_base",
3064 ));
3065
3066 let funcref_ptr = unsafe {
3067 err!(self.builder.build_in_bounds_gep(
3068 self.intrinsics.ptr_ty,
3069 casted_table_base,
3070 &[func_index],
3071 "funcref_ptr",
3072 ))
3073 };
3074
3075 let anyfunc_struct_ptr = err!(self.builder.build_load(
3077 self.intrinsics.ptr_ty,
3078 funcref_ptr,
3079 "anyfunc_struct_ptr",
3080 ))
3081 .into_pointer_value();
3082
3083 {
3085 let funcref_not_null = err!(
3086 self.builder
3087 .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3088 );
3089
3090 let funcref_continue_deref_block = self
3091 .context
3092 .append_basic_block(self.function, "funcref_continue_deref_block");
3093
3094 let funcref_is_null_block = self
3095 .context
3096 .append_basic_block(self.function, "funcref_is_null_block");
3097 err!(self.builder.build_conditional_branch(
3098 funcref_not_null,
3099 funcref_continue_deref_block,
3100 funcref_is_null_block,
3101 ));
3102 self.builder.position_at_end(funcref_is_null_block);
3103 self.build_call_with_param_attributes(
3104 self.intrinsics.throw_trap,
3105 &[self.intrinsics.trap_call_indirect_null.into()],
3106 "throw",
3107 )?;
3108 err!(self.builder.build_unreachable());
3109 self.builder.position_at_end(funcref_continue_deref_block);
3110 }
3111
3112 let func_ptr_ptr = self
3114 .builder
3115 .build_struct_gep(
3116 self.intrinsics.anyfunc_ty,
3117 anyfunc_struct_ptr,
3118 0,
3119 "func_ptr_ptr",
3120 )
3121 .unwrap();
3122 let sigindex_ptr = self
3123 .builder
3124 .build_struct_gep(
3125 self.intrinsics.anyfunc_ty,
3126 anyfunc_struct_ptr,
3127 1,
3128 "sigindex_ptr",
3129 )
3130 .unwrap();
3131 let ctx_ptr_ptr = self
3132 .builder
3133 .build_struct_gep(
3134 self.intrinsics.anyfunc_ty,
3135 anyfunc_struct_ptr,
3136 2,
3137 "ctx_ptr_ptr",
3138 )
3139 .unwrap();
3140 let (func_ptr, found_dynamic_sigindex, ctx_ptr) = (
3141 err!(
3142 self.builder
3143 .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3144 )
3145 .into_pointer_value(),
3146 err!(
3147 self.builder
3148 .build_load(self.intrinsics.i32_ty, sigindex_ptr, "sigindex")
3149 )
3150 .into_int_value(),
3151 err!(
3152 self.builder
3153 .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3154 ),
3155 );
3156
3157 let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3161
3162 let sigindices_equal = err!(self.builder.build_int_compare(
3165 IntPredicate::EQ,
3166 expected_dynamic_sigindex,
3167 found_dynamic_sigindex,
3168 "sigindices_equal",
3169 ));
3170
3171 let initialized_and_sigindices_match = err!(self.builder.build_and(
3172 elem_initialized,
3173 sigindices_equal,
3174 ""
3175 ));
3176
3177 let initialized_and_sigindices_match = self
3179 .build_call_with_param_attributes(
3180 self.intrinsics.expect_i1,
3181 &[
3182 initialized_and_sigindices_match.into(),
3183 self.intrinsics.i1_ty.const_int(1, false).into(),
3184 ],
3185 "initialized_and_sigindices_match_expect",
3186 )?
3187 .try_as_basic_value()
3188 .unwrap_basic()
3189 .into_int_value();
3190
3191 let continue_block = self
3192 .context
3193 .append_basic_block(self.function, "continue_block");
3194 let sigindices_notequal_block = self
3195 .context
3196 .append_basic_block(self.function, "sigindices_notequal_block");
3197 err!(self.builder.build_conditional_branch(
3198 initialized_and_sigindices_match,
3199 continue_block,
3200 sigindices_notequal_block,
3201 ));
3202
3203 self.builder.position_at_end(sigindices_notequal_block);
3204 let trap_code = err!(self.builder.build_select(
3205 elem_initialized,
3206 self.intrinsics.trap_call_indirect_sig,
3207 self.intrinsics.trap_call_indirect_null,
3208 "",
3209 ));
3210 self.build_call_with_param_attributes(
3211 self.intrinsics.throw_trap,
3212 &[trap_code.into()],
3213 "throw",
3214 )?;
3215 err!(self.builder.build_unreachable());
3216 self.builder.position_at_end(continue_block);
3217
3218 if self.m0_param.is_some() {
3219 self.build_m0_indirect_call(
3220 table_index,
3221 ctx_ptr.into_pointer_value(),
3222 func_type,
3223 func_ptr,
3224 func_index,
3225 )?;
3226 } else {
3227 let call_site = self.build_indirect_call(
3228 ctx_ptr.into_pointer_value(),
3229 func_type,
3230 func_ptr,
3231 None,
3232 )?;
3233
3234 self.abi
3235 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3236 .iter()
3237 .for_each(|ret| self.state.push1(*ret));
3238 }
3239 }
3240
3241 Operator::I32Add | Operator::I64Add => {
3246 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3247 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3248 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3249 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3250 let res = err!(self.builder.build_int_add(v1, v2, ""));
3251 self.state.push1(res);
3252 }
3253 Operator::I8x16Add => {
3254 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3255 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3256 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3257 let res = err!(self.builder.build_int_add(v1, v2, ""));
3258 let res = err!(
3259 self.builder
3260 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3261 );
3262 self.state.push1(res);
3263 }
3264 Operator::I16x8Add => {
3265 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3266 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3267 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3268 let res = err!(self.builder.build_int_add(v1, v2, ""));
3269 let res = err!(
3270 self.builder
3271 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3272 );
3273 self.state.push1(res);
3274 }
3275 Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3276 let extend_op = match op {
3277 Operator::I16x8ExtAddPairwiseI8x16S => {
3278 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3279 }
3280 Operator::I16x8ExtAddPairwiseI8x16U => {
3281 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3282 }
3283 _ => unreachable!("Unhandled internal variant"),
3284 };
3285 let (v, i) = self.state.pop1_extra()?;
3286 let (v, _) = self.v128_into_i8x16(v, i)?;
3287
3288 let left = err!(self.builder.build_shuffle_vector(
3289 v,
3290 v.get_type().get_undef(),
3291 VectorType::const_vector(&[
3292 self.intrinsics.i32_consts[0],
3293 self.intrinsics.i32_consts[2],
3294 self.intrinsics.i32_consts[4],
3295 self.intrinsics.i32_consts[6],
3296 self.intrinsics.i32_consts[8],
3297 self.intrinsics.i32_consts[10],
3298 self.intrinsics.i32_consts[12],
3299 self.intrinsics.i32_consts[14],
3300 ]),
3301 "",
3302 ));
3303 let left = err!(extend_op(self, left));
3304 let right = err!(self.builder.build_shuffle_vector(
3305 v,
3306 v.get_type().get_undef(),
3307 VectorType::const_vector(&[
3308 self.intrinsics.i32_consts[1],
3309 self.intrinsics.i32_consts[3],
3310 self.intrinsics.i32_consts[5],
3311 self.intrinsics.i32_consts[7],
3312 self.intrinsics.i32_consts[9],
3313 self.intrinsics.i32_consts[11],
3314 self.intrinsics.i32_consts[13],
3315 self.intrinsics.i32_consts[15],
3316 ]),
3317 "",
3318 ));
3319 let right = err!(extend_op(self, right));
3320
3321 let res = err!(self.builder.build_int_add(left, right, ""));
3322 let res = err!(
3323 self.builder
3324 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3325 );
3326 self.state.push1(res);
3327 }
3328 Operator::I32x4Add => {
3329 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3330 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3331 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3332 let res = err!(self.builder.build_int_add(v1, v2, ""));
3333 let res = err!(
3334 self.builder
3335 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3336 );
3337 self.state.push1(res);
3338 }
3339 Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3340 let extend_op = match op {
3341 Operator::I32x4ExtAddPairwiseI16x8S => {
3342 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3343 }
3344 Operator::I32x4ExtAddPairwiseI16x8U => {
3345 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3346 }
3347 _ => unreachable!("Unhandled internal variant"),
3348 };
3349 let (v, i) = self.state.pop1_extra()?;
3350 let (v, _) = self.v128_into_i16x8(v, i)?;
3351
3352 let left = err!(self.builder.build_shuffle_vector(
3353 v,
3354 v.get_type().get_undef(),
3355 VectorType::const_vector(&[
3356 self.intrinsics.i32_consts[0],
3357 self.intrinsics.i32_consts[2],
3358 self.intrinsics.i32_consts[4],
3359 self.intrinsics.i32_consts[6],
3360 ]),
3361 "",
3362 ));
3363 let left = err!(extend_op(self, left));
3364 let right = err!(self.builder.build_shuffle_vector(
3365 v,
3366 v.get_type().get_undef(),
3367 VectorType::const_vector(&[
3368 self.intrinsics.i32_consts[1],
3369 self.intrinsics.i32_consts[3],
3370 self.intrinsics.i32_consts[5],
3371 self.intrinsics.i32_consts[7],
3372 ]),
3373 "",
3374 ));
3375 let right = err!(extend_op(self, right));
3376
3377 let res = err!(self.builder.build_int_add(left, right, ""));
3378 let res = err!(
3379 self.builder
3380 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3381 );
3382 self.state.push1(res);
3383 }
3384 Operator::I64x2Add => {
3385 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3386 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3387 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3388 let res = err!(self.builder.build_int_add(v1, v2, ""));
3389 let res = err!(
3390 self.builder
3391 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3392 );
3393 self.state.push1(res);
3394 }
3395 Operator::I8x16AddSatS => {
3396 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3397 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3398 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3399 let res = self
3400 .build_call_with_param_attributes(
3401 self.intrinsics.sadd_sat_i8x16,
3402 &[v1.into(), v2.into()],
3403 "",
3404 )?
3405 .try_as_basic_value()
3406 .unwrap_basic();
3407 let res = err!(
3408 self.builder
3409 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3410 );
3411 self.state.push1(res);
3412 }
3413 Operator::I16x8AddSatS => {
3414 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3415 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3416 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3417 let res = self
3418 .build_call_with_param_attributes(
3419 self.intrinsics.sadd_sat_i16x8,
3420 &[v1.into(), v2.into()],
3421 "",
3422 )?
3423 .try_as_basic_value()
3424 .unwrap_basic();
3425 let res = err!(
3426 self.builder
3427 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3428 );
3429 self.state.push1(res);
3430 }
3431 Operator::I8x16AddSatU => {
3432 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3433 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3434 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3435 let res = self
3436 .build_call_with_param_attributes(
3437 self.intrinsics.uadd_sat_i8x16,
3438 &[v1.into(), v2.into()],
3439 "",
3440 )?
3441 .try_as_basic_value()
3442 .unwrap_basic();
3443 let res = err!(
3444 self.builder
3445 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3446 );
3447 self.state.push1(res);
3448 }
3449 Operator::I16x8AddSatU => {
3450 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3451 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3452 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3453 let res = self
3454 .build_call_with_param_attributes(
3455 self.intrinsics.uadd_sat_i16x8,
3456 &[v1.into(), v2.into()],
3457 "",
3458 )?
3459 .try_as_basic_value()
3460 .unwrap_basic();
3461 let res = err!(
3462 self.builder
3463 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3464 );
3465 self.state.push1(res);
3466 }
3467 Operator::I32Sub | Operator::I64Sub => {
3468 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3469 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3470 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3471 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3472 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3473 self.state.push1(res);
3474 }
3475 Operator::I8x16Sub => {
3476 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3477 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3478 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3479 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3480 let res = err!(
3481 self.builder
3482 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3483 );
3484 self.state.push1(res);
3485 }
3486 Operator::I16x8Sub => {
3487 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3488 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3489 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3490 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3491 let res = err!(
3492 self.builder
3493 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3494 );
3495 self.state.push1(res);
3496 }
3497 Operator::I32x4Sub => {
3498 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3499 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3500 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3501 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3502 let res = err!(
3503 self.builder
3504 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3505 );
3506 self.state.push1(res);
3507 }
3508 Operator::I64x2Sub => {
3509 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3510 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3511 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3512 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3513 let res = err!(
3514 self.builder
3515 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3516 );
3517 self.state.push1(res);
3518 }
3519 Operator::I8x16SubSatS => {
3520 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3521 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3522 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3523 let res = self
3524 .build_call_with_param_attributes(
3525 self.intrinsics.ssub_sat_i8x16,
3526 &[v1.into(), v2.into()],
3527 "",
3528 )?
3529 .try_as_basic_value()
3530 .unwrap_basic();
3531 let res = err!(
3532 self.builder
3533 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3534 );
3535 self.state.push1(res);
3536 }
3537 Operator::I16x8SubSatS => {
3538 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3539 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3540 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3541 let res = self
3542 .build_call_with_param_attributes(
3543 self.intrinsics.ssub_sat_i16x8,
3544 &[v1.into(), v2.into()],
3545 "",
3546 )?
3547 .try_as_basic_value()
3548 .unwrap_basic();
3549 let res = err!(
3550 self.builder
3551 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3552 );
3553 self.state.push1(res);
3554 }
3555 Operator::I8x16SubSatU => {
3556 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3557 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3558 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3559 let res = self
3560 .build_call_with_param_attributes(
3561 self.intrinsics.usub_sat_i8x16,
3562 &[v1.into(), v2.into()],
3563 "",
3564 )?
3565 .try_as_basic_value()
3566 .unwrap_basic();
3567 let res = err!(
3568 self.builder
3569 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3570 );
3571 self.state.push1(res);
3572 }
3573 Operator::I16x8SubSatU => {
3574 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3575 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3576 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3577 let res = self
3578 .build_call_with_param_attributes(
3579 self.intrinsics.usub_sat_i16x8,
3580 &[v1.into(), v2.into()],
3581 "",
3582 )?
3583 .try_as_basic_value()
3584 .unwrap_basic();
3585 let res = err!(
3586 self.builder
3587 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3588 );
3589 self.state.push1(res);
3590 }
3591 Operator::I32Mul | Operator::I64Mul => {
3592 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3593 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3594 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3595 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3596 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3597 self.state.push1(res);
3598 }
3599 Operator::I16x8Mul => {
3600 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3601 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3602 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3603 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3604 let res = err!(
3605 self.builder
3606 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3607 );
3608 self.state.push1(res);
3609 }
3610 Operator::I32x4Mul => {
3611 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3612 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3613 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3614 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3615 let res = err!(
3616 self.builder
3617 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3618 );
3619 self.state.push1(res);
3620 }
3621 Operator::I64x2Mul => {
3622 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3623 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3624 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3625 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3626 let res = err!(
3627 self.builder
3628 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3629 );
3630 self.state.push1(res);
3631 }
3632 Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
3633 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3634 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3635 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3636 let res = self
3637 .build_call_with_param_attributes(
3638 self.intrinsics.x86_64.pmulhrsw128,
3639 &[v1.into(), v2.into()],
3640 "",
3641 )?
3642 .try_as_basic_value()
3643 .unwrap_basic();
3644 let res = err!(
3645 self.builder
3646 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3647 );
3648 self.state.push1(res);
3649 }
3650 Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
3651 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3652 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3653 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3654
3655 let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
3656 let max_values = VectorType::const_vector(&[max_value; 8]);
3657
3658 let v1 = err!(
3659 self.builder
3660 .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
3661 );
3662 let v2 = err!(
3663 self.builder
3664 .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
3665 );
3666 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3667
3668 let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
3670 let bits = VectorType::const_vector(&[bit; 8]);
3671
3672 let res = err!(self.builder.build_int_add(res, bits, ""));
3673
3674 let fifteen = self.intrinsics.i32_consts[15];
3675 let fifteens = VectorType::const_vector(&[fifteen; 8]);
3676
3677 let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
3678 let saturate_up = {
3679 let max_values = err!(self.builder.build_int_s_extend(
3680 max_values,
3681 self.intrinsics.i32x8_ty,
3682 ""
3683 ));
3684 err!(
3685 self.builder
3686 .build_int_compare(IntPredicate::SGT, res, max_values, "")
3687 )
3688 };
3689
3690 let res = err!(
3691 self.builder
3692 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
3693 );
3694
3695 let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
3696 .into_vector_value();
3697 let res = err!(
3698 self.builder
3699 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3700 );
3701 self.state.push1(res);
3702 }
3703 Operator::I16x8ExtMulLowI8x16S
3704 | Operator::I16x8ExtMulLowI8x16U
3705 | Operator::I16x8ExtMulHighI8x16S
3706 | Operator::I16x8ExtMulHighI8x16U => {
3707 let extend_op = match op {
3708 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
3709 |s: &Self, v| -> Result<VectorValue, CompileError> {
3710 err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
3711 }
3712 }
3713 Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
3714 |s: &Self, v| -> Result<VectorValue, CompileError> {
3715 err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
3716 }
3717 }
3718 _ => unreachable!("Unhandled internal variant"),
3719 };
3720 let shuffle_array = match op {
3721 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
3722 self.intrinsics.i32_consts[0],
3723 self.intrinsics.i32_consts[1],
3724 self.intrinsics.i32_consts[2],
3725 self.intrinsics.i32_consts[3],
3726 self.intrinsics.i32_consts[4],
3727 self.intrinsics.i32_consts[5],
3728 self.intrinsics.i32_consts[6],
3729 self.intrinsics.i32_consts[7],
3730 ],
3731 Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
3732 self.intrinsics.i32_consts[8],
3733 self.intrinsics.i32_consts[9],
3734 self.intrinsics.i32_consts[10],
3735 self.intrinsics.i32_consts[11],
3736 self.intrinsics.i32_consts[12],
3737 self.intrinsics.i32_consts[13],
3738 self.intrinsics.i32_consts[14],
3739 self.intrinsics.i32_consts[15],
3740 ],
3741 _ => unreachable!("Unhandled internal variant"),
3742 };
3743 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3744 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3745 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3746 let val1 = err!(self.builder.build_shuffle_vector(
3747 v1,
3748 v1.get_type().get_undef(),
3749 VectorType::const_vector(&shuffle_array),
3750 "",
3751 ));
3752 let val1 = err!(extend_op(self, val1));
3753 let val2 = err!(self.builder.build_shuffle_vector(
3754 v2,
3755 v2.get_type().get_undef(),
3756 VectorType::const_vector(&shuffle_array),
3757 "",
3758 ));
3759 let val2 = err!(extend_op(self, val2));
3760 let res = err!(self.builder.build_int_mul(val1, val2, ""));
3761 let res = err!(
3762 self.builder
3763 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3764 );
3765 self.state.push1(res);
3766 }
3767 Operator::I32x4ExtMulLowI16x8S
3768 | Operator::I32x4ExtMulLowI16x8U
3769 | Operator::I32x4ExtMulHighI16x8S
3770 | Operator::I32x4ExtMulHighI16x8U => {
3771 let extend_op = match op {
3772 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
3773 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3774 }
3775 Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
3776 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3777 }
3778 _ => unreachable!("Unhandled internal variant"),
3779 };
3780 let shuffle_array = match op {
3781 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
3782 self.intrinsics.i32_consts[0],
3783 self.intrinsics.i32_consts[1],
3784 self.intrinsics.i32_consts[2],
3785 self.intrinsics.i32_consts[3],
3786 ],
3787 Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
3788 self.intrinsics.i32_consts[4],
3789 self.intrinsics.i32_consts[5],
3790 self.intrinsics.i32_consts[6],
3791 self.intrinsics.i32_consts[7],
3792 ],
3793 _ => unreachable!("Unhandled internal variant"),
3794 };
3795 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3796 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3797 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3798 let val1 = err!(self.builder.build_shuffle_vector(
3799 v1,
3800 v1.get_type().get_undef(),
3801 VectorType::const_vector(&shuffle_array),
3802 "",
3803 ));
3804 let val1 = err!(extend_op(self, val1));
3805 let val2 = err!(self.builder.build_shuffle_vector(
3806 v2,
3807 v2.get_type().get_undef(),
3808 VectorType::const_vector(&shuffle_array),
3809 "",
3810 ));
3811 let val2 = err!(extend_op(self, val2));
3812 let res = err!(self.builder.build_int_mul(val1, val2, ""));
3813 let res = err!(
3814 self.builder
3815 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3816 );
3817 self.state.push1(res);
3818 }
3819 Operator::I64x2ExtMulLowI32x4S
3820 | Operator::I64x2ExtMulLowI32x4U
3821 | Operator::I64x2ExtMulHighI32x4S
3822 | Operator::I64x2ExtMulHighI32x4U => {
3823 let extend_op = match op {
3824 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
3825 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
3826 }
3827 Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
3828 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
3829 }
3830 _ => unreachable!("Unhandled internal variant"),
3831 };
3832 let shuffle_array = match op {
3833 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
3834 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
3835 }
3836 Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
3837 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
3838 }
3839 _ => unreachable!("Unhandled internal variant"),
3840 };
3841 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3842 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3843 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3844 let val1 = err!(self.builder.build_shuffle_vector(
3845 v1,
3846 v1.get_type().get_undef(),
3847 VectorType::const_vector(&shuffle_array),
3848 "",
3849 ));
3850 let val1 = err!(extend_op(self, val1));
3851 let val2 = err!(self.builder.build_shuffle_vector(
3852 v2,
3853 v2.get_type().get_undef(),
3854 VectorType::const_vector(&shuffle_array),
3855 "",
3856 ));
3857 let val2 = err!(extend_op(self, val2));
3858 let res = err!(self.builder.build_int_mul(val1, val2, ""));
3859 let res = err!(
3860 self.builder
3861 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3862 );
3863 self.state.push1(res);
3864 }
3865 Operator::I32x4DotI16x8S => {
3866 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3867 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3868 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3869 let low_i16 = [
3870 self.intrinsics.i32_consts[0],
3871 self.intrinsics.i32_consts[2],
3872 self.intrinsics.i32_consts[4],
3873 self.intrinsics.i32_consts[6],
3874 ];
3875 let high_i16 = [
3876 self.intrinsics.i32_consts[1],
3877 self.intrinsics.i32_consts[3],
3878 self.intrinsics.i32_consts[5],
3879 self.intrinsics.i32_consts[7],
3880 ];
3881 let v1_low = err!(self.builder.build_shuffle_vector(
3882 v1,
3883 v1.get_type().get_undef(),
3884 VectorType::const_vector(&low_i16),
3885 "",
3886 ));
3887 let v1_low = err!(self.builder.build_int_s_extend(
3888 v1_low,
3889 self.intrinsics.i32x4_ty,
3890 ""
3891 ));
3892 let v1_high = err!(self.builder.build_shuffle_vector(
3893 v1,
3894 v1.get_type().get_undef(),
3895 VectorType::const_vector(&high_i16),
3896 "",
3897 ));
3898 let v1_high = err!(self.builder.build_int_s_extend(
3899 v1_high,
3900 self.intrinsics.i32x4_ty,
3901 ""
3902 ));
3903 let v2_low = err!(self.builder.build_shuffle_vector(
3904 v2,
3905 v2.get_type().get_undef(),
3906 VectorType::const_vector(&low_i16),
3907 "",
3908 ));
3909 let v2_low = err!(self.builder.build_int_s_extend(
3910 v2_low,
3911 self.intrinsics.i32x4_ty,
3912 ""
3913 ));
3914 let v2_high = err!(self.builder.build_shuffle_vector(
3915 v2,
3916 v2.get_type().get_undef(),
3917 VectorType::const_vector(&high_i16),
3918 "",
3919 ));
3920 let v2_high = err!(self.builder.build_int_s_extend(
3921 v2_high,
3922 self.intrinsics.i32x4_ty,
3923 ""
3924 ));
3925 let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
3926 let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
3927
3928 let res = err!(self.builder.build_int_add(low_product, high_product, ""));
3929 let res = err!(
3930 self.builder
3931 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3932 );
3933 self.state.push1(res);
3934 }
3935 Operator::I16x8RelaxedDotI8x16I7x16S
3936 if self.cpu_features.contains(CpuFeature::SSSE3) =>
3937 {
3938 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3939 let (a, _) = self.v128_into_i8x16(v1, i1)?;
3940 let (b, _) = self.v128_into_i8x16(v2, i2)?;
3941
3942 let res = self
3943 .build_call_with_param_attributes(
3944 self.intrinsics.x86_64.pmaddubsw128,
3945 &[b.into(), a.into()],
3946 "",
3947 )?
3948 .try_as_basic_value()
3949 .unwrap_basic()
3950 .into_vector_value();
3951 let res = err!(
3952 self.builder
3953 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3954 );
3955 self.state.push1(res);
3956 }
3957 Operator::I16x8RelaxedDotI8x16I7x16S => {
3958 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3959 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3960 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3961
3962 let left_indices = [
3963 self.intrinsics.i32_consts[0],
3964 self.intrinsics.i32_consts[2],
3965 self.intrinsics.i32_consts[4],
3966 self.intrinsics.i32_consts[6],
3967 self.intrinsics.i32_consts[8],
3968 self.intrinsics.i32_consts[10],
3969 self.intrinsics.i32_consts[12],
3970 self.intrinsics.i32_consts[14],
3971 ];
3972 let right_indices = [
3973 self.intrinsics.i32_consts[1],
3974 self.intrinsics.i32_consts[3],
3975 self.intrinsics.i32_consts[5],
3976 self.intrinsics.i32_consts[7],
3977 self.intrinsics.i32_consts[9],
3978 self.intrinsics.i32_consts[11],
3979 self.intrinsics.i32_consts[13],
3980 self.intrinsics.i32_consts[15],
3981 ];
3982
3983 let v1_left = err!(self.builder.build_shuffle_vector(
3984 v1,
3985 v1.get_type().get_undef(),
3986 VectorType::const_vector(&left_indices),
3987 "",
3988 ));
3989 let v1_left = err!(self.builder.build_int_s_extend(
3990 v1_left,
3991 self.intrinsics.i16x8_ty,
3992 ""
3993 ));
3994 let v1_right = err!(self.builder.build_shuffle_vector(
3995 v1,
3996 v1.get_type().get_undef(),
3997 VectorType::const_vector(&right_indices),
3998 "",
3999 ));
4000 let v1_right = err!(self.builder.build_int_s_extend(
4001 v1_right,
4002 self.intrinsics.i16x8_ty,
4003 ""
4004 ));
4005
4006 let v2_left = err!(self.builder.build_shuffle_vector(
4007 v2,
4008 v2.get_type().get_undef(),
4009 VectorType::const_vector(&left_indices),
4010 "",
4011 ));
4012 let v2_left = err!(self.builder.build_int_s_extend(
4013 v2_left,
4014 self.intrinsics.i16x8_ty,
4015 ""
4016 ));
4017 let v2_right = err!(self.builder.build_shuffle_vector(
4018 v2,
4019 v2.get_type().get_undef(),
4020 VectorType::const_vector(&right_indices),
4021 "",
4022 ));
4023 let v2_right = err!(self.builder.build_int_s_extend(
4024 v2_right,
4025 self.intrinsics.i16x8_ty,
4026 ""
4027 ));
4028
4029 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4030 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4031 let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4032 let res = err!(
4033 self.builder
4034 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4035 );
4036 self.state.push1(res);
4037 }
4038 Operator::I32x4RelaxedDotI8x16I7x16AddS
4039 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4040 {
4041 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4042 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4043 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4044 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4045
4046 let dot16 = self
4049 .build_call_with_param_attributes(
4050 self.intrinsics.x86_64.pmaddubsw128,
4051 &[v2.into(), v1.into()],
4052 "",
4053 )?
4054 .try_as_basic_value()
4055 .unwrap_basic()
4056 .into_vector_value();
4057 let ones =
4058 VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4059 let dot32 = self
4060 .build_call_with_param_attributes(
4061 self.intrinsics.x86_64.pmaddwd128,
4062 &[dot16.into(), ones.into()],
4063 "",
4064 )?
4065 .try_as_basic_value()
4066 .unwrap_basic()
4067 .into_vector_value();
4068 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4069 let res = err!(
4070 self.builder
4071 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4072 );
4073 self.state.push1(res);
4074 }
4075 Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4076 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4077 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4078 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4079 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4080
4081 let left_indices = [
4082 self.intrinsics.i32_consts[0],
4083 self.intrinsics.i32_consts[2],
4084 self.intrinsics.i32_consts[4],
4085 self.intrinsics.i32_consts[6],
4086 self.intrinsics.i32_consts[8],
4087 self.intrinsics.i32_consts[10],
4088 self.intrinsics.i32_consts[12],
4089 self.intrinsics.i32_consts[14],
4090 ];
4091 let right_indices = [
4092 self.intrinsics.i32_consts[1],
4093 self.intrinsics.i32_consts[3],
4094 self.intrinsics.i32_consts[5],
4095 self.intrinsics.i32_consts[7],
4096 self.intrinsics.i32_consts[9],
4097 self.intrinsics.i32_consts[11],
4098 self.intrinsics.i32_consts[13],
4099 self.intrinsics.i32_consts[15],
4100 ];
4101
4102 let v1_left = err!(self.builder.build_shuffle_vector(
4103 v1,
4104 v1.get_type().get_undef(),
4105 VectorType::const_vector(&left_indices),
4106 "",
4107 ));
4108 let v1_left = err!(self.builder.build_int_s_extend(
4109 v1_left,
4110 self.intrinsics.i16x8_ty,
4111 ""
4112 ));
4113 let v1_right = err!(self.builder.build_shuffle_vector(
4114 v1,
4115 v1.get_type().get_undef(),
4116 VectorType::const_vector(&right_indices),
4117 "",
4118 ));
4119 let v1_right = err!(self.builder.build_int_s_extend(
4120 v1_right,
4121 self.intrinsics.i16x8_ty,
4122 ""
4123 ));
4124
4125 let v2_left = err!(self.builder.build_shuffle_vector(
4126 v2,
4127 v2.get_type().get_undef(),
4128 VectorType::const_vector(&left_indices),
4129 "",
4130 ));
4131 let v2_left = err!(self.builder.build_int_s_extend(
4132 v2_left,
4133 self.intrinsics.i16x8_ty,
4134 ""
4135 ));
4136 let v2_right = err!(self.builder.build_shuffle_vector(
4137 v2,
4138 v2.get_type().get_undef(),
4139 VectorType::const_vector(&right_indices),
4140 "",
4141 ));
4142 let v2_right = err!(self.builder.build_int_s_extend(
4143 v2_right,
4144 self.intrinsics.i16x8_ty,
4145 ""
4146 ));
4147
4148 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4149 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4150 let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4151
4152 let pair_left = err!(self.builder.build_shuffle_vector(
4153 dot16,
4154 dot16.get_type().get_undef(),
4155 VectorType::const_vector(&[
4156 self.intrinsics.i32_consts[0],
4157 self.intrinsics.i32_consts[2],
4158 self.intrinsics.i32_consts[4],
4159 self.intrinsics.i32_consts[6],
4160 ]),
4161 "",
4162 ));
4163 let pair_left = err!(self.builder.build_int_s_extend(
4164 pair_left,
4165 self.intrinsics.i32x4_ty,
4166 ""
4167 ));
4168 let pair_right = err!(self.builder.build_shuffle_vector(
4169 dot16,
4170 dot16.get_type().get_undef(),
4171 VectorType::const_vector(&[
4172 self.intrinsics.i32_consts[1],
4173 self.intrinsics.i32_consts[3],
4174 self.intrinsics.i32_consts[5],
4175 self.intrinsics.i32_consts[7],
4176 ]),
4177 "",
4178 ));
4179 let pair_right = err!(self.builder.build_int_s_extend(
4180 pair_right,
4181 self.intrinsics.i32x4_ty,
4182 ""
4183 ));
4184 let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4185 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4186 let res = err!(
4187 self.builder
4188 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4189 );
4190 self.state.push1(res);
4191 }
4192 Operator::I32DivS | Operator::I64DivS => {
4193 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4194 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4195 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4196 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4197
4198 self.trap_if_zero_or_overflow(v1, v2)?;
4199
4200 let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4201 self.state.push1(res);
4202 }
4203 Operator::I32DivU | Operator::I64DivU => {
4204 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4205 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4206 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4207 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4208
4209 self.trap_if_zero(v2)?;
4210
4211 let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4212 self.state.push1(res);
4213 }
4214 Operator::I32RemS | Operator::I64RemS => {
4215 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4216 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4217 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4218 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4219 let int_type = v1.get_type();
4220 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4221 let min_value = int_type.const_int(i32::MIN as u64, false);
4222 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4223 (min_value, neg_one_value)
4224 } else if int_type == self.intrinsics.i64_ty {
4225 let min_value = int_type.const_int(i64::MIN as u64, false);
4226 let neg_one_value = int_type.const_int(-1i64 as u64, false);
4227 (min_value, neg_one_value)
4228 } else {
4229 unreachable!()
4230 };
4231
4232 self.trap_if_zero(v2)?;
4233
4234 let will_overflow = err!(self.builder.build_and(
4246 err!(self.builder.build_int_compare(
4247 IntPredicate::EQ,
4248 v1,
4249 min_value,
4250 "left_is_min"
4251 )),
4252 err!(self.builder.build_int_compare(
4253 IntPredicate::EQ,
4254 v2,
4255 neg_one_value,
4256 "right_is_neg_one",
4257 )),
4258 "srem_will_overflow",
4259 ));
4260 let v1 =
4261 err!(
4262 self.builder
4263 .build_select(will_overflow, int_type.const_zero(), v1, "")
4264 )
4265 .into_int_value();
4266 let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4267 self.state.push1(res);
4268 }
4269 Operator::I32RemU | Operator::I64RemU => {
4270 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4271 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4272 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4273 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4274
4275 self.trap_if_zero(v2)?;
4276
4277 let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4278 self.state.push1(res);
4279 }
4280 Operator::I32And | Operator::I64And | Operator::V128And => {
4281 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4282 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4283 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4284 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4285 let res = err!(self.builder.build_and(v1, v2, ""));
4286 self.state.push1(res);
4287 }
4288 Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4289 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4290 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4291 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4292 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4293 let res = err!(self.builder.build_or(v1, v2, ""));
4294 self.state.push1(res);
4295 }
4296 Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4297 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4298 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4299 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4300 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4301 let res = err!(self.builder.build_xor(v1, v2, ""));
4302 self.state.push1(res);
4303 }
4304 Operator::V128AndNot => {
4305 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4306 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4307 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4308 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4309 let v2 = err!(self.builder.build_not(v2, ""));
4310 let res = err!(self.builder.build_and(v1, v2, ""));
4311 self.state.push1(res);
4312 }
4313 Operator::I8x16RelaxedLaneselect
4314 | Operator::I16x8RelaxedLaneselect
4315 | Operator::I32x4RelaxedLaneselect
4316 | Operator::I64x2RelaxedLaneselect
4317 if self.cpu_features.contains(CpuFeature::SSE41) =>
4318 {
4319 let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4320 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4321 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4322 let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4323
4324 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4325 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4326 let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4327 let res = self
4328 .build_call_with_param_attributes(
4329 self.intrinsics.x86_64.pblendvb,
4330 &[v2.into(), v1.into(), mask.into()],
4331 "",
4332 )?
4333 .try_as_basic_value()
4334 .unwrap_basic();
4335 let res = err!(
4336 self.builder
4337 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4338 );
4339 self.state.push1(res);
4340 }
4341 Operator::I8x16RelaxedLaneselect
4342 | Operator::I16x8RelaxedLaneselect
4343 | Operator::I32x4RelaxedLaneselect
4344 | Operator::I64x2RelaxedLaneselect
4345 | Operator::V128Bitselect => {
4346 let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4347 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4348 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4349 let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4350 let v1 = err!(
4351 self.builder
4352 .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
4353 )
4354 .into_vector_value();
4355 let v2 = err!(
4356 self.builder
4357 .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
4358 )
4359 .into_vector_value();
4360 let cond = err!(
4361 self.builder
4362 .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
4363 )
4364 .into_vector_value();
4365 let res = err!(self.builder.build_select(cond, v1, v2, ""));
4366 let res = err!(
4367 self.builder
4368 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4369 );
4370 self.state.push1(res);
4371 }
4372 Operator::I8x16Bitmask => {
4373 let (v, i) = self.state.pop1_extra()?;
4374 let (v, _) = self.v128_into_i8x16(v, i)?;
4375
4376 let zeros = self.intrinsics.i8x16_ty.const_zero();
4377 let res = err!(
4378 self.builder
4379 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4380 );
4381 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
4382 .into_int_value();
4383 let res = err!(
4384 self.builder
4385 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4386 );
4387 self.state.push1(res);
4388 }
4389 Operator::I16x8Bitmask => {
4390 let (v, i) = self.state.pop1_extra()?;
4391 let (v, _) = self.v128_into_i16x8(v, i)?;
4392
4393 let zeros = self.intrinsics.i16x8_ty.const_zero();
4394 let res = err!(
4395 self.builder
4396 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4397 );
4398 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
4399 .into_int_value();
4400 let res = err!(
4401 self.builder
4402 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4403 );
4404 self.state.push1(res);
4405 }
4406 Operator::I32x4Bitmask => {
4407 let (v, i) = self.state.pop1_extra()?;
4408 let (v, _) = self.v128_into_i32x4(v, i)?;
4409
4410 let zeros = self.intrinsics.i32x4_ty.const_zero();
4411 let res = err!(
4412 self.builder
4413 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4414 );
4415 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
4416 .into_int_value();
4417 let res = err!(
4418 self.builder
4419 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4420 );
4421 self.state.push1(res);
4422 }
4423 Operator::I64x2Bitmask => {
4424 let (v, i) = self.state.pop1_extra()?;
4425 let (v, _) = self.v128_into_i64x2(v, i)?;
4426
4427 let zeros = self.intrinsics.i64x2_ty.const_zero();
4428 let res = err!(
4429 self.builder
4430 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4431 );
4432 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
4433 .into_int_value();
4434 let res = err!(
4435 self.builder
4436 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4437 );
4438 self.state.push1(res);
4439 }
4440 Operator::I32Shl => {
4441 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4442 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4443 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4444 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4445 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4446 let v2 = err!(self.builder.build_and(v2, mask, ""));
4447 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4448 self.state.push1(res);
4449 }
4450 Operator::I64Shl => {
4451 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4452 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4453 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4454 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4455 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4456 let v2 = err!(self.builder.build_and(v2, mask, ""));
4457 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4458 self.state.push1(res);
4459 }
4460 Operator::I8x16Shl => {
4461 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4462 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4463 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4464 let v2 = v2.into_int_value();
4465 let v2 = err!(
4466 self.builder
4467 .build_and(v2, self.intrinsics.i32_consts[7], "")
4468 );
4469 let v2 = err!(
4470 self.builder
4471 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4472 );
4473 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4474 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4475 let res = err!(
4476 self.builder
4477 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4478 );
4479 self.state.push1(res);
4480 }
4481 Operator::I16x8Shl => {
4482 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4483 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4484 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4485 let v2 = v2.into_int_value();
4486 let v2 = err!(
4487 self.builder
4488 .build_and(v2, self.intrinsics.i32_consts[15], "")
4489 );
4490 let v2 = err!(
4491 self.builder
4492 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4493 );
4494 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4495 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4496 let res = err!(
4497 self.builder
4498 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4499 );
4500 self.state.push1(res);
4501 }
4502 Operator::I32x4Shl => {
4503 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4504 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4505 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4506 let v2 = v2.into_int_value();
4507 let v2 = err!(self.builder.build_and(
4508 v2,
4509 self.intrinsics.i32_ty.const_int(31, false),
4510 ""
4511 ));
4512 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4513 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4514 let res = err!(
4515 self.builder
4516 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4517 );
4518 self.state.push1(res);
4519 }
4520 Operator::I64x2Shl => {
4521 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4522 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4523 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4524 let v2 = v2.into_int_value();
4525 let v2 = err!(self.builder.build_and(
4526 v2,
4527 self.intrinsics.i32_ty.const_int(63, false),
4528 ""
4529 ));
4530 let v2 = err!(
4531 self.builder
4532 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4533 );
4534 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4535 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4536 let res = err!(
4537 self.builder
4538 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4539 );
4540 self.state.push1(res);
4541 }
4542 Operator::I32ShrS => {
4543 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4544 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4545 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4546 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4547 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4548 let v2 = err!(self.builder.build_and(v2, mask, ""));
4549 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4550 self.state.push1(res);
4551 }
4552 Operator::I64ShrS => {
4553 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4554 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4555 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4556 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4557 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4558 let v2 = err!(self.builder.build_and(v2, mask, ""));
4559 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4560 self.state.push1(res);
4561 }
4562 Operator::I8x16ShrS => {
4563 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4564 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4565 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4566 let v2 = v2.into_int_value();
4567 let v2 = err!(
4568 self.builder
4569 .build_and(v2, self.intrinsics.i32_consts[7], "")
4570 );
4571 let v2 = err!(
4572 self.builder
4573 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4574 );
4575 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4576 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4577 let res = err!(
4578 self.builder
4579 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4580 );
4581 self.state.push1(res);
4582 }
4583 Operator::I16x8ShrS => {
4584 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4585 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4586 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4587 let v2 = v2.into_int_value();
4588 let v2 = err!(
4589 self.builder
4590 .build_and(v2, self.intrinsics.i32_consts[15], "")
4591 );
4592 let v2 = err!(
4593 self.builder
4594 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4595 );
4596 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4597 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4598 let res = err!(
4599 self.builder
4600 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4601 );
4602 self.state.push1(res);
4603 }
4604 Operator::I32x4ShrS => {
4605 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4606 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4607 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4608 let v2 = v2.into_int_value();
4609 let v2 = err!(self.builder.build_and(
4610 v2,
4611 self.intrinsics.i32_ty.const_int(31, false),
4612 ""
4613 ));
4614 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4615 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4616 let res = err!(
4617 self.builder
4618 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4619 );
4620 self.state.push1(res);
4621 }
4622 Operator::I64x2ShrS => {
4623 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4624 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4625 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4626 let v2 = v2.into_int_value();
4627 let v2 = err!(self.builder.build_and(
4628 v2,
4629 self.intrinsics.i32_ty.const_int(63, false),
4630 ""
4631 ));
4632 let v2 = err!(
4633 self.builder
4634 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4635 );
4636 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4637 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4638 let res = err!(
4639 self.builder
4640 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4641 );
4642 self.state.push1(res);
4643 }
4644 Operator::I32ShrU => {
4645 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4646 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4647 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4648 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4649 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4650 let v2 = err!(self.builder.build_and(v2, mask, ""));
4651 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4652 self.state.push1(res);
4653 }
4654 Operator::I64ShrU => {
4655 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4656 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4657 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4658 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4659 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4660 let v2 = err!(self.builder.build_and(v2, mask, ""));
4661 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4662 self.state.push1(res);
4663 }
4664 Operator::I8x16ShrU => {
4665 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4666 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4667 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4668 let v2 = v2.into_int_value();
4669 let v2 = err!(
4670 self.builder
4671 .build_and(v2, self.intrinsics.i32_consts[7], "")
4672 );
4673 let v2 = err!(
4674 self.builder
4675 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4676 );
4677 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4678 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4679 let res = err!(
4680 self.builder
4681 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4682 );
4683 self.state.push1(res);
4684 }
4685 Operator::I16x8ShrU => {
4686 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4687 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4688 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4689 let v2 = v2.into_int_value();
4690 let v2 = err!(
4691 self.builder
4692 .build_and(v2, self.intrinsics.i32_consts[15], "")
4693 );
4694 let v2 = err!(
4695 self.builder
4696 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4697 );
4698 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4699 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4700 let res = err!(
4701 self.builder
4702 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4703 );
4704 self.state.push1(res);
4705 }
4706 Operator::I32x4ShrU => {
4707 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4708 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4709 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4710 let v2 = v2.into_int_value();
4711 let v2 = err!(self.builder.build_and(
4712 v2,
4713 self.intrinsics.i32_ty.const_int(31, false),
4714 ""
4715 ));
4716 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4717 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4718 let res = err!(
4719 self.builder
4720 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4721 );
4722 self.state.push1(res);
4723 }
4724 Operator::I64x2ShrU => {
4725 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4726 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4727 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4728 let v2 = v2.into_int_value();
4729 let v2 = err!(self.builder.build_and(
4730 v2,
4731 self.intrinsics.i32_ty.const_int(63, false),
4732 ""
4733 ));
4734 let v2 = err!(
4735 self.builder
4736 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4737 );
4738 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4739 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4740 let res = err!(
4741 self.builder
4742 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4743 );
4744 self.state.push1(res);
4745 }
4746 Operator::I32Rotl => {
4747 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4748 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4749 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4750 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4751 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4752 let v2 = err!(self.builder.build_and(v2, mask, ""));
4753 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
4754 let rhs = {
4755 let negv2 = err!(self.builder.build_int_neg(v2, ""));
4756 let rhs = err!(self.builder.build_and(negv2, mask, ""));
4757 err!(self.builder.build_right_shift(v1, rhs, false, ""))
4758 };
4759 let res = err!(self.builder.build_or(lhs, rhs, ""));
4760 self.state.push1(res);
4761 }
4762 Operator::I64Rotl => {
4763 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4764 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4765 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4766 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4767 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4768 let v2 = err!(self.builder.build_and(v2, mask, ""));
4769 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
4770 let rhs = {
4771 let negv2 = err!(self.builder.build_int_neg(v2, ""));
4772 let rhs = err!(self.builder.build_and(negv2, mask, ""));
4773 err!(self.builder.build_right_shift(v1, rhs, false, ""))
4774 };
4775 let res = err!(self.builder.build_or(lhs, rhs, ""));
4776 self.state.push1(res);
4777 }
4778 Operator::I32Rotr => {
4779 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4780 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4781 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4782 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4783 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4784 let v2 = err!(self.builder.build_and(v2, mask, ""));
4785 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
4786 let rhs = {
4787 let negv2 = err!(self.builder.build_int_neg(v2, ""));
4788 let rhs = err!(self.builder.build_and(negv2, mask, ""));
4789 err!(self.builder.build_left_shift(v1, rhs, ""))
4790 };
4791 let res = err!(self.builder.build_or(lhs, rhs, ""));
4792 self.state.push1(res);
4793 }
4794 Operator::I64Rotr => {
4795 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4796 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4797 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4798 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4799 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4800 let v2 = err!(self.builder.build_and(v2, mask, ""));
4801 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
4802 let rhs = {
4803 let negv2 = err!(self.builder.build_int_neg(v2, ""));
4804 let rhs = err!(self.builder.build_and(negv2, mask, ""));
4805 err!(self.builder.build_left_shift(v1, rhs, ""))
4806 };
4807 let res = err!(self.builder.build_or(lhs, rhs, ""));
4808 self.state.push1(res);
4809 }
4810 Operator::I32Clz => {
4811 let (input, info) = self.state.pop1_extra()?;
4812 let input = self.apply_pending_canonicalization(input, info)?;
4813 let is_zero_undef = self.intrinsics.i1_zero;
4814 let res = self
4815 .build_call_with_param_attributes(
4816 self.intrinsics.ctlz_i32,
4817 &[input.into(), is_zero_undef.into()],
4818 "",
4819 )?
4820 .try_as_basic_value()
4821 .unwrap_basic();
4822 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4823 }
4824 Operator::I64Clz => {
4825 let (input, info) = self.state.pop1_extra()?;
4826 let input = self.apply_pending_canonicalization(input, info)?;
4827 let is_zero_undef = self.intrinsics.i1_zero;
4828 let res = self
4829 .build_call_with_param_attributes(
4830 self.intrinsics.ctlz_i64,
4831 &[input.into(), is_zero_undef.into()],
4832 "",
4833 )?
4834 .try_as_basic_value()
4835 .unwrap_basic();
4836 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4837 }
4838 Operator::I32Ctz => {
4839 let (input, info) = self.state.pop1_extra()?;
4840 let input = self.apply_pending_canonicalization(input, info)?;
4841 let is_zero_undef = self.intrinsics.i1_zero;
4842 let res = self
4843 .build_call_with_param_attributes(
4844 self.intrinsics.cttz_i32,
4845 &[input.into(), is_zero_undef.into()],
4846 "",
4847 )?
4848 .try_as_basic_value()
4849 .unwrap_basic();
4850 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4851 }
4852 Operator::I64Ctz => {
4853 let (input, info) = self.state.pop1_extra()?;
4854 let input = self.apply_pending_canonicalization(input, info)?;
4855 let is_zero_undef = self.intrinsics.i1_zero;
4856 let res = self
4857 .build_call_with_param_attributes(
4858 self.intrinsics.cttz_i64,
4859 &[input.into(), is_zero_undef.into()],
4860 "",
4861 )?
4862 .try_as_basic_value()
4863 .unwrap_basic();
4864 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4865 }
4866 Operator::I8x16Popcnt => {
4867 let (v, i) = self.state.pop1_extra()?;
4868 let (v, _) = self.v128_into_i8x16(v, i)?;
4869 let res = self
4870 .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
4871 .try_as_basic_value()
4872 .unwrap_basic();
4873 let res = err!(
4874 self.builder
4875 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4876 );
4877 self.state.push1(res);
4878 }
4879 Operator::I32Popcnt => {
4880 let (input, info) = self.state.pop1_extra()?;
4881 let input = self.apply_pending_canonicalization(input, info)?;
4882 let res = self
4883 .build_call_with_param_attributes(
4884 self.intrinsics.ctpop_i32,
4885 &[input.into()],
4886 "",
4887 )?
4888 .try_as_basic_value()
4889 .unwrap_basic();
4890 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4891 }
4892 Operator::I64Popcnt => {
4893 let (input, info) = self.state.pop1_extra()?;
4894 let input = self.apply_pending_canonicalization(input, info)?;
4895 let res = self
4896 .build_call_with_param_attributes(
4897 self.intrinsics.ctpop_i64,
4898 &[input.into()],
4899 "",
4900 )?
4901 .try_as_basic_value()
4902 .unwrap_basic();
4903 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4904 }
4905 Operator::I32Eqz => {
4906 let input = self.state.pop1()?.into_int_value();
4907 let cond = err!(self.builder.build_int_compare(
4908 IntPredicate::EQ,
4909 input,
4910 self.intrinsics.i32_zero,
4911 "",
4912 ));
4913 let res = err!(
4914 self.builder
4915 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
4916 );
4917 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4918 }
4919 Operator::I64Eqz => {
4920 let input = self.state.pop1()?.into_int_value();
4921 let cond = err!(self.builder.build_int_compare(
4922 IntPredicate::EQ,
4923 input,
4924 self.intrinsics.i64_zero,
4925 "",
4926 ));
4927 let res = err!(
4928 self.builder
4929 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
4930 );
4931 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4932 }
4933 Operator::I8x16Abs => {
4934 let (v, i) = self.state.pop1_extra()?;
4935 let (v, _) = self.v128_into_i8x16(v, i)?;
4936
4937 let seven = self.intrinsics.i8_ty.const_int(7, false);
4938 let seven = VectorType::const_vector(&[seven; 16]);
4939 let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
4940 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4941 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4942 let res = err!(
4943 self.builder
4944 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4945 );
4946 self.state.push1(res);
4947 }
4948 Operator::I16x8Abs => {
4949 let (v, i) = self.state.pop1_extra()?;
4950 let (v, _) = self.v128_into_i16x8(v, i)?;
4951
4952 let fifteen = self.intrinsics.i16_ty.const_int(15, false);
4953 let fifteen = VectorType::const_vector(&[fifteen; 8]);
4954 let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
4955 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4956 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4957 let res = err!(
4958 self.builder
4959 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4960 );
4961 self.state.push1(res);
4962 }
4963 Operator::I32x4Abs => {
4964 let (v, i) = self.state.pop1_extra()?;
4965 let (v, _) = self.v128_into_i32x4(v, i)?;
4966
4967 let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
4968 let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
4969 let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
4970 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4971 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4972 let res = err!(
4973 self.builder
4974 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4975 );
4976 self.state.push1(res);
4977 }
4978 Operator::I64x2Abs => {
4979 let (v, i) = self.state.pop1_extra()?;
4980 let (v, _) = self.v128_into_i64x2(v, i)?;
4981
4982 let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
4983 let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
4984 let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
4985 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4986 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4987 let res = err!(
4988 self.builder
4989 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4990 );
4991 self.state.push1(res);
4992 }
4993 Operator::I8x16MinS => {
4994 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4995 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4996 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4997 let cmp = err!(
4998 self.builder
4999 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5000 );
5001 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5002 let res = err!(
5003 self.builder
5004 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5005 );
5006 self.state.push1(res);
5007 }
5008 Operator::I8x16MinU => {
5009 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5010 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5011 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5012 let cmp = err!(
5013 self.builder
5014 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5015 );
5016 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5017 let res = err!(
5018 self.builder
5019 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5020 );
5021 self.state.push1(res);
5022 }
5023 Operator::I8x16MaxS => {
5024 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5025 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5026 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5027 let cmp = err!(
5028 self.builder
5029 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5030 );
5031 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5032 let res = err!(
5033 self.builder
5034 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5035 );
5036 self.state.push1(res);
5037 }
5038 Operator::I8x16MaxU => {
5039 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5040 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5041 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5042 let cmp = err!(
5043 self.builder
5044 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5045 );
5046 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5047 let res = err!(
5048 self.builder
5049 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5050 );
5051 self.state.push1(res);
5052 }
5053 Operator::I16x8MinS => {
5054 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5055 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5056 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5057 let cmp = err!(
5058 self.builder
5059 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5060 );
5061 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5062 let res = err!(
5063 self.builder
5064 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5065 );
5066 self.state.push1(res);
5067 }
5068 Operator::I16x8MinU => {
5069 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5070 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5071 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5072 let cmp = err!(
5073 self.builder
5074 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5075 );
5076 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5077 let res = err!(
5078 self.builder
5079 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5080 );
5081 self.state.push1(res);
5082 }
5083 Operator::I16x8MaxS => {
5084 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5085 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5086 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5087 let cmp = err!(
5088 self.builder
5089 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5090 );
5091 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5092 let res = err!(
5093 self.builder
5094 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5095 );
5096 self.state.push1(res);
5097 }
5098 Operator::I16x8MaxU => {
5099 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5100 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5101 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5102 let cmp = err!(
5103 self.builder
5104 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5105 );
5106 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5107 let res = err!(
5108 self.builder
5109 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5110 );
5111 self.state.push1(res);
5112 }
5113 Operator::I32x4MinS => {
5114 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5115 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5116 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5117 let cmp = err!(
5118 self.builder
5119 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5120 );
5121 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5122 let res = err!(
5123 self.builder
5124 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5125 );
5126 self.state.push1(res);
5127 }
5128 Operator::I32x4MinU => {
5129 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5130 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5131 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5132 let cmp = err!(
5133 self.builder
5134 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5135 );
5136 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5137 let res = err!(
5138 self.builder
5139 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5140 );
5141 self.state.push1(res);
5142 }
5143 Operator::I32x4MaxS => {
5144 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5145 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5146 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5147 let cmp = err!(
5148 self.builder
5149 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5150 );
5151 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5152 let res = err!(
5153 self.builder
5154 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5155 );
5156 self.state.push1(res);
5157 }
5158 Operator::I32x4MaxU => {
5159 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5160 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5161 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5162 let cmp = err!(
5163 self.builder
5164 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5165 );
5166 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5167 let res = err!(
5168 self.builder
5169 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5170 );
5171 self.state.push1(res);
5172 }
5173 Operator::I8x16AvgrU => {
5174 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5175 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5176 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5177
5178 let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5189 let one = self.intrinsics.i16_ty.const_int(1, false);
5190 let one = VectorType::const_vector(&[one; 16]);
5191
5192 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5193 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5194 let res = err!(self.builder.build_int_add(
5195 err!(self.builder.build_int_add(one, v1, "")),
5196 v2,
5197 ""
5198 ));
5199 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5200 let res = err!(
5201 self.builder
5202 .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5203 );
5204 let res = err!(
5205 self.builder
5206 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5207 );
5208 self.state.push1(res);
5209 }
5210 Operator::I16x8AvgrU => {
5211 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5212 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5213 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5214
5215 let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5226 let one = self.intrinsics.i32_consts[1];
5227 let one = VectorType::const_vector(&[one; 8]);
5228
5229 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5230 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5231 let res = err!(self.builder.build_int_add(
5232 err!(self.builder.build_int_add(one, v1, "")),
5233 v2,
5234 ""
5235 ));
5236 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5237 let res = err!(
5238 self.builder
5239 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5240 );
5241 let res = err!(
5242 self.builder
5243 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5244 );
5245 self.state.push1(res);
5246 }
5247
5248 Operator::F32Add => {
5253 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5254 let res = self
5255 .build_call_with_param_attributes(
5256 self.intrinsics.add_f32,
5257 &[
5258 v1.into(),
5259 v2.into(),
5260 self.intrinsics.fp_rounding_md,
5261 self.intrinsics.fp_exception_md,
5262 ],
5263 "",
5264 )?
5265 .try_as_basic_value()
5266 .unwrap_basic();
5267 self.state.push1_extra(
5268 res,
5269 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5270 );
5271 }
5272 Operator::F64Add => {
5273 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5274 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5275 let res = self
5276 .build_call_with_param_attributes(
5277 self.intrinsics.add_f64,
5278 &[
5279 v1.into(),
5280 v2.into(),
5281 self.intrinsics.fp_rounding_md,
5282 self.intrinsics.fp_exception_md,
5283 ],
5284 "",
5285 )?
5286 .try_as_basic_value()
5287 .unwrap_basic();
5288 self.state.push1_extra(
5289 res,
5290 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5291 );
5292 }
5293 Operator::F32x4Add => {
5294 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5295 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5296 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5297 let res = self
5298 .build_call_with_param_attributes(
5299 self.intrinsics.add_f32x4,
5300 &[
5301 v1.into(),
5302 v2.into(),
5303 self.intrinsics.fp_rounding_md,
5304 self.intrinsics.fp_exception_md,
5305 ],
5306 "",
5307 )?
5308 .try_as_basic_value()
5309 .unwrap_basic();
5310 let res = err!(
5311 self.builder
5312 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5313 );
5314 self.state.push1_extra(
5315 res,
5316 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5317 );
5318 }
5319 Operator::F64x2Add => {
5320 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5321 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5322 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5323 let res = self
5324 .build_call_with_param_attributes(
5325 self.intrinsics.add_f64x2,
5326 &[
5327 v1.into(),
5328 v2.into(),
5329 self.intrinsics.fp_rounding_md,
5330 self.intrinsics.fp_exception_md,
5331 ],
5332 "",
5333 )?
5334 .try_as_basic_value()
5335 .unwrap_basic();
5336 let res = err!(
5337 self.builder
5338 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5339 );
5340 self.state.push1_extra(
5341 res,
5342 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5343 );
5344 }
5345 Operator::F32Sub => {
5346 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5347 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5348 let res = self
5349 .build_call_with_param_attributes(
5350 self.intrinsics.sub_f32,
5351 &[
5352 v1.into(),
5353 v2.into(),
5354 self.intrinsics.fp_rounding_md,
5355 self.intrinsics.fp_exception_md,
5356 ],
5357 "",
5358 )?
5359 .try_as_basic_value()
5360 .unwrap_basic();
5361 self.state.push1_extra(
5362 res,
5363 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5364 );
5365 }
5366 Operator::F64Sub => {
5367 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5368 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5369 let res = self
5370 .build_call_with_param_attributes(
5371 self.intrinsics.sub_f64,
5372 &[
5373 v1.into(),
5374 v2.into(),
5375 self.intrinsics.fp_rounding_md,
5376 self.intrinsics.fp_exception_md,
5377 ],
5378 "",
5379 )?
5380 .try_as_basic_value()
5381 .unwrap_basic();
5382 self.state.push1_extra(
5383 res,
5384 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5385 );
5386 }
5387 Operator::F32x4Sub => {
5388 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5389 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5390 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5391 let res = self
5392 .build_call_with_param_attributes(
5393 self.intrinsics.sub_f32x4,
5394 &[
5395 v1.into(),
5396 v2.into(),
5397 self.intrinsics.fp_rounding_md,
5398 self.intrinsics.fp_exception_md,
5399 ],
5400 "",
5401 )?
5402 .try_as_basic_value()
5403 .unwrap_basic();
5404 let res = err!(
5405 self.builder
5406 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5407 );
5408 self.state.push1_extra(
5409 res,
5410 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5411 );
5412 }
5413 Operator::F64x2Sub => {
5414 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5415 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5416 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5417 let res = self
5418 .build_call_with_param_attributes(
5419 self.intrinsics.sub_f64x2,
5420 &[
5421 v1.into(),
5422 v2.into(),
5423 self.intrinsics.fp_rounding_md,
5424 self.intrinsics.fp_exception_md,
5425 ],
5426 "",
5427 )?
5428 .try_as_basic_value()
5429 .unwrap_basic();
5430 let res = err!(
5431 self.builder
5432 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5433 );
5434 self.state.push1_extra(
5435 res,
5436 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5437 );
5438 }
5439 Operator::F32Mul => {
5440 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5441 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5442 let res = self
5443 .build_call_with_param_attributes(
5444 self.intrinsics.mul_f32,
5445 &[
5446 v1.into(),
5447 v2.into(),
5448 self.intrinsics.fp_rounding_md,
5449 self.intrinsics.fp_exception_md,
5450 ],
5451 "",
5452 )?
5453 .try_as_basic_value()
5454 .unwrap_basic();
5455 self.state.push1_extra(
5456 res,
5457 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5458 );
5459 }
5460 Operator::F64Mul => {
5461 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5462 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5463 let res = self
5464 .build_call_with_param_attributes(
5465 self.intrinsics.mul_f64,
5466 &[
5467 v1.into(),
5468 v2.into(),
5469 self.intrinsics.fp_rounding_md,
5470 self.intrinsics.fp_exception_md,
5471 ],
5472 "",
5473 )?
5474 .try_as_basic_value()
5475 .unwrap_basic();
5476 self.state.push1_extra(
5477 res,
5478 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5479 );
5480 }
5481 Operator::F32x4Mul => {
5482 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5483 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5484 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5485 let res = self
5486 .build_call_with_param_attributes(
5487 self.intrinsics.mul_f32x4,
5488 &[
5489 v1.into(),
5490 v2.into(),
5491 self.intrinsics.fp_rounding_md,
5492 self.intrinsics.fp_exception_md,
5493 ],
5494 "",
5495 )?
5496 .try_as_basic_value()
5497 .unwrap_basic();
5498 let res = err!(
5499 self.builder
5500 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5501 );
5502 self.state.push1_extra(
5503 res,
5504 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5505 );
5506 }
5507 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
5508 if self.cpu_features.contains(CpuFeature::FMA) =>
5509 {
5510 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5511 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5512 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5513 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5514
5515 let v1 = match op {
5516 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5517 _ => v1,
5518 };
5519 let res = self
5520 .build_call_with_param_attributes(
5521 self.intrinsics.muladd_f32x4,
5522 &[
5523 v1.into(),
5524 v2.into(),
5525 v3.into(),
5526 self.intrinsics.fp_rounding_md,
5527 self.intrinsics.fp_exception_md,
5528 ],
5529 "",
5530 )?
5531 .try_as_basic_value()
5532 .unwrap_basic();
5533 let res = err!(
5534 self.builder
5535 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5536 );
5537 let info = (i1.strip_pending() & i2.strip_pending())?;
5538 let info = (info & i3.strip_pending())?;
5539 let info = (info | ExtraInfo::pending_f32_nan())?;
5540 self.state.push1_extra(res, info);
5541 }
5542 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
5543 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5544 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5545 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5546 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5547
5548 let v1 = match op {
5549 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5550 _ => v1,
5551 };
5552 let mul = self
5553 .build_call_with_param_attributes(
5554 self.intrinsics.mul_f32x4,
5555 &[
5556 v1.into(),
5557 v2.into(),
5558 self.intrinsics.fp_rounding_md,
5559 self.intrinsics.fp_exception_md,
5560 ],
5561 "",
5562 )?
5563 .try_as_basic_value()
5564 .unwrap_basic();
5565 let mul = mul.into_vector_value();
5566 let res = self
5567 .build_call_with_param_attributes(
5568 self.intrinsics.add_f32x4,
5569 &[
5570 mul.into(),
5571 v3.into(),
5572 self.intrinsics.fp_rounding_md,
5573 self.intrinsics.fp_exception_md,
5574 ],
5575 "",
5576 )?
5577 .try_as_basic_value()
5578 .unwrap_basic();
5579 let res = err!(
5580 self.builder
5581 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5582 );
5583 let info = (i1.strip_pending() & i2.strip_pending())?;
5584 let info = (info & i3.strip_pending())?;
5585 let info = (info | ExtraInfo::pending_f32_nan())?;
5586 self.state.push1_extra(res, info);
5587 }
5588 Operator::F64x2Mul => {
5589 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5590 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5591 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5592 let res = self
5593 .build_call_with_param_attributes(
5594 self.intrinsics.mul_f64x2,
5595 &[
5596 v1.into(),
5597 v2.into(),
5598 self.intrinsics.fp_rounding_md,
5599 self.intrinsics.fp_exception_md,
5600 ],
5601 "",
5602 )?
5603 .try_as_basic_value()
5604 .unwrap_basic();
5605 let res = err!(
5606 self.builder
5607 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5608 );
5609 self.state.push1_extra(
5610 res,
5611 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5612 );
5613 }
5614 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
5615 if self.cpu_features.contains(CpuFeature::FMA) =>
5616 {
5617 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5618 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5619 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5620 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5621
5622 let v1 = match op {
5623 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5624 _ => v1,
5625 };
5626 let res = self
5627 .build_call_with_param_attributes(
5628 self.intrinsics.muladd_f64x2,
5629 &[
5630 v1.into(),
5631 v2.into(),
5632 v3.into(),
5633 self.intrinsics.fp_rounding_md,
5634 self.intrinsics.fp_exception_md,
5635 ],
5636 "",
5637 )?
5638 .try_as_basic_value()
5639 .unwrap_basic();
5640 let res = err!(
5641 self.builder
5642 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5643 );
5644 let info = (i1.strip_pending() & i2.strip_pending())?;
5645 let info = (info & i3.strip_pending())?;
5646 let info = (info | ExtraInfo::pending_f64_nan())?;
5647 self.state.push1_extra(res, info);
5648 }
5649 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
5650 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5651 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5652 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5653 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5654
5655 let v1 = match op {
5656 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5657 _ => v1,
5658 };
5659 let mul = self
5660 .build_call_with_param_attributes(
5661 self.intrinsics.mul_f64x2,
5662 &[
5663 v1.into(),
5664 v2.into(),
5665 self.intrinsics.fp_rounding_md,
5666 self.intrinsics.fp_exception_md,
5667 ],
5668 "",
5669 )?
5670 .try_as_basic_value()
5671 .unwrap_basic();
5672 let mul = mul.into_vector_value();
5673 let res = self
5674 .build_call_with_param_attributes(
5675 self.intrinsics.add_f64x2,
5676 &[
5677 mul.into(),
5678 v3.into(),
5679 self.intrinsics.fp_rounding_md,
5680 self.intrinsics.fp_exception_md,
5681 ],
5682 "",
5683 )?
5684 .try_as_basic_value()
5685 .unwrap_basic();
5686 let res = err!(
5687 self.builder
5688 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5689 );
5690 let info = (i1.strip_pending() & i2.strip_pending())?;
5691 let info = (info & i3.strip_pending())?;
5692 let info = (info | ExtraInfo::pending_f64_nan())?;
5693 self.state.push1_extra(res, info);
5694 }
5695 Operator::F32Div => {
5696 let (v1, v2) = self.state.pop2()?;
5697 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5698 let res = self
5699 .build_call_with_param_attributes(
5700 self.intrinsics.div_f32,
5701 &[
5702 v1.into(),
5703 v2.into(),
5704 self.intrinsics.fp_rounding_md,
5705 self.intrinsics.fp_exception_md,
5706 ],
5707 "",
5708 )?
5709 .try_as_basic_value()
5710 .unwrap_basic();
5711 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5712 }
5713 Operator::F64Div => {
5714 let (v1, v2) = self.state.pop2()?;
5715 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5716 let res = self
5717 .build_call_with_param_attributes(
5718 self.intrinsics.div_f64,
5719 &[
5720 v1.into(),
5721 v2.into(),
5722 self.intrinsics.fp_rounding_md,
5723 self.intrinsics.fp_exception_md,
5724 ],
5725 "",
5726 )?
5727 .try_as_basic_value()
5728 .unwrap_basic();
5729 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5730 }
5731 Operator::F32x4Div => {
5732 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5733 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
5734 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
5735 let res = self
5736 .build_call_with_param_attributes(
5737 self.intrinsics.div_f32x4,
5738 &[
5739 v1.into(),
5740 v2.into(),
5741 self.intrinsics.fp_rounding_md,
5742 self.intrinsics.fp_exception_md,
5743 ],
5744 "",
5745 )?
5746 .try_as_basic_value()
5747 .unwrap_basic();
5748 let res = err!(
5749 self.builder
5750 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5751 );
5752 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5753 }
5754 Operator::F64x2Div => {
5755 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5756 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
5757 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
5758 let res = self
5759 .build_call_with_param_attributes(
5760 self.intrinsics.div_f64x2,
5761 &[
5762 v1.into(),
5763 v2.into(),
5764 self.intrinsics.fp_rounding_md,
5765 self.intrinsics.fp_exception_md,
5766 ],
5767 "",
5768 )?
5769 .try_as_basic_value()
5770 .unwrap_basic();
5771 let res = err!(
5772 self.builder
5773 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5774 );
5775 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5776 }
5777 Operator::F32Sqrt => {
5778 let input = self.state.pop1()?;
5779 let res = self
5780 .build_call_with_param_attributes(
5781 self.intrinsics.sqrt_f32,
5782 &[input.into()],
5783 "",
5784 )?
5785 .try_as_basic_value()
5786 .unwrap_basic();
5787 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5788 }
5789 Operator::F64Sqrt => {
5790 let input = self.state.pop1()?;
5791 let res = self
5792 .build_call_with_param_attributes(
5793 self.intrinsics.sqrt_f64,
5794 &[input.into()],
5795 "",
5796 )?
5797 .try_as_basic_value()
5798 .unwrap_basic();
5799 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5800 }
5801 Operator::F32x4Sqrt => {
5802 let (v, i) = self.state.pop1_extra()?;
5803 let (v, _) = self.v128_into_f32x4(v, i)?;
5804 let res = self
5805 .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
5806 .try_as_basic_value()
5807 .unwrap_basic();
5808 let bits = err!(
5809 self.builder
5810 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
5811 );
5812 self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
5813 }
5814 Operator::F64x2Sqrt => {
5815 let (v, i) = self.state.pop1_extra()?;
5816 let (v, _) = self.v128_into_f64x2(v, i)?;
5817 let res = self
5818 .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
5819 .try_as_basic_value()
5820 .unwrap_basic();
5821 let bits = err!(
5822 self.builder
5823 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
5824 );
5825 self.state.push1(bits);
5826 }
5827 Operator::F32Min => {
5828 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5829 let lhs = self
5830 .apply_pending_canonicalization(lhs, lhs_info)?
5831 .into_float_value();
5832 let rhs = self
5833 .apply_pending_canonicalization(rhs, rhs_info)?
5834 .into_float_value();
5835
5836 let res = self
5837 .build_call_with_param_attributes(
5838 self.intrinsics.minimum_f32,
5839 &[lhs.into(), rhs.into()],
5840 "",
5841 )?
5842 .try_as_basic_value()
5843 .unwrap_basic();
5844
5845 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5846 let res = res.into_float_value();
5847
5848 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5849 }
5850 Operator::F64Min => {
5851 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5852 let lhs = self
5853 .apply_pending_canonicalization(lhs, lhs_info)?
5854 .into_float_value();
5855 let rhs = self
5856 .apply_pending_canonicalization(rhs, rhs_info)?
5857 .into_float_value();
5858
5859 let res = self
5860 .build_call_with_param_attributes(
5861 self.intrinsics.minimum_f64,
5862 &[lhs.into(), rhs.into()],
5863 "",
5864 )?
5865 .try_as_basic_value()
5866 .unwrap_basic();
5867
5868 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5869 let res = res.into_float_value();
5870
5871 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5872 }
5873 Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
5874 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5875 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5876 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5877 let res = self
5878 .build_call_with_param_attributes(
5879 self.intrinsics.x86_64.min_ps,
5880 &[v1.into(), v2.into()],
5881 "",
5882 )?
5883 .try_as_basic_value()
5884 .unwrap_basic();
5885 let res = err!(
5886 self.builder
5887 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5888 );
5889 self.state.push1_extra(
5890 res,
5891 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5892 );
5893 }
5894 Operator::F32x4Min | Operator::F32x4RelaxedMin => {
5895 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5896 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5897 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5898 let res = self
5899 .build_call_with_param_attributes(
5900 self.intrinsics.minimum_f32x4,
5901 &[v1.into(), v2.into()],
5902 "",
5903 )?
5904 .try_as_basic_value()
5905 .unwrap_basic();
5906
5907 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5908 let res = res.into_vector_value();
5909
5910 let res = err!(
5911 self.builder
5912 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5913 );
5914 self.state.push1_extra(
5915 res,
5916 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5917 );
5918 }
5919 Operator::F32x4PMin => {
5920 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5922 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
5923 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
5924 let cmp = err!(
5925 self.builder
5926 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
5927 );
5928 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
5929 let res = err!(
5930 self.builder
5931 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5932 );
5933 self.state.push1(res);
5934 }
5935 Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
5936 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5937 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5938 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5939 let res = self
5940 .build_call_with_param_attributes(
5941 self.intrinsics.x86_64.min_pd,
5942 &[v1.into(), v2.into()],
5943 "",
5944 )?
5945 .try_as_basic_value()
5946 .unwrap_basic();
5947 let res = err!(
5948 self.builder
5949 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5950 );
5951 self.state.push1_extra(
5952 res,
5953 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5954 );
5955 }
5956 Operator::F64x2Min | Operator::F64x2RelaxedMin => {
5957 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5958 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5959 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5960 let res = self
5961 .build_call_with_param_attributes(
5962 self.intrinsics.minimum_f64x2,
5963 &[v1.into(), v2.into()],
5964 "",
5965 )?
5966 .try_as_basic_value()
5967 .unwrap_basic();
5968
5969 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5970 let res = res.into_vector_value();
5971
5972 let res = err!(
5973 self.builder
5974 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5975 );
5976 self.state.push1_extra(
5977 res,
5978 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5979 );
5980 }
5981 Operator::F64x2PMin => {
5982 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5984 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
5985 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
5986 let cmp = err!(
5987 self.builder
5988 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
5989 );
5990 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
5991 let res = err!(
5992 self.builder
5993 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5994 );
5995 self.state.push1(res);
5996 }
5997 Operator::F32Max => {
5998 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5999 let lhs = self
6000 .apply_pending_canonicalization(lhs, lhs_info)?
6001 .into_float_value();
6002 let rhs = self
6003 .apply_pending_canonicalization(rhs, rhs_info)?
6004 .into_float_value();
6005
6006 let res = self
6007 .build_call_with_param_attributes(
6008 self.intrinsics.maximum_f32,
6009 &[lhs.into(), rhs.into()],
6010 "",
6011 )?
6012 .try_as_basic_value()
6013 .unwrap_basic();
6014
6015 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6016 let res = res.into_float_value();
6017
6018 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6019 }
6020 Operator::F64Max => {
6021 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6022 let lhs = self
6023 .apply_pending_canonicalization(lhs, lhs_info)?
6024 .into_float_value();
6025 let rhs = self
6026 .apply_pending_canonicalization(rhs, rhs_info)?
6027 .into_float_value();
6028
6029 let res = self
6030 .build_call_with_param_attributes(
6031 self.intrinsics.maximum_f64,
6032 &[lhs.into(), rhs.into()],
6033 "",
6034 )?
6035 .try_as_basic_value()
6036 .unwrap_basic();
6037
6038 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6039 let res = res.into_float_value();
6040
6041 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6042 }
6043 Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6044 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6045 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6046 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6047 let res = self
6048 .build_call_with_param_attributes(
6049 self.intrinsics.x86_64.max_ps,
6050 &[v1.into(), v2.into()],
6051 "",
6052 )?
6053 .try_as_basic_value()
6054 .unwrap_basic();
6055 let res = err!(
6056 self.builder
6057 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6058 );
6059 self.state.push1_extra(
6060 res,
6061 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6062 );
6063 }
6064 Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6065 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6066 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6067 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6068 let res = self
6069 .build_call_with_param_attributes(
6070 self.intrinsics.maximum_f32x4,
6071 &[v1.into(), v2.into()],
6072 "",
6073 )?
6074 .try_as_basic_value()
6075 .unwrap_basic();
6076
6077 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6078 let res = res.into_vector_value();
6079
6080 let res = err!(
6081 self.builder
6082 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6083 );
6084 self.state.push1_extra(
6085 res,
6086 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6087 );
6088 }
6089 Operator::F32x4PMax => {
6090 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6092 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6093 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6094 let cmp = err!(
6095 self.builder
6096 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6097 );
6098 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6099
6100 let res = err!(
6101 self.builder
6102 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6103 );
6104 self.state.push1(res);
6105 }
6106 Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6107 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6108 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6109 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6110 let res = self
6111 .build_call_with_param_attributes(
6112 self.intrinsics.x86_64.max_pd,
6113 &[v1.into(), v2.into()],
6114 "",
6115 )?
6116 .try_as_basic_value()
6117 .unwrap_basic();
6118 let res = err!(
6119 self.builder
6120 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6121 );
6122 self.state.push1_extra(
6123 res,
6124 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6125 );
6126 }
6127 Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6128 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6129 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6130 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6131 let res = self
6132 .build_call_with_param_attributes(
6133 self.intrinsics.maximum_f64x2,
6134 &[v1.into(), v2.into()],
6135 "",
6136 )?
6137 .try_as_basic_value()
6138 .unwrap_basic();
6139
6140 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6141 let res = res.into_vector_value();
6142
6143 let res = err!(
6144 self.builder
6145 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6146 );
6147 self.state.push1_extra(
6148 res,
6149 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6150 );
6151 }
6152 Operator::F64x2PMax => {
6153 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6155 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6156 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6157 let cmp = err!(
6158 self.builder
6159 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6160 );
6161 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6162 let res = err!(
6163 self.builder
6164 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6165 );
6166 self.state.push1(res);
6167 }
6168 Operator::F32Ceil => {
6169 let (input, info) = self.state.pop1_extra()?;
6170 let res = err!(self.build_call_with_param_attributes(
6171 self.intrinsics.ceil_f32,
6172 &[input.into()],
6173 ""
6174 ))
6175 .try_as_basic_value()
6176 .unwrap_basic();
6177 let (res, info) = self.finalize_rounding_result(res, info)?;
6178 self.state.push1_extra(res, info);
6179 }
6180 Operator::F32x4Ceil => {
6181 let (v, i) = self.state.pop1_extra()?;
6182 let (v, _) = self.v128_into_f32x4(v, i)?;
6183 let res = err!(self.build_call_with_param_attributes(
6184 self.intrinsics.ceil_f32x4,
6185 &[v.into()],
6186 ""
6187 ))
6188 .try_as_basic_value()
6189 .unwrap_basic();
6190 let (res, info) = self.finalize_rounding_result(res, i)?;
6191 let res = err!(
6192 self.builder
6193 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6194 );
6195 self.state.push1_extra(res, info);
6196 }
6197 Operator::F64Ceil => {
6198 let (input, info) = self.state.pop1_extra()?;
6199 let res = err!(self.build_call_with_param_attributes(
6200 self.intrinsics.ceil_f64,
6201 &[input.into()],
6202 ""
6203 ))
6204 .try_as_basic_value()
6205 .unwrap_basic();
6206 let (res, info) = self.finalize_rounding_result(res, info)?;
6207 self.state.push1_extra(res, info);
6208 }
6209 Operator::F64x2Ceil => {
6210 let (v, i) = self.state.pop1_extra()?;
6211 let (v, _) = self.v128_into_f64x2(v, i)?;
6212 let res = err!(self.build_call_with_param_attributes(
6213 self.intrinsics.ceil_f64x2,
6214 &[v.into()],
6215 ""
6216 ))
6217 .try_as_basic_value()
6218 .unwrap_basic();
6219 let (res, info) = self.finalize_rounding_result(res, i)?;
6220 let res = err!(
6221 self.builder
6222 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6223 );
6224 self.state.push1_extra(res, info);
6225 }
6226 Operator::F32Floor => {
6227 let (input, info) = self.state.pop1_extra()?;
6228 let res = err!(self.build_call_with_param_attributes(
6229 self.intrinsics.floor_f32,
6230 &[input.into()],
6231 ""
6232 ))
6233 .try_as_basic_value()
6234 .unwrap_basic();
6235 let (res, info) = self.finalize_rounding_result(res, info)?;
6236 self.state.push1_extra(res, info);
6237 }
6238 Operator::F32x4Floor => {
6239 let (v, i) = self.state.pop1_extra()?;
6240 let (v, _) = self.v128_into_f32x4(v, i)?;
6241 let res = err!(self.build_call_with_param_attributes(
6242 self.intrinsics.floor_f32x4,
6243 &[v.into()],
6244 ""
6245 ))
6246 .try_as_basic_value()
6247 .unwrap_basic();
6248 let (res, info) = self.finalize_rounding_result(res, i)?;
6249 let res = err!(
6250 self.builder
6251 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6252 );
6253 self.state.push1_extra(res, info);
6254 }
6255 Operator::F64Floor => {
6256 let (input, info) = self.state.pop1_extra()?;
6257 let res = err!(self.build_call_with_param_attributes(
6258 self.intrinsics.floor_f64,
6259 &[input.into()],
6260 ""
6261 ))
6262 .try_as_basic_value()
6263 .unwrap_basic();
6264 let (res, info) = self.finalize_rounding_result(res, info)?;
6265 self.state.push1_extra(res, info);
6266 }
6267 Operator::F64x2Floor => {
6268 let (v, i) = self.state.pop1_extra()?;
6269 let (v, _) = self.v128_into_f64x2(v, i)?;
6270 let res = err!(self.build_call_with_param_attributes(
6271 self.intrinsics.floor_f64x2,
6272 &[v.into()],
6273 ""
6274 ))
6275 .try_as_basic_value()
6276 .unwrap_basic();
6277 let (res, info) = self.finalize_rounding_result(res, i)?;
6278 let res = err!(
6279 self.builder
6280 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6281 );
6282 self.state.push1_extra(res, info);
6283 }
6284 Operator::F32Trunc => {
6285 let (v, info) = self.state.pop1_extra()?;
6286 let res = err!(
6287 self.builder
6288 .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
6289 )
6290 .try_as_basic_value()
6291 .unwrap_basic();
6292 let (res, info) = self.finalize_rounding_result(res, info)?;
6293 self.state.push1_extra(res, info);
6294 }
6295 Operator::F32x4Trunc => {
6296 let (v, i) = self.state.pop1_extra()?;
6297 let (v, _) = self.v128_into_f32x4(v, i)?;
6298 let res = err!(self.build_call_with_param_attributes(
6299 self.intrinsics.trunc_f32x4,
6300 &[v.into()],
6301 ""
6302 ))
6303 .try_as_basic_value()
6304 .unwrap_basic();
6305 let (res, info) = self.finalize_rounding_result(res, i)?;
6306 let res = err!(
6307 self.builder
6308 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6309 );
6310 self.state.push1_extra(res, info);
6311 }
6312 Operator::F64Trunc => {
6313 let (v, info) = self.state.pop1_extra()?;
6314 let res = err!(
6315 self.builder
6316 .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
6317 )
6318 .try_as_basic_value()
6319 .unwrap_basic();
6320 let (res, info) = self.finalize_rounding_result(res, info)?;
6321 self.state.push1_extra(res, info);
6322 }
6323 Operator::F64x2Trunc => {
6324 let (v, i) = self.state.pop1_extra()?;
6325 let (v, _) = self.v128_into_f64x2(v, i)?;
6326 let res = err!(self.build_call_with_param_attributes(
6327 self.intrinsics.trunc_f64x2,
6328 &[v.into()],
6329 ""
6330 ))
6331 .try_as_basic_value()
6332 .unwrap_basic();
6333 let (res, info) = self.finalize_rounding_result(res, i)?;
6334 let res = err!(
6335 self.builder
6336 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6337 );
6338 self.state.push1_extra(res, info);
6339 }
6340 Operator::F32Nearest => {
6341 let (v, info) = self.state.pop1_extra()?;
6342 let res = err!(self.build_call_with_param_attributes(
6343 self.intrinsics.nearbyint_f32,
6344 &[v.into()],
6345 ""
6346 ))
6347 .try_as_basic_value()
6348 .unwrap_basic();
6349 let (res, info) = self.finalize_rounding_result(res, info)?;
6350 self.state.push1_extra(res, info);
6351 }
6352 Operator::F32x4Nearest => {
6353 let (v, i) = self.state.pop1_extra()?;
6354 let (v, _) = self.v128_into_f32x4(v, i)?;
6355 let res = err!(self.build_call_with_param_attributes(
6356 self.intrinsics.nearbyint_f32x4,
6357 &[v.into()],
6358 ""
6359 ))
6360 .try_as_basic_value()
6361 .unwrap_basic();
6362 let (res, info) = self.finalize_rounding_result(res, i)?;
6363 let res = err!(
6364 self.builder
6365 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6366 );
6367 self.state.push1_extra(res, info);
6368 }
6369 Operator::F64Nearest => {
6370 let (v, info) = self.state.pop1_extra()?;
6371 let res = err!(self.build_call_with_param_attributes(
6372 self.intrinsics.nearbyint_f64,
6373 &[v.into()],
6374 ""
6375 ))
6376 .try_as_basic_value()
6377 .unwrap_basic();
6378 let (res, info) = self.finalize_rounding_result(res, info)?;
6379 self.state.push1_extra(res, info);
6380 }
6381 Operator::F64x2Nearest => {
6382 let (v, i) = self.state.pop1_extra()?;
6383 let (v, _) = self.v128_into_f64x2(v, i)?;
6384 let res = err!(self.build_call_with_param_attributes(
6385 self.intrinsics.nearbyint_f64x2,
6386 &[v.into()],
6387 ""
6388 ))
6389 .try_as_basic_value()
6390 .unwrap_basic();
6391 let (res, info) = self.finalize_rounding_result(res, i)?;
6392 let res = err!(
6393 self.builder
6394 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6395 );
6396 self.state.push1_extra(res, info);
6397 }
6398 Operator::F32Abs => {
6399 let (v, i) = self.state.pop1_extra()?;
6400 let v = self.apply_pending_canonicalization(v, i)?;
6401 let res = err!(
6402 self.builder
6403 .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
6404 )
6405 .try_as_basic_value()
6406 .unwrap_basic();
6407 self.state.push1_extra(res, i.strip_pending());
6410 }
6411 Operator::F64Abs => {
6412 let (v, i) = self.state.pop1_extra()?;
6413 let v = self.apply_pending_canonicalization(v, i)?;
6414 let res = err!(
6415 self.builder
6416 .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
6417 )
6418 .try_as_basic_value()
6419 .unwrap_basic();
6420 self.state.push1_extra(res, i.strip_pending());
6423 }
6424 Operator::F32x4Abs => {
6425 let (v, i) = self.state.pop1_extra()?;
6426 let v = err!(self.builder.build_bit_cast(
6427 v.into_int_value(),
6428 self.intrinsics.f32x4_ty,
6429 ""
6430 ));
6431 let v = self.apply_pending_canonicalization(v, i)?;
6432 let res = self
6433 .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
6434 .try_as_basic_value()
6435 .unwrap_basic();
6436 let res = err!(
6437 self.builder
6438 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6439 );
6440 self.state.push1_extra(res, i.strip_pending());
6443 }
6444 Operator::F64x2Abs => {
6445 let (v, i) = self.state.pop1_extra()?;
6446 let v = err!(self.builder.build_bit_cast(
6447 v.into_int_value(),
6448 self.intrinsics.f64x2_ty,
6449 ""
6450 ));
6451 let v = self.apply_pending_canonicalization(v, i)?;
6452 let res = self
6453 .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
6454 .try_as_basic_value()
6455 .unwrap_basic();
6456 let res = err!(
6457 self.builder
6458 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6459 );
6460 self.state.push1_extra(res, i.strip_pending());
6463 }
6464 Operator::F32x4Neg => {
6465 let (v, i) = self.state.pop1_extra()?;
6466 let v = err!(self.builder.build_bit_cast(
6467 v.into_int_value(),
6468 self.intrinsics.f32x4_ty,
6469 ""
6470 ));
6471 let v = self
6472 .apply_pending_canonicalization(v, i)?
6473 .into_vector_value();
6474 let res = err!(self.builder.build_float_neg(v, ""));
6475 let res = err!(
6476 self.builder
6477 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6478 );
6479 self.state.push1_extra(res, i.strip_pending());
6482 }
6483 Operator::F64x2Neg => {
6484 let (v, i) = self.state.pop1_extra()?;
6485 let v = err!(self.builder.build_bit_cast(
6486 v.into_int_value(),
6487 self.intrinsics.f64x2_ty,
6488 ""
6489 ));
6490 let v = self
6491 .apply_pending_canonicalization(v, i)?
6492 .into_vector_value();
6493 let res = err!(self.builder.build_float_neg(v, ""));
6494 let res = err!(
6495 self.builder
6496 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6497 );
6498 self.state.push1_extra(res, i.strip_pending());
6501 }
6502 Operator::F32Neg | Operator::F64Neg => {
6503 let (v, i) = self.state.pop1_extra()?;
6504 let v = self
6505 .apply_pending_canonicalization(v, i)?
6506 .into_float_value();
6507 let res = err!(self.builder.build_float_neg(v, ""));
6508 self.state.push1_extra(res, i.strip_pending());
6511 }
6512 Operator::F32Copysign => {
6513 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6514 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6515 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6516 let res = self
6517 .build_call_with_param_attributes(
6518 self.intrinsics.copysign_f32,
6519 &[mag.into(), sgn.into()],
6520 "",
6521 )?
6522 .try_as_basic_value()
6523 .unwrap_basic();
6524 self.state.push1_extra(res, mag_info.strip_pending());
6527 }
6528 Operator::F64Copysign => {
6529 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6530 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6531 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6532 let res = self
6533 .build_call_with_param_attributes(
6534 self.intrinsics.copysign_f64,
6535 &[mag.into(), sgn.into()],
6536 "",
6537 )?
6538 .try_as_basic_value()
6539 .unwrap_basic();
6540 self.state.push1_extra(res, mag_info.strip_pending());
6543 }
6544
6545 Operator::I32Eq | Operator::I64Eq => {
6550 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6551 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6552 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6553 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6554 let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6555 let res = err!(
6556 self.builder
6557 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6558 );
6559 self.state.push1_extra(
6560 res,
6561 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6562 );
6563 }
6564 Operator::I8x16Eq => {
6565 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6566 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6567 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6568 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6569 let res = err!(
6570 self.builder
6571 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6572 );
6573 let res = err!(
6574 self.builder
6575 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6576 );
6577 self.state.push1(res);
6578 }
6579 Operator::I16x8Eq => {
6580 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6581 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6582 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6583 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6584 let res = err!(
6585 self.builder
6586 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6587 );
6588 let res = err!(
6589 self.builder
6590 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6591 );
6592 self.state.push1(res);
6593 }
6594 Operator::I32x4Eq => {
6595 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6596 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6597 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6598 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6599 let res = err!(
6600 self.builder
6601 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6602 );
6603 let res = err!(
6604 self.builder
6605 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6606 );
6607 self.state.push1(res);
6608 }
6609 Operator::I64x2Eq => {
6610 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6611 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6612 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6613 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6614 let res = err!(
6615 self.builder
6616 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6617 );
6618 let res = err!(
6619 self.builder
6620 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6621 );
6622 self.state.push1(res);
6623 }
6624 Operator::I32Ne | Operator::I64Ne => {
6625 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6626 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6627 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6628 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6629 let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6630 let res = err!(
6631 self.builder
6632 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6633 );
6634 self.state.push1_extra(
6635 res,
6636 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6637 );
6638 }
6639 Operator::I8x16Ne => {
6640 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6641 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6642 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6643 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6644 let res = err!(
6645 self.builder
6646 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6647 );
6648 let res = err!(
6649 self.builder
6650 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6651 );
6652 self.state.push1(res);
6653 }
6654 Operator::I16x8Ne => {
6655 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6656 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6657 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6658 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6659 let res = err!(
6660 self.builder
6661 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6662 );
6663 let res = err!(
6664 self.builder
6665 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6666 );
6667 self.state.push1(res);
6668 }
6669 Operator::I32x4Ne => {
6670 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6671 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6672 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6673 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6674 let res = err!(
6675 self.builder
6676 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6677 );
6678 let res = err!(
6679 self.builder
6680 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6681 );
6682 self.state.push1(res);
6683 }
6684 Operator::I64x2Ne => {
6685 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6686 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6687 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6688 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6689 let res = err!(
6690 self.builder
6691 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6692 );
6693 let res = err!(
6694 self.builder
6695 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6696 );
6697 self.state.push1(res);
6698 }
6699 Operator::I32LtS | Operator::I64LtS => {
6700 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6701 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6702 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6703 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6704 let cond = err!(
6705 self.builder
6706 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6707 );
6708 let res = err!(
6709 self.builder
6710 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6711 );
6712 self.state.push1_extra(
6713 res,
6714 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6715 );
6716 }
6717 Operator::I8x16LtS => {
6718 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6719 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6720 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6721 let res = err!(
6722 self.builder
6723 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6724 );
6725 let res = err!(
6726 self.builder
6727 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6728 );
6729 let res = err!(
6730 self.builder
6731 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6732 );
6733 self.state.push1(res);
6734 }
6735 Operator::I16x8LtS => {
6736 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6737 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6738 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6739 let res = err!(
6740 self.builder
6741 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6742 );
6743 let res = err!(
6744 self.builder
6745 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6746 );
6747 let res = err!(
6748 self.builder
6749 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6750 );
6751 self.state.push1(res);
6752 }
6753 Operator::I32x4LtS => {
6754 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6755 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6756 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6757 let res = err!(
6758 self.builder
6759 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6760 );
6761 let res = err!(
6762 self.builder
6763 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6764 );
6765 let res = err!(
6766 self.builder
6767 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6768 );
6769 self.state.push1(res);
6770 }
6771 Operator::I64x2LtS => {
6772 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6773 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6774 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6775 let res = err!(
6776 self.builder
6777 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6778 );
6779 let res = err!(
6780 self.builder
6781 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6782 );
6783 let res = err!(
6784 self.builder
6785 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6786 );
6787 self.state.push1(res);
6788 }
6789 Operator::I32LtU | Operator::I64LtU => {
6790 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6791 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6792 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6793 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6794 let cond = err!(
6795 self.builder
6796 .build_int_compare(IntPredicate::ULT, v1, v2, "")
6797 );
6798 let res = err!(
6799 self.builder
6800 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6801 );
6802 self.state.push1(res);
6803 }
6804 Operator::I8x16LtU => {
6805 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6806 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6807 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6808 let res = err!(
6809 self.builder
6810 .build_int_compare(IntPredicate::ULT, v1, v2, "")
6811 );
6812 let res = err!(
6813 self.builder
6814 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6815 );
6816 let res = err!(
6817 self.builder
6818 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6819 );
6820 self.state.push1(res);
6821 }
6822 Operator::I16x8LtU => {
6823 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6824 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6825 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6826 let res = err!(
6827 self.builder
6828 .build_int_compare(IntPredicate::ULT, v1, v2, "")
6829 );
6830 let res = err!(
6831 self.builder
6832 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6833 );
6834 let res = err!(
6835 self.builder
6836 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6837 );
6838 self.state.push1(res);
6839 }
6840 Operator::I32x4LtU => {
6841 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6842 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6843 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6844 let res = err!(
6845 self.builder
6846 .build_int_compare(IntPredicate::ULT, v1, v2, "")
6847 );
6848 let res = err!(
6849 self.builder
6850 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6851 );
6852 let res = err!(
6853 self.builder
6854 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6855 );
6856 self.state.push1(res);
6857 }
6858 Operator::I32LeS | Operator::I64LeS => {
6859 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6860 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6861 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6862 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6863 let cond = err!(
6864 self.builder
6865 .build_int_compare(IntPredicate::SLE, v1, v2, "")
6866 );
6867 let res = err!(
6868 self.builder
6869 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6870 );
6871 self.state.push1_extra(
6872 res,
6873 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6874 );
6875 }
6876 Operator::I8x16LeS => {
6877 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6878 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6879 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6880 let res = err!(
6881 self.builder
6882 .build_int_compare(IntPredicate::SLE, v1, v2, "")
6883 );
6884 let res = err!(
6885 self.builder
6886 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6887 );
6888 let res = err!(
6889 self.builder
6890 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6891 );
6892 self.state.push1(res);
6893 }
6894 Operator::I16x8LeS => {
6895 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6896 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6897 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6898 let res = err!(
6899 self.builder
6900 .build_int_compare(IntPredicate::SLE, v1, v2, "")
6901 );
6902 let res = err!(
6903 self.builder
6904 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6905 );
6906 let res = err!(
6907 self.builder
6908 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6909 );
6910 self.state.push1(res);
6911 }
6912 Operator::I32x4LeS => {
6913 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6914 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6915 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6916 let res = err!(
6917 self.builder
6918 .build_int_compare(IntPredicate::SLE, v1, v2, "")
6919 );
6920 let res = err!(
6921 self.builder
6922 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6923 );
6924 let res = err!(
6925 self.builder
6926 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6927 );
6928 self.state.push1(res);
6929 }
6930 Operator::I64x2LeS => {
6931 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6932 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6933 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6934 let res = err!(
6935 self.builder
6936 .build_int_compare(IntPredicate::SLE, v1, v2, "")
6937 );
6938 let res = err!(
6939 self.builder
6940 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6941 );
6942 let res = err!(
6943 self.builder
6944 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6945 );
6946 self.state.push1(res);
6947 }
6948 Operator::I32LeU | Operator::I64LeU => {
6949 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6950 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6951 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6952 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6953 let cond = err!(
6954 self.builder
6955 .build_int_compare(IntPredicate::ULE, v1, v2, "")
6956 );
6957 let res = err!(
6958 self.builder
6959 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6960 );
6961 self.state.push1_extra(
6962 res,
6963 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6964 );
6965 }
6966 Operator::I8x16LeU => {
6967 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6968 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6969 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6970 let res = err!(
6971 self.builder
6972 .build_int_compare(IntPredicate::ULE, v1, v2, "")
6973 );
6974 let res = err!(
6975 self.builder
6976 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6977 );
6978 let res = err!(
6979 self.builder
6980 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6981 );
6982 self.state.push1(res);
6983 }
6984 Operator::I16x8LeU => {
6985 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6986 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6987 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6988 let res = err!(
6989 self.builder
6990 .build_int_compare(IntPredicate::ULE, v1, v2, "")
6991 );
6992 let res = err!(
6993 self.builder
6994 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6995 );
6996 let res = err!(
6997 self.builder
6998 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6999 );
7000 self.state.push1(res);
7001 }
7002 Operator::I32x4LeU => {
7003 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7004 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7005 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7006 let res = err!(
7007 self.builder
7008 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7009 );
7010 let res = err!(
7011 self.builder
7012 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7013 );
7014 let res = err!(
7015 self.builder
7016 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7017 );
7018 self.state.push1(res);
7019 }
7020 Operator::I32GtS | Operator::I64GtS => {
7021 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7022 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7023 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7024 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7025 let cond = err!(
7026 self.builder
7027 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7028 );
7029 let res = err!(
7030 self.builder
7031 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7032 );
7033 self.state.push1_extra(
7034 res,
7035 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7036 );
7037 }
7038 Operator::I8x16GtS => {
7039 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7040 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7041 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7042 let res = err!(
7043 self.builder
7044 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7045 );
7046 let res = err!(
7047 self.builder
7048 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7049 );
7050 let res = err!(
7051 self.builder
7052 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7053 );
7054 self.state.push1(res);
7055 }
7056 Operator::I16x8GtS => {
7057 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7058 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7059 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7060 let res = err!(
7061 self.builder
7062 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7063 );
7064 let res = err!(
7065 self.builder
7066 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7067 );
7068 let res = err!(
7069 self.builder
7070 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7071 );
7072 self.state.push1(res);
7073 }
7074 Operator::I32x4GtS => {
7075 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7076 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7077 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7078 let res = err!(
7079 self.builder
7080 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7081 );
7082 let res = err!(
7083 self.builder
7084 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7085 );
7086 let res = err!(
7087 self.builder
7088 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7089 );
7090 self.state.push1(res);
7091 }
7092 Operator::I64x2GtS => {
7093 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7094 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7095 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7096 let res = err!(
7097 self.builder
7098 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7099 );
7100 let res = err!(
7101 self.builder
7102 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7103 );
7104 let res = err!(
7105 self.builder
7106 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7107 );
7108 self.state.push1(res);
7109 }
7110 Operator::I32GtU | Operator::I64GtU => {
7111 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7112 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7113 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7114 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7115 let cond = err!(
7116 self.builder
7117 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7118 );
7119 let res = err!(
7120 self.builder
7121 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7122 );
7123 self.state.push1_extra(
7124 res,
7125 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7126 );
7127 }
7128 Operator::I8x16GtU => {
7129 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7130 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7131 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7132 let res = err!(
7133 self.builder
7134 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7135 );
7136 let res = err!(
7137 self.builder
7138 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7139 );
7140 let res = err!(
7141 self.builder
7142 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7143 );
7144 self.state.push1(res);
7145 }
7146 Operator::I16x8GtU => {
7147 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7148 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7149 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7150 let res = err!(
7151 self.builder
7152 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7153 );
7154 let res = err!(
7155 self.builder
7156 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7157 );
7158 let res = err!(
7159 self.builder
7160 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7161 );
7162 self.state.push1(res);
7163 }
7164 Operator::I32x4GtU => {
7165 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7166 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7167 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7168 let res = err!(
7169 self.builder
7170 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7171 );
7172 let res = err!(
7173 self.builder
7174 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7175 );
7176 let res = err!(
7177 self.builder
7178 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7179 );
7180 self.state.push1(res);
7181 }
7182 Operator::I32GeS | Operator::I64GeS => {
7183 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7184 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7185 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7186 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7187 let cond = err!(
7188 self.builder
7189 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7190 );
7191 let res = err!(
7192 self.builder
7193 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7194 );
7195 self.state.push1(res);
7196 }
7197 Operator::I8x16GeS => {
7198 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7199 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7200 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7201 let res = err!(
7202 self.builder
7203 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7204 );
7205 let res = err!(
7206 self.builder
7207 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7208 );
7209 let res = err!(
7210 self.builder
7211 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7212 );
7213 self.state.push1(res);
7214 }
7215 Operator::I16x8GeS => {
7216 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7217 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7218 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7219 let res = err!(
7220 self.builder
7221 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7222 );
7223 let res = err!(
7224 self.builder
7225 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7226 );
7227 let res = err!(
7228 self.builder
7229 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7230 );
7231 self.state.push1(res);
7232 }
7233 Operator::I32x4GeS => {
7234 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7235 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7236 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7237 let res = err!(
7238 self.builder
7239 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7240 );
7241 let res = err!(
7242 self.builder
7243 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7244 );
7245 let res = err!(
7246 self.builder
7247 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7248 );
7249 self.state.push1(res);
7250 }
7251 Operator::I64x2GeS => {
7252 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7253 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7254 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7255 let res = err!(
7256 self.builder
7257 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7258 );
7259 let res = err!(
7260 self.builder
7261 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7262 );
7263 let res = err!(
7264 self.builder
7265 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7266 );
7267 self.state.push1(res);
7268 }
7269 Operator::I32GeU | Operator::I64GeU => {
7270 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7271 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7272 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7273 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7274 let cond = err!(
7275 self.builder
7276 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7277 );
7278 let res = err!(
7279 self.builder
7280 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7281 );
7282 self.state.push1_extra(
7283 res,
7284 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7285 );
7286 }
7287 Operator::I8x16GeU => {
7288 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7289 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7290 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7291 let res = err!(
7292 self.builder
7293 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7294 );
7295 let res = err!(
7296 self.builder
7297 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7298 );
7299 let res = err!(
7300 self.builder
7301 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7302 );
7303 self.state.push1(res);
7304 }
7305 Operator::I16x8GeU => {
7306 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7307 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7308 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7309 let res = err!(
7310 self.builder
7311 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7312 );
7313 let res = err!(
7314 self.builder
7315 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7316 );
7317 let res = err!(
7318 self.builder
7319 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7320 );
7321 self.state.push1(res);
7322 }
7323 Operator::I32x4GeU => {
7324 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7325 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7326 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7327 let res = err!(
7328 self.builder
7329 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7330 );
7331 let res = err!(
7332 self.builder
7333 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7334 );
7335 let res = err!(
7336 self.builder
7337 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7338 );
7339 self.state.push1(res);
7340 }
7341
7342 Operator::F32Eq | Operator::F64Eq => {
7347 let (v1, v2) = self.state.pop2()?;
7348 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7349 let cond = err!(
7350 self.builder
7351 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7352 );
7353 let res = err!(
7354 self.builder
7355 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7356 );
7357 self.state.push1_extra(
7358 res,
7359 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7360 );
7361 }
7362 Operator::F32x4Eq => {
7363 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7364 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7365 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7366 let res = err!(
7367 self.builder
7368 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7369 );
7370 let res = err!(
7371 self.builder
7372 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7373 );
7374 let res = err!(
7375 self.builder
7376 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7377 );
7378 self.state.push1(res);
7379 }
7380 Operator::F64x2Eq => {
7381 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7382 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7383 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7384 let res = err!(
7385 self.builder
7386 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7387 );
7388 let res = err!(
7389 self.builder
7390 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7391 );
7392 let res = err!(
7393 self.builder
7394 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7395 );
7396 self.state.push1(res);
7397 }
7398 Operator::F32Ne | Operator::F64Ne => {
7399 let (v1, v2) = self.state.pop2()?;
7400 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7401 let cond = err!(
7402 self.builder
7403 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7404 );
7405 let res = err!(
7406 self.builder
7407 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7408 );
7409 self.state.push1_extra(
7410 res,
7411 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7412 );
7413 }
7414 Operator::F32x4Ne => {
7415 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7416 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7417 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7418 let res = err!(
7419 self.builder
7420 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7421 );
7422 let res = err!(
7423 self.builder
7424 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7425 );
7426 let res = err!(
7427 self.builder
7428 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7429 );
7430 self.state.push1(res);
7431 }
7432 Operator::F64x2Ne => {
7433 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7434 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7435 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7436 let res = err!(
7437 self.builder
7438 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7439 );
7440 let res = err!(
7441 self.builder
7442 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7443 );
7444 let res = err!(
7445 self.builder
7446 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7447 );
7448 self.state.push1(res);
7449 }
7450 Operator::F32Lt | Operator::F64Lt => {
7451 let (v1, v2) = self.state.pop2()?;
7452 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7453 let cond = err!(
7454 self.builder
7455 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7456 );
7457 let res = err!(
7458 self.builder
7459 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7460 );
7461 self.state.push1_extra(
7462 res,
7463 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7464 );
7465 }
7466 Operator::F32x4Lt => {
7467 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7468 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7469 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7470 let res = err!(
7471 self.builder
7472 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7473 );
7474 let res = err!(
7475 self.builder
7476 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7477 );
7478 let res = err!(
7479 self.builder
7480 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7481 );
7482 self.state.push1(res);
7483 }
7484 Operator::F64x2Lt => {
7485 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7486 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7487 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7488 let res = err!(
7489 self.builder
7490 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7491 );
7492 let res = err!(
7493 self.builder
7494 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7495 );
7496 let res = err!(
7497 self.builder
7498 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7499 );
7500 self.state.push1(res);
7501 }
7502 Operator::F32Le | Operator::F64Le => {
7503 let (v1, v2) = self.state.pop2()?;
7504 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7505 let cond = err!(
7506 self.builder
7507 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7508 );
7509 let res = err!(
7510 self.builder
7511 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7512 );
7513 self.state.push1_extra(
7514 res,
7515 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7516 );
7517 }
7518 Operator::F32x4Le => {
7519 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7520 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7521 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7522 let res = err!(
7523 self.builder
7524 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7525 );
7526 let res = err!(
7527 self.builder
7528 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7529 );
7530 let res = err!(
7531 self.builder
7532 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7533 );
7534 self.state.push1(res);
7535 }
7536 Operator::F64x2Le => {
7537 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7538 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7539 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7540 let res = err!(
7541 self.builder
7542 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7543 );
7544 let res = err!(
7545 self.builder
7546 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7547 );
7548 let res = err!(
7549 self.builder
7550 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7551 );
7552 self.state.push1(res);
7553 }
7554 Operator::F32Gt | Operator::F64Gt => {
7555 let (v1, v2) = self.state.pop2()?;
7556 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7557 let cond = err!(
7558 self.builder
7559 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7560 );
7561 let res = err!(
7562 self.builder
7563 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7564 );
7565 self.state.push1_extra(
7566 res,
7567 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7568 );
7569 }
7570 Operator::F32x4Gt => {
7571 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7572 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7573 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7574 let res = err!(
7575 self.builder
7576 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7577 );
7578 let res = err!(
7579 self.builder
7580 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7581 );
7582 let res = err!(
7583 self.builder
7584 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7585 );
7586 self.state.push1(res);
7587 }
7588 Operator::F64x2Gt => {
7589 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7590 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7591 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7592 let res = err!(
7593 self.builder
7594 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7595 );
7596 let res = err!(
7597 self.builder
7598 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7599 );
7600 let res = err!(
7601 self.builder
7602 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7603 );
7604 self.state.push1(res);
7605 }
7606 Operator::F32Ge | Operator::F64Ge => {
7607 let (v1, v2) = self.state.pop2()?;
7608 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7609 let cond = err!(
7610 self.builder
7611 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7612 );
7613 let res = err!(
7614 self.builder
7615 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7616 );
7617 self.state.push1_extra(
7618 res,
7619 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7620 );
7621 }
7622 Operator::F32x4Ge => {
7623 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7624 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7625 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7626 let res = err!(
7627 self.builder
7628 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7629 );
7630 let res = err!(
7631 self.builder
7632 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7633 );
7634 let res = err!(
7635 self.builder
7636 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7637 );
7638 self.state.push1(res);
7639 }
7640 Operator::F64x2Ge => {
7641 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7642 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7643 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7644 let res = err!(
7645 self.builder
7646 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7647 );
7648 let res = err!(
7649 self.builder
7650 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7651 );
7652 let res = err!(
7653 self.builder
7654 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7655 );
7656 self.state.push1(res);
7657 }
7658
7659 Operator::I32WrapI64 => {
7664 let (v, i) = self.state.pop1_extra()?;
7665 let v = self.apply_pending_canonicalization(v, i)?;
7666 let v = v.into_int_value();
7667 let res = err!(
7668 self.builder
7669 .build_int_truncate(v, self.intrinsics.i32_ty, "")
7670 );
7671 self.state.push1(res);
7672 }
7673 Operator::I64ExtendI32S => {
7674 let (v, i) = self.state.pop1_extra()?;
7675 let v = self.apply_pending_canonicalization(v, i)?;
7676 let v = v.into_int_value();
7677 let res = err!(
7678 self.builder
7679 .build_int_s_extend(v, self.intrinsics.i64_ty, "")
7680 );
7681 self.state.push1(res);
7682 }
7683 Operator::I64ExtendI32U => {
7684 let (v, i) = self.state.pop1_extra()?;
7685 let v = self.apply_pending_canonicalization(v, i)?;
7686 let v = v.into_int_value();
7687 let res = err!(
7688 self.builder
7689 .build_int_z_extend(v, self.intrinsics.i64_ty, "")
7690 );
7691 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
7692 }
7693 Operator::I16x8ExtendLowI8x16S => {
7694 let (v, i) = self.state.pop1_extra()?;
7695 let (v, _) = self.v128_into_i8x16(v, i)?;
7696 let low = err!(self.builder.build_shuffle_vector(
7697 v,
7698 v.get_type().get_undef(),
7699 VectorType::const_vector(&[
7700 self.intrinsics.i32_consts[0],
7701 self.intrinsics.i32_consts[1],
7702 self.intrinsics.i32_consts[2],
7703 self.intrinsics.i32_consts[3],
7704 self.intrinsics.i32_consts[4],
7705 self.intrinsics.i32_consts[5],
7706 self.intrinsics.i32_consts[6],
7707 self.intrinsics.i32_consts[7],
7708 ]),
7709 "",
7710 ));
7711 let res = err!(
7712 self.builder
7713 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7714 );
7715 let res = err!(
7716 self.builder
7717 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7718 );
7719 self.state.push1(res);
7720 }
7721 Operator::I16x8ExtendHighI8x16S => {
7722 let (v, i) = self.state.pop1_extra()?;
7723 let (v, _) = self.v128_into_i8x16(v, i)?;
7724 let low = err!(self.builder.build_shuffle_vector(
7725 v,
7726 v.get_type().get_undef(),
7727 VectorType::const_vector(&[
7728 self.intrinsics.i32_consts[8],
7729 self.intrinsics.i32_consts[9],
7730 self.intrinsics.i32_consts[10],
7731 self.intrinsics.i32_consts[11],
7732 self.intrinsics.i32_consts[12],
7733 self.intrinsics.i32_consts[13],
7734 self.intrinsics.i32_consts[14],
7735 self.intrinsics.i32_consts[15],
7736 ]),
7737 "",
7738 ));
7739 let res = err!(
7740 self.builder
7741 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7742 );
7743 let res = err!(
7744 self.builder
7745 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7746 );
7747 self.state.push1(res);
7748 }
7749 Operator::I16x8ExtendLowI8x16U => {
7750 let (v, i) = self.state.pop1_extra()?;
7751 let (v, _) = self.v128_into_i8x16(v, i)?;
7752 let low = err!(self.builder.build_shuffle_vector(
7753 v,
7754 v.get_type().get_undef(),
7755 VectorType::const_vector(&[
7756 self.intrinsics.i32_consts[0],
7757 self.intrinsics.i32_consts[1],
7758 self.intrinsics.i32_consts[2],
7759 self.intrinsics.i32_consts[3],
7760 self.intrinsics.i32_consts[4],
7761 self.intrinsics.i32_consts[5],
7762 self.intrinsics.i32_consts[6],
7763 self.intrinsics.i32_consts[7],
7764 ]),
7765 "",
7766 ));
7767 let res = err!(
7768 self.builder
7769 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
7770 );
7771 let res = err!(
7772 self.builder
7773 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7774 );
7775 self.state.push1(res);
7776 }
7777 Operator::I16x8ExtendHighI8x16U => {
7778 let (v, i) = self.state.pop1_extra()?;
7779 let (v, _) = self.v128_into_i8x16(v, i)?;
7780 let low = err!(self.builder.build_shuffle_vector(
7781 v,
7782 v.get_type().get_undef(),
7783 VectorType::const_vector(&[
7784 self.intrinsics.i32_consts[8],
7785 self.intrinsics.i32_consts[9],
7786 self.intrinsics.i32_consts[10],
7787 self.intrinsics.i32_consts[11],
7788 self.intrinsics.i32_consts[12],
7789 self.intrinsics.i32_consts[13],
7790 self.intrinsics.i32_consts[14],
7791 self.intrinsics.i32_consts[15],
7792 ]),
7793 "",
7794 ));
7795 let res = err!(
7796 self.builder
7797 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
7798 );
7799 let res = err!(
7800 self.builder
7801 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7802 );
7803 self.state.push1(res);
7804 }
7805 Operator::I32x4ExtendLowI16x8S => {
7806 let (v, i) = self.state.pop1_extra()?;
7807 let (v, _) = self.v128_into_i16x8(v, i)?;
7808 let low = err!(self.builder.build_shuffle_vector(
7809 v,
7810 v.get_type().get_undef(),
7811 VectorType::const_vector(&[
7812 self.intrinsics.i32_consts[0],
7813 self.intrinsics.i32_consts[1],
7814 self.intrinsics.i32_consts[2],
7815 self.intrinsics.i32_consts[3],
7816 ]),
7817 "",
7818 ));
7819 let res = err!(
7820 self.builder
7821 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
7822 );
7823 let res = err!(
7824 self.builder
7825 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7826 );
7827 self.state.push1(res);
7828 }
7829 Operator::I32x4ExtendHighI16x8S => {
7830 let (v, i) = self.state.pop1_extra()?;
7831 let (v, _) = self.v128_into_i16x8(v, i)?;
7832 let low = err!(self.builder.build_shuffle_vector(
7833 v,
7834 v.get_type().get_undef(),
7835 VectorType::const_vector(&[
7836 self.intrinsics.i32_consts[4],
7837 self.intrinsics.i32_consts[5],
7838 self.intrinsics.i32_consts[6],
7839 self.intrinsics.i32_consts[7],
7840 ]),
7841 "",
7842 ));
7843 let res = err!(
7844 self.builder
7845 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
7846 );
7847 let res = err!(
7848 self.builder
7849 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7850 );
7851 self.state.push1(res);
7852 }
7853 Operator::I32x4ExtendLowI16x8U => {
7854 let (v, i) = self.state.pop1_extra()?;
7855 let (v, _) = self.v128_into_i16x8(v, i)?;
7856 let low = err!(self.builder.build_shuffle_vector(
7857 v,
7858 v.get_type().get_undef(),
7859 VectorType::const_vector(&[
7860 self.intrinsics.i32_consts[0],
7861 self.intrinsics.i32_consts[1],
7862 self.intrinsics.i32_consts[2],
7863 self.intrinsics.i32_consts[3],
7864 ]),
7865 "",
7866 ));
7867 let res = err!(
7868 self.builder
7869 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
7870 );
7871 let res = err!(
7872 self.builder
7873 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7874 );
7875 self.state.push1(res);
7876 }
7877 Operator::I32x4ExtendHighI16x8U => {
7878 let (v, i) = self.state.pop1_extra()?;
7879 let (v, _) = self.v128_into_i16x8(v, i)?;
7880 let low = err!(self.builder.build_shuffle_vector(
7881 v,
7882 v.get_type().get_undef(),
7883 VectorType::const_vector(&[
7884 self.intrinsics.i32_consts[4],
7885 self.intrinsics.i32_consts[5],
7886 self.intrinsics.i32_consts[6],
7887 self.intrinsics.i32_consts[7],
7888 ]),
7889 "",
7890 ));
7891 let res = err!(
7892 self.builder
7893 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
7894 );
7895 let res = err!(
7896 self.builder
7897 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7898 );
7899 self.state.push1(res);
7900 }
7901 Operator::I64x2ExtendLowI32x4U
7902 | Operator::I64x2ExtendLowI32x4S
7903 | Operator::I64x2ExtendHighI32x4U
7904 | Operator::I64x2ExtendHighI32x4S => {
7905 let extend = match op {
7906 Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
7907 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
7908 }
7909 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
7910 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
7911 }
7912 _ => unreachable!("Unhandled inner case"),
7913 };
7914 let indices = match op {
7915 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
7916 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
7917 }
7918 Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
7919 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
7920 }
7921 _ => unreachable!("Unhandled inner case"),
7922 };
7923 let (v, i) = self.state.pop1_extra()?;
7924 let (v, _) = self.v128_into_i32x4(v, i)?;
7925 let low = err!(self.builder.build_shuffle_vector(
7926 v,
7927 v.get_type().get_undef(),
7928 VectorType::const_vector(&indices),
7929 "",
7930 ));
7931 let res = err!(extend(self, low));
7932 let res = err!(
7933 self.builder
7934 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7935 );
7936 self.state.push1(res);
7937 }
7938 Operator::I8x16NarrowI16x8S => {
7939 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7940 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7941 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7942 let min = self.intrinsics.i16_ty.const_int(0xff80, false);
7943 let max = self.intrinsics.i16_ty.const_int(0x007f, false);
7944 let min = VectorType::const_vector(&[min; 8]);
7945 let max = VectorType::const_vector(&[max; 8]);
7946 let apply_min_clamp_v1 =
7947 err!(
7948 self.builder
7949 .build_int_compare(IntPredicate::SLT, v1, min, "")
7950 );
7951 let apply_max_clamp_v1 =
7952 err!(
7953 self.builder
7954 .build_int_compare(IntPredicate::SGT, v1, max, "")
7955 );
7956 let apply_min_clamp_v2 =
7957 err!(
7958 self.builder
7959 .build_int_compare(IntPredicate::SLT, v2, min, "")
7960 );
7961 let apply_max_clamp_v2 =
7962 err!(
7963 self.builder
7964 .build_int_compare(IntPredicate::SGT, v2, max, "")
7965 );
7966 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
7967 .into_vector_value();
7968 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
7969 .into_vector_value();
7970 let v1 = err!(self.builder.build_int_truncate(
7971 v1,
7972 self.intrinsics.i8_ty.vec_type(8),
7973 ""
7974 ));
7975 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
7976 .into_vector_value();
7977 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
7978 .into_vector_value();
7979 let v2 = err!(self.builder.build_int_truncate(
7980 v2,
7981 self.intrinsics.i8_ty.vec_type(8),
7982 ""
7983 ));
7984 let res = err!(self.builder.build_shuffle_vector(
7985 v1,
7986 v2,
7987 VectorType::const_vector(&[
7988 self.intrinsics.i32_consts[0],
7989 self.intrinsics.i32_consts[1],
7990 self.intrinsics.i32_consts[2],
7991 self.intrinsics.i32_consts[3],
7992 self.intrinsics.i32_consts[4],
7993 self.intrinsics.i32_consts[5],
7994 self.intrinsics.i32_consts[6],
7995 self.intrinsics.i32_consts[7],
7996 self.intrinsics.i32_consts[8],
7997 self.intrinsics.i32_consts[9],
7998 self.intrinsics.i32_consts[10],
7999 self.intrinsics.i32_consts[11],
8000 self.intrinsics.i32_consts[12],
8001 self.intrinsics.i32_consts[13],
8002 self.intrinsics.i32_consts[14],
8003 self.intrinsics.i32_consts[15],
8004 ]),
8005 "",
8006 ));
8007 let res = err!(
8008 self.builder
8009 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8010 );
8011 self.state.push1(res);
8012 }
8013 Operator::I8x16NarrowI16x8U => {
8014 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8015 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8016 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8017 let min = self.intrinsics.i16x8_ty.const_zero();
8018 let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8019 let max = VectorType::const_vector(&[max; 8]);
8020 let apply_min_clamp_v1 =
8021 err!(
8022 self.builder
8023 .build_int_compare(IntPredicate::SLT, v1, min, "")
8024 );
8025 let apply_max_clamp_v1 =
8026 err!(
8027 self.builder
8028 .build_int_compare(IntPredicate::SGT, v1, max, "")
8029 );
8030 let apply_min_clamp_v2 =
8031 err!(
8032 self.builder
8033 .build_int_compare(IntPredicate::SLT, v2, min, "")
8034 );
8035 let apply_max_clamp_v2 =
8036 err!(
8037 self.builder
8038 .build_int_compare(IntPredicate::SGT, v2, max, "")
8039 );
8040 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8041 .into_vector_value();
8042 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8043 .into_vector_value();
8044 let v1 = err!(self.builder.build_int_truncate(
8045 v1,
8046 self.intrinsics.i8_ty.vec_type(8),
8047 ""
8048 ));
8049 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8050 .into_vector_value();
8051 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8052 .into_vector_value();
8053 let v2 = err!(self.builder.build_int_truncate(
8054 v2,
8055 self.intrinsics.i8_ty.vec_type(8),
8056 ""
8057 ));
8058 let res = err!(self.builder.build_shuffle_vector(
8059 v1,
8060 v2,
8061 VectorType::const_vector(&[
8062 self.intrinsics.i32_consts[0],
8063 self.intrinsics.i32_consts[1],
8064 self.intrinsics.i32_consts[2],
8065 self.intrinsics.i32_consts[3],
8066 self.intrinsics.i32_consts[4],
8067 self.intrinsics.i32_consts[5],
8068 self.intrinsics.i32_consts[6],
8069 self.intrinsics.i32_consts[7],
8070 self.intrinsics.i32_consts[8],
8071 self.intrinsics.i32_consts[9],
8072 self.intrinsics.i32_consts[10],
8073 self.intrinsics.i32_consts[11],
8074 self.intrinsics.i32_consts[12],
8075 self.intrinsics.i32_consts[13],
8076 self.intrinsics.i32_consts[14],
8077 self.intrinsics.i32_consts[15],
8078 ]),
8079 "",
8080 ));
8081 let res = err!(
8082 self.builder
8083 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8084 );
8085 self.state.push1(res);
8086 }
8087 Operator::I16x8NarrowI32x4S => {
8088 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8089 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8090 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8091 let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8092 let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8093 let min = VectorType::const_vector(&[min; 4]);
8094 let max = VectorType::const_vector(&[max; 4]);
8095 let apply_min_clamp_v1 =
8096 err!(
8097 self.builder
8098 .build_int_compare(IntPredicate::SLT, v1, min, "")
8099 );
8100 let apply_max_clamp_v1 =
8101 err!(
8102 self.builder
8103 .build_int_compare(IntPredicate::SGT, v1, max, "")
8104 );
8105 let apply_min_clamp_v2 =
8106 err!(
8107 self.builder
8108 .build_int_compare(IntPredicate::SLT, v2, min, "")
8109 );
8110 let apply_max_clamp_v2 =
8111 err!(
8112 self.builder
8113 .build_int_compare(IntPredicate::SGT, v2, max, "")
8114 );
8115 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8116 .into_vector_value();
8117 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8118 .into_vector_value();
8119 let v1 = err!(self.builder.build_int_truncate(
8120 v1,
8121 self.intrinsics.i16_ty.vec_type(4),
8122 ""
8123 ));
8124 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8125 .into_vector_value();
8126 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8127 .into_vector_value();
8128 let v2 = err!(self.builder.build_int_truncate(
8129 v2,
8130 self.intrinsics.i16_ty.vec_type(4),
8131 ""
8132 ));
8133 let res = err!(self.builder.build_shuffle_vector(
8134 v1,
8135 v2,
8136 VectorType::const_vector(&[
8137 self.intrinsics.i32_consts[0],
8138 self.intrinsics.i32_consts[1],
8139 self.intrinsics.i32_consts[2],
8140 self.intrinsics.i32_consts[3],
8141 self.intrinsics.i32_consts[4],
8142 self.intrinsics.i32_consts[5],
8143 self.intrinsics.i32_consts[6],
8144 self.intrinsics.i32_consts[7],
8145 ]),
8146 "",
8147 ));
8148 let res = err!(
8149 self.builder
8150 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8151 );
8152 self.state.push1(res);
8153 }
8154 Operator::I16x8NarrowI32x4U => {
8155 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8156 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8157 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8158 let min = self.intrinsics.i32x4_ty.const_zero();
8159 let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8160 let max = VectorType::const_vector(&[max; 4]);
8161 let apply_min_clamp_v1 =
8162 err!(
8163 self.builder
8164 .build_int_compare(IntPredicate::SLT, v1, min, "")
8165 );
8166 let apply_max_clamp_v1 =
8167 err!(
8168 self.builder
8169 .build_int_compare(IntPredicate::SGT, v1, max, "")
8170 );
8171 let apply_min_clamp_v2 =
8172 err!(
8173 self.builder
8174 .build_int_compare(IntPredicate::SLT, v2, min, "")
8175 );
8176 let apply_max_clamp_v2 =
8177 err!(
8178 self.builder
8179 .build_int_compare(IntPredicate::SGT, v2, max, "")
8180 );
8181 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8182 .into_vector_value();
8183 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8184 .into_vector_value();
8185 let v1 = err!(self.builder.build_int_truncate(
8186 v1,
8187 self.intrinsics.i16_ty.vec_type(4),
8188 ""
8189 ));
8190 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8191 .into_vector_value();
8192 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8193 .into_vector_value();
8194 let v2 = err!(self.builder.build_int_truncate(
8195 v2,
8196 self.intrinsics.i16_ty.vec_type(4),
8197 ""
8198 ));
8199 let res = err!(self.builder.build_shuffle_vector(
8200 v1,
8201 v2,
8202 VectorType::const_vector(&[
8203 self.intrinsics.i32_consts[0],
8204 self.intrinsics.i32_consts[1],
8205 self.intrinsics.i32_consts[2],
8206 self.intrinsics.i32_consts[3],
8207 self.intrinsics.i32_consts[4],
8208 self.intrinsics.i32_consts[5],
8209 self.intrinsics.i32_consts[6],
8210 self.intrinsics.i32_consts[7],
8211 ]),
8212 "",
8213 ));
8214 let res = err!(
8215 self.builder
8216 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8217 );
8218 self.state.push1(res);
8219 }
8220 Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8221 let (v, i) = self.state.pop1_extra()?;
8222 let (v, _) = self.v128_into_f32x4(v, i)?;
8223 let res = self
8224 .build_call_with_param_attributes(
8225 self.intrinsics.x86_64.cvttps2dq,
8226 &[v.into()],
8227 "",
8228 )?
8229 .try_as_basic_value()
8230 .unwrap_basic();
8231 let res = err!(
8232 self.builder
8233 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8234 );
8235 self.state.push1(res);
8236 }
8237 Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
8238 let (v, i) = self.state.pop1_extra()?;
8239 let v = self.apply_pending_canonicalization(v, i)?;
8240 let v = v.into_int_value();
8241 let res = self.trunc_sat_into_int(
8242 self.intrinsics.f32x4_ty,
8243 self.intrinsics.i32x4_ty,
8244 LEF32_GEQ_I32_MIN,
8245 GEF32_LEQ_I32_MAX,
8246 i32::MIN as u64,
8247 i32::MAX as u64,
8248 v,
8249 )?;
8250 self.state.push1(res);
8251 }
8252 Operator::I32x4RelaxedTruncF32x4U
8253 if self.cpu_features.contains(CpuFeature::AVX512F)
8254 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8255 {
8256 let (v, i) = self.state.pop1_extra()?;
8257 let (v, _) = self.v128_into_f32x4(v, i)?;
8258 let res = self
8259 .build_call_with_param_attributes(
8260 self.intrinsics.x86_64.cvtps2udq128,
8261 &[
8262 v.into(),
8263 self.intrinsics.i32x4_ty.const_zero().into(),
8264 self.intrinsics.i8_ty.const_int(0xff, false).into(),
8265 ],
8266 "",
8267 )?
8268 .try_as_basic_value()
8269 .unwrap_basic();
8270 let res = err!(
8271 self.builder
8272 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8273 );
8274 self.state.push1(res);
8275 }
8276 Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
8277 let (v, i) = self.state.pop1_extra()?;
8278 let v = self.apply_pending_canonicalization(v, i)?;
8279 let v = v.into_int_value();
8280 let res = self.trunc_sat_into_int(
8281 self.intrinsics.f32x4_ty,
8282 self.intrinsics.i32x4_ty,
8283 LEF32_GEQ_U32_MIN,
8284 GEF32_LEQ_U32_MAX,
8285 u32::MIN as u64,
8286 u32::MAX as u64,
8287 v,
8288 )?;
8289 self.state.push1(res);
8290 }
8291 Operator::I32x4RelaxedTruncF64x2SZero
8292 if self.cpu_features.contains(CpuFeature::SSE2) =>
8293 {
8294 let (v, i) = self.state.pop1_extra()?;
8295 let (v, _) = self.v128_into_f64x2(v, i)?;
8296 let res = self
8297 .build_call_with_param_attributes(
8298 self.intrinsics.x86_64.cvtpd2dq,
8299 &[v.into()],
8300 "",
8301 )?
8302 .try_as_basic_value()
8303 .unwrap_basic();
8304 let res = err!(
8305 self.builder
8306 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8307 );
8308 self.state.push1(res);
8309 }
8310 Operator::I32x4RelaxedTruncF64x2UZero
8311 if self.cpu_features.contains(CpuFeature::AVX512F)
8312 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8313 {
8314 let (v, i) = self.state.pop1_extra()?;
8315 let (v, _) = self.v128_into_f64x2(v, i)?;
8316 let res = self
8317 .build_call_with_param_attributes(
8318 self.intrinsics.x86_64.cvtpd2udq128,
8319 &[
8320 v.into(),
8321 self.intrinsics.i32x4_ty.const_zero().into(),
8322 self.intrinsics.i8_ty.const_int(0xff, false).into(),
8323 ],
8324 "",
8325 )?
8326 .try_as_basic_value()
8327 .unwrap_basic();
8328 let res = err!(
8329 self.builder
8330 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8331 );
8332 self.state.push1(res);
8333 }
8334 Operator::I32x4TruncSatF64x2SZero
8335 | Operator::I32x4TruncSatF64x2UZero
8336 | Operator::I32x4RelaxedTruncF64x2SZero
8337 | Operator::I32x4RelaxedTruncF64x2UZero => {
8338 let ((min, max), (cmp_min, cmp_max)) = match op {
8339 Operator::I32x4TruncSatF64x2SZero => (
8340 (i32::MIN as u64, i32::MAX as u64),
8341 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8342 ),
8343 Operator::I32x4TruncSatF64x2UZero => (
8344 (u32::MIN as u64, u32::MAX as u64),
8345 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8346 ),
8347 Operator::I32x4RelaxedTruncF64x2SZero => (
8348 (i32::MIN as u64, i32::MAX as u64),
8349 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8350 ),
8351 Operator::I32x4RelaxedTruncF64x2UZero => (
8352 (u32::MIN as u64, u32::MAX as u64),
8353 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8354 ),
8355 _ => unreachable!("Unhandled internal variant"),
8356 };
8357 let (v, i) = self.state.pop1_extra()?;
8358 let v = self.apply_pending_canonicalization(v, i)?;
8359 let v = v.into_int_value();
8360 let res = self.trunc_sat(
8361 self.intrinsics.f64x2_ty,
8362 self.intrinsics.i32_ty.vec_type(2),
8363 cmp_min,
8364 cmp_max,
8365 min,
8366 max,
8367 v,
8368 )?;
8369
8370 let zero = self.intrinsics.i32_consts[0];
8371 let zeros = VectorType::const_vector(&[zero; 2]);
8372 let res = err!(self.builder.build_shuffle_vector(
8373 res,
8374 zeros,
8375 VectorType::const_vector(&[
8376 self.intrinsics.i32_consts[0],
8377 self.intrinsics.i32_consts[1],
8378 self.intrinsics.i32_consts[2],
8379 self.intrinsics.i32_consts[3],
8380 ]),
8381 "",
8382 ));
8383 let res = err!(
8384 self.builder
8385 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8386 );
8387 self.state.push1(res);
8388 }
8389 Operator::I32TruncF32S => {
8420 let v1 = self.state.pop1()?.into_float_value();
8421 self.trap_if_not_representable_as_int(
8422 0xcf000000, 0x4effffff, v1,
8425 )?;
8426 let res = err!(self.builder.build_float_to_signed_int(
8427 v1,
8428 self.intrinsics.i32_ty,
8429 ""
8430 ));
8431 self.state.push1(res);
8432 }
8433 Operator::I32TruncF64S => {
8434 let v1 = self.state.pop1()?.into_float_value();
8435 self.trap_if_not_representable_as_int(
8436 0xc1e00000001fffff, 0x41dfffffffffffff, v1,
8439 )?;
8440 let res = err!(self.builder.build_float_to_signed_int(
8441 v1,
8442 self.intrinsics.i32_ty,
8443 ""
8444 ));
8445 self.state.push1(res);
8446 }
8447 Operator::I32TruncSatF32S => {
8448 let (v, i) = self.state.pop1_extra()?;
8449 let v = self.apply_pending_canonicalization(v, i)?;
8450 let v = v.into_float_value();
8451 let res = self.trunc_sat_scalar(
8452 self.intrinsics.i32_ty,
8453 LEF32_GEQ_I32_MIN,
8454 GEF32_LEQ_I32_MAX,
8455 i32::MIN as u32 as u64,
8456 i32::MAX as u32 as u64,
8457 v,
8458 )?;
8459 self.state.push1(res);
8460 }
8461 Operator::I32TruncSatF64S => {
8462 let (v, i) = self.state.pop1_extra()?;
8463 let v = self.apply_pending_canonicalization(v, i)?;
8464 let v = v.into_float_value();
8465 let res = self.trunc_sat_scalar(
8466 self.intrinsics.i32_ty,
8467 LEF64_GEQ_I32_MIN,
8468 GEF64_LEQ_I32_MAX,
8469 i32::MIN as u64,
8470 i32::MAX as u64,
8471 v,
8472 )?;
8473 self.state.push1(res);
8474 }
8475 Operator::I64TruncF32S => {
8476 let v1 = self.state.pop1()?.into_float_value();
8477 self.trap_if_not_representable_as_int(
8478 0xdf000000, 0x5effffff, v1,
8481 )?;
8482 let res = err!(self.builder.build_float_to_signed_int(
8483 v1,
8484 self.intrinsics.i64_ty,
8485 ""
8486 ));
8487 self.state.push1(res);
8488 }
8489 Operator::I64TruncF64S => {
8490 let v1 = self.state.pop1()?.into_float_value();
8491 self.trap_if_not_representable_as_int(
8492 0xc3e0000000000000, 0x43dfffffffffffff, v1,
8495 )?;
8496 let res = err!(self.builder.build_float_to_signed_int(
8497 v1,
8498 self.intrinsics.i64_ty,
8499 ""
8500 ));
8501 self.state.push1(res);
8502 }
8503 Operator::I64TruncSatF32S => {
8504 let (v, i) = self.state.pop1_extra()?;
8505 let v = self.apply_pending_canonicalization(v, i)?;
8506 let v = v.into_float_value();
8507 let res = self.trunc_sat_scalar(
8508 self.intrinsics.i64_ty,
8509 LEF32_GEQ_I64_MIN,
8510 GEF32_LEQ_I64_MAX,
8511 i64::MIN as u64,
8512 i64::MAX as u64,
8513 v,
8514 )?;
8515 self.state.push1(res);
8516 }
8517 Operator::I64TruncSatF64S => {
8518 let (v, i) = self.state.pop1_extra()?;
8519 let v = self.apply_pending_canonicalization(v, i)?;
8520 let v = v.into_float_value();
8521 let res = self.trunc_sat_scalar(
8522 self.intrinsics.i64_ty,
8523 LEF64_GEQ_I64_MIN,
8524 GEF64_LEQ_I64_MAX,
8525 i64::MIN as u64,
8526 i64::MAX as u64,
8527 v,
8528 )?;
8529 self.state.push1(res);
8530 }
8531 Operator::I32TruncF32U => {
8532 let v1 = self.state.pop1()?.into_float_value();
8533 self.trap_if_not_representable_as_int(
8534 0xbf7fffff, 0x4f7fffff, v1,
8537 )?;
8538 let res = err!(self.builder.build_float_to_unsigned_int(
8539 v1,
8540 self.intrinsics.i32_ty,
8541 ""
8542 ));
8543 self.state.push1(res);
8544 }
8545 Operator::I32TruncF64U => {
8546 let v1 = self.state.pop1()?.into_float_value();
8547 self.trap_if_not_representable_as_int(
8548 0xbfefffffffffffff, 0x41efffffffffffff, v1,
8551 )?;
8552 let res = err!(self.builder.build_float_to_unsigned_int(
8553 v1,
8554 self.intrinsics.i32_ty,
8555 ""
8556 ));
8557 self.state.push1(res);
8558 }
8559 Operator::I32TruncSatF32U => {
8560 let (v, i) = self.state.pop1_extra()?;
8561 let v = self.apply_pending_canonicalization(v, i)?;
8562 let v = v.into_float_value();
8563 let res = self.trunc_sat_scalar(
8564 self.intrinsics.i32_ty,
8565 LEF32_GEQ_U32_MIN,
8566 GEF32_LEQ_U32_MAX,
8567 u32::MIN as u64,
8568 u32::MAX as u64,
8569 v,
8570 )?;
8571 self.state.push1(res);
8572 }
8573 Operator::I32TruncSatF64U => {
8574 let (v, i) = self.state.pop1_extra()?;
8575 let v = self.apply_pending_canonicalization(v, i)?;
8576 let v = v.into_float_value();
8577 let res = self.trunc_sat_scalar(
8578 self.intrinsics.i32_ty,
8579 LEF64_GEQ_U32_MIN,
8580 GEF64_LEQ_U32_MAX,
8581 u32::MIN as u64,
8582 u32::MAX as u64,
8583 v,
8584 )?;
8585 self.state.push1(res);
8586 }
8587 Operator::I64TruncF32U => {
8588 let v1 = self.state.pop1()?.into_float_value();
8589 self.trap_if_not_representable_as_int(
8590 0xbf7fffff, 0x5f7fffff, v1,
8593 )?;
8594 let res = err!(self.builder.build_float_to_unsigned_int(
8595 v1,
8596 self.intrinsics.i64_ty,
8597 ""
8598 ));
8599 self.state.push1(res);
8600 }
8601 Operator::I64TruncF64U => {
8602 let v1 = self.state.pop1()?.into_float_value();
8603 self.trap_if_not_representable_as_int(
8604 0xbfefffffffffffff, 0x43efffffffffffff, v1,
8607 )?;
8608 let res = err!(self.builder.build_float_to_unsigned_int(
8609 v1,
8610 self.intrinsics.i64_ty,
8611 ""
8612 ));
8613 self.state.push1(res);
8614 }
8615 Operator::I64TruncSatF32U => {
8616 let (v, i) = self.state.pop1_extra()?;
8617 let v = self.apply_pending_canonicalization(v, i)?;
8618 let v = v.into_float_value();
8619 let res = self.trunc_sat_scalar(
8620 self.intrinsics.i64_ty,
8621 LEF32_GEQ_U64_MIN,
8622 GEF32_LEQ_U64_MAX,
8623 u64::MIN,
8624 u64::MAX,
8625 v,
8626 )?;
8627 self.state.push1(res);
8628 }
8629 Operator::I64TruncSatF64U => {
8630 let (v, i) = self.state.pop1_extra()?;
8631 let v = self.apply_pending_canonicalization(v, i)?;
8632 let v = v.into_float_value();
8633 let res = self.trunc_sat_scalar(
8634 self.intrinsics.i64_ty,
8635 LEF64_GEQ_U64_MIN,
8636 GEF64_LEQ_U64_MAX,
8637 u64::MIN,
8638 u64::MAX,
8639 v,
8640 )?;
8641 self.state.push1(res);
8642 }
8643 Operator::F32DemoteF64 => {
8644 let v = self.state.pop1()?;
8645 let v = v.into_float_value();
8646 let res = self
8647 .build_call_with_param_attributes(
8648 self.intrinsics.fptrunc_f64,
8649 &[
8650 v.into(),
8651 self.intrinsics.fp_rounding_md,
8652 self.intrinsics.fp_exception_md,
8653 ],
8654 "",
8655 )?
8656 .try_as_basic_value()
8657 .unwrap_basic();
8658 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
8659 }
8660 Operator::F64PromoteF32 => {
8661 let v = self.state.pop1()?;
8662 let v = v.into_float_value();
8663 let res = self
8664 .build_call_with_param_attributes(
8665 self.intrinsics.fpext_f32,
8666 &[v.into(), self.intrinsics.fp_exception_md],
8667 "",
8668 )?
8669 .try_as_basic_value()
8670 .unwrap_basic();
8671 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
8672 }
8673 Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
8674 let (v, i) = self.state.pop1_extra()?;
8675 let v = self.apply_pending_canonicalization(v, i)?;
8676 let v = v.into_int_value();
8677 let res = err!(self.builder.build_signed_int_to_float(
8678 v,
8679 self.intrinsics.f32_ty,
8680 ""
8681 ));
8682 self.state.push1(res);
8683 }
8684 Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
8685 let (v, i) = self.state.pop1_extra()?;
8686 let v = self.apply_pending_canonicalization(v, i)?;
8687 let v = v.into_int_value();
8688 let res = err!(self.builder.build_signed_int_to_float(
8689 v,
8690 self.intrinsics.f64_ty,
8691 ""
8692 ));
8693 self.state.push1(res);
8694 }
8695 Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
8696 let (v, i) = self.state.pop1_extra()?;
8697 let v = self.apply_pending_canonicalization(v, i)?;
8698 let v = v.into_int_value();
8699 let res = err!(self.builder.build_unsigned_int_to_float(
8700 v,
8701 self.intrinsics.f32_ty,
8702 ""
8703 ));
8704 self.state.push1(res);
8705 }
8706 Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
8707 let (v, i) = self.state.pop1_extra()?;
8708 let v = self.apply_pending_canonicalization(v, i)?;
8709 let v = v.into_int_value();
8710 let res = err!(self.builder.build_unsigned_int_to_float(
8711 v,
8712 self.intrinsics.f64_ty,
8713 ""
8714 ));
8715 self.state.push1(res);
8716 }
8717 Operator::F32x4ConvertI32x4S => {
8718 let v = self.state.pop1()?;
8719 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8720 .into_vector_value();
8721 let res = err!(self.builder.build_signed_int_to_float(
8722 v,
8723 self.intrinsics.f32x4_ty,
8724 ""
8725 ));
8726 let res = err!(
8727 self.builder
8728 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8729 );
8730 self.state.push1(res);
8731 }
8732 Operator::F32x4ConvertI32x4U => {
8733 let v = self.state.pop1()?;
8734 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8735 .into_vector_value();
8736 let res = err!(self.builder.build_unsigned_int_to_float(
8737 v,
8738 self.intrinsics.f32x4_ty,
8739 ""
8740 ));
8741 let res = err!(
8742 self.builder
8743 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8744 );
8745 self.state.push1(res);
8746 }
8747 Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
8748 let extend = match op {
8749 Operator::F64x2ConvertLowI32x4U => {
8750 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8751 }
8752 Operator::F64x2ConvertLowI32x4S => {
8753 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8754 }
8755 _ => unreachable!("Unhandled inner case"),
8756 };
8757 let (v, i) = self.state.pop1_extra()?;
8758 let (v, _) = self.v128_into_i32x4(v, i)?;
8759 let low = err!(self.builder.build_shuffle_vector(
8760 v,
8761 v.get_type().get_undef(),
8762 VectorType::const_vector(&[
8763 self.intrinsics.i32_consts[0],
8764 self.intrinsics.i32_consts[1],
8765 ]),
8766 "",
8767 ));
8768 let res = err!(extend(self, low));
8769 let res = err!(self.builder.build_signed_int_to_float(
8770 res,
8771 self.intrinsics.f64x2_ty,
8772 ""
8773 ));
8774 let res = err!(
8775 self.builder
8776 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8777 );
8778 self.state.push1(res);
8779 }
8780 Operator::F64x2PromoteLowF32x4 => {
8781 let (v, i) = self.state.pop1_extra()?;
8782 let (v, _) = self.v128_into_f32x4(v, i)?;
8783 let low = err!(self.builder.build_shuffle_vector(
8784 v,
8785 v.get_type().get_undef(),
8786 VectorType::const_vector(&[
8787 self.intrinsics.i32_consts[0],
8788 self.intrinsics.i32_consts[1],
8789 ]),
8790 "",
8791 ));
8792 let res = err!(
8793 self.builder
8794 .build_float_ext(low, self.intrinsics.f64x2_ty, "")
8795 );
8796 let res = err!(
8797 self.builder
8798 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8799 );
8800 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
8801 }
8802 Operator::F32x4DemoteF64x2Zero => {
8803 let (v, i) = self.state.pop1_extra()?;
8804 let (v, _) = self.v128_into_f64x2(v, i)?;
8805 let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
8806 let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
8807 let zeros = f32x2_ty.const_zero();
8808 let res = err!(self.builder.build_shuffle_vector(
8809 res,
8810 zeros,
8811 VectorType::const_vector(&[
8812 self.intrinsics.i32_consts[0],
8813 self.intrinsics.i32_consts[1],
8814 self.intrinsics.i32_consts[2],
8815 self.intrinsics.i32_consts[3],
8816 ]),
8817 "",
8818 ));
8819 let res = err!(
8820 self.builder
8821 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8822 );
8823 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
8824 }
8825 Operator::I32ReinterpretF32 => {
8850 let (v, i) = self.state.pop1_extra()?;
8851 let v = self.apply_pending_canonicalization(v, i)?;
8852 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
8853 self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
8854 }
8855 Operator::I64ReinterpretF64 => {
8856 let (v, i) = self.state.pop1_extra()?;
8857 let v = self.apply_pending_canonicalization(v, i)?;
8858 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
8859 self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
8860 }
8861 Operator::F32ReinterpretI32 => {
8862 let (v, i) = self.state.pop1_extra()?;
8863 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
8864 self.state.push1_extra(ret, i);
8865 }
8866 Operator::F64ReinterpretI64 => {
8867 let (v, i) = self.state.pop1_extra()?;
8868 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
8869 self.state.push1_extra(ret, i);
8870 }
8871
8872 Operator::I32Extend8S => {
8877 let value = self.state.pop1()?.into_int_value();
8878 let narrow_value = err!(self.builder.build_int_truncate(
8879 value,
8880 self.intrinsics.i8_ty,
8881 ""
8882 ));
8883 let extended_value = err!(self.builder.build_int_s_extend(
8884 narrow_value,
8885 self.intrinsics.i32_ty,
8886 ""
8887 ));
8888 self.state.push1(extended_value);
8889 }
8890 Operator::I32Extend16S => {
8891 let value = self.state.pop1()?.into_int_value();
8892 let narrow_value = err!(self.builder.build_int_truncate(
8893 value,
8894 self.intrinsics.i16_ty,
8895 ""
8896 ));
8897 let extended_value = err!(self.builder.build_int_s_extend(
8898 narrow_value,
8899 self.intrinsics.i32_ty,
8900 ""
8901 ));
8902 self.state.push1(extended_value);
8903 }
8904 Operator::I64Extend8S => {
8905 let value = self.state.pop1()?.into_int_value();
8906 let narrow_value = err!(self.builder.build_int_truncate(
8907 value,
8908 self.intrinsics.i8_ty,
8909 ""
8910 ));
8911 let extended_value = err!(self.builder.build_int_s_extend(
8912 narrow_value,
8913 self.intrinsics.i64_ty,
8914 ""
8915 ));
8916 self.state.push1(extended_value);
8917 }
8918 Operator::I64Extend16S => {
8919 let value = self.state.pop1()?.into_int_value();
8920 let narrow_value = err!(self.builder.build_int_truncate(
8921 value,
8922 self.intrinsics.i16_ty,
8923 ""
8924 ));
8925 let extended_value = err!(self.builder.build_int_s_extend(
8926 narrow_value,
8927 self.intrinsics.i64_ty,
8928 ""
8929 ));
8930 self.state.push1(extended_value);
8931 }
8932 Operator::I64Extend32S => {
8933 let value = self.state.pop1()?.into_int_value();
8934 let narrow_value = err!(self.builder.build_int_truncate(
8935 value,
8936 self.intrinsics.i32_ty,
8937 ""
8938 ));
8939 let extended_value = err!(self.builder.build_int_s_extend(
8940 narrow_value,
8941 self.intrinsics.i64_ty,
8942 ""
8943 ));
8944 self.state.push1(extended_value);
8945 }
8946
8947 Operator::I32Load { ref memarg } => {
8952 let offset = self.state.pop1()?.into_int_value();
8953 let memory_index = MemoryIndex::from_u32(0);
8954 let effective_address = self.resolve_memory_ptr(
8955 memory_index,
8956 memarg,
8957 self.intrinsics.ptr_ty,
8958 offset,
8959 4,
8960 )?;
8961 let result = err!(self.builder.build_load(
8962 self.intrinsics.i32_ty,
8963 effective_address,
8964 ""
8965 ));
8966 self.annotate_user_memaccess(
8967 memory_index,
8968 memarg,
8969 1,
8970 result.as_instruction_value().unwrap(),
8971 )?;
8972 self.state.push1(result);
8973 }
8974 Operator::I64Load { ref memarg } => {
8975 let offset = self.state.pop1()?.into_int_value();
8976 let memory_index = MemoryIndex::from_u32(0);
8977 let effective_address = self.resolve_memory_ptr(
8978 memory_index,
8979 memarg,
8980 self.intrinsics.ptr_ty,
8981 offset,
8982 8,
8983 )?;
8984 let result = err!(self.builder.build_load(
8985 self.intrinsics.i64_ty,
8986 effective_address,
8987 ""
8988 ));
8989 self.annotate_user_memaccess(
8990 memory_index,
8991 memarg,
8992 1,
8993 result.as_instruction_value().unwrap(),
8994 )?;
8995 self.state.push1(result);
8996 }
8997 Operator::F32Load { ref memarg } => {
8998 let offset = self.state.pop1()?.into_int_value();
8999 let memory_index = MemoryIndex::from_u32(0);
9000 let effective_address = self.resolve_memory_ptr(
9001 memory_index,
9002 memarg,
9003 self.intrinsics.ptr_ty,
9004 offset,
9005 4,
9006 )?;
9007 let result = err!(self.builder.build_load(
9008 self.intrinsics.f32_ty,
9009 effective_address,
9010 ""
9011 ));
9012 self.annotate_user_memaccess(
9013 memory_index,
9014 memarg,
9015 1,
9016 result.as_instruction_value().unwrap(),
9017 )?;
9018 self.state.push1(result);
9019 }
9020 Operator::F64Load { ref memarg } => {
9021 let offset = self.state.pop1()?.into_int_value();
9022 let memory_index = MemoryIndex::from_u32(0);
9023 let effective_address = self.resolve_memory_ptr(
9024 memory_index,
9025 memarg,
9026 self.intrinsics.ptr_ty,
9027 offset,
9028 8,
9029 )?;
9030 let result = err!(self.builder.build_load(
9031 self.intrinsics.f64_ty,
9032 effective_address,
9033 ""
9034 ));
9035 self.annotate_user_memaccess(
9036 memory_index,
9037 memarg,
9038 1,
9039 result.as_instruction_value().unwrap(),
9040 )?;
9041 self.state.push1(result);
9042 }
9043 Operator::V128Load { ref memarg } => {
9044 let offset = self.state.pop1()?.into_int_value();
9045 let memory_index = MemoryIndex::from_u32(0);
9046 let effective_address = self.resolve_memory_ptr(
9047 memory_index,
9048 memarg,
9049 self.intrinsics.ptr_ty,
9050 offset,
9051 16,
9052 )?;
9053 let result = err!(self.builder.build_load(
9054 self.intrinsics.i128_ty,
9055 effective_address,
9056 ""
9057 ));
9058 self.annotate_user_memaccess(
9059 memory_index,
9060 memarg,
9061 1,
9062 result.as_instruction_value().unwrap(),
9063 )?;
9064 self.state.push1(result);
9065 }
9066 Operator::V128Load8Lane { ref memarg, lane } => {
9067 let (v, i) = self.state.pop1_extra()?;
9068 let (v, _i) = self.v128_into_i8x16(v, i)?;
9069 let offset = self.state.pop1()?.into_int_value();
9070 let memory_index = MemoryIndex::from_u32(memarg.memory);
9071 let effective_address = self.resolve_memory_ptr(
9072 memory_index,
9073 memarg,
9074 self.intrinsics.ptr_ty,
9075 offset,
9076 1,
9077 )?;
9078 let element = err!(self.builder.build_load(
9079 self.intrinsics.i8_ty,
9080 effective_address,
9081 ""
9082 ));
9083 self.annotate_user_memaccess(
9084 memory_index,
9085 memarg,
9086 1,
9087 element.as_instruction_value().unwrap(),
9088 )?;
9089 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9090 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9091 let res = err!(
9092 self.builder
9093 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9094 );
9095 self.state.push1(res);
9096 }
9097 Operator::V128Load16Lane { ref memarg, lane } => {
9098 let (v, i) = self.state.pop1_extra()?;
9099 let (v, i) = self.v128_into_i16x8(v, i)?;
9100 let offset = self.state.pop1()?.into_int_value();
9101 let memory_index = MemoryIndex::from_u32(memarg.memory);
9102 let effective_address = self.resolve_memory_ptr(
9103 memory_index,
9104 memarg,
9105 self.intrinsics.ptr_ty,
9106 offset,
9107 2,
9108 )?;
9109 let element = err!(self.builder.build_load(
9110 self.intrinsics.i16_ty,
9111 effective_address,
9112 ""
9113 ));
9114 self.annotate_user_memaccess(
9115 memory_index,
9116 memarg,
9117 1,
9118 element.as_instruction_value().unwrap(),
9119 )?;
9120 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9121 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9122 let res = err!(
9123 self.builder
9124 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9125 );
9126 self.state.push1_extra(res, i);
9127 }
9128 Operator::V128Load32Lane { ref memarg, lane } => {
9129 let (v, i) = self.state.pop1_extra()?;
9130 let (v, i) = self.v128_into_i32x4(v, i)?;
9131 let offset = self.state.pop1()?.into_int_value();
9132 let memory_index = MemoryIndex::from_u32(memarg.memory);
9133 let effective_address = self.resolve_memory_ptr(
9134 memory_index,
9135 memarg,
9136 self.intrinsics.ptr_ty,
9137 offset,
9138 4,
9139 )?;
9140 let element = err!(self.builder.build_load(
9141 self.intrinsics.i32_ty,
9142 effective_address,
9143 ""
9144 ));
9145 self.annotate_user_memaccess(
9146 memory_index,
9147 memarg,
9148 1,
9149 element.as_instruction_value().unwrap(),
9150 )?;
9151 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9152 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9153 let res = err!(
9154 self.builder
9155 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9156 );
9157 self.state.push1_extra(res, i);
9158 }
9159 Operator::V128Load64Lane { ref memarg, lane } => {
9160 let (v, i) = self.state.pop1_extra()?;
9161 let (v, i) = self.v128_into_i64x2(v, i)?;
9162 let offset = self.state.pop1()?.into_int_value();
9163 let memory_index = MemoryIndex::from_u32(memarg.memory);
9164 let effective_address = self.resolve_memory_ptr(
9165 memory_index,
9166 memarg,
9167 self.intrinsics.ptr_ty,
9168 offset,
9169 8,
9170 )?;
9171 let element = err!(self.builder.build_load(
9172 self.intrinsics.i64_ty,
9173 effective_address,
9174 ""
9175 ));
9176 self.annotate_user_memaccess(
9177 memory_index,
9178 memarg,
9179 1,
9180 element.as_instruction_value().unwrap(),
9181 )?;
9182 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9183 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9184 let res = err!(
9185 self.builder
9186 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9187 );
9188 self.state.push1_extra(res, i);
9189 }
9190
9191 Operator::I32Store { ref memarg } => {
9192 let value = self.state.pop1()?;
9193 let offset = self.state.pop1()?.into_int_value();
9194 let memory_index = MemoryIndex::from_u32(0);
9195 let effective_address = self.resolve_memory_ptr(
9196 memory_index,
9197 memarg,
9198 self.intrinsics.ptr_ty,
9199 offset,
9200 4,
9201 )?;
9202 let dead_load = err!(self.builder.build_load(
9203 self.intrinsics.i32_ty,
9204 effective_address,
9205 ""
9206 ));
9207 self.annotate_user_memaccess(
9208 memory_index,
9209 memarg,
9210 1,
9211 dead_load.as_instruction_value().unwrap(),
9212 )?;
9213 let store = err!(self.builder.build_store(effective_address, value));
9214 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9215 }
9216 Operator::I64Store { ref memarg } => {
9217 let value = self.state.pop1()?;
9218 let offset = self.state.pop1()?.into_int_value();
9219 let memory_index = MemoryIndex::from_u32(0);
9220 let effective_address = self.resolve_memory_ptr(
9221 memory_index,
9222 memarg,
9223 self.intrinsics.ptr_ty,
9224 offset,
9225 8,
9226 )?;
9227 let dead_load = err!(self.builder.build_load(
9228 self.intrinsics.i64_ty,
9229 effective_address,
9230 ""
9231 ));
9232 self.annotate_user_memaccess(
9233 memory_index,
9234 memarg,
9235 1,
9236 dead_load.as_instruction_value().unwrap(),
9237 )?;
9238 let store = err!(self.builder.build_store(effective_address, value));
9239 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9240 }
9241 Operator::F32Store { ref memarg } => {
9242 let (v, i) = self.state.pop1_extra()?;
9243 let v = self.apply_pending_canonicalization(v, i)?;
9244 let offset = self.state.pop1()?.into_int_value();
9245 let memory_index = MemoryIndex::from_u32(0);
9246 let effective_address = self.resolve_memory_ptr(
9247 memory_index,
9248 memarg,
9249 self.intrinsics.ptr_ty,
9250 offset,
9251 4,
9252 )?;
9253 let dead_load = err!(self.builder.build_load(
9254 self.intrinsics.f32_ty,
9255 effective_address,
9256 ""
9257 ));
9258 self.annotate_user_memaccess(
9259 memory_index,
9260 memarg,
9261 1,
9262 dead_load.as_instruction_value().unwrap(),
9263 )?;
9264 let store = err!(self.builder.build_store(effective_address, v));
9265 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9266 }
9267 Operator::F64Store { ref memarg } => {
9268 let (v, i) = self.state.pop1_extra()?;
9269 let v = self.apply_pending_canonicalization(v, i)?;
9270 let offset = self.state.pop1()?.into_int_value();
9271 let memory_index = MemoryIndex::from_u32(0);
9272 let effective_address = self.resolve_memory_ptr(
9273 memory_index,
9274 memarg,
9275 self.intrinsics.ptr_ty,
9276 offset,
9277 8,
9278 )?;
9279 let dead_load = err!(self.builder.build_load(
9280 self.intrinsics.f64_ty,
9281 effective_address,
9282 ""
9283 ));
9284 self.annotate_user_memaccess(
9285 memory_index,
9286 memarg,
9287 1,
9288 dead_load.as_instruction_value().unwrap(),
9289 )?;
9290 let store = err!(self.builder.build_store(effective_address, v));
9291 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9292 }
9293 Operator::V128Store { ref memarg } => {
9294 let (v, i) = self.state.pop1_extra()?;
9295 let v = self.apply_pending_canonicalization(v, i)?;
9296 let offset = self.state.pop1()?.into_int_value();
9297 let memory_index = MemoryIndex::from_u32(0);
9298 let effective_address = self.resolve_memory_ptr(
9299 memory_index,
9300 memarg,
9301 self.intrinsics.ptr_ty,
9302 offset,
9303 16,
9304 )?;
9305 let dead_load = err!(self.builder.build_load(
9306 self.intrinsics.i128_ty,
9307 effective_address,
9308 ""
9309 ));
9310 self.annotate_user_memaccess(
9311 memory_index,
9312 memarg,
9313 1,
9314 dead_load.as_instruction_value().unwrap(),
9315 )?;
9316 let store = err!(self.builder.build_store(effective_address, v));
9317 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9318 }
9319 Operator::V128Store8Lane { ref memarg, lane } => {
9320 let (v, i) = self.state.pop1_extra()?;
9321 let (v, _i) = self.v128_into_i8x16(v, i)?;
9322 let offset = self.state.pop1()?.into_int_value();
9323 let memory_index = MemoryIndex::from_u32(memarg.memory);
9324
9325 let effective_address = self.resolve_memory_ptr(
9326 memory_index,
9327 memarg,
9328 self.intrinsics.ptr_ty,
9329 offset,
9330 1,
9331 )?;
9332 let dead_load = err!(self.builder.build_load(
9333 self.intrinsics.i8_ty,
9334 effective_address,
9335 ""
9336 ));
9337 self.annotate_user_memaccess(
9338 memory_index,
9339 memarg,
9340 1,
9341 dead_load.as_instruction_value().unwrap(),
9342 )?;
9343 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9344 let val = err!(self.builder.build_extract_element(v, idx, ""));
9345 let store = err!(self.builder.build_store(effective_address, val));
9346 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9347 }
9348 Operator::V128Store16Lane { ref memarg, lane } => {
9349 let (v, i) = self.state.pop1_extra()?;
9350 let (v, _i) = self.v128_into_i16x8(v, i)?;
9351 let offset = self.state.pop1()?.into_int_value();
9352 let memory_index = MemoryIndex::from_u32(memarg.memory);
9353
9354 let effective_address = self.resolve_memory_ptr(
9355 memory_index,
9356 memarg,
9357 self.intrinsics.ptr_ty,
9358 offset,
9359 2,
9360 )?;
9361 let dead_load = err!(self.builder.build_load(
9362 self.intrinsics.i16_ty,
9363 effective_address,
9364 ""
9365 ));
9366 self.annotate_user_memaccess(
9367 memory_index,
9368 memarg,
9369 1,
9370 dead_load.as_instruction_value().unwrap(),
9371 )?;
9372 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9373 let val = err!(self.builder.build_extract_element(v, idx, ""));
9374 let store = err!(self.builder.build_store(effective_address, val));
9375 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9376 }
9377 Operator::V128Store32Lane { ref memarg, lane } => {
9378 let (v, i) = self.state.pop1_extra()?;
9379 let (v, _i) = self.v128_into_i32x4(v, i)?;
9380 let offset = self.state.pop1()?.into_int_value();
9381 let memory_index = MemoryIndex::from_u32(memarg.memory);
9382
9383 let effective_address = self.resolve_memory_ptr(
9384 memory_index,
9385 memarg,
9386 self.intrinsics.ptr_ty,
9387 offset,
9388 4,
9389 )?;
9390 let dead_load = err!(self.builder.build_load(
9391 self.intrinsics.i32_ty,
9392 effective_address,
9393 ""
9394 ));
9395 self.annotate_user_memaccess(
9396 memory_index,
9397 memarg,
9398 1,
9399 dead_load.as_instruction_value().unwrap(),
9400 )?;
9401 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9402 let val = err!(self.builder.build_extract_element(v, idx, ""));
9403 let store = err!(self.builder.build_store(effective_address, val));
9404 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9405 }
9406 Operator::V128Store64Lane { ref memarg, lane } => {
9407 let (v, i) = self.state.pop1_extra()?;
9408 let (v, _i) = self.v128_into_i64x2(v, i)?;
9409 let offset = self.state.pop1()?.into_int_value();
9410 let memory_index = MemoryIndex::from_u32(memarg.memory);
9411
9412 let effective_address = self.resolve_memory_ptr(
9413 memory_index,
9414 memarg,
9415 self.intrinsics.ptr_ty,
9416 offset,
9417 8,
9418 )?;
9419 let dead_load = err!(self.builder.build_load(
9420 self.intrinsics.i64_ty,
9421 effective_address,
9422 ""
9423 ));
9424 self.annotate_user_memaccess(
9425 memory_index,
9426 memarg,
9427 1,
9428 dead_load.as_instruction_value().unwrap(),
9429 )?;
9430 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9431 let val = err!(self.builder.build_extract_element(v, idx, ""));
9432 let store = err!(self.builder.build_store(effective_address, val));
9433 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9434 }
9435 Operator::I32Load8S { ref memarg } => {
9436 let offset = self.state.pop1()?.into_int_value();
9437 let memory_index = MemoryIndex::from_u32(0);
9438 let effective_address = self.resolve_memory_ptr(
9439 memory_index,
9440 memarg,
9441 self.intrinsics.ptr_ty,
9442 offset,
9443 1,
9444 )?;
9445 let narrow_result = err!(self.builder.build_load(
9446 self.intrinsics.i8_ty,
9447 effective_address,
9448 ""
9449 ));
9450 self.annotate_user_memaccess(
9451 memory_index,
9452 memarg,
9453 1,
9454 narrow_result.as_instruction_value().unwrap(),
9455 )?;
9456 let result = err!(self.builder.build_int_s_extend(
9457 narrow_result.into_int_value(),
9458 self.intrinsics.i32_ty,
9459 "",
9460 ));
9461 self.state.push1(result);
9462 }
9463 Operator::I32Load16S { ref memarg } => {
9464 let offset = self.state.pop1()?.into_int_value();
9465 let memory_index = MemoryIndex::from_u32(0);
9466 let effective_address = self.resolve_memory_ptr(
9467 memory_index,
9468 memarg,
9469 self.intrinsics.ptr_ty,
9470 offset,
9471 2,
9472 )?;
9473 let narrow_result = err!(self.builder.build_load(
9474 self.intrinsics.i16_ty,
9475 effective_address,
9476 ""
9477 ));
9478 self.annotate_user_memaccess(
9479 memory_index,
9480 memarg,
9481 1,
9482 narrow_result.as_instruction_value().unwrap(),
9483 )?;
9484 let result = err!(self.builder.build_int_s_extend(
9485 narrow_result.into_int_value(),
9486 self.intrinsics.i32_ty,
9487 "",
9488 ));
9489 self.state.push1(result);
9490 }
9491 Operator::I64Load8S { ref memarg } => {
9492 let offset = self.state.pop1()?.into_int_value();
9493 let memory_index = MemoryIndex::from_u32(0);
9494 let effective_address = self.resolve_memory_ptr(
9495 memory_index,
9496 memarg,
9497 self.intrinsics.ptr_ty,
9498 offset,
9499 1,
9500 )?;
9501 let narrow_result = err!(self.builder.build_load(
9502 self.intrinsics.i8_ty,
9503 effective_address,
9504 ""
9505 ))
9506 .into_int_value();
9507 self.annotate_user_memaccess(
9508 memory_index,
9509 memarg,
9510 1,
9511 narrow_result.as_instruction_value().unwrap(),
9512 )?;
9513 let result = err!(self.builder.build_int_s_extend(
9514 narrow_result,
9515 self.intrinsics.i64_ty,
9516 ""
9517 ));
9518 self.state.push1(result);
9519 }
9520 Operator::I64Load16S { ref memarg } => {
9521 let offset = self.state.pop1()?.into_int_value();
9522 let memory_index = MemoryIndex::from_u32(0);
9523 let effective_address = self.resolve_memory_ptr(
9524 memory_index,
9525 memarg,
9526 self.intrinsics.ptr_ty,
9527 offset,
9528 2,
9529 )?;
9530 let narrow_result = err!(self.builder.build_load(
9531 self.intrinsics.i16_ty,
9532 effective_address,
9533 ""
9534 ))
9535 .into_int_value();
9536 self.annotate_user_memaccess(
9537 memory_index,
9538 memarg,
9539 1,
9540 narrow_result.as_instruction_value().unwrap(),
9541 )?;
9542 let result = err!(self.builder.build_int_s_extend(
9543 narrow_result,
9544 self.intrinsics.i64_ty,
9545 ""
9546 ));
9547 self.state.push1(result);
9548 }
9549 Operator::I64Load32S { ref memarg } => {
9550 let offset = self.state.pop1()?.into_int_value();
9551 let memory_index = MemoryIndex::from_u32(0);
9552 let effective_address = self.resolve_memory_ptr(
9553 memory_index,
9554 memarg,
9555 self.intrinsics.ptr_ty,
9556 offset,
9557 4,
9558 )?;
9559 let narrow_result = err!(self.builder.build_load(
9560 self.intrinsics.i32_ty,
9561 effective_address,
9562 ""
9563 ));
9564 self.annotate_user_memaccess(
9565 memory_index,
9566 memarg,
9567 1,
9568 narrow_result.as_instruction_value().unwrap(),
9569 )?;
9570 let result = err!(self.builder.build_int_s_extend(
9571 narrow_result.into_int_value(),
9572 self.intrinsics.i64_ty,
9573 "",
9574 ));
9575 self.state.push1(result);
9576 }
9577
9578 Operator::I32Load8U { ref memarg } => {
9579 let offset = self.state.pop1()?.into_int_value();
9580 let memory_index = MemoryIndex::from_u32(0);
9581 let effective_address = self.resolve_memory_ptr(
9582 memory_index,
9583 memarg,
9584 self.intrinsics.ptr_ty,
9585 offset,
9586 1,
9587 )?;
9588 let narrow_result = err!(self.builder.build_load(
9589 self.intrinsics.i8_ty,
9590 effective_address,
9591 ""
9592 ));
9593 self.annotate_user_memaccess(
9594 memory_index,
9595 memarg,
9596 1,
9597 narrow_result.as_instruction_value().unwrap(),
9598 )?;
9599 let result = err!(self.builder.build_int_z_extend(
9600 narrow_result.into_int_value(),
9601 self.intrinsics.i32_ty,
9602 "",
9603 ));
9604 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9605 }
9606 Operator::I32Load16U { ref memarg } => {
9607 let offset = self.state.pop1()?.into_int_value();
9608 let memory_index = MemoryIndex::from_u32(0);
9609 let effective_address = self.resolve_memory_ptr(
9610 memory_index,
9611 memarg,
9612 self.intrinsics.ptr_ty,
9613 offset,
9614 2,
9615 )?;
9616 let narrow_result = err!(self.builder.build_load(
9617 self.intrinsics.i16_ty,
9618 effective_address,
9619 ""
9620 ));
9621 self.annotate_user_memaccess(
9622 memory_index,
9623 memarg,
9624 1,
9625 narrow_result.as_instruction_value().unwrap(),
9626 )?;
9627 let result = err!(self.builder.build_int_z_extend(
9628 narrow_result.into_int_value(),
9629 self.intrinsics.i32_ty,
9630 "",
9631 ));
9632 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9633 }
9634 Operator::I64Load8U { ref memarg } => {
9635 let offset = self.state.pop1()?.into_int_value();
9636 let memory_index = MemoryIndex::from_u32(0);
9637 let effective_address = self.resolve_memory_ptr(
9638 memory_index,
9639 memarg,
9640 self.intrinsics.ptr_ty,
9641 offset,
9642 1,
9643 )?;
9644 let narrow_result = err!(self.builder.build_load(
9645 self.intrinsics.i8_ty,
9646 effective_address,
9647 ""
9648 ));
9649 self.annotate_user_memaccess(
9650 memory_index,
9651 memarg,
9652 1,
9653 narrow_result.as_instruction_value().unwrap(),
9654 )?;
9655 let result = err!(self.builder.build_int_z_extend(
9656 narrow_result.into_int_value(),
9657 self.intrinsics.i64_ty,
9658 "",
9659 ));
9660 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9661 }
9662 Operator::I64Load16U { ref memarg } => {
9663 let offset = self.state.pop1()?.into_int_value();
9664 let memory_index = MemoryIndex::from_u32(0);
9665 let effective_address = self.resolve_memory_ptr(
9666 memory_index,
9667 memarg,
9668 self.intrinsics.ptr_ty,
9669 offset,
9670 2,
9671 )?;
9672 let narrow_result = err!(self.builder.build_load(
9673 self.intrinsics.i16_ty,
9674 effective_address,
9675 ""
9676 ));
9677 self.annotate_user_memaccess(
9678 memory_index,
9679 memarg,
9680 1,
9681 narrow_result.as_instruction_value().unwrap(),
9682 )?;
9683 let result = err!(self.builder.build_int_z_extend(
9684 narrow_result.into_int_value(),
9685 self.intrinsics.i64_ty,
9686 "",
9687 ));
9688 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9689 }
9690 Operator::I64Load32U { ref memarg } => {
9691 let offset = self.state.pop1()?.into_int_value();
9692 let memory_index = MemoryIndex::from_u32(0);
9693 let effective_address = self.resolve_memory_ptr(
9694 memory_index,
9695 memarg,
9696 self.intrinsics.ptr_ty,
9697 offset,
9698 4,
9699 )?;
9700 let narrow_result = err!(self.builder.build_load(
9701 self.intrinsics.i32_ty,
9702 effective_address,
9703 ""
9704 ));
9705 self.annotate_user_memaccess(
9706 memory_index,
9707 memarg,
9708 1,
9709 narrow_result.as_instruction_value().unwrap(),
9710 )?;
9711 let result = err!(self.builder.build_int_z_extend(
9712 narrow_result.into_int_value(),
9713 self.intrinsics.i64_ty,
9714 "",
9715 ));
9716 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9717 }
9718
9719 Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9720 let value = self.state.pop1()?.into_int_value();
9721 let offset = self.state.pop1()?.into_int_value();
9722 let memory_index = MemoryIndex::from_u32(0);
9723 let effective_address = self.resolve_memory_ptr(
9724 memory_index,
9725 memarg,
9726 self.intrinsics.ptr_ty,
9727 offset,
9728 1,
9729 )?;
9730 let dead_load = err!(self.builder.build_load(
9731 self.intrinsics.i8_ty,
9732 effective_address,
9733 ""
9734 ));
9735 self.annotate_user_memaccess(
9736 memory_index,
9737 memarg,
9738 1,
9739 dead_load.as_instruction_value().unwrap(),
9740 )?;
9741 let narrow_value = err!(self.builder.build_int_truncate(
9742 value,
9743 self.intrinsics.i8_ty,
9744 ""
9745 ));
9746 let store = err!(self.builder.build_store(effective_address, narrow_value));
9747 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9748 }
9749 Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
9750 let value = self.state.pop1()?.into_int_value();
9751 let offset = self.state.pop1()?.into_int_value();
9752 let memory_index = MemoryIndex::from_u32(0);
9753 let effective_address = self.resolve_memory_ptr(
9754 memory_index,
9755 memarg,
9756 self.intrinsics.ptr_ty,
9757 offset,
9758 2,
9759 )?;
9760 let dead_load = err!(self.builder.build_load(
9761 self.intrinsics.i16_ty,
9762 effective_address,
9763 ""
9764 ));
9765 self.annotate_user_memaccess(
9766 memory_index,
9767 memarg,
9768 1,
9769 dead_load.as_instruction_value().unwrap(),
9770 )?;
9771 let narrow_value = err!(self.builder.build_int_truncate(
9772 value,
9773 self.intrinsics.i16_ty,
9774 ""
9775 ));
9776 let store = err!(self.builder.build_store(effective_address, narrow_value));
9777 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9778 }
9779 Operator::I64Store32 { ref memarg } => {
9780 let value = self.state.pop1()?.into_int_value();
9781 let offset = self.state.pop1()?.into_int_value();
9782 let memory_index = MemoryIndex::from_u32(0);
9783 let effective_address = self.resolve_memory_ptr(
9784 memory_index,
9785 memarg,
9786 self.intrinsics.ptr_ty,
9787 offset,
9788 4,
9789 )?;
9790 let dead_load = err!(self.builder.build_load(
9791 self.intrinsics.i32_ty,
9792 effective_address,
9793 ""
9794 ));
9795 self.annotate_user_memaccess(
9796 memory_index,
9797 memarg,
9798 1,
9799 dead_load.as_instruction_value().unwrap(),
9800 )?;
9801 let narrow_value = err!(self.builder.build_int_truncate(
9802 value,
9803 self.intrinsics.i32_ty,
9804 ""
9805 ));
9806 let store = err!(self.builder.build_store(effective_address, narrow_value));
9807 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9808 }
9809 Operator::I8x16Neg => {
9810 let (v, i) = self.state.pop1_extra()?;
9811 let (v, _) = self.v128_into_i8x16(v, i)?;
9812 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9813 let res = err!(
9814 self.builder
9815 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9816 );
9817 self.state.push1(res);
9818 }
9819 Operator::I16x8Neg => {
9820 let (v, i) = self.state.pop1_extra()?;
9821 let (v, _) = self.v128_into_i16x8(v, i)?;
9822 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9823 let res = err!(
9824 self.builder
9825 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9826 );
9827 self.state.push1(res);
9828 }
9829 Operator::I32x4Neg => {
9830 let (v, i) = self.state.pop1_extra()?;
9831 let (v, _) = self.v128_into_i32x4(v, i)?;
9832 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9833 let res = err!(
9834 self.builder
9835 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9836 );
9837 self.state.push1(res);
9838 }
9839 Operator::I64x2Neg => {
9840 let (v, i) = self.state.pop1_extra()?;
9841 let (v, _) = self.v128_into_i64x2(v, i)?;
9842 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9843 let res = err!(
9844 self.builder
9845 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9846 );
9847 self.state.push1(res);
9848 }
9849 Operator::V128Not => {
9850 let (v, i) = self.state.pop1_extra()?;
9851 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
9852 let res = err!(self.builder.build_not(v, ""));
9853 self.state.push1(res);
9854 }
9855 Operator::V128AnyTrue => {
9856 let v = self.state.pop1()?.into_int_value();
9859 let res = err!(self.builder.build_int_compare(
9860 IntPredicate::NE,
9861 v,
9862 v.get_type().const_zero(),
9863 "",
9864 ));
9865 let res = err!(
9866 self.builder
9867 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9868 );
9869 self.state.push1_extra(
9870 res,
9871 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
9872 );
9873 }
9874 Operator::I8x16AllTrue
9875 | Operator::I16x8AllTrue
9876 | Operator::I32x4AllTrue
9877 | Operator::I64x2AllTrue => {
9878 let vec_ty = match op {
9879 Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
9880 Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
9881 Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
9882 Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
9883 _ => unreachable!(),
9884 };
9885 let (v, i) = self.state.pop1_extra()?;
9886 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
9887 let lane_int_ty = self.context.custom_width_int_type(vec_ty.get_size());
9888 let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
9889 let mask = err!(self.builder.build_int_compare(
9890 IntPredicate::NE,
9891 vec,
9892 vec_ty.const_zero(),
9893 "mask",
9894 ));
9895 let cmask =
9896 err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
9897 let res = err!(self.builder.build_int_compare(
9898 IntPredicate::EQ,
9899 cmask,
9900 lane_int_ty.const_int(u64::MAX, true),
9901 "",
9902 ));
9903 let res = err!(
9904 self.builder
9905 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9906 );
9907 self.state.push1_extra(
9908 res,
9909 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
9910 );
9911 }
9912 Operator::I8x16ExtractLaneS { lane } => {
9913 let (v, i) = self.state.pop1_extra()?;
9914 let (v, _) = self.v128_into_i8x16(v, i)?;
9915 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9916 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9917 let res = err!(
9918 self.builder
9919 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
9920 );
9921 self.state.push1(res);
9922 }
9923 Operator::I8x16ExtractLaneU { lane } => {
9924 let (v, i) = self.state.pop1_extra()?;
9925 let (v, _) = self.v128_into_i8x16(v, i)?;
9926 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9927 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9928 let res = err!(
9929 self.builder
9930 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9931 );
9932 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
9933 }
9934 Operator::I16x8ExtractLaneS { lane } => {
9935 let (v, i) = self.state.pop1_extra()?;
9936 let (v, _) = self.v128_into_i16x8(v, i)?;
9937 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9938 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9939 let res = err!(
9940 self.builder
9941 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
9942 );
9943 self.state.push1(res);
9944 }
9945 Operator::I16x8ExtractLaneU { lane } => {
9946 let (v, i) = self.state.pop1_extra()?;
9947 let (v, _) = self.v128_into_i16x8(v, i)?;
9948 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9949 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9950 let res = err!(
9951 self.builder
9952 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9953 );
9954 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
9955 }
9956 Operator::I32x4ExtractLane { lane } => {
9957 let (v, i) = self.state.pop1_extra()?;
9958 let (v, i) = self.v128_into_i32x4(v, i)?;
9959 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9960 let res = err!(self.builder.build_extract_element(v, idx, ""));
9961 self.state.push1_extra(res, i);
9962 }
9963 Operator::I64x2ExtractLane { lane } => {
9964 let (v, i) = self.state.pop1_extra()?;
9965 let (v, i) = self.v128_into_i64x2(v, i)?;
9966 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9967 let res = err!(self.builder.build_extract_element(v, idx, ""));
9968 self.state.push1_extra(res, i);
9969 }
9970 Operator::F32x4ExtractLane { lane } => {
9971 let (v, i) = self.state.pop1_extra()?;
9972 let (v, i) = self.v128_into_f32x4(v, i)?;
9973 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9974 let res = err!(self.builder.build_extract_element(v, idx, ""));
9975 self.state.push1_extra(res, i);
9976 }
9977 Operator::F64x2ExtractLane { lane } => {
9978 let (v, i) = self.state.pop1_extra()?;
9979 let (v, i) = self.v128_into_f64x2(v, i)?;
9980 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9981 let res = err!(self.builder.build_extract_element(v, idx, ""));
9982 self.state.push1_extra(res, i);
9983 }
9984 Operator::I8x16ReplaceLane { lane } => {
9985 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
9986 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
9987 let v2 = v2.into_int_value();
9988 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
9989 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9990 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
9991 let res = err!(
9992 self.builder
9993 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9994 );
9995 self.state.push1(res);
9996 }
9997 Operator::I16x8ReplaceLane { lane } => {
9998 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
9999 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10000 let v2 = v2.into_int_value();
10001 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10002 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10003 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10004 let res = err!(
10005 self.builder
10006 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10007 );
10008 self.state.push1(res);
10009 }
10010 Operator::I32x4ReplaceLane { lane } => {
10011 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10012 let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10013 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10014 let v2 = v2.into_int_value();
10015 let i2 = i2.strip_pending();
10016 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10017 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10018 let res = err!(
10019 self.builder
10020 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10021 );
10022 self.state
10023 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10024 }
10025 Operator::I64x2ReplaceLane { lane } => {
10026 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10027 let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10028 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10029 let v2 = v2.into_int_value();
10030 let i2 = i2.strip_pending();
10031 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10032 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10033 let res = err!(
10034 self.builder
10035 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10036 );
10037 self.state
10038 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10039 }
10040 Operator::F32x4ReplaceLane { lane } => {
10041 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10042 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10043 let push_pending_f32_nan_to_result =
10044 i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10045 let (v1, v2) = if !push_pending_f32_nan_to_result {
10046 (
10047 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10048 .into_vector_value(),
10049 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10050 .into_float_value(),
10051 )
10052 } else {
10053 (v1, v2.into_float_value())
10054 };
10055 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10056 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10057 let res = err!(
10058 self.builder
10059 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10060 );
10061 let info = if push_pending_f32_nan_to_result {
10062 ExtraInfo::pending_f32_nan()
10063 } else {
10064 (i1.strip_pending() & i2.strip_pending())?
10065 };
10066 self.state.push1_extra(res, info);
10067 }
10068 Operator::F64x2ReplaceLane { lane } => {
10069 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10070 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10071 let push_pending_f64_nan_to_result =
10072 i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10073 let (v1, v2) = if !push_pending_f64_nan_to_result {
10074 (
10075 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10076 .into_vector_value(),
10077 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10078 .into_float_value(),
10079 )
10080 } else {
10081 (v1, v2.into_float_value())
10082 };
10083 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10084 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10085 let res = err!(
10086 self.builder
10087 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10088 );
10089 let info = if push_pending_f64_nan_to_result {
10090 ExtraInfo::pending_f64_nan()
10091 } else {
10092 (i1.strip_pending() & i2.strip_pending())?
10093 };
10094 self.state.push1_extra(res, info);
10095 }
10096 Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10097 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10098 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10099 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10100
10101 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10102 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10103 let res = self
10104 .build_call_with_param_attributes(
10105 self.intrinsics.x86_64.pshufb128,
10106 &[v1.into(), v2.into()],
10107 "",
10108 )?
10109 .try_as_basic_value()
10110 .unwrap_basic();
10111 let res = err!(
10112 self.builder
10113 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10114 );
10115 self.state.push1(res);
10116 }
10117 Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10118 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10119 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10120 let v1 = err!(
10121 self.builder
10122 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10123 )
10124 .into_vector_value();
10125 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10126 let v2 = err!(
10127 self.builder
10128 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10129 )
10130 .into_vector_value();
10131 let lanes = self.intrinsics.i8_ty.const_int(16, false);
10132 let lanes =
10133 self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10134 let mut res = self.intrinsics.i8x16_ty.get_undef();
10135 let idx_out_of_range = err!(self.builder.build_int_compare(
10136 IntPredicate::UGE,
10137 v2,
10138 lanes,
10139 "idx_out_of_range",
10140 ));
10141 let idx_clamped = err!(self.builder.build_select(
10142 idx_out_of_range,
10143 self.intrinsics.i8x16_ty.const_zero(),
10144 v2,
10145 "idx_clamped",
10146 ))
10147 .into_vector_value();
10148 for i in 0..16 {
10149 let idx = err!(self.builder.build_extract_element(
10150 idx_clamped,
10151 self.intrinsics.i32_ty.const_int(i, false),
10152 "idx",
10153 ))
10154 .into_int_value();
10155 let replace_with_zero = err!(self.builder.build_extract_element(
10156 idx_out_of_range,
10157 self.intrinsics.i32_ty.const_int(i, false),
10158 "replace_with_zero",
10159 ))
10160 .into_int_value();
10161 let elem =
10162 err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10163 let elem_or_zero = err!(self.builder.build_select(
10164 replace_with_zero,
10165 self.intrinsics.i8_zero,
10166 elem,
10167 "elem_or_zero",
10168 ));
10169 res = err!(self.builder.build_insert_element(
10170 res,
10171 elem_or_zero,
10172 self.intrinsics.i32_ty.const_int(i, false),
10173 "",
10174 ));
10175 }
10176 let res = err!(
10177 self.builder
10178 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10179 );
10180 self.state.push1(res);
10181 }
10182 Operator::I8x16Shuffle { lanes } => {
10183 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10184 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10185 let v1 = err!(
10186 self.builder
10187 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10188 )
10189 .into_vector_value();
10190 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10191 let v2 = err!(
10192 self.builder
10193 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10194 )
10195 .into_vector_value();
10196 let mask = VectorType::const_vector(
10197 lanes
10198 .iter()
10199 .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10200 .collect::<Vec<IntValue>>()
10201 .as_slice(),
10202 );
10203 let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10204 let res = err!(
10205 self.builder
10206 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10207 );
10208 self.state.push1(res);
10209 }
10210 Operator::V128Load8x8S { ref memarg } => {
10211 let offset = self.state.pop1()?.into_int_value();
10212 let memory_index = MemoryIndex::from_u32(0);
10213 let effective_address = self.resolve_memory_ptr(
10214 memory_index,
10215 memarg,
10216 self.intrinsics.ptr_ty,
10217 offset,
10218 8,
10219 )?;
10220 let v = err!(self.builder.build_load(
10221 self.intrinsics.i64_ty,
10222 effective_address,
10223 ""
10224 ));
10225 let v = err!(
10226 self.builder
10227 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10228 )
10229 .into_vector_value();
10230 let res = err!(
10231 self.builder
10232 .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10233 );
10234 let res = err!(
10235 self.builder
10236 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10237 );
10238 self.state.push1(res);
10239 }
10240 Operator::V128Load8x8U { ref memarg } => {
10241 let offset = self.state.pop1()?.into_int_value();
10242 let memory_index = MemoryIndex::from_u32(0);
10243 let effective_address = self.resolve_memory_ptr(
10244 memory_index,
10245 memarg,
10246 self.intrinsics.ptr_ty,
10247 offset,
10248 8,
10249 )?;
10250 let v = err!(self.builder.build_load(
10251 self.intrinsics.i64_ty,
10252 effective_address,
10253 ""
10254 ));
10255 let v = err!(
10256 self.builder
10257 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10258 )
10259 .into_vector_value();
10260 let res = err!(
10261 self.builder
10262 .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10263 );
10264 let res = err!(
10265 self.builder
10266 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10267 );
10268 self.state.push1(res);
10269 }
10270 Operator::V128Load16x4S { ref memarg } => {
10271 let offset = self.state.pop1()?.into_int_value();
10272 let memory_index = MemoryIndex::from_u32(0);
10273 let effective_address = self.resolve_memory_ptr(
10274 memory_index,
10275 memarg,
10276 self.intrinsics.ptr_ty,
10277 offset,
10278 8,
10279 )?;
10280 let v = err!(self.builder.build_load(
10281 self.intrinsics.i64_ty,
10282 effective_address,
10283 ""
10284 ));
10285 let v = err!(self.builder.build_bit_cast(
10286 v,
10287 self.intrinsics.i16_ty.vec_type(4),
10288 ""
10289 ))
10290 .into_vector_value();
10291 let res = err!(
10292 self.builder
10293 .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10294 );
10295 let res = err!(
10296 self.builder
10297 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10298 );
10299 self.state.push1(res);
10300 }
10301 Operator::V128Load16x4U { ref memarg } => {
10302 let offset = self.state.pop1()?.into_int_value();
10303 let memory_index = MemoryIndex::from_u32(0);
10304 let effective_address = self.resolve_memory_ptr(
10305 memory_index,
10306 memarg,
10307 self.intrinsics.ptr_ty,
10308 offset,
10309 8,
10310 )?;
10311 let v = err!(self.builder.build_load(
10312 self.intrinsics.i64_ty,
10313 effective_address,
10314 ""
10315 ));
10316 let v = err!(self.builder.build_bit_cast(
10317 v,
10318 self.intrinsics.i16_ty.vec_type(4),
10319 ""
10320 ))
10321 .into_vector_value();
10322 let res = err!(
10323 self.builder
10324 .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10325 );
10326 let res = err!(
10327 self.builder
10328 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10329 );
10330 self.state.push1(res);
10331 }
10332 Operator::V128Load32x2S { ref memarg } => {
10333 let offset = self.state.pop1()?.into_int_value();
10334 let memory_index = MemoryIndex::from_u32(0);
10335 let effective_address = self.resolve_memory_ptr(
10336 memory_index,
10337 memarg,
10338 self.intrinsics.ptr_ty,
10339 offset,
10340 8,
10341 )?;
10342 let v = err!(self.builder.build_load(
10343 self.intrinsics.i64_ty,
10344 effective_address,
10345 ""
10346 ));
10347 let v = err!(self.builder.build_bit_cast(
10348 v,
10349 self.intrinsics.i32_ty.vec_type(2),
10350 ""
10351 ))
10352 .into_vector_value();
10353 let res = err!(
10354 self.builder
10355 .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10356 );
10357 let res = err!(
10358 self.builder
10359 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10360 );
10361 self.state.push1(res);
10362 }
10363 Operator::V128Load32x2U { ref memarg } => {
10364 let offset = self.state.pop1()?.into_int_value();
10365 let memory_index = MemoryIndex::from_u32(0);
10366 let effective_address = self.resolve_memory_ptr(
10367 memory_index,
10368 memarg,
10369 self.intrinsics.ptr_ty,
10370 offset,
10371 8,
10372 )?;
10373 let v = err!(self.builder.build_load(
10374 self.intrinsics.i64_ty,
10375 effective_address,
10376 ""
10377 ));
10378 let v = err!(self.builder.build_bit_cast(
10379 v,
10380 self.intrinsics.i32_ty.vec_type(2),
10381 ""
10382 ))
10383 .into_vector_value();
10384 let res = err!(
10385 self.builder
10386 .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10387 );
10388 let res = err!(
10389 self.builder
10390 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10391 );
10392 self.state.push1(res);
10393 }
10394 Operator::V128Load32Zero { ref memarg } => {
10395 let offset = self.state.pop1()?.into_int_value();
10396 let memory_index = MemoryIndex::from_u32(0);
10397 let effective_address = self.resolve_memory_ptr(
10398 memory_index,
10399 memarg,
10400 self.intrinsics.ptr_ty,
10401 offset,
10402 4,
10403 )?;
10404 let elem = err!(self.builder.build_load(
10405 self.intrinsics.i32_ty,
10406 effective_address,
10407 ""
10408 ));
10409 self.annotate_user_memaccess(
10410 memory_index,
10411 memarg,
10412 1,
10413 elem.as_instruction_value().unwrap(),
10414 )?;
10415 let res = err!(self.builder.build_int_z_extend(
10416 elem.into_int_value(),
10417 self.intrinsics.i128_ty,
10418 "",
10419 ));
10420 self.state.push1(res);
10421 }
10422 Operator::V128Load64Zero { ref memarg } => {
10423 let offset = self.state.pop1()?.into_int_value();
10424 let memory_index = MemoryIndex::from_u32(0);
10425 let effective_address = self.resolve_memory_ptr(
10426 memory_index,
10427 memarg,
10428 self.intrinsics.ptr_ty,
10429 offset,
10430 8,
10431 )?;
10432 let elem = err!(self.builder.build_load(
10433 self.intrinsics.i64_ty,
10434 effective_address,
10435 ""
10436 ));
10437 self.annotate_user_memaccess(
10438 memory_index,
10439 memarg,
10440 1,
10441 elem.as_instruction_value().unwrap(),
10442 )?;
10443 let res = err!(self.builder.build_int_z_extend(
10444 elem.into_int_value(),
10445 self.intrinsics.i128_ty,
10446 "",
10447 ));
10448 self.state.push1(res);
10449 }
10450 Operator::V128Load8Splat { ref memarg } => {
10451 let offset = self.state.pop1()?.into_int_value();
10452 let memory_index = MemoryIndex::from_u32(0);
10453 let effective_address = self.resolve_memory_ptr(
10454 memory_index,
10455 memarg,
10456 self.intrinsics.ptr_ty,
10457 offset,
10458 1,
10459 )?;
10460 let elem = err!(self.builder.build_load(
10461 self.intrinsics.i8_ty,
10462 effective_address,
10463 ""
10464 ));
10465 self.annotate_user_memaccess(
10466 memory_index,
10467 memarg,
10468 1,
10469 elem.as_instruction_value().unwrap(),
10470 )?;
10471 let res = self.splat_vector(elem, self.intrinsics.i8x16_ty)?;
10472 let res = err!(
10473 self.builder
10474 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10475 );
10476 self.state.push1(res);
10477 }
10478 Operator::V128Load16Splat { ref memarg } => {
10479 let offset = self.state.pop1()?.into_int_value();
10480 let memory_index = MemoryIndex::from_u32(0);
10481 let effective_address = self.resolve_memory_ptr(
10482 memory_index,
10483 memarg,
10484 self.intrinsics.ptr_ty,
10485 offset,
10486 2,
10487 )?;
10488 let elem = err!(self.builder.build_load(
10489 self.intrinsics.i16_ty,
10490 effective_address,
10491 ""
10492 ));
10493 self.annotate_user_memaccess(
10494 memory_index,
10495 memarg,
10496 1,
10497 elem.as_instruction_value().unwrap(),
10498 )?;
10499 let res = self.splat_vector(elem, self.intrinsics.i16x8_ty)?;
10500 let res = err!(
10501 self.builder
10502 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10503 );
10504 self.state.push1(res);
10505 }
10506 Operator::V128Load32Splat { ref memarg } => {
10507 let offset = self.state.pop1()?.into_int_value();
10508 let memory_index = MemoryIndex::from_u32(0);
10509 let effective_address = self.resolve_memory_ptr(
10510 memory_index,
10511 memarg,
10512 self.intrinsics.ptr_ty,
10513 offset,
10514 4,
10515 )?;
10516 let elem = err!(self.builder.build_load(
10517 self.intrinsics.i32_ty,
10518 effective_address,
10519 ""
10520 ));
10521 self.annotate_user_memaccess(
10522 memory_index,
10523 memarg,
10524 1,
10525 elem.as_instruction_value().unwrap(),
10526 )?;
10527 let res = self.splat_vector(elem, self.intrinsics.i32x4_ty)?;
10528 let res = err!(
10529 self.builder
10530 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10531 );
10532 self.state.push1(res);
10533 }
10534 Operator::V128Load64Splat { ref memarg } => {
10535 let offset = self.state.pop1()?.into_int_value();
10536 let memory_index = MemoryIndex::from_u32(0);
10537 let effective_address = self.resolve_memory_ptr(
10538 memory_index,
10539 memarg,
10540 self.intrinsics.ptr_ty,
10541 offset,
10542 8,
10543 )?;
10544 let elem = err!(self.builder.build_load(
10545 self.intrinsics.i64_ty,
10546 effective_address,
10547 ""
10548 ));
10549 self.annotate_user_memaccess(
10550 memory_index,
10551 memarg,
10552 1,
10553 elem.as_instruction_value().unwrap(),
10554 )?;
10555 let res = self.splat_vector(elem, self.intrinsics.i64x2_ty)?;
10556 let res = err!(
10557 self.builder
10558 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10559 );
10560 self.state.push1(res);
10561 }
10562 Operator::AtomicFence => {
10563 }
10571 Operator::I32AtomicLoad { ref memarg } => {
10572 let offset = self.state.pop1()?.into_int_value();
10573 let memory_index = MemoryIndex::from_u32(0);
10574 let effective_address = self.resolve_memory_ptr(
10575 memory_index,
10576 memarg,
10577 self.intrinsics.ptr_ty,
10578 offset,
10579 4,
10580 )?;
10581 self.trap_if_misaligned(memarg, effective_address, 4)?;
10582 let result = err!(self.builder.build_load(
10583 self.intrinsics.i32_ty,
10584 effective_address,
10585 "atomic_load"
10586 ));
10587 let load = result.as_instruction_value().unwrap();
10588 self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10589 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10590 .unwrap();
10591 self.state.push1(result);
10592 }
10593 Operator::I64AtomicLoad { ref memarg } => {
10594 let offset = self.state.pop1()?.into_int_value();
10595 let memory_index = MemoryIndex::from_u32(0);
10596 let effective_address = self.resolve_memory_ptr(
10597 memory_index,
10598 memarg,
10599 self.intrinsics.ptr_ty,
10600 offset,
10601 8,
10602 )?;
10603 self.trap_if_misaligned(memarg, effective_address, 8)?;
10604 let result = err!(self.builder.build_load(
10605 self.intrinsics.i64_ty,
10606 effective_address,
10607 ""
10608 ));
10609 let load = result.as_instruction_value().unwrap();
10610 self.annotate_user_memaccess(memory_index, memarg, 8, load)?;
10611 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10612 .unwrap();
10613 self.state.push1(result);
10614 }
10615 Operator::I32AtomicLoad8U { ref memarg } => {
10616 let offset = self.state.pop1()?.into_int_value();
10617 let memory_index = MemoryIndex::from_u32(0);
10618 let effective_address = self.resolve_memory_ptr(
10619 memory_index,
10620 memarg,
10621 self.intrinsics.ptr_ty,
10622 offset,
10623 1,
10624 )?;
10625 self.trap_if_misaligned(memarg, effective_address, 1)?;
10626 let narrow_result = err!(self.builder.build_load(
10627 self.intrinsics.i8_ty,
10628 effective_address,
10629 ""
10630 ))
10631 .into_int_value();
10632 let load = narrow_result.as_instruction_value().unwrap();
10633 self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10634 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10635 .unwrap();
10636 let result = err!(self.builder.build_int_z_extend(
10637 narrow_result,
10638 self.intrinsics.i32_ty,
10639 ""
10640 ));
10641 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10642 }
10643 Operator::I32AtomicLoad16U { ref memarg } => {
10644 let offset = self.state.pop1()?.into_int_value();
10645 let memory_index = MemoryIndex::from_u32(0);
10646 let effective_address = self.resolve_memory_ptr(
10647 memory_index,
10648 memarg,
10649 self.intrinsics.ptr_ty,
10650 offset,
10651 2,
10652 )?;
10653 self.trap_if_misaligned(memarg, effective_address, 2)?;
10654 let narrow_result = err!(self.builder.build_load(
10655 self.intrinsics.i16_ty,
10656 effective_address,
10657 ""
10658 ))
10659 .into_int_value();
10660 let load = narrow_result.as_instruction_value().unwrap();
10661 self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10662 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10663 .unwrap();
10664 let result = err!(self.builder.build_int_z_extend(
10665 narrow_result,
10666 self.intrinsics.i32_ty,
10667 ""
10668 ));
10669 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10670 }
10671 Operator::I64AtomicLoad8U { ref memarg } => {
10672 let offset = self.state.pop1()?.into_int_value();
10673 let memory_index = MemoryIndex::from_u32(0);
10674 let effective_address = self.resolve_memory_ptr(
10675 memory_index,
10676 memarg,
10677 self.intrinsics.ptr_ty,
10678 offset,
10679 1,
10680 )?;
10681 self.trap_if_misaligned(memarg, effective_address, 1)?;
10682 let narrow_result = err!(self.builder.build_load(
10683 self.intrinsics.i8_ty,
10684 effective_address,
10685 ""
10686 ))
10687 .into_int_value();
10688 let load = narrow_result.as_instruction_value().unwrap();
10689 self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10690 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10691 .unwrap();
10692 let result = err!(self.builder.build_int_z_extend(
10693 narrow_result,
10694 self.intrinsics.i64_ty,
10695 ""
10696 ));
10697 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10698 }
10699 Operator::I64AtomicLoad16U { ref memarg } => {
10700 let offset = self.state.pop1()?.into_int_value();
10701 let memory_index = MemoryIndex::from_u32(0);
10702 let effective_address = self.resolve_memory_ptr(
10703 memory_index,
10704 memarg,
10705 self.intrinsics.ptr_ty,
10706 offset,
10707 2,
10708 )?;
10709 self.trap_if_misaligned(memarg, effective_address, 2)?;
10710 let narrow_result = err!(self.builder.build_load(
10711 self.intrinsics.i16_ty,
10712 effective_address,
10713 ""
10714 ))
10715 .into_int_value();
10716 let load = narrow_result.as_instruction_value().unwrap();
10717 self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10718 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10719 .unwrap();
10720 let result = err!(self.builder.build_int_z_extend(
10721 narrow_result,
10722 self.intrinsics.i64_ty,
10723 ""
10724 ));
10725 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10726 }
10727 Operator::I64AtomicLoad32U { ref memarg } => {
10728 let offset = self.state.pop1()?.into_int_value();
10729 let memory_index = MemoryIndex::from_u32(0);
10730 let effective_address = self.resolve_memory_ptr(
10731 memory_index,
10732 memarg,
10733 self.intrinsics.ptr_ty,
10734 offset,
10735 4,
10736 )?;
10737 self.trap_if_misaligned(memarg, effective_address, 4)?;
10738 let narrow_result = err!(self.builder.build_load(
10739 self.intrinsics.i32_ty,
10740 effective_address,
10741 ""
10742 ))
10743 .into_int_value();
10744 let load = narrow_result.as_instruction_value().unwrap();
10745 self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10746 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10747 .unwrap();
10748 let result = err!(self.builder.build_int_z_extend(
10749 narrow_result,
10750 self.intrinsics.i64_ty,
10751 ""
10752 ));
10753 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10754 }
10755 Operator::I32AtomicStore { ref memarg } => {
10756 let value = self.state.pop1()?;
10757 let offset = self.state.pop1()?.into_int_value();
10758 let memory_index = MemoryIndex::from_u32(0);
10759 let effective_address = self.resolve_memory_ptr(
10760 memory_index,
10761 memarg,
10762 self.intrinsics.ptr_ty,
10763 offset,
10764 4,
10765 )?;
10766 self.trap_if_misaligned(memarg, effective_address, 4)?;
10767 let store = err!(self.builder.build_store(effective_address, value));
10768 self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
10769 store
10770 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10771 .unwrap();
10772 }
10773 Operator::I64AtomicStore { ref memarg } => {
10774 let value = self.state.pop1()?;
10775 let offset = self.state.pop1()?.into_int_value();
10776 let memory_index = MemoryIndex::from_u32(0);
10777 let effective_address = self.resolve_memory_ptr(
10778 memory_index,
10779 memarg,
10780 self.intrinsics.ptr_ty,
10781 offset,
10782 8,
10783 )?;
10784 self.trap_if_misaligned(memarg, effective_address, 8)?;
10785 let store = err!(self.builder.build_store(effective_address, value));
10786 self.annotate_user_memaccess(memory_index, memarg, 8, store)?;
10787 store
10788 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10789 .unwrap();
10790 }
10791 Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10792 let value = self.state.pop1()?.into_int_value();
10793 let offset = self.state.pop1()?.into_int_value();
10794 let memory_index = MemoryIndex::from_u32(0);
10795 let effective_address = self.resolve_memory_ptr(
10796 memory_index,
10797 memarg,
10798 self.intrinsics.ptr_ty,
10799 offset,
10800 1,
10801 )?;
10802 self.trap_if_misaligned(memarg, effective_address, 1)?;
10803 let narrow_value = err!(self.builder.build_int_truncate(
10804 value,
10805 self.intrinsics.i8_ty,
10806 ""
10807 ));
10808 let store = err!(self.builder.build_store(effective_address, narrow_value));
10809 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
10810 store
10811 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10812 .unwrap();
10813 }
10814 Operator::I32AtomicStore16 { ref memarg }
10815 | Operator::I64AtomicStore16 { ref memarg } => {
10816 let value = self.state.pop1()?.into_int_value();
10817 let offset = self.state.pop1()?.into_int_value();
10818 let memory_index = MemoryIndex::from_u32(0);
10819 let effective_address = self.resolve_memory_ptr(
10820 memory_index,
10821 memarg,
10822 self.intrinsics.ptr_ty,
10823 offset,
10824 2,
10825 )?;
10826 self.trap_if_misaligned(memarg, effective_address, 2)?;
10827 let narrow_value = err!(self.builder.build_int_truncate(
10828 value,
10829 self.intrinsics.i16_ty,
10830 ""
10831 ));
10832 let store = err!(self.builder.build_store(effective_address, narrow_value));
10833 self.annotate_user_memaccess(memory_index, memarg, 2, store)?;
10834 store
10835 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10836 .unwrap();
10837 }
10838 Operator::I64AtomicStore32 { ref memarg } => {
10839 let value = self.state.pop1()?.into_int_value();
10840 let offset = self.state.pop1()?.into_int_value();
10841 let memory_index = MemoryIndex::from_u32(0);
10842 let effective_address = self.resolve_memory_ptr(
10843 memory_index,
10844 memarg,
10845 self.intrinsics.ptr_ty,
10846 offset,
10847 4,
10848 )?;
10849 self.trap_if_misaligned(memarg, effective_address, 4)?;
10850 let narrow_value = err!(self.builder.build_int_truncate(
10851 value,
10852 self.intrinsics.i32_ty,
10853 ""
10854 ));
10855 let store = err!(self.builder.build_store(effective_address, narrow_value));
10856 self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
10857 store
10858 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10859 .unwrap();
10860 }
10861 Operator::I32AtomicRmw8AddU { ref memarg } => {
10862 let value = self.state.pop1()?.into_int_value();
10863 let offset = self.state.pop1()?.into_int_value();
10864 let memory_index = MemoryIndex::from_u32(0);
10865 let effective_address = self.resolve_memory_ptr(
10866 memory_index,
10867 memarg,
10868 self.intrinsics.ptr_ty,
10869 offset,
10870 1,
10871 )?;
10872 self.trap_if_misaligned(memarg, effective_address, 1)?;
10873 let narrow_value = err!(self.builder.build_int_truncate(
10874 value,
10875 self.intrinsics.i8_ty,
10876 ""
10877 ));
10878 let old = self
10879 .builder
10880 .build_atomicrmw(
10881 AtomicRMWBinOp::Add,
10882 effective_address,
10883 narrow_value,
10884 AtomicOrdering::SequentiallyConsistent,
10885 )
10886 .unwrap();
10887 tbaa_label(
10888 self.module,
10889 self.intrinsics,
10890 format!("memory {}", memory_index.as_u32()),
10891 old.as_instruction_value().unwrap(),
10892 );
10893 let old = err!(
10894 self.builder
10895 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
10896 );
10897 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
10898 }
10899 Operator::I32AtomicRmw16AddU { ref memarg } => {
10900 let value = self.state.pop1()?.into_int_value();
10901 let offset = self.state.pop1()?.into_int_value();
10902 let memory_index = MemoryIndex::from_u32(0);
10903 let effective_address = self.resolve_memory_ptr(
10904 memory_index,
10905 memarg,
10906 self.intrinsics.ptr_ty,
10907 offset,
10908 2,
10909 )?;
10910 self.trap_if_misaligned(memarg, effective_address, 2)?;
10911 let narrow_value = err!(self.builder.build_int_truncate(
10912 value,
10913 self.intrinsics.i16_ty,
10914 ""
10915 ));
10916 let old = self
10917 .builder
10918 .build_atomicrmw(
10919 AtomicRMWBinOp::Add,
10920 effective_address,
10921 narrow_value,
10922 AtomicOrdering::SequentiallyConsistent,
10923 )
10924 .unwrap();
10925 tbaa_label(
10926 self.module,
10927 self.intrinsics,
10928 format!("memory {}", memory_index.as_u32()),
10929 old.as_instruction_value().unwrap(),
10930 );
10931 let old = err!(
10932 self.builder
10933 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
10934 );
10935 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
10936 }
10937 Operator::I32AtomicRmwAdd { ref memarg } => {
10938 let value = self.state.pop1()?.into_int_value();
10939 let offset = self.state.pop1()?.into_int_value();
10940 let memory_index = MemoryIndex::from_u32(0);
10941 let effective_address = self.resolve_memory_ptr(
10942 memory_index,
10943 memarg,
10944 self.intrinsics.ptr_ty,
10945 offset,
10946 4,
10947 )?;
10948 self.trap_if_misaligned(memarg, effective_address, 4)?;
10949 let old = self
10950 .builder
10951 .build_atomicrmw(
10952 AtomicRMWBinOp::Add,
10953 effective_address,
10954 value,
10955 AtomicOrdering::SequentiallyConsistent,
10956 )
10957 .unwrap();
10958 tbaa_label(
10959 self.module,
10960 self.intrinsics,
10961 format!("memory {}", memory_index.as_u32()),
10962 old.as_instruction_value().unwrap(),
10963 );
10964 self.state.push1(old);
10965 }
10966 Operator::I64AtomicRmw8AddU { ref memarg } => {
10967 let value = self.state.pop1()?.into_int_value();
10968 let offset = self.state.pop1()?.into_int_value();
10969 let memory_index = MemoryIndex::from_u32(0);
10970 let effective_address = self.resolve_memory_ptr(
10971 memory_index,
10972 memarg,
10973 self.intrinsics.ptr_ty,
10974 offset,
10975 1,
10976 )?;
10977 self.trap_if_misaligned(memarg, effective_address, 1)?;
10978 let narrow_value = err!(self.builder.build_int_truncate(
10979 value,
10980 self.intrinsics.i8_ty,
10981 ""
10982 ));
10983 let old = self
10984 .builder
10985 .build_atomicrmw(
10986 AtomicRMWBinOp::Add,
10987 effective_address,
10988 narrow_value,
10989 AtomicOrdering::SequentiallyConsistent,
10990 )
10991 .unwrap();
10992 self.annotate_user_memaccess(
10993 memory_index,
10994 memarg,
10995 0,
10996 old.as_instruction_value().unwrap(),
10997 )?;
10998 let old = err!(
10999 self.builder
11000 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11001 );
11002 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11003 }
11004 Operator::I64AtomicRmw16AddU { ref memarg } => {
11005 let value = self.state.pop1()?.into_int_value();
11006 let offset = self.state.pop1()?.into_int_value();
11007 let memory_index = MemoryIndex::from_u32(0);
11008 let effective_address = self.resolve_memory_ptr(
11009 memory_index,
11010 memarg,
11011 self.intrinsics.ptr_ty,
11012 offset,
11013 2,
11014 )?;
11015 self.trap_if_misaligned(memarg, effective_address, 2)?;
11016 let narrow_value = err!(self.builder.build_int_truncate(
11017 value,
11018 self.intrinsics.i16_ty,
11019 ""
11020 ));
11021 let old = self
11022 .builder
11023 .build_atomicrmw(
11024 AtomicRMWBinOp::Add,
11025 effective_address,
11026 narrow_value,
11027 AtomicOrdering::SequentiallyConsistent,
11028 )
11029 .unwrap();
11030 self.annotate_user_memaccess(
11031 memory_index,
11032 memarg,
11033 0,
11034 old.as_instruction_value().unwrap(),
11035 )?;
11036 let old = err!(
11037 self.builder
11038 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11039 );
11040 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11041 }
11042 Operator::I64AtomicRmw32AddU { ref memarg } => {
11043 let value = self.state.pop1()?.into_int_value();
11044 let offset = self.state.pop1()?.into_int_value();
11045 let memory_index = MemoryIndex::from_u32(0);
11046 let effective_address = self.resolve_memory_ptr(
11047 memory_index,
11048 memarg,
11049 self.intrinsics.ptr_ty,
11050 offset,
11051 4,
11052 )?;
11053 self.trap_if_misaligned(memarg, effective_address, 4)?;
11054 let narrow_value = err!(self.builder.build_int_truncate(
11055 value,
11056 self.intrinsics.i32_ty,
11057 ""
11058 ));
11059 let old = self
11060 .builder
11061 .build_atomicrmw(
11062 AtomicRMWBinOp::Add,
11063 effective_address,
11064 narrow_value,
11065 AtomicOrdering::SequentiallyConsistent,
11066 )
11067 .unwrap();
11068 self.annotate_user_memaccess(
11069 memory_index,
11070 memarg,
11071 0,
11072 old.as_instruction_value().unwrap(),
11073 )?;
11074 let old = err!(
11075 self.builder
11076 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11077 );
11078 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11079 }
11080 Operator::I64AtomicRmwAdd { ref memarg } => {
11081 let value = self.state.pop1()?.into_int_value();
11082 let offset = self.state.pop1()?.into_int_value();
11083 let memory_index = MemoryIndex::from_u32(0);
11084 let effective_address = self.resolve_memory_ptr(
11085 memory_index,
11086 memarg,
11087 self.intrinsics.ptr_ty,
11088 offset,
11089 8,
11090 )?;
11091 self.trap_if_misaligned(memarg, effective_address, 8)?;
11092 let old = self
11093 .builder
11094 .build_atomicrmw(
11095 AtomicRMWBinOp::Add,
11096 effective_address,
11097 value,
11098 AtomicOrdering::SequentiallyConsistent,
11099 )
11100 .unwrap();
11101 self.annotate_user_memaccess(
11102 memory_index,
11103 memarg,
11104 0,
11105 old.as_instruction_value().unwrap(),
11106 )?;
11107 self.state.push1(old);
11108 }
11109 Operator::I32AtomicRmw8SubU { ref memarg } => {
11110 let value = self.state.pop1()?.into_int_value();
11111 let offset = self.state.pop1()?.into_int_value();
11112 let memory_index = MemoryIndex::from_u32(0);
11113 let effective_address = self.resolve_memory_ptr(
11114 memory_index,
11115 memarg,
11116 self.intrinsics.ptr_ty,
11117 offset,
11118 1,
11119 )?;
11120 self.trap_if_misaligned(memarg, effective_address, 1)?;
11121 let narrow_value = err!(self.builder.build_int_truncate(
11122 value,
11123 self.intrinsics.i8_ty,
11124 ""
11125 ));
11126 let old = self
11127 .builder
11128 .build_atomicrmw(
11129 AtomicRMWBinOp::Sub,
11130 effective_address,
11131 narrow_value,
11132 AtomicOrdering::SequentiallyConsistent,
11133 )
11134 .unwrap();
11135 self.annotate_user_memaccess(
11136 memory_index,
11137 memarg,
11138 0,
11139 old.as_instruction_value().unwrap(),
11140 )?;
11141 let old = err!(
11142 self.builder
11143 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11144 );
11145 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11146 }
11147 Operator::I32AtomicRmw16SubU { ref memarg } => {
11148 let value = self.state.pop1()?.into_int_value();
11149 let offset = self.state.pop1()?.into_int_value();
11150 let memory_index = MemoryIndex::from_u32(0);
11151 let effective_address = self.resolve_memory_ptr(
11152 memory_index,
11153 memarg,
11154 self.intrinsics.ptr_ty,
11155 offset,
11156 2,
11157 )?;
11158 self.trap_if_misaligned(memarg, effective_address, 2)?;
11159 let narrow_value = err!(self.builder.build_int_truncate(
11160 value,
11161 self.intrinsics.i16_ty,
11162 ""
11163 ));
11164 let old = self
11165 .builder
11166 .build_atomicrmw(
11167 AtomicRMWBinOp::Sub,
11168 effective_address,
11169 narrow_value,
11170 AtomicOrdering::SequentiallyConsistent,
11171 )
11172 .unwrap();
11173 self.annotate_user_memaccess(
11174 memory_index,
11175 memarg,
11176 0,
11177 old.as_instruction_value().unwrap(),
11178 )?;
11179 let old = err!(
11180 self.builder
11181 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11182 );
11183 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11184 }
11185 Operator::I32AtomicRmwSub { ref memarg } => {
11186 let value = self.state.pop1()?.into_int_value();
11187 let offset = self.state.pop1()?.into_int_value();
11188 let memory_index = MemoryIndex::from_u32(0);
11189 let effective_address = self.resolve_memory_ptr(
11190 memory_index,
11191 memarg,
11192 self.intrinsics.ptr_ty,
11193 offset,
11194 4,
11195 )?;
11196 self.trap_if_misaligned(memarg, effective_address, 4)?;
11197 let old = self
11198 .builder
11199 .build_atomicrmw(
11200 AtomicRMWBinOp::Sub,
11201 effective_address,
11202 value,
11203 AtomicOrdering::SequentiallyConsistent,
11204 )
11205 .unwrap();
11206 self.annotate_user_memaccess(
11207 memory_index,
11208 memarg,
11209 0,
11210 old.as_instruction_value().unwrap(),
11211 )?;
11212 self.state.push1(old);
11213 }
11214 Operator::I64AtomicRmw8SubU { ref memarg } => {
11215 let value = self.state.pop1()?.into_int_value();
11216 let offset = self.state.pop1()?.into_int_value();
11217 let memory_index = MemoryIndex::from_u32(0);
11218 let effective_address = self.resolve_memory_ptr(
11219 memory_index,
11220 memarg,
11221 self.intrinsics.ptr_ty,
11222 offset,
11223 1,
11224 )?;
11225 self.trap_if_misaligned(memarg, effective_address, 1)?;
11226 let narrow_value = err!(self.builder.build_int_truncate(
11227 value,
11228 self.intrinsics.i8_ty,
11229 ""
11230 ));
11231 let old = self
11232 .builder
11233 .build_atomicrmw(
11234 AtomicRMWBinOp::Sub,
11235 effective_address,
11236 narrow_value,
11237 AtomicOrdering::SequentiallyConsistent,
11238 )
11239 .unwrap();
11240 self.annotate_user_memaccess(
11241 memory_index,
11242 memarg,
11243 0,
11244 old.as_instruction_value().unwrap(),
11245 )?;
11246 let old = err!(
11247 self.builder
11248 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11249 );
11250 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11251 }
11252 Operator::I64AtomicRmw16SubU { ref memarg } => {
11253 let value = self.state.pop1()?.into_int_value();
11254 let offset = self.state.pop1()?.into_int_value();
11255 let memory_index = MemoryIndex::from_u32(0);
11256 let effective_address = self.resolve_memory_ptr(
11257 memory_index,
11258 memarg,
11259 self.intrinsics.ptr_ty,
11260 offset,
11261 2,
11262 )?;
11263 self.trap_if_misaligned(memarg, effective_address, 2)?;
11264 let narrow_value = err!(self.builder.build_int_truncate(
11265 value,
11266 self.intrinsics.i16_ty,
11267 ""
11268 ));
11269 let old = self
11270 .builder
11271 .build_atomicrmw(
11272 AtomicRMWBinOp::Sub,
11273 effective_address,
11274 narrow_value,
11275 AtomicOrdering::SequentiallyConsistent,
11276 )
11277 .unwrap();
11278 self.annotate_user_memaccess(
11279 memory_index,
11280 memarg,
11281 0,
11282 old.as_instruction_value().unwrap(),
11283 )?;
11284 let old = err!(
11285 self.builder
11286 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11287 );
11288 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11289 }
11290 Operator::I64AtomicRmw32SubU { ref memarg } => {
11291 let value = self.state.pop1()?.into_int_value();
11292 let offset = self.state.pop1()?.into_int_value();
11293 let memory_index = MemoryIndex::from_u32(0);
11294 let effective_address = self.resolve_memory_ptr(
11295 memory_index,
11296 memarg,
11297 self.intrinsics.ptr_ty,
11298 offset,
11299 4,
11300 )?;
11301 self.trap_if_misaligned(memarg, effective_address, 4)?;
11302 let narrow_value = err!(self.builder.build_int_truncate(
11303 value,
11304 self.intrinsics.i32_ty,
11305 ""
11306 ));
11307 let old = self
11308 .builder
11309 .build_atomicrmw(
11310 AtomicRMWBinOp::Sub,
11311 effective_address,
11312 narrow_value,
11313 AtomicOrdering::SequentiallyConsistent,
11314 )
11315 .unwrap();
11316 self.annotate_user_memaccess(
11317 memory_index,
11318 memarg,
11319 0,
11320 old.as_instruction_value().unwrap(),
11321 )?;
11322 let old = err!(
11323 self.builder
11324 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11325 );
11326 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11327 }
11328 Operator::I64AtomicRmwSub { ref memarg } => {
11329 let value = self.state.pop1()?.into_int_value();
11330 let offset = self.state.pop1()?.into_int_value();
11331 let memory_index = MemoryIndex::from_u32(0);
11332 let effective_address = self.resolve_memory_ptr(
11333 memory_index,
11334 memarg,
11335 self.intrinsics.ptr_ty,
11336 offset,
11337 8,
11338 )?;
11339 self.trap_if_misaligned(memarg, effective_address, 8)?;
11340 let old = self
11341 .builder
11342 .build_atomicrmw(
11343 AtomicRMWBinOp::Sub,
11344 effective_address,
11345 value,
11346 AtomicOrdering::SequentiallyConsistent,
11347 )
11348 .unwrap();
11349 self.annotate_user_memaccess(
11350 memory_index,
11351 memarg,
11352 0,
11353 old.as_instruction_value().unwrap(),
11354 )?;
11355 self.state.push1(old);
11356 }
11357 Operator::I32AtomicRmw8AndU { ref memarg } => {
11358 let value = self.state.pop1()?.into_int_value();
11359 let offset = self.state.pop1()?.into_int_value();
11360 let memory_index = MemoryIndex::from_u32(0);
11361 let effective_address = self.resolve_memory_ptr(
11362 memory_index,
11363 memarg,
11364 self.intrinsics.ptr_ty,
11365 offset,
11366 1,
11367 )?;
11368 self.trap_if_misaligned(memarg, effective_address, 1)?;
11369 let narrow_value = err!(self.builder.build_int_truncate(
11370 value,
11371 self.intrinsics.i8_ty,
11372 ""
11373 ));
11374 let old = self
11375 .builder
11376 .build_atomicrmw(
11377 AtomicRMWBinOp::And,
11378 effective_address,
11379 narrow_value,
11380 AtomicOrdering::SequentiallyConsistent,
11381 )
11382 .unwrap();
11383 self.annotate_user_memaccess(
11384 memory_index,
11385 memarg,
11386 0,
11387 old.as_instruction_value().unwrap(),
11388 )?;
11389 let old = err!(
11390 self.builder
11391 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11392 );
11393 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11394 }
11395 Operator::I32AtomicRmw16AndU { ref memarg } => {
11396 let value = self.state.pop1()?.into_int_value();
11397 let offset = self.state.pop1()?.into_int_value();
11398 let memory_index = MemoryIndex::from_u32(0);
11399 let effective_address = self.resolve_memory_ptr(
11400 memory_index,
11401 memarg,
11402 self.intrinsics.ptr_ty,
11403 offset,
11404 2,
11405 )?;
11406 self.trap_if_misaligned(memarg, effective_address, 2)?;
11407 let narrow_value = err!(self.builder.build_int_truncate(
11408 value,
11409 self.intrinsics.i16_ty,
11410 ""
11411 ));
11412 let old = self
11413 .builder
11414 .build_atomicrmw(
11415 AtomicRMWBinOp::And,
11416 effective_address,
11417 narrow_value,
11418 AtomicOrdering::SequentiallyConsistent,
11419 )
11420 .unwrap();
11421 self.annotate_user_memaccess(
11422 memory_index,
11423 memarg,
11424 0,
11425 old.as_instruction_value().unwrap(),
11426 )?;
11427 let old = err!(
11428 self.builder
11429 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11430 );
11431 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11432 }
11433 Operator::I32AtomicRmwAnd { ref memarg } => {
11434 let value = self.state.pop1()?.into_int_value();
11435 let offset = self.state.pop1()?.into_int_value();
11436 let memory_index = MemoryIndex::from_u32(0);
11437 let effective_address = self.resolve_memory_ptr(
11438 memory_index,
11439 memarg,
11440 self.intrinsics.ptr_ty,
11441 offset,
11442 4,
11443 )?;
11444 self.trap_if_misaligned(memarg, effective_address, 4)?;
11445 let old = self
11446 .builder
11447 .build_atomicrmw(
11448 AtomicRMWBinOp::And,
11449 effective_address,
11450 value,
11451 AtomicOrdering::SequentiallyConsistent,
11452 )
11453 .unwrap();
11454 self.annotate_user_memaccess(
11455 memory_index,
11456 memarg,
11457 0,
11458 old.as_instruction_value().unwrap(),
11459 )?;
11460 self.state.push1(old);
11461 }
11462 Operator::I64AtomicRmw8AndU { ref memarg } => {
11463 let value = self.state.pop1()?.into_int_value();
11464 let offset = self.state.pop1()?.into_int_value();
11465 let memory_index = MemoryIndex::from_u32(0);
11466 let effective_address = self.resolve_memory_ptr(
11467 memory_index,
11468 memarg,
11469 self.intrinsics.ptr_ty,
11470 offset,
11471 1,
11472 )?;
11473 self.trap_if_misaligned(memarg, effective_address, 1)?;
11474 let narrow_value = err!(self.builder.build_int_truncate(
11475 value,
11476 self.intrinsics.i8_ty,
11477 ""
11478 ));
11479 let old = self
11480 .builder
11481 .build_atomicrmw(
11482 AtomicRMWBinOp::And,
11483 effective_address,
11484 narrow_value,
11485 AtomicOrdering::SequentiallyConsistent,
11486 )
11487 .unwrap();
11488 self.annotate_user_memaccess(
11489 memory_index,
11490 memarg,
11491 0,
11492 old.as_instruction_value().unwrap(),
11493 )?;
11494 let old = err!(
11495 self.builder
11496 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11497 );
11498 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11499 }
11500 Operator::I64AtomicRmw16AndU { ref memarg } => {
11501 let value = self.state.pop1()?.into_int_value();
11502 let offset = self.state.pop1()?.into_int_value();
11503 let memory_index = MemoryIndex::from_u32(0);
11504 let effective_address = self.resolve_memory_ptr(
11505 memory_index,
11506 memarg,
11507 self.intrinsics.ptr_ty,
11508 offset,
11509 2,
11510 )?;
11511 self.trap_if_misaligned(memarg, effective_address, 2)?;
11512 let narrow_value = err!(self.builder.build_int_truncate(
11513 value,
11514 self.intrinsics.i16_ty,
11515 ""
11516 ));
11517 let old = self
11518 .builder
11519 .build_atomicrmw(
11520 AtomicRMWBinOp::And,
11521 effective_address,
11522 narrow_value,
11523 AtomicOrdering::SequentiallyConsistent,
11524 )
11525 .unwrap();
11526 self.annotate_user_memaccess(
11527 memory_index,
11528 memarg,
11529 0,
11530 old.as_instruction_value().unwrap(),
11531 )?;
11532 let old = err!(
11533 self.builder
11534 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11535 );
11536 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11537 }
11538 Operator::I64AtomicRmw32AndU { ref memarg } => {
11539 let value = self.state.pop1()?.into_int_value();
11540 let offset = self.state.pop1()?.into_int_value();
11541 let memory_index = MemoryIndex::from_u32(0);
11542 let effective_address = self.resolve_memory_ptr(
11543 memory_index,
11544 memarg,
11545 self.intrinsics.ptr_ty,
11546 offset,
11547 4,
11548 )?;
11549 self.trap_if_misaligned(memarg, effective_address, 4)?;
11550 let narrow_value = err!(self.builder.build_int_truncate(
11551 value,
11552 self.intrinsics.i32_ty,
11553 ""
11554 ));
11555 let old = self
11556 .builder
11557 .build_atomicrmw(
11558 AtomicRMWBinOp::And,
11559 effective_address,
11560 narrow_value,
11561 AtomicOrdering::SequentiallyConsistent,
11562 )
11563 .unwrap();
11564 self.annotate_user_memaccess(
11565 memory_index,
11566 memarg,
11567 0,
11568 old.as_instruction_value().unwrap(),
11569 )?;
11570 let old = err!(
11571 self.builder
11572 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11573 );
11574 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11575 }
11576 Operator::I64AtomicRmwAnd { ref memarg } => {
11577 let value = self.state.pop1()?.into_int_value();
11578 let offset = self.state.pop1()?.into_int_value();
11579 let memory_index = MemoryIndex::from_u32(0);
11580 let effective_address = self.resolve_memory_ptr(
11581 memory_index,
11582 memarg,
11583 self.intrinsics.ptr_ty,
11584 offset,
11585 8,
11586 )?;
11587 self.trap_if_misaligned(memarg, effective_address, 8)?;
11588 let old = self
11589 .builder
11590 .build_atomicrmw(
11591 AtomicRMWBinOp::And,
11592 effective_address,
11593 value,
11594 AtomicOrdering::SequentiallyConsistent,
11595 )
11596 .unwrap();
11597 self.annotate_user_memaccess(
11598 memory_index,
11599 memarg,
11600 0,
11601 old.as_instruction_value().unwrap(),
11602 )?;
11603 self.state.push1(old);
11604 }
11605 Operator::I32AtomicRmw8OrU { ref memarg } => {
11606 let value = self.state.pop1()?.into_int_value();
11607 let offset = self.state.pop1()?.into_int_value();
11608 let memory_index = MemoryIndex::from_u32(0);
11609 let effective_address = self.resolve_memory_ptr(
11610 memory_index,
11611 memarg,
11612 self.intrinsics.ptr_ty,
11613 offset,
11614 1,
11615 )?;
11616 self.trap_if_misaligned(memarg, effective_address, 1)?;
11617 let narrow_value = err!(self.builder.build_int_truncate(
11618 value,
11619 self.intrinsics.i8_ty,
11620 ""
11621 ));
11622 let old = self
11623 .builder
11624 .build_atomicrmw(
11625 AtomicRMWBinOp::Or,
11626 effective_address,
11627 narrow_value,
11628 AtomicOrdering::SequentiallyConsistent,
11629 )
11630 .unwrap();
11631 self.annotate_user_memaccess(
11632 memory_index,
11633 memarg,
11634 0,
11635 old.as_instruction_value().unwrap(),
11636 )?;
11637 let old = err!(
11638 self.builder
11639 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11640 );
11641 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11642 }
11643 Operator::I32AtomicRmw16OrU { ref memarg } => {
11644 let value = self.state.pop1()?.into_int_value();
11645 let offset = self.state.pop1()?.into_int_value();
11646 let memory_index = MemoryIndex::from_u32(0);
11647 let effective_address = self.resolve_memory_ptr(
11648 memory_index,
11649 memarg,
11650 self.intrinsics.ptr_ty,
11651 offset,
11652 2,
11653 )?;
11654 self.trap_if_misaligned(memarg, effective_address, 2)?;
11655 let narrow_value = err!(self.builder.build_int_truncate(
11656 value,
11657 self.intrinsics.i16_ty,
11658 ""
11659 ));
11660 let old = self
11661 .builder
11662 .build_atomicrmw(
11663 AtomicRMWBinOp::Or,
11664 effective_address,
11665 narrow_value,
11666 AtomicOrdering::SequentiallyConsistent,
11667 )
11668 .unwrap();
11669 self.annotate_user_memaccess(
11670 memory_index,
11671 memarg,
11672 0,
11673 old.as_instruction_value().unwrap(),
11674 )?;
11675 let old = err!(
11676 self.builder
11677 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11678 );
11679 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11680 }
11681 Operator::I32AtomicRmwOr { ref memarg } => {
11682 let value = self.state.pop1()?.into_int_value();
11683 let offset = self.state.pop1()?.into_int_value();
11684 let memory_index = MemoryIndex::from_u32(0);
11685 let effective_address = self.resolve_memory_ptr(
11686 memory_index,
11687 memarg,
11688 self.intrinsics.ptr_ty,
11689 offset,
11690 4,
11691 )?;
11692 self.trap_if_misaligned(memarg, effective_address, 4)?;
11693 let old = self
11694 .builder
11695 .build_atomicrmw(
11696 AtomicRMWBinOp::Or,
11697 effective_address,
11698 value,
11699 AtomicOrdering::SequentiallyConsistent,
11700 )
11701 .unwrap();
11702 self.annotate_user_memaccess(
11703 memory_index,
11704 memarg,
11705 0,
11706 old.as_instruction_value().unwrap(),
11707 )?;
11708 let old = err!(
11709 self.builder
11710 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11711 );
11712 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11713 }
11714 Operator::I64AtomicRmw8OrU { ref memarg } => {
11715 let value = self.state.pop1()?.into_int_value();
11716 let offset = self.state.pop1()?.into_int_value();
11717 let memory_index = MemoryIndex::from_u32(0);
11718 let effective_address = self.resolve_memory_ptr(
11719 memory_index,
11720 memarg,
11721 self.intrinsics.ptr_ty,
11722 offset,
11723 1,
11724 )?;
11725 self.trap_if_misaligned(memarg, effective_address, 1)?;
11726 let narrow_value = err!(self.builder.build_int_truncate(
11727 value,
11728 self.intrinsics.i8_ty,
11729 ""
11730 ));
11731 let old = self
11732 .builder
11733 .build_atomicrmw(
11734 AtomicRMWBinOp::Or,
11735 effective_address,
11736 narrow_value,
11737 AtomicOrdering::SequentiallyConsistent,
11738 )
11739 .unwrap();
11740 self.annotate_user_memaccess(
11741 memory_index,
11742 memarg,
11743 0,
11744 old.as_instruction_value().unwrap(),
11745 )?;
11746 let old = err!(
11747 self.builder
11748 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11749 );
11750 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11751 }
11752 Operator::I64AtomicRmw16OrU { ref memarg } => {
11753 let value = self.state.pop1()?.into_int_value();
11754 let offset = self.state.pop1()?.into_int_value();
11755 let memory_index = MemoryIndex::from_u32(0);
11756 let effective_address = self.resolve_memory_ptr(
11757 memory_index,
11758 memarg,
11759 self.intrinsics.ptr_ty,
11760 offset,
11761 2,
11762 )?;
11763 self.trap_if_misaligned(memarg, effective_address, 2)?;
11764 let narrow_value = err!(self.builder.build_int_truncate(
11765 value,
11766 self.intrinsics.i16_ty,
11767 ""
11768 ));
11769 let old = self
11770 .builder
11771 .build_atomicrmw(
11772 AtomicRMWBinOp::Or,
11773 effective_address,
11774 narrow_value,
11775 AtomicOrdering::SequentiallyConsistent,
11776 )
11777 .unwrap();
11778 self.annotate_user_memaccess(
11779 memory_index,
11780 memarg,
11781 0,
11782 old.as_instruction_value().unwrap(),
11783 )?;
11784 let old = err!(
11785 self.builder
11786 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11787 );
11788 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11789 }
11790 Operator::I64AtomicRmw32OrU { ref memarg } => {
11791 let value = self.state.pop1()?.into_int_value();
11792 let offset = self.state.pop1()?.into_int_value();
11793 let memory_index = MemoryIndex::from_u32(0);
11794 let effective_address = self.resolve_memory_ptr(
11795 memory_index,
11796 memarg,
11797 self.intrinsics.ptr_ty,
11798 offset,
11799 4,
11800 )?;
11801 self.trap_if_misaligned(memarg, effective_address, 4)?;
11802 let narrow_value = err!(self.builder.build_int_truncate(
11803 value,
11804 self.intrinsics.i32_ty,
11805 ""
11806 ));
11807 let old = self
11808 .builder
11809 .build_atomicrmw(
11810 AtomicRMWBinOp::Or,
11811 effective_address,
11812 narrow_value,
11813 AtomicOrdering::SequentiallyConsistent,
11814 )
11815 .unwrap();
11816 self.annotate_user_memaccess(
11817 memory_index,
11818 memarg,
11819 0,
11820 old.as_instruction_value().unwrap(),
11821 )?;
11822 let old = err!(
11823 self.builder
11824 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11825 );
11826 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11827 }
11828 Operator::I64AtomicRmwOr { ref memarg } => {
11829 let value = self.state.pop1()?.into_int_value();
11830 let offset = self.state.pop1()?.into_int_value();
11831 let memory_index = MemoryIndex::from_u32(0);
11832 let effective_address = self.resolve_memory_ptr(
11833 memory_index,
11834 memarg,
11835 self.intrinsics.ptr_ty,
11836 offset,
11837 8,
11838 )?;
11839 self.trap_if_misaligned(memarg, effective_address, 8)?;
11840 let old = self
11841 .builder
11842 .build_atomicrmw(
11843 AtomicRMWBinOp::Or,
11844 effective_address,
11845 value,
11846 AtomicOrdering::SequentiallyConsistent,
11847 )
11848 .unwrap();
11849 self.annotate_user_memaccess(
11850 memory_index,
11851 memarg,
11852 0,
11853 old.as_instruction_value().unwrap(),
11854 )?;
11855 self.state.push1(old);
11856 }
11857 Operator::I32AtomicRmw8XorU { ref memarg } => {
11858 let value = self.state.pop1()?.into_int_value();
11859 let offset = self.state.pop1()?.into_int_value();
11860 let memory_index = MemoryIndex::from_u32(0);
11861 let effective_address = self.resolve_memory_ptr(
11862 memory_index,
11863 memarg,
11864 self.intrinsics.ptr_ty,
11865 offset,
11866 1,
11867 )?;
11868 self.trap_if_misaligned(memarg, effective_address, 2)?;
11869 let narrow_value = err!(self.builder.build_int_truncate(
11870 value,
11871 self.intrinsics.i8_ty,
11872 ""
11873 ));
11874 let old = self
11875 .builder
11876 .build_atomicrmw(
11877 AtomicRMWBinOp::Xor,
11878 effective_address,
11879 narrow_value,
11880 AtomicOrdering::SequentiallyConsistent,
11881 )
11882 .unwrap();
11883 self.annotate_user_memaccess(
11884 memory_index,
11885 memarg,
11886 0,
11887 old.as_instruction_value().unwrap(),
11888 )?;
11889 let old = err!(
11890 self.builder
11891 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11892 );
11893 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11894 }
11895 Operator::I32AtomicRmw16XorU { ref memarg } => {
11896 let value = self.state.pop1()?.into_int_value();
11897 let offset = self.state.pop1()?.into_int_value();
11898 let memory_index = MemoryIndex::from_u32(0);
11899 let effective_address = self.resolve_memory_ptr(
11900 memory_index,
11901 memarg,
11902 self.intrinsics.ptr_ty,
11903 offset,
11904 2,
11905 )?;
11906 self.trap_if_misaligned(memarg, effective_address, 2)?;
11907 let narrow_value = err!(self.builder.build_int_truncate(
11908 value,
11909 self.intrinsics.i16_ty,
11910 ""
11911 ));
11912 let old = self
11913 .builder
11914 .build_atomicrmw(
11915 AtomicRMWBinOp::Xor,
11916 effective_address,
11917 narrow_value,
11918 AtomicOrdering::SequentiallyConsistent,
11919 )
11920 .unwrap();
11921 self.annotate_user_memaccess(
11922 memory_index,
11923 memarg,
11924 0,
11925 old.as_instruction_value().unwrap(),
11926 )?;
11927 let old = err!(
11928 self.builder
11929 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11930 );
11931 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11932 }
11933 Operator::I32AtomicRmwXor { ref memarg } => {
11934 let value = self.state.pop1()?.into_int_value();
11935 let offset = self.state.pop1()?.into_int_value();
11936 let memory_index = MemoryIndex::from_u32(0);
11937 let effective_address = self.resolve_memory_ptr(
11938 memory_index,
11939 memarg,
11940 self.intrinsics.ptr_ty,
11941 offset,
11942 4,
11943 )?;
11944 self.trap_if_misaligned(memarg, effective_address, 4)?;
11945 let old = self
11946 .builder
11947 .build_atomicrmw(
11948 AtomicRMWBinOp::Xor,
11949 effective_address,
11950 value,
11951 AtomicOrdering::SequentiallyConsistent,
11952 )
11953 .unwrap();
11954 self.annotate_user_memaccess(
11955 memory_index,
11956 memarg,
11957 0,
11958 old.as_instruction_value().unwrap(),
11959 )?;
11960 self.state.push1(old);
11961 }
11962 Operator::I64AtomicRmw8XorU { ref memarg } => {
11963 let value = self.state.pop1()?.into_int_value();
11964 let offset = self.state.pop1()?.into_int_value();
11965 let memory_index = MemoryIndex::from_u32(0);
11966 let effective_address = self.resolve_memory_ptr(
11967 memory_index,
11968 memarg,
11969 self.intrinsics.ptr_ty,
11970 offset,
11971 1,
11972 )?;
11973 self.trap_if_misaligned(memarg, effective_address, 1)?;
11974 let narrow_value = err!(self.builder.build_int_truncate(
11975 value,
11976 self.intrinsics.i8_ty,
11977 ""
11978 ));
11979 let old = self
11980 .builder
11981 .build_atomicrmw(
11982 AtomicRMWBinOp::Xor,
11983 effective_address,
11984 narrow_value,
11985 AtomicOrdering::SequentiallyConsistent,
11986 )
11987 .unwrap();
11988 self.annotate_user_memaccess(
11989 memory_index,
11990 memarg,
11991 0,
11992 old.as_instruction_value().unwrap(),
11993 )?;
11994 let old = err!(
11995 self.builder
11996 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11997 );
11998 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11999 }
12000 Operator::I64AtomicRmw16XorU { ref memarg } => {
12001 let value = self.state.pop1()?.into_int_value();
12002 let offset = self.state.pop1()?.into_int_value();
12003 let memory_index = MemoryIndex::from_u32(0);
12004 let effective_address = self.resolve_memory_ptr(
12005 memory_index,
12006 memarg,
12007 self.intrinsics.ptr_ty,
12008 offset,
12009 2,
12010 )?;
12011 self.trap_if_misaligned(memarg, effective_address, 2)?;
12012 let narrow_value = err!(self.builder.build_int_truncate(
12013 value,
12014 self.intrinsics.i16_ty,
12015 ""
12016 ));
12017 let old = self
12018 .builder
12019 .build_atomicrmw(
12020 AtomicRMWBinOp::Xor,
12021 effective_address,
12022 narrow_value,
12023 AtomicOrdering::SequentiallyConsistent,
12024 )
12025 .unwrap();
12026 self.annotate_user_memaccess(
12027 memory_index,
12028 memarg,
12029 0,
12030 old.as_instruction_value().unwrap(),
12031 )?;
12032 let old = err!(
12033 self.builder
12034 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12035 );
12036 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12037 }
12038 Operator::I64AtomicRmw32XorU { ref memarg } => {
12039 let value = self.state.pop1()?.into_int_value();
12040 let offset = self.state.pop1()?.into_int_value();
12041 let memory_index = MemoryIndex::from_u32(0);
12042 let effective_address = self.resolve_memory_ptr(
12043 memory_index,
12044 memarg,
12045 self.intrinsics.ptr_ty,
12046 offset,
12047 4,
12048 )?;
12049 self.trap_if_misaligned(memarg, effective_address, 4)?;
12050 let narrow_value = err!(self.builder.build_int_truncate(
12051 value,
12052 self.intrinsics.i32_ty,
12053 ""
12054 ));
12055 let old = self
12056 .builder
12057 .build_atomicrmw(
12058 AtomicRMWBinOp::Xor,
12059 effective_address,
12060 narrow_value,
12061 AtomicOrdering::SequentiallyConsistent,
12062 )
12063 .unwrap();
12064 self.annotate_user_memaccess(
12065 memory_index,
12066 memarg,
12067 0,
12068 old.as_instruction_value().unwrap(),
12069 )?;
12070 let old = err!(
12071 self.builder
12072 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12073 );
12074 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12075 }
12076 Operator::I64AtomicRmwXor { ref memarg } => {
12077 let value = self.state.pop1()?.into_int_value();
12078 let offset = self.state.pop1()?.into_int_value();
12079 let memory_index = MemoryIndex::from_u32(0);
12080 let effective_address = self.resolve_memory_ptr(
12081 memory_index,
12082 memarg,
12083 self.intrinsics.ptr_ty,
12084 offset,
12085 8,
12086 )?;
12087 self.trap_if_misaligned(memarg, effective_address, 8)?;
12088 let old = self
12089 .builder
12090 .build_atomicrmw(
12091 AtomicRMWBinOp::Xor,
12092 effective_address,
12093 value,
12094 AtomicOrdering::SequentiallyConsistent,
12095 )
12096 .unwrap();
12097 self.annotate_user_memaccess(
12098 memory_index,
12099 memarg,
12100 0,
12101 old.as_instruction_value().unwrap(),
12102 )?;
12103 self.state.push1(old);
12104 }
12105 Operator::I32AtomicRmw8XchgU { ref memarg } => {
12106 let value = self.state.pop1()?.into_int_value();
12107 let offset = self.state.pop1()?.into_int_value();
12108 let memory_index = MemoryIndex::from_u32(0);
12109 let effective_address = self.resolve_memory_ptr(
12110 memory_index,
12111 memarg,
12112 self.intrinsics.ptr_ty,
12113 offset,
12114 1,
12115 )?;
12116 self.trap_if_misaligned(memarg, effective_address, 1)?;
12117 let narrow_value = err!(self.builder.build_int_truncate(
12118 value,
12119 self.intrinsics.i8_ty,
12120 ""
12121 ));
12122 let old = self
12123 .builder
12124 .build_atomicrmw(
12125 AtomicRMWBinOp::Xchg,
12126 effective_address,
12127 narrow_value,
12128 AtomicOrdering::SequentiallyConsistent,
12129 )
12130 .unwrap();
12131 self.annotate_user_memaccess(
12132 memory_index,
12133 memarg,
12134 0,
12135 old.as_instruction_value().unwrap(),
12136 )?;
12137 let old = err!(
12138 self.builder
12139 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12140 );
12141 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12142 }
12143 Operator::I32AtomicRmw16XchgU { ref memarg } => {
12144 let value = self.state.pop1()?.into_int_value();
12145 let offset = self.state.pop1()?.into_int_value();
12146 let memory_index = MemoryIndex::from_u32(0);
12147 let effective_address = self.resolve_memory_ptr(
12148 memory_index,
12149 memarg,
12150 self.intrinsics.ptr_ty,
12151 offset,
12152 2,
12153 )?;
12154 self.trap_if_misaligned(memarg, effective_address, 2)?;
12155 let narrow_value = err!(self.builder.build_int_truncate(
12156 value,
12157 self.intrinsics.i16_ty,
12158 ""
12159 ));
12160 let old = self
12161 .builder
12162 .build_atomicrmw(
12163 AtomicRMWBinOp::Xchg,
12164 effective_address,
12165 narrow_value,
12166 AtomicOrdering::SequentiallyConsistent,
12167 )
12168 .unwrap();
12169 self.annotate_user_memaccess(
12170 memory_index,
12171 memarg,
12172 0,
12173 old.as_instruction_value().unwrap(),
12174 )?;
12175 let old = err!(
12176 self.builder
12177 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12178 );
12179 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12180 }
12181 Operator::I32AtomicRmwXchg { ref memarg } => {
12182 let value = self.state.pop1()?.into_int_value();
12183 let offset = self.state.pop1()?.into_int_value();
12184 let memory_index = MemoryIndex::from_u32(0);
12185 let effective_address = self.resolve_memory_ptr(
12186 memory_index,
12187 memarg,
12188 self.intrinsics.ptr_ty,
12189 offset,
12190 4,
12191 )?;
12192 self.trap_if_misaligned(memarg, effective_address, 4)?;
12193 let old = self
12194 .builder
12195 .build_atomicrmw(
12196 AtomicRMWBinOp::Xchg,
12197 effective_address,
12198 value,
12199 AtomicOrdering::SequentiallyConsistent,
12200 )
12201 .unwrap();
12202 self.annotate_user_memaccess(
12203 memory_index,
12204 memarg,
12205 0,
12206 old.as_instruction_value().unwrap(),
12207 )?;
12208 self.state.push1(old);
12209 }
12210 Operator::I64AtomicRmw8XchgU { ref memarg } => {
12211 let value = self.state.pop1()?.into_int_value();
12212 let offset = self.state.pop1()?.into_int_value();
12213 let memory_index = MemoryIndex::from_u32(0);
12214 let effective_address = self.resolve_memory_ptr(
12215 memory_index,
12216 memarg,
12217 self.intrinsics.ptr_ty,
12218 offset,
12219 1,
12220 )?;
12221 self.trap_if_misaligned(memarg, effective_address, 1)?;
12222 let narrow_value = err!(self.builder.build_int_truncate(
12223 value,
12224 self.intrinsics.i8_ty,
12225 ""
12226 ));
12227 let old = self
12228 .builder
12229 .build_atomicrmw(
12230 AtomicRMWBinOp::Xchg,
12231 effective_address,
12232 narrow_value,
12233 AtomicOrdering::SequentiallyConsistent,
12234 )
12235 .unwrap();
12236 self.annotate_user_memaccess(
12237 memory_index,
12238 memarg,
12239 0,
12240 old.as_instruction_value().unwrap(),
12241 )?;
12242 let old = err!(
12243 self.builder
12244 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12245 );
12246 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12247 }
12248 Operator::I64AtomicRmw16XchgU { ref memarg } => {
12249 let value = self.state.pop1()?.into_int_value();
12250 let offset = self.state.pop1()?.into_int_value();
12251 let memory_index = MemoryIndex::from_u32(0);
12252 let effective_address = self.resolve_memory_ptr(
12253 memory_index,
12254 memarg,
12255 self.intrinsics.ptr_ty,
12256 offset,
12257 2,
12258 )?;
12259 self.trap_if_misaligned(memarg, effective_address, 2)?;
12260 let narrow_value = err!(self.builder.build_int_truncate(
12261 value,
12262 self.intrinsics.i16_ty,
12263 ""
12264 ));
12265 let old = self
12266 .builder
12267 .build_atomicrmw(
12268 AtomicRMWBinOp::Xchg,
12269 effective_address,
12270 narrow_value,
12271 AtomicOrdering::SequentiallyConsistent,
12272 )
12273 .unwrap();
12274 self.annotate_user_memaccess(
12275 memory_index,
12276 memarg,
12277 0,
12278 old.as_instruction_value().unwrap(),
12279 )?;
12280 let old = err!(
12281 self.builder
12282 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12283 );
12284 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12285 }
12286 Operator::I64AtomicRmw32XchgU { ref memarg } => {
12287 let value = self.state.pop1()?.into_int_value();
12288 let offset = self.state.pop1()?.into_int_value();
12289 let memory_index = MemoryIndex::from_u32(0);
12290 let effective_address = self.resolve_memory_ptr(
12291 memory_index,
12292 memarg,
12293 self.intrinsics.ptr_ty,
12294 offset,
12295 4,
12296 )?;
12297 self.trap_if_misaligned(memarg, effective_address, 4)?;
12298 let narrow_value = err!(self.builder.build_int_truncate(
12299 value,
12300 self.intrinsics.i32_ty,
12301 ""
12302 ));
12303 let old = self
12304 .builder
12305 .build_atomicrmw(
12306 AtomicRMWBinOp::Xchg,
12307 effective_address,
12308 narrow_value,
12309 AtomicOrdering::SequentiallyConsistent,
12310 )
12311 .unwrap();
12312 self.annotate_user_memaccess(
12313 memory_index,
12314 memarg,
12315 0,
12316 old.as_instruction_value().unwrap(),
12317 )?;
12318 let old = err!(
12319 self.builder
12320 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12321 );
12322 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12323 }
12324 Operator::I64AtomicRmwXchg { ref memarg } => {
12325 let value = self.state.pop1()?.into_int_value();
12326 let offset = self.state.pop1()?.into_int_value();
12327 let memory_index = MemoryIndex::from_u32(0);
12328 let effective_address = self.resolve_memory_ptr(
12329 memory_index,
12330 memarg,
12331 self.intrinsics.ptr_ty,
12332 offset,
12333 8,
12334 )?;
12335 self.trap_if_misaligned(memarg, effective_address, 8)?;
12336 let old = self
12337 .builder
12338 .build_atomicrmw(
12339 AtomicRMWBinOp::Xchg,
12340 effective_address,
12341 value,
12342 AtomicOrdering::SequentiallyConsistent,
12343 )
12344 .unwrap();
12345 self.annotate_user_memaccess(
12346 memory_index,
12347 memarg,
12348 0,
12349 old.as_instruction_value().unwrap(),
12350 )?;
12351 self.state.push1(old);
12352 }
12353 Operator::I32AtomicRmw8CmpxchgU { ref memarg } => {
12354 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12355 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12356 let new = self.apply_pending_canonicalization(new, new_info)?;
12357 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12358 let offset = self.state.pop1()?.into_int_value();
12359 let memory_index = MemoryIndex::from_u32(0);
12360 let effective_address = self.resolve_memory_ptr(
12361 memory_index,
12362 memarg,
12363 self.intrinsics.ptr_ty,
12364 offset,
12365 1,
12366 )?;
12367 self.trap_if_misaligned(memarg, effective_address, 1)?;
12368 let narrow_cmp = err!(self.builder.build_int_truncate(
12369 cmp,
12370 self.intrinsics.i8_ty,
12371 ""
12372 ));
12373 let narrow_new = err!(self.builder.build_int_truncate(
12374 new,
12375 self.intrinsics.i8_ty,
12376 ""
12377 ));
12378 let old = self
12379 .builder
12380 .build_cmpxchg(
12381 effective_address,
12382 narrow_cmp,
12383 narrow_new,
12384 AtomicOrdering::SequentiallyConsistent,
12385 AtomicOrdering::SequentiallyConsistent,
12386 )
12387 .unwrap();
12388 self.annotate_user_memaccess(
12389 memory_index,
12390 memarg,
12391 0,
12392 old.as_instruction_value().unwrap(),
12393 )?;
12394 let old = self
12395 .builder
12396 .build_extract_value(old, 0, "")
12397 .unwrap()
12398 .into_int_value();
12399 let old = err!(
12400 self.builder
12401 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12402 );
12403 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12404 }
12405 Operator::I32AtomicRmw16CmpxchgU { ref memarg } => {
12406 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12407 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12408 let new = self.apply_pending_canonicalization(new, new_info)?;
12409 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12410 let offset = self.state.pop1()?.into_int_value();
12411 let memory_index = MemoryIndex::from_u32(0);
12412 let effective_address = self.resolve_memory_ptr(
12413 memory_index,
12414 memarg,
12415 self.intrinsics.ptr_ty,
12416 offset,
12417 2,
12418 )?;
12419 self.trap_if_misaligned(memarg, effective_address, 2)?;
12420 let narrow_cmp = err!(self.builder.build_int_truncate(
12421 cmp,
12422 self.intrinsics.i16_ty,
12423 ""
12424 ));
12425 let narrow_new = err!(self.builder.build_int_truncate(
12426 new,
12427 self.intrinsics.i16_ty,
12428 ""
12429 ));
12430 let old = self
12431 .builder
12432 .build_cmpxchg(
12433 effective_address,
12434 narrow_cmp,
12435 narrow_new,
12436 AtomicOrdering::SequentiallyConsistent,
12437 AtomicOrdering::SequentiallyConsistent,
12438 )
12439 .unwrap();
12440 self.annotate_user_memaccess(
12441 memory_index,
12442 memarg,
12443 0,
12444 old.as_instruction_value().unwrap(),
12445 )?;
12446 let old = self
12447 .builder
12448 .build_extract_value(old, 0, "")
12449 .unwrap()
12450 .into_int_value();
12451 let old = err!(
12452 self.builder
12453 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12454 );
12455 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12456 }
12457 Operator::I32AtomicRmwCmpxchg { ref memarg } => {
12458 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12459 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12460 let new = self.apply_pending_canonicalization(new, new_info)?;
12461 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12462 let offset = self.state.pop1()?.into_int_value();
12463 let memory_index = MemoryIndex::from_u32(0);
12464 let effective_address = self.resolve_memory_ptr(
12465 memory_index,
12466 memarg,
12467 self.intrinsics.ptr_ty,
12468 offset,
12469 4,
12470 )?;
12471 self.trap_if_misaligned(memarg, effective_address, 4)?;
12472 let old = self
12473 .builder
12474 .build_cmpxchg(
12475 effective_address,
12476 cmp,
12477 new,
12478 AtomicOrdering::SequentiallyConsistent,
12479 AtomicOrdering::SequentiallyConsistent,
12480 )
12481 .unwrap();
12482 self.annotate_user_memaccess(
12483 memory_index,
12484 memarg,
12485 0,
12486 old.as_instruction_value().unwrap(),
12487 )?;
12488 let old = err!(self.builder.build_extract_value(old, 0, ""));
12489 self.state.push1(old);
12490 }
12491 Operator::I64AtomicRmw8CmpxchgU { ref memarg } => {
12492 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12493 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12494 let new = self.apply_pending_canonicalization(new, new_info)?;
12495 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12496 let offset = self.state.pop1()?.into_int_value();
12497 let memory_index = MemoryIndex::from_u32(0);
12498 let effective_address = self.resolve_memory_ptr(
12499 memory_index,
12500 memarg,
12501 self.intrinsics.ptr_ty,
12502 offset,
12503 1,
12504 )?;
12505 self.trap_if_misaligned(memarg, effective_address, 1)?;
12506 let narrow_cmp = err!(self.builder.build_int_truncate(
12507 cmp,
12508 self.intrinsics.i8_ty,
12509 ""
12510 ));
12511 let narrow_new = err!(self.builder.build_int_truncate(
12512 new,
12513 self.intrinsics.i8_ty,
12514 ""
12515 ));
12516 let old = self
12517 .builder
12518 .build_cmpxchg(
12519 effective_address,
12520 narrow_cmp,
12521 narrow_new,
12522 AtomicOrdering::SequentiallyConsistent,
12523 AtomicOrdering::SequentiallyConsistent,
12524 )
12525 .unwrap();
12526 self.annotate_user_memaccess(
12527 memory_index,
12528 memarg,
12529 0,
12530 old.as_instruction_value().unwrap(),
12531 )?;
12532 let old = self
12533 .builder
12534 .build_extract_value(old, 0, "")
12535 .unwrap()
12536 .into_int_value();
12537 let old = err!(
12538 self.builder
12539 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12540 );
12541 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12542 }
12543 Operator::I64AtomicRmw16CmpxchgU { ref memarg } => {
12544 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12545 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12546 let new = self.apply_pending_canonicalization(new, new_info)?;
12547 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12548 let offset = self.state.pop1()?.into_int_value();
12549 let memory_index = MemoryIndex::from_u32(0);
12550 let effective_address = self.resolve_memory_ptr(
12551 memory_index,
12552 memarg,
12553 self.intrinsics.ptr_ty,
12554 offset,
12555 2,
12556 )?;
12557 self.trap_if_misaligned(memarg, effective_address, 2)?;
12558 let narrow_cmp = err!(self.builder.build_int_truncate(
12559 cmp,
12560 self.intrinsics.i16_ty,
12561 ""
12562 ));
12563 let narrow_new = err!(self.builder.build_int_truncate(
12564 new,
12565 self.intrinsics.i16_ty,
12566 ""
12567 ));
12568 let old = self
12569 .builder
12570 .build_cmpxchg(
12571 effective_address,
12572 narrow_cmp,
12573 narrow_new,
12574 AtomicOrdering::SequentiallyConsistent,
12575 AtomicOrdering::SequentiallyConsistent,
12576 )
12577 .unwrap();
12578 self.annotate_user_memaccess(
12579 memory_index,
12580 memarg,
12581 0,
12582 old.as_instruction_value().unwrap(),
12583 )?;
12584 let old = self
12585 .builder
12586 .build_extract_value(old, 0, "")
12587 .unwrap()
12588 .into_int_value();
12589 let old = err!(
12590 self.builder
12591 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12592 );
12593 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12594 }
12595 Operator::I64AtomicRmw32CmpxchgU { ref memarg } => {
12596 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12597 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12598 let new = self.apply_pending_canonicalization(new, new_info)?;
12599 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12600 let offset = self.state.pop1()?.into_int_value();
12601 let memory_index = MemoryIndex::from_u32(0);
12602 let effective_address = self.resolve_memory_ptr(
12603 memory_index,
12604 memarg,
12605 self.intrinsics.ptr_ty,
12606 offset,
12607 4,
12608 )?;
12609 self.trap_if_misaligned(memarg, effective_address, 4)?;
12610 let narrow_cmp = err!(self.builder.build_int_truncate(
12611 cmp,
12612 self.intrinsics.i32_ty,
12613 ""
12614 ));
12615 let narrow_new = err!(self.builder.build_int_truncate(
12616 new,
12617 self.intrinsics.i32_ty,
12618 ""
12619 ));
12620 let old = self
12621 .builder
12622 .build_cmpxchg(
12623 effective_address,
12624 narrow_cmp,
12625 narrow_new,
12626 AtomicOrdering::SequentiallyConsistent,
12627 AtomicOrdering::SequentiallyConsistent,
12628 )
12629 .unwrap();
12630 self.annotate_user_memaccess(
12631 memory_index,
12632 memarg,
12633 0,
12634 old.as_instruction_value().unwrap(),
12635 )?;
12636 let old = self
12637 .builder
12638 .build_extract_value(old, 0, "")
12639 .unwrap()
12640 .into_int_value();
12641 let old = err!(
12642 self.builder
12643 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12644 );
12645 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12646 }
12647 Operator::I64AtomicRmwCmpxchg { ref memarg } => {
12648 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12649 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12650 let new = self.apply_pending_canonicalization(new, new_info)?;
12651 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12652 let offset = self.state.pop1()?.into_int_value();
12653 let memory_index = MemoryIndex::from_u32(0);
12654 let effective_address = self.resolve_memory_ptr(
12655 memory_index,
12656 memarg,
12657 self.intrinsics.ptr_ty,
12658 offset,
12659 8,
12660 )?;
12661 self.trap_if_misaligned(memarg, effective_address, 8)?;
12662 let old = self
12663 .builder
12664 .build_cmpxchg(
12665 effective_address,
12666 cmp,
12667 new,
12668 AtomicOrdering::SequentiallyConsistent,
12669 AtomicOrdering::SequentiallyConsistent,
12670 )
12671 .unwrap();
12672 self.annotate_user_memaccess(
12673 memory_index,
12674 memarg,
12675 0,
12676 old.as_instruction_value().unwrap(),
12677 )?;
12678 let old = err!(self.builder.build_extract_value(old, 0, ""));
12679 self.state.push1(old);
12680 }
12681
12682 Operator::MemoryGrow { mem } => {
12683 let memory_index = MemoryIndex::from_u32(mem);
12684 let delta = self.state.pop1()?;
12685 let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
12686 let grow = err!(self.builder.build_indirect_call(
12687 self.intrinsics.memory_grow_ty,
12688 grow_fn_ptr,
12689 &[
12690 vmctx.as_basic_value_enum().into(),
12691 delta.into(),
12692 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12693 ],
12694 "",
12695 ));
12696 self.state.push1(grow.try_as_basic_value().unwrap_basic());
12697 }
12698 Operator::MemorySize { mem } => {
12699 let memory_index = MemoryIndex::from_u32(mem);
12700 let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
12701 let size = err!(self.builder.build_indirect_call(
12702 self.intrinsics.memory_size_ty,
12703 size_fn_ptr,
12704 &[
12705 vmctx.as_basic_value_enum().into(),
12706 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12707 ],
12708 "",
12709 ));
12710 self.state.push1(size.try_as_basic_value().unwrap_basic());
12712 }
12713 Operator::MemoryInit { data_index, mem } => {
12714 let (dest, src, len) = self.state.pop3()?;
12715 let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
12716 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12717 self.build_call_with_param_attributes(
12718 self.intrinsics.memory_init,
12719 &[
12720 vmctx.as_basic_value_enum().into(),
12721 mem.into(),
12722 segment.into(),
12723 dest.into(),
12724 src.into(),
12725 len.into(),
12726 ],
12727 "",
12728 )?;
12729 }
12730 Operator::DataDrop { data_index } => {
12731 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12732 self.build_call_with_param_attributes(
12733 self.intrinsics.data_drop,
12734 &[vmctx.as_basic_value_enum().into(), segment.into()],
12735 "",
12736 )?;
12737 }
12738 Operator::MemoryCopy { dst_mem, src_mem } => {
12739 let _dst = dst_mem;
12741 let (memory_copy, src) = if let Some(local_memory_index) = self
12742 .wasm_module
12743 .local_memory_index(MemoryIndex::from_u32(src_mem))
12744 {
12745 (self.intrinsics.memory_copy, local_memory_index.as_u32())
12746 } else {
12747 (self.intrinsics.imported_memory_copy, src_mem)
12748 };
12749
12750 let (dest_pos, src_pos, len) = self.state.pop3()?;
12751 let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
12752 self.build_call_with_param_attributes(
12753 memory_copy,
12754 &[
12755 vmctx.as_basic_value_enum().into(),
12756 src_index.into(),
12757 dest_pos.into(),
12758 src_pos.into(),
12759 len.into(),
12760 ],
12761 "",
12762 )?;
12763 }
12764 Operator::MemoryFill { mem } => {
12765 let (memory_fill, mem) = if let Some(local_memory_index) = self
12766 .wasm_module
12767 .local_memory_index(MemoryIndex::from_u32(mem))
12768 {
12769 (self.intrinsics.memory_fill, local_memory_index.as_u32())
12770 } else {
12771 (self.intrinsics.imported_memory_fill, mem)
12772 };
12773
12774 let (dst, val, len) = self.state.pop3()?;
12775 let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
12776 self.build_call_with_param_attributes(
12777 memory_fill,
12778 &[
12779 vmctx.as_basic_value_enum().into(),
12780 mem_index.into(),
12781 dst.into(),
12782 val.into(),
12783 len.into(),
12784 ],
12785 "",
12786 )?;
12787 }
12788 Operator::RefNull { hty } => {
12793 let ty = err!(wpheaptype_to_type(hty));
12794 let ty = type_to_llvm(self.intrinsics, ty)?;
12795 self.state.push1(ty.const_zero());
12796 }
12797 Operator::RefIsNull => {
12798 let value = self.state.pop1()?.into_pointer_value();
12799 let is_null = err!(self.builder.build_is_null(value, ""));
12800 let is_null = err!(self.builder.build_int_z_extend(
12801 is_null,
12802 self.intrinsics.i32_ty,
12803 ""
12804 ));
12805 self.state.push1(is_null);
12806 }
12807 Operator::RefFunc { function_index } => {
12808 let index = self
12809 .intrinsics
12810 .i32_ty
12811 .const_int(function_index.into(), false);
12812 let value = self
12813 .build_call_with_param_attributes(
12814 self.intrinsics.func_ref,
12815 &[self.ctx.basic().into(), index.into()],
12816 "",
12817 )?
12818 .try_as_basic_value()
12819 .unwrap_basic();
12820 self.state.push1(value);
12821 }
12822 Operator::TableGet { table } => {
12823 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
12824 let elem = self.state.pop1()?;
12825 let table_get = if self
12826 .wasm_module
12827 .local_table_index(TableIndex::from_u32(table))
12828 .is_some()
12829 {
12830 self.intrinsics.table_get
12831 } else {
12832 self.intrinsics.imported_table_get
12833 };
12834 let value = self
12835 .build_call_with_param_attributes(
12836 table_get,
12837 &[self.ctx.basic().into(), table_index.into(), elem.into()],
12838 "",
12839 )?
12840 .try_as_basic_value()
12841 .unwrap_basic();
12842 let value = err!(
12843 self.builder.build_bit_cast(
12844 value,
12845 type_to_llvm(
12846 self.intrinsics,
12847 self.wasm_module
12848 .tables
12849 .get(TableIndex::from_u32(table))
12850 .unwrap()
12851 .ty,
12852 )?,
12853 "",
12854 )
12855 );
12856 self.state.push1(value);
12857 }
12858 Operator::TableSet { table } => {
12859 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
12860 let (elem, value) = self.state.pop2()?;
12861 let value = err!(
12862 self.builder
12863 .build_bit_cast(value, self.intrinsics.ptr_ty, "")
12864 );
12865 let table_set = if self
12866 .wasm_module
12867 .local_table_index(TableIndex::from_u32(table))
12868 .is_some()
12869 {
12870 self.intrinsics.table_set
12871 } else {
12872 self.intrinsics.imported_table_set
12873 };
12874 self.build_call_with_param_attributes(
12875 table_set,
12876 &[
12877 self.ctx.basic().into(),
12878 table_index.into(),
12879 elem.into(),
12880 value.into(),
12881 ],
12882 "",
12883 )?;
12884 }
12885 Operator::TableCopy {
12886 dst_table,
12887 src_table,
12888 } => {
12889 let (dst, src, len) = self.state.pop3()?;
12890 let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
12891 let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
12892 self.build_call_with_param_attributes(
12893 self.intrinsics.table_copy,
12894 &[
12895 self.ctx.basic().into(),
12896 dst_table.into(),
12897 src_table.into(),
12898 dst.into(),
12899 src.into(),
12900 len.into(),
12901 ],
12902 "",
12903 )?;
12904 }
12905 Operator::TableInit { elem_index, table } => {
12906 let (dst, src, len) = self.state.pop3()?;
12907 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
12908 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
12909 self.build_call_with_param_attributes(
12910 self.intrinsics.table_init,
12911 &[
12912 self.ctx.basic().into(),
12913 table.into(),
12914 segment.into(),
12915 dst.into(),
12916 src.into(),
12917 len.into(),
12918 ],
12919 "",
12920 )?;
12921 }
12922 Operator::ElemDrop { elem_index } => {
12923 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
12924 self.build_call_with_param_attributes(
12925 self.intrinsics.elem_drop,
12926 &[self.ctx.basic().into(), segment.into()],
12927 "",
12928 )?;
12929 }
12930 Operator::TableFill { table } => {
12931 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
12932 let (start, elem, len) = self.state.pop3()?;
12933 let elem = err!(
12934 self.builder
12935 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
12936 );
12937 self.build_call_with_param_attributes(
12938 self.intrinsics.table_fill,
12939 &[
12940 self.ctx.basic().into(),
12941 table.into(),
12942 start.into(),
12943 elem.into(),
12944 len.into(),
12945 ],
12946 "",
12947 )?;
12948 }
12949 Operator::TableGrow { table } => {
12950 let (elem, delta) = self.state.pop2()?;
12951 let elem = err!(
12952 self.builder
12953 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
12954 );
12955 let (table_grow, table_index) = if let Some(local_table_index) = self
12956 .wasm_module
12957 .local_table_index(TableIndex::from_u32(table))
12958 {
12959 (self.intrinsics.table_grow, local_table_index.as_u32())
12960 } else {
12961 (self.intrinsics.imported_table_grow, table)
12962 };
12963 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
12964 let size = self
12965 .build_call_with_param_attributes(
12966 table_grow,
12967 &[
12968 self.ctx.basic().into(),
12969 elem.into(),
12970 delta.into(),
12971 table_index.into(),
12972 ],
12973 "",
12974 )?
12975 .try_as_basic_value()
12976 .unwrap_basic();
12977 self.state.push1(size);
12978 }
12979 Operator::TableSize { table } => {
12980 let (table_size, table_index) = if let Some(local_table_index) = self
12981 .wasm_module
12982 .local_table_index(TableIndex::from_u32(table))
12983 {
12984 (self.intrinsics.table_size, local_table_index.as_u32())
12985 } else {
12986 (self.intrinsics.imported_table_size, table)
12987 };
12988 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
12989 let size = self
12990 .build_call_with_param_attributes(
12991 table_size,
12992 &[self.ctx.basic().into(), table_index.into()],
12993 "",
12994 )?
12995 .try_as_basic_value()
12996 .unwrap_basic();
12997 self.state.push1(size);
12998 }
12999 Operator::MemoryAtomicWait32 { memarg } => {
13000 let memory_index = MemoryIndex::from_u32(memarg.memory);
13001 let (dst, val, timeout) = self.state.pop3()?;
13002 let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
13003 let ret = err!(
13004 self.builder.build_indirect_call(
13005 self.intrinsics.memory_wait32_ty,
13006 wait32_fn_ptr,
13007 &[
13008 vmctx.as_basic_value_enum().into(),
13009 self.intrinsics
13010 .i32_ty
13011 .const_int(memarg.memory as u64, false)
13012 .into(),
13013 dst.into(),
13014 val.into(),
13015 timeout.into(),
13016 ],
13017 "",
13018 )
13019 );
13020 self.state.push1(ret.try_as_basic_value().unwrap_basic());
13021 }
13022 Operator::MemoryAtomicWait64 { memarg } => {
13023 let memory_index = MemoryIndex::from_u32(memarg.memory);
13024 let (dst, val, timeout) = self.state.pop3()?;
13025 let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
13026 let ret = err!(
13027 self.builder.build_indirect_call(
13028 self.intrinsics.memory_wait64_ty,
13029 wait64_fn_ptr,
13030 &[
13031 vmctx.as_basic_value_enum().into(),
13032 self.intrinsics
13033 .i32_ty
13034 .const_int(memarg.memory as u64, false)
13035 .into(),
13036 dst.into(),
13037 val.into(),
13038 timeout.into(),
13039 ],
13040 "",
13041 )
13042 );
13043 self.state.push1(ret.try_as_basic_value().unwrap_basic());
13044 }
13045 Operator::MemoryAtomicNotify { memarg } => {
13046 let memory_index = MemoryIndex::from_u32(memarg.memory);
13047 let (dst, count) = self.state.pop2()?;
13048 let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
13049 let cnt = err!(
13050 self.builder.build_indirect_call(
13051 self.intrinsics.memory_notify_ty,
13052 notify_fn_ptr,
13053 &[
13054 vmctx.as_basic_value_enum().into(),
13055 self.intrinsics
13056 .i32_ty
13057 .const_int(memarg.memory as u64, false)
13058 .into(),
13059 dst.into(),
13060 count.into(),
13061 ],
13062 "",
13063 )
13064 );
13065 self.state.push1(cnt.try_as_basic_value().unwrap_basic());
13066 }
13067
13068 Operator::TryTable { try_table } => {
13069 let current_block = self
13070 .builder
13071 .get_insert_block()
13072 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13073
13074 self.builder.position_at_end(current_block);
13075
13076 let end_block = self.context.append_basic_block(self.function, "try_end");
13077
13078 let end_phis = {
13079 self.builder.position_at_end(end_block);
13080
13081 let phis = self
13082 .module_translation
13083 .blocktype_params_results(&try_table.ty)?
13084 .1
13085 .iter()
13086 .map(|&wp_ty| {
13087 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
13088 type_to_llvm(self.intrinsics, wasm_ty)
13089 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
13090 })
13091 })
13092 .collect::<Result<_, _>>()?;
13093
13094 self.builder.position_at_end(current_block);
13095 phis
13096 };
13097
13098 let catches: Vec<_> = try_table
13102 .catches
13103 .into_iter()
13104 .unique_by(|v| match v {
13105 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
13106 Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
13107 })
13108 .collect();
13109
13110 let null = self.intrinsics.ptr_ty.const_zero();
13112
13113 let mut catch_tag_values = vec![];
13114 let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
13115 .iter()
13116 .map(|catch| match catch {
13117 Catch::All { .. } | Catch::AllRef { .. } => {
13118 catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
13119 Ok(null.into())
13120 }
13121 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
13122 catch_tag_values.push(*tag);
13123 Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
13124 }
13125 })
13126 .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
13127
13128 let mut outer_catch_blocks = vec![];
13132 for outer_landingpad in self.state.landingpads.iter().rev() {
13133 for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
13134 if !catch_tag_values.contains(tag) {
13135 catch_tag_values.push(*tag);
13136 lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
13137 null.into()
13138 } else {
13139 *self.tags_cache.get(&(*tag as i32)).expect(
13140 "If a previous try_table encountered a tag, \
13141 it should be in the cache",
13142 )
13143 });
13144 outer_catch_blocks.push(*catch_info);
13145 }
13146 }
13147 }
13148
13149 let mut maybe_lpad_block = None;
13153 let mut catch_blocks = vec![];
13154 if !lpad_clauses.is_empty() {
13155 let lpad_block = self.context.append_basic_block(self.function, "catch");
13156 let catch_all_block =
13157 self.context.append_basic_block(self.function, "catch_all");
13158 let catch_specific_block = self
13159 .context
13160 .append_basic_block(self.function, "catch_specific");
13161 let catch_end_block =
13162 self.context.append_basic_block(self.function, "catch_end");
13163 let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
13164
13165 self.builder.position_at_end(lpad_block);
13166
13167 let res = err!(self.builder.build_landing_pad(
13168 self.intrinsics.lpad_exception_ty,
13169 self.intrinsics.personality,
13170 &lpad_clauses,
13171 false,
13172 "exc_struct",
13173 ));
13174
13175 let res = res.into_struct_value();
13176
13177 let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
13178 let pre_selector =
13179 err!(self.builder.build_extract_value(res, 1, "pre_selector"));
13180
13181 let pre_selector_is_zero = err!(self.builder.build_int_compare(
13184 IntPredicate::EQ,
13185 pre_selector.into_int_value(),
13186 self.intrinsics.i32_zero,
13187 "pre_selector_is_zero"
13188 ));
13189 err!(self.builder.build_conditional_branch(
13190 pre_selector_is_zero,
13191 catch_all_block,
13192 catch_specific_block
13193 ));
13194
13195 self.builder.position_at_end(catch_all_block);
13196 err!(self.builder.build_unconditional_branch(catch_end_block));
13197
13198 self.builder.position_at_end(catch_specific_block);
13199 let selector_value = self.build_call_with_param_attributes(
13200 self.intrinsics.personality2,
13201 &[self.ctx.basic().into(), uw_exc.into()],
13202 "selector",
13203 )?;
13204 err!(self.builder.build_unconditional_branch(catch_end_block));
13205
13206 self.builder.position_at_end(catch_end_block);
13207 let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
13208 selector.add_incoming(&[
13209 (
13210 &self
13211 .intrinsics
13212 .i32_ty
13213 .const_int(CATCH_ALL_TAG_VALUE as u64, false),
13214 catch_all_block,
13215 ),
13216 (
13217 &selector_value
13218 .try_as_basic_value()
13219 .unwrap_basic()
13220 .into_int_value(),
13221 catch_specific_block,
13222 ),
13223 ]);
13224
13225 let uw_exc = uw_exc.into_pointer_value();
13270 let exnref = self.build_call_with_param_attributes(
13271 self.intrinsics.exception_into_exnref,
13272 &[uw_exc.into()],
13273 "exnref",
13274 )?;
13275
13276 let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
13277 let selector = selector.as_basic_value().into_int_value();
13278
13279 for catch in catches.iter() {
13280 match catch {
13281 Catch::All { label } => {
13282 let b = self
13283 .context
13284 .append_basic_block(self.function, "catch_all_clause");
13285 self.builder.position_at_end(b);
13286 let frame = self.state.frame_at_depth(*label)?;
13287
13288 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13289
13290 self.builder.position_at_end(catch_end_block);
13291 catch_blocks.push((b, None));
13292 }
13293 Catch::One { tag, label } => {
13294 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13295 let signature = &self.wasm_module.signatures[tag_idx];
13296 let params = signature.params();
13297
13298 let b = self.context.append_basic_block(
13299 self.function,
13300 format!("catch_one_clause_{tag}").as_str(),
13301 );
13302 self.builder.position_at_end(b);
13303
13304 let exnref_phi = err!(
13305 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13306 );
13307 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13308
13309 let exn_payload_ptr = err!(self.builder.build_direct_call(
13311 self.intrinsics.read_exnref,
13312 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13313 "exn_ptr",
13314 ));
13315 let exn_payload_ptr = exn_payload_ptr
13316 .try_as_basic_value()
13317 .unwrap_basic()
13318 .into_pointer_value();
13319
13320 let values = params
13322 .iter()
13323 .enumerate()
13324 .map(|(i, v)| {
13325 let name = format!("value_{i}");
13326 let ptr = err!(unsafe {
13327 self.builder.build_gep(
13328 self.intrinsics.i128_ty,
13329 exn_payload_ptr,
13330 &[self
13331 .intrinsics
13332 .i32_ty
13333 .const_int(i as u64, false)],
13334 format!("{name}_ptr").as_str(),
13335 )
13336 });
13337 err_nt!(self.builder.build_load(
13338 type_to_llvm(self.intrinsics, *v)?,
13339 ptr,
13340 &name,
13341 ))
13342 })
13343 .collect::<Result<Vec<_>, CompileError>>()?;
13344
13345 let frame = self.state.frame_at_depth(*label)?;
13346
13347 for (phi, value) in frame.phis().iter().zip(values.iter()) {
13348 phi.add_incoming(&[(value, b)])
13349 }
13350
13351 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13352
13353 self.builder.position_at_end(catch_end_block);
13354 catch_blocks.push((b, Some(exnref_phi)));
13355 }
13356 Catch::OneRef { label, tag } => {
13357 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13358 let signature = &self.wasm_module.signatures[tag_idx];
13359 let params = signature.params();
13360
13361 let b = self.context.append_basic_block(
13362 self.function,
13363 format!("catch_one_ref_clause_{tag}").as_str(),
13364 );
13365 self.builder.position_at_end(b);
13366
13367 let exnref_phi = err!(
13368 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13369 );
13370 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13371
13372 let exn_payload_ptr = err!(self.builder.build_direct_call(
13374 self.intrinsics.read_exnref,
13375 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13376 "exn_ptr",
13377 ));
13378 let exn_payload_ptr = exn_payload_ptr
13379 .try_as_basic_value()
13380 .unwrap_basic()
13381 .into_pointer_value();
13382
13383 let mut values = params
13385 .iter()
13386 .enumerate()
13387 .map(|(i, v)| {
13388 let name = format!("value_{i}");
13389 let ptr = err!(unsafe {
13390 self.builder.build_gep(
13391 self.intrinsics.i128_ty,
13392 exn_payload_ptr,
13393 &[self
13394 .intrinsics
13395 .i32_ty
13396 .const_int(i as u64, false)],
13397 format!("{name}_ptr").as_str(),
13398 )
13399 });
13400 err_nt!(self.builder.build_load(
13401 type_to_llvm(self.intrinsics, *v)?,
13402 ptr,
13403 &name,
13404 ))
13405 })
13406 .collect::<Result<Vec<_>, CompileError>>()?;
13407
13408 values.push(exnref_phi.as_basic_value());
13409
13410 let frame = self.state.frame_at_depth(*label)?;
13411
13412 for (phi, value) in frame.phis().iter().zip(values.iter()) {
13413 phi.add_incoming(&[(value, b)])
13414 }
13415
13416 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13417
13418 self.builder.position_at_end(catch_end_block);
13419 catch_blocks.push((b, Some(exnref_phi)));
13420 }
13421 Catch::AllRef { label } => {
13422 let b = self
13423 .context
13424 .append_basic_block(self.function, "catch_all_ref_clause");
13425 self.builder.position_at_end(b);
13426
13427 let exnref_phi = err!(
13428 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13429 );
13430 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13431
13432 let frame = self.state.frame_at_depth(*label)?;
13433
13434 let phis = frame.phis();
13435
13436 assert_eq!(phis.len(), 1);
13437 phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
13438
13439 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13440
13441 self.builder.position_at_end(catch_end_block);
13442 catch_blocks.push((b, Some(exnref_phi)));
13443 }
13444 }
13445 }
13446
13447 for catch_info in &outer_catch_blocks {
13448 if let Some(phi) = catch_info.exnref_phi {
13449 phi.add_incoming(&[(&exnref, catch_end_block)]);
13450 }
13451 }
13452
13453 err!(
13454 self.builder.build_switch(
13455 selector,
13456 rethrow_block,
13457 catch_blocks
13458 .iter()
13459 .enumerate()
13460 .map(|(i, v)| (
13461 self.intrinsics
13462 .i32_ty
13463 .const_int(catch_tag_values[i] as _, false),
13464 v.0
13465 ))
13466 .chain(outer_catch_blocks.iter().map(|catch_info| (
13467 self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
13468 catch_info.catch_block
13469 )))
13470 .collect::<Vec<_>>()
13471 .as_slice()
13472 )
13473 );
13474
13475 self.builder.position_at_end(rethrow_block);
13479
13480 self.build_call_with_param_attributes(
13481 self.intrinsics.throw,
13482 &[self.ctx.basic().into(), exnref.into()],
13483 "rethrow",
13484 )?;
13485 err!(self.builder.build_unreachable());
13487
13488 maybe_lpad_block = Some(lpad_block);
13489 }
13490
13491 self.builder.position_at_end(current_block);
13493
13494 let catch_tags_and_blocks = catch_tag_values
13497 .into_iter()
13498 .zip(catch_blocks)
13499 .map(|(tag, (block, exnref_phi))| TagCatchInfo {
13500 tag,
13501 catch_block: block,
13502 exnref_phi,
13503 })
13504 .collect::<Vec<_>>();
13505 self.state.push_landingpad(
13506 maybe_lpad_block,
13507 end_block,
13508 end_phis,
13509 &catch_tags_and_blocks,
13510 self.module_translation
13511 .blocktype_params_results(&try_table.ty)?
13512 .0
13513 .len(),
13514 );
13515 }
13516 Operator::Throw { tag_index } => {
13517 let current_block = self
13518 .builder
13519 .get_insert_block()
13520 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13521
13522 let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
13523 let signature = &self.wasm_module.signatures[sig_index];
13524 let params = signature.params();
13525 let values = self.state.popn_save_extra(params.len())?;
13526
13527 values.iter().enumerate().try_for_each(|(i, (v, _))| {
13528 let t = type_to_llvm(self.intrinsics, params[i])?;
13529 if t != v.get_type() {
13530 return Err(CompileError::Codegen(format!(
13531 "Incompatible types: {:?} != {:?}",
13532 t,
13533 v.get_type()
13534 )));
13535 }
13536
13537 Ok(())
13538 })?;
13539
13540 let exnref = err!(
13542 self.builder.build_direct_call(
13543 self.intrinsics.alloc_exception,
13544 &[
13545 self.ctx.basic().into(),
13546 self.intrinsics
13547 .i32_ty
13548 .const_int(tag_index as _, false)
13549 .into()
13550 ],
13551 "exnref",
13552 )
13553 );
13554 let exnref = exnref.try_as_basic_value().unwrap_basic();
13555
13556 let exn_payload_ptr = err!(self.builder.build_direct_call(
13557 self.intrinsics.read_exnref,
13558 &[self.ctx.basic().into(), exnref.into()],
13559 "exn_ptr",
13560 ));
13561 let exn_payload_ptr = exn_payload_ptr
13562 .try_as_basic_value()
13563 .unwrap_basic()
13564 .into_pointer_value();
13565
13566 for (i, value) in values.into_iter().enumerate() {
13567 let ptr = err!(unsafe {
13568 self.builder.build_gep(
13569 self.intrinsics.i128_ty,
13570 exn_payload_ptr,
13571 &[self.intrinsics.i32_ty.const_int(i as u64, false)],
13572 format!("value_{i}_ptr").as_str(),
13573 )
13574 });
13575 err!(self.builder.build_store(ptr, value.0));
13576 }
13577
13578 if let Some(pad) = self.state.get_innermost_landingpad() {
13579 let unreachable_block = self
13580 .context
13581 .append_basic_block(self.function, "_throw_unreachable");
13582
13583 err!(self.builder.build_invoke(
13584 self.intrinsics.throw,
13585 &[self.ctx.basic(), exnref],
13586 unreachable_block,
13587 pad,
13588 "throw",
13589 ));
13590
13591 self.builder.position_at_end(unreachable_block);
13592 err!(self.builder.build_unreachable());
13594
13595 self.builder.position_at_end(current_block);
13596 } else {
13597 self.build_call_with_param_attributes(
13598 self.intrinsics.throw,
13599 &[self.ctx.basic().into(), exnref.into()],
13600 "throw",
13601 )?;
13602 err!(self.builder.build_unreachable());
13604 }
13605
13606 self.state.reachable = false;
13607 }
13608 Operator::ThrowRef => {
13609 let current_block = self
13610 .builder
13611 .get_insert_block()
13612 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13613
13614 let exnref = self.state.pop1()?;
13615
13616 if let Some(pad) = self.state.get_innermost_landingpad() {
13617 let unreachable_block = self
13618 .context
13619 .append_basic_block(self.function, "_rethrow_unreachable");
13620
13621 err!(self.builder.build_invoke(
13622 self.intrinsics.throw,
13623 &[self.ctx.basic(), exnref],
13624 unreachable_block,
13625 pad,
13626 "throw",
13627 ));
13628
13629 self.builder.position_at_end(unreachable_block);
13630 err!(self.builder.build_unreachable());
13632
13633 self.builder.position_at_end(current_block);
13634 } else {
13635 self.build_call_with_param_attributes(
13636 self.intrinsics.throw,
13637 &[self.ctx.basic().into(), exnref.into()],
13638 "throw",
13639 )?;
13640 err!(self.builder.build_unreachable());
13642 }
13643
13644 self.state.reachable = false;
13645 }
13646 Operator::I64Add128 | Operator::I64Sub128 => {
13647 let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
13648 let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
13649 let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
13650 let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
13651
13652 let lhs_lo = self
13653 .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
13654 .into_int_value();
13655 let lhs_hi = self
13656 .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
13657 .into_int_value();
13658 let rhs_lo = self
13659 .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
13660 .into_int_value();
13661 let rhs_hi = self
13662 .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
13663 .into_int_value();
13664
13665 let idx0 = self.intrinsics.i32_ty.const_zero();
13666 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13667
13668 let lhs = self.intrinsics.i64x2_ty.get_undef();
13669 let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
13670 let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
13671 let lhs = err!(
13672 self.builder
13673 .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
13674 )
13675 .into_int_value();
13676
13677 let rhs = self.intrinsics.i64x2_ty.get_undef();
13678 let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
13679 let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
13680 let rhs = err!(
13681 self.builder
13682 .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
13683 )
13684 .into_int_value();
13685
13686 let result = err!(match op {
13687 Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
13688 Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
13689 _ => unreachable!(),
13690 });
13691 let result = err!(self.builder.build_bit_cast(
13692 result,
13693 self.intrinsics.i64x2_ty,
13694 ""
13695 ))
13696 .into_vector_value();
13697 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13698 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13699
13700 self.state.push1(result_lo);
13701 self.state.push1(result_hi);
13702 }
13703 Operator::I64MulWideS | Operator::I64MulWideU => {
13704 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
13705 let lhs = self
13706 .apply_pending_canonicalization(lhs, lhs_info)?
13707 .into_int_value();
13708 let rhs = self
13709 .apply_pending_canonicalization(rhs, rhs_info)?
13710 .into_int_value();
13711
13712 let lhs = err!(match op {
13713 Operator::I64MulWideS => {
13714 self.builder
13715 .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
13716 }
13717 Operator::I64MulWideU => {
13718 self.builder
13719 .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
13720 }
13721 _ => unreachable!(),
13722 });
13723 let rhs = err!(match op {
13724 Operator::I64MulWideS => {
13725 self.builder
13726 .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
13727 }
13728 Operator::I64MulWideU => {
13729 self.builder
13730 .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
13731 }
13732 _ => unreachable!(),
13733 });
13734
13735 let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
13736 let result = err!(self.builder.build_bit_cast(
13737 result,
13738 self.intrinsics.i64x2_ty,
13739 ""
13740 ))
13741 .into_vector_value();
13742 let idx0 = self.intrinsics.i32_ty.const_zero();
13743 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13744 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13745 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13746
13747 self.state.push1(result_lo);
13748 self.state.push1(result_hi);
13749 }
13750 _ => {
13751 return Err(CompileError::Codegen(format!(
13752 "Operator {op:?} unimplemented",
13753 )));
13754 }
13755 }
13756
13757 Ok(())
13758 }
13759
13760 fn build_call_with_param_attributes(
13761 &self,
13762 function: FunctionValue<'ctx>,
13763 args: &[BasicMetadataValueEnum<'ctx>],
13764 name: &str,
13765 ) -> Result<CallSiteValue<'ctx>, CompileError> {
13766 let call = self
13767 .builder
13768 .build_call(function, args, name)
13769 .map_err(|e| CompileError::Codegen(e.to_string()))?;
13770
13771 if matches!(
13776 self.target_triple.architecture,
13777 Architecture::Riscv32(..) | Architecture::Riscv64(..)
13778 ) {
13779 let param_types = function.get_type().get_param_types();
13780 for (i, ty) in param_types.into_iter().enumerate() {
13781 if ty == self.context.i32_type().into() {
13782 call.add_attribute(
13783 AttributeLoc::Param(i as u32),
13784 self.context
13785 .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
13786 );
13787 call.add_attribute(
13788 AttributeLoc::Param(i as u32),
13789 self.context
13790 .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
13791 );
13792 }
13793 }
13794 }
13795
13796 Ok(call)
13797 }
13798}
13799
13800fn is_f32_arithmetic(bits: u32) -> bool {
13801 let bits = bits & 0x7FFF_FFFF;
13803 bits < 0x7FC0_0000
13804}
13805
13806fn is_f64_arithmetic(bits: u64) -> bool {
13807 let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
13809 bits < 0x7FF8_0000_0000_0000
13810}