1use std::collections::HashMap;
2use std::num::NonZero;
3
4use super::{
5 intrinsics::{
6 CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
7 },
8 state::{ControlFrame, ExtraInfo, IfElseState, State, TagCatchInfo},
10};
11use crate::{compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle};
12use enumset::EnumSet;
13use inkwell::{
14 AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
15 attributes::{Attribute, AttributeLoc},
16 builder::Builder,
17 context::Context,
18 module::{Linkage, Module},
19 passes::PassBuilderOptions,
20 targets::{FileType, TargetData, TargetMachine},
21 types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
22 values::{
23 BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
24 FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
25 PointerValue, VectorValue,
26 },
27};
28use itertools::Itertools;
29use smallvec::SmallVec;
30use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
31use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
32
33use crate::{
34 abi::{Abi, get_abi},
35 config::LLVM,
36 error::{err, err_nt},
37 object_file::{CompiledFunction, load_object_file},
38};
39use wasmer_compiler::{
40 CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
41 GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
42 GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
43 LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
44 LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
45 from_binaryreadererror_wasmerror,
46 misc::CompiledKind,
47 types::{
48 relocation::RelocationTarget,
49 symbols::{Symbol, SymbolRegistry},
50 },
51 wasmparser::{Catch, MemArg, Operator},
52 wpheaptype_to_type, wptype_to_type,
53};
54use wasmer_types::{
55 CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
56 ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
57};
58use wasmer_types::{TagIndex, entity::PrimaryMap};
59use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
60
61const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
62const FUNCTION_SECTION_MACHO: &str = "__TEXT";
63const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
64
65const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
71
72pub struct FuncTranslator {
73 ctx: Context,
74 target_triple: Triple,
75 target_machines: HashMap<OptimizationStyle, 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 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
83}
84
85impl wasmer_compiler::FuncTranslator for FuncTranslator {}
86
87impl FuncTranslator {
88 pub fn new(
89 target_triple: Triple,
90 target_machines: HashMap<OptimizationStyle, TargetMachine>,
91 binary_fmt: BinaryFormat,
92 pointer_width: u8,
93 cpu_features: EnumSet<CpuFeature>,
94 non_volatile_memory_ops: bool,
95 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
96 ) -> Result<Self, CompileError> {
97 let abi_source_tm = target_machines
98 .get(&OptimizationStyle::ForSpeed)
99 .expect("target_machines must contain OptimizationStyle::ForSpeed");
100 let abi = get_abi(abi_source_tm);
101 Ok(Self {
102 ctx: Context::create(),
103 target_triple,
104 target_machines,
105 abi,
106 func_section: match binary_fmt {
107 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
108 BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
109 _ => {
110 return Err(CompileError::UnsupportedTarget(format!(
111 "Unsupported binary format: {binary_fmt:?}"
112 )));
113 }
114 },
115 binary_fmt,
116 pointer_width,
117 cpu_features,
118 non_volatile_memory_ops,
119 wasm_apply_data_relocs_fn_index,
120 })
121 }
122
123 #[allow(clippy::too_many_arguments)]
124 pub fn translate_to_module(
125 &self,
126 wasm_module: &ModuleInfo,
127 module_translation: &ModuleTranslationState,
128 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
129 local_func_index: &LocalFunctionIndex,
130 function_body: &FunctionBodyData,
131 config: &LLVM,
132 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
133 _table_styles: &PrimaryMap<TableIndex, TableStyle>,
134 symbol_registry: &dyn SymbolRegistry,
135 target: &Triple,
136 opt_style: OptimizationStyle,
137 ) -> Result<Module<'_>, CompileError> {
138 let func_index = wasm_module.func_index(*local_func_index);
140 let function =
141 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
142 let function_name =
143 symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
144
145 let m0_is_enabled = memory_styles
148 .get(MemoryIndex::from_u32(0))
149 .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
150
151 let module_name = match wasm_module.name.as_ref() {
152 None => format!("<anonymous module> function {function_name}"),
153 Some(module_name) => format!("module {module_name} function {function_name}"),
154 };
155 let module = self.ctx.create_module(module_name.as_str());
156
157 let target_machine = &self.target_machines.values().next().unwrap();
158 let target_triple = target_machine.get_triple();
159 let target_data = target_machine.get_target_data();
160 module.set_triple(&target_triple);
161 module.set_data_layout(&target_data.get_data_layout());
162 let wasm_fn_type = wasm_module
163 .signatures
164 .get(wasm_module.functions[func_index])
165 .unwrap();
166
167 let offsets = VMOffsets::new(self.pointer_width, wasm_module);
168 let intrinsics = Intrinsics::declare(
169 &module,
170 &self.ctx,
171 &target_data,
172 &self.target_triple,
173 &self.binary_fmt,
174 );
175 let (func_type, func_attrs) = self.abi.func_type_to_llvm(
176 &self.ctx,
177 &intrinsics,
178 Some(&offsets),
179 wasm_fn_type,
180 m0_is_enabled,
181 )?;
182
183 let func = module.add_function(&function_name, func_type, Some(Linkage::External));
184 for (attr, attr_loc) in &func_attrs {
185 func.add_attribute(*attr_loc, *attr);
186 }
187
188 if !matches!(target.operating_system, OperatingSystem::Windows) {
189 func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
190 }
191
192 func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
193 func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
194
195 let section = match self.binary_fmt {
196 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
197 BinaryFormat::Macho => {
198 format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
199 }
200 _ => {
201 return Err(CompileError::UnsupportedTarget(format!(
202 "Unsupported binary format: {:?}",
203 self.binary_fmt
204 )));
205 }
206 };
207
208 func.set_personality_function(intrinsics.personality);
209 func.as_global_value().set_section(Some(§ion));
210
211 func.set_linkage(Linkage::DLLExport);
212 func.as_global_value()
213 .set_dll_storage_class(DLLStorageClass::Export);
214
215 let entry = self.ctx.append_basic_block(func, "entry");
216 let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
217 let return_ = self.ctx.append_basic_block(func, "return");
218 let alloca_builder = self.ctx.create_builder();
219 let cache_builder = self.ctx.create_builder();
220 let builder = self.ctx.create_builder();
221 cache_builder.position_at_end(entry);
222 let br = err!(cache_builder.build_unconditional_branch(start_of_code));
223 alloca_builder.position_before(&br);
224 cache_builder.position_before(&br);
225 builder.position_at_end(start_of_code);
226
227 let mut state = State::new();
228 builder.position_at_end(return_);
229 let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
230 .results()
231 .iter()
232 .map(|&wasm_ty| {
233 type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
234 })
235 .collect::<Result<_, _>>()?;
236 state.push_block(return_, phis, 0);
237 builder.position_at_end(start_of_code);
238
239 let mut reader = MiddlewareBinaryReader::new_with_offset(
240 function_body.data,
241 function_body.module_offset,
242 );
243 reader.set_middleware_chain(
244 config
245 .middlewares
246 .generate_function_middleware_chain(*local_func_index),
247 );
248
249 let mut params = vec![];
250 let first_param =
251 if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
252 if m0_is_enabled { 3 } else { 2 }
253 } else if m0_is_enabled {
254 2
255 } else {
256 1
257 };
258 let mut is_first_alloca = true;
259 let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
260 let alloca = err!(alloca_builder.build_alloca(ty, &name));
261 if is_first_alloca {
262 alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
263 is_first_alloca = false;
264 }
265 Ok(alloca)
266 };
267
268 for idx in 0..wasm_fn_type.params().len() {
286 let ty = wasm_fn_type.params()[idx];
287 let ty = type_to_llvm(&intrinsics, ty)?;
288 let value = func
289 .get_nth_param((idx as u32).checked_add(first_param).unwrap())
290 .unwrap();
291 let alloca = insert_alloca(ty, format!("param_{idx}"))?;
292 err!(cache_builder.build_store(alloca, value));
293 params.push((ty, alloca));
294 }
295
296 let mut locals = vec![];
297 let num_locals = reader.read_local_count()?;
298 for idx in 0..num_locals {
299 let (count, ty) = reader.read_local_decl()?;
300 let ty = err!(wptype_to_type(ty));
301 let ty = type_to_llvm(&intrinsics, ty)?;
302 for _ in 0..count {
303 let alloca = insert_alloca(ty, format!("local_{idx}"))?;
304 err!(cache_builder.build_store(alloca, ty.const_zero()));
305 locals.push((ty, alloca));
306 }
307 }
308
309 let mut params_locals = params.clone();
310 params_locals.extend(locals.iter().cloned());
311
312 let mut m0_param = None;
313
314 if m0_is_enabled {
315 let m0 = self.abi.get_m0_ptr_param(&func);
316 m0.set_name("m0_base_ptr");
317 m0_param = Some(m0);
318 }
319
320 let mut fcg = LLVMFunctionCodeGenerator {
321 m0_param,
322 context: &self.ctx,
323 builder,
324 alloca_builder,
325 intrinsics: &intrinsics,
326 target_data: &target_data,
327 state,
328 function: func,
329 locals: params_locals,
330 ctx: CtxType::new(
331 wasm_module,
332 &func,
333 &cache_builder,
334 &*self.abi,
335 self.pointer_width,
336 m0_param,
337 ),
338 unreachable_depth: 0,
339 memory_styles,
340 _table_styles,
341 module: &module,
342 module_translation,
343 signature_hashes,
344 wasm_module,
345 symbol_registry,
346 abi: &*self.abi,
347 config,
348 target_triple: self.target_triple.clone(),
349 tags_cache: HashMap::new(),
350 binary_fmt: self.binary_fmt,
351 cpu_features: self.cpu_features,
352 non_volatile_memory_ops: self.non_volatile_memory_ops,
353 };
354
355 fcg.ctx.add_func(
356 func_index,
357 func.as_global_value().as_pointer_value(),
358 func_type,
359 fcg.ctx.basic(),
360 &func_attrs,
361 );
362
363 while fcg.state.has_control_frames() {
364 let pos = reader.current_position() as u32;
365 let op = reader.read_operator()?;
366 fcg.translate_operator(op, pos)?;
367 }
368
369 fcg.finalize(wasm_fn_type)?;
370
371 if let Some(ref callbacks) = config.callbacks {
372 callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
373 }
374
375 let mut passes = vec![];
376 if config.enable_verifier {
377 passes.push("verify");
378 }
379
380 match opt_style {
381 OptimizationStyle::Disabled => {
382 passes.push("default<O0>");
383 }
384 OptimizationStyle::ForSize => {
385 passes.push("default<O1>");
387 }
388 OptimizationStyle::ForSpeed => {
389 passes.push("sccp");
390 passes.push("early-cse");
391 passes.push("adce");
393 passes.push("sroa");
394 passes.push("aggressive-instcombine");
395 passes.push("jump-threading");
396 passes.push("simplifycfg");
398 passes.push("reassociate");
399 passes.push("loop-rotate");
400 passes.push("indvars");
401 passes.push("sccp");
405 passes.push("reassociate");
406 passes.push("simplifycfg");
407 passes.push("gvn");
408 passes.push("memcpyopt");
409 passes.push("dse");
410 passes.push("dce");
411 passes.push("reassociate");
413 passes.push("simplifycfg");
414 passes.push("mem2reg");
415 }
416 }
417
418 module
419 .run_passes(
420 &passes.join(","),
421 target_machine,
422 PassBuilderOptions::create(),
423 )
424 .unwrap();
425
426 if let Some(ref callbacks) = config.callbacks {
427 callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
428 }
429
430 Ok(module)
431 }
432
433 #[allow(clippy::too_many_arguments)]
434 pub fn translate(
435 &self,
436 wasm_module: &ModuleInfo,
437 module_translation: &ModuleTranslationState,
438 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
439 local_func_index: &LocalFunctionIndex,
440 function_body: &FunctionBodyData,
441 config: &LLVM,
442 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
443 table_styles: &PrimaryMap<TableIndex, TableStyle>,
444 symbol_registry: &ModuleBasedSymbolRegistry,
445 target: &Triple,
446 ) -> Result<CompiledFunction, CompileError> {
447 let func_index = wasm_module.func_index(*local_func_index);
448 let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
449 OptimizationStyle::Disabled
453 } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
454 OptimizationStyle::ForSize
455 } else {
456 OptimizationStyle::ForSpeed
457 };
458 let module = self.translate_to_module(
459 wasm_module,
460 module_translation,
461 signature_hashes,
462 local_func_index,
463 function_body,
464 config,
465 memory_styles,
466 table_styles,
467 symbol_registry,
468 target,
469 opt_style,
470 )?;
471 let function =
472 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
473
474 let target_machine = self.target_machines.get(&opt_style).unwrap();
475 let memory_buffer = target_machine
476 .write_to_memory_buffer(&module, FileType::Object)
477 .unwrap();
478
479 if let Some(ref callbacks) = config.callbacks {
480 let module_hash = wasm_module.hash().map(|m| m.to_string());
481 callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
482 let asm_buffer = target_machine
483 .write_to_memory_buffer(&module, FileType::Assembly)
484 .unwrap();
485 callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
486 }
487
488 let mem_buf_slice = memory_buffer.as_slice();
489
490 load_object_file(
491 mem_buf_slice,
492 &self.func_section,
493 RelocationTarget::LocalFunc(*local_func_index),
494 |name: &str| {
495 Ok({
496 let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
497 name.strip_prefix("_").unwrap_or(name)
498 } else {
499 name
500 }
501 .to_string();
502 if let Some(Symbol::LocalFunction(local_func_index)) =
503 symbol_registry.name_to_symbol(&name)
504 {
505 Some(RelocationTarget::LocalFunc(local_func_index))
506 } else {
507 None
508 }
509 })
510 },
511 self.binary_fmt,
512 &self.target_triple,
513 )
514 }
515}
516
517impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
518 fn splat_vector(
520 &self,
521 value: BasicValueEnum<'ctx>,
522 vec_ty: VectorType<'ctx>,
523 ) -> Result<VectorValue<'ctx>, CompileError> {
524 err_nt!(
527 self.builder.build_shuffle_vector(
528 err!(self.builder.build_insert_element(
529 vec_ty.get_undef(),
530 value,
531 self.intrinsics.i32_zero,
532 "",
533 )),
534 vec_ty.get_undef(),
535 self.intrinsics
536 .i32_ty
537 .vec_type(vec_ty.get_size())
538 .const_zero(),
539 "",
540 )
541 )
542 }
543
544 #[allow(clippy::too_many_arguments)]
547 fn trunc_sat<T: FloatMathType<'ctx>>(
548 &self,
549 fvec_ty: T,
550 ivec_ty: T::MathConvType,
551 lower_bound: u64, upper_bound: u64, int_min_value: u64,
554 int_max_value: u64,
555 value: IntValue<'ctx>,
556 ) -> Result<VectorValue<'ctx>, CompileError> {
557 let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
571 let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
572 let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
573 let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
574
575 let is_signed = int_min_value != 0;
576 let int_min_value = self.splat_vector(
577 ivec_element_ty
578 .const_int(int_min_value, is_signed)
579 .as_basic_value_enum(),
580 ivec_ty,
581 )?;
582 let int_max_value = self.splat_vector(
583 ivec_element_ty
584 .const_int(int_max_value, is_signed)
585 .as_basic_value_enum(),
586 ivec_ty,
587 )?;
588 let lower_bound = if is_signed {
589 err!(self.builder.build_signed_int_to_float(
590 ivec_element_ty.const_int(lower_bound, is_signed),
591 fvec_element_ty,
592 "",
593 ))
594 } else {
595 err!(self.builder.build_unsigned_int_to_float(
596 ivec_element_ty.const_int(lower_bound, is_signed),
597 fvec_element_ty,
598 "",
599 ))
600 };
601 let upper_bound = if is_signed {
602 err!(self.builder.build_signed_int_to_float(
603 ivec_element_ty.const_int(upper_bound, is_signed),
604 fvec_element_ty,
605 "",
606 ))
607 } else {
608 err!(self.builder.build_unsigned_int_to_float(
609 ivec_element_ty.const_int(upper_bound, is_signed),
610 fvec_element_ty,
611 "",
612 ))
613 };
614
615 let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
616 let zero = fvec_ty.const_zero();
617 let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
618 let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
619 let nan_cmp =
620 err!(
621 self.builder
622 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
623 );
624 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
625 FloatPredicate::OGT,
626 value,
627 upper_bound,
628 "above_upper_bound",
629 ));
630 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
631 FloatPredicate::OLT,
632 value,
633 lower_bound,
634 "below_lower_bound",
635 ));
636 let not_representable = err!(self.builder.build_or(
637 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
638 below_lower_bound_cmp,
639 "not_representable_as_int",
640 ));
641 let value =
642 err!(
643 self.builder
644 .build_select(not_representable, zero, value, "safe_to_convert")
645 )
646 .into_vector_value();
647 let value = if is_signed {
648 self.builder
649 .build_float_to_signed_int(value, ivec_ty, "as_int")
650 } else {
651 self.builder
652 .build_float_to_unsigned_int(value, ivec_ty, "as_int")
653 };
654
655 let value = err!(value);
656 let value =
657 err!(
658 self.builder
659 .build_select(above_upper_bound_cmp, int_max_value, value, "")
660 )
661 .into_vector_value();
662 err_nt!(
663 self.builder
664 .build_select(below_lower_bound_cmp, int_min_value, value, "")
665 .map(|v| v.into_vector_value())
666 )
667 }
668
669 #[allow(clippy::too_many_arguments)]
672 fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
673 &self,
674 fvec_ty: T,
675 ivec_ty: T::MathConvType,
676 lower_bound: u64, upper_bound: u64, int_min_value: u64,
679 int_max_value: u64,
680 value: IntValue<'ctx>,
681 ) -> Result<IntValue<'ctx>, CompileError> {
682 let res = self.trunc_sat(
683 fvec_ty,
684 ivec_ty,
685 lower_bound,
686 upper_bound,
687 int_min_value,
688 int_max_value,
689 value,
690 )?;
691 err_nt!(
692 self.builder
693 .build_bit_cast(res, self.intrinsics.i128_ty, "")
694 .map(|v| v.into_int_value())
695 )
696 }
697
698 fn trunc_sat_scalar(
701 &self,
702 int_ty: IntType<'ctx>,
703 lower_bound: u64, upper_bound: u64, int_min_value: u64,
706 int_max_value: u64,
707 value: FloatValue<'ctx>,
708 ) -> Result<IntValue<'ctx>, CompileError> {
709 let is_signed = int_min_value != 0;
725 let int_min_value = int_ty.const_int(int_min_value, is_signed);
726 let int_max_value = int_ty.const_int(int_max_value, is_signed);
727
728 let lower_bound = if is_signed {
729 err!(self.builder.build_signed_int_to_float(
730 int_ty.const_int(lower_bound, is_signed),
731 value.get_type(),
732 "",
733 ))
734 } else {
735 err!(self.builder.build_unsigned_int_to_float(
736 int_ty.const_int(lower_bound, is_signed),
737 value.get_type(),
738 "",
739 ))
740 };
741 let upper_bound = if is_signed {
742 err!(self.builder.build_signed_int_to_float(
743 int_ty.const_int(upper_bound, is_signed),
744 value.get_type(),
745 "",
746 ))
747 } else {
748 err!(self.builder.build_unsigned_int_to_float(
749 int_ty.const_int(upper_bound, is_signed),
750 value.get_type(),
751 "",
752 ))
753 };
754
755 let zero = value.get_type().const_zero();
756
757 let nan_cmp =
758 err!(
759 self.builder
760 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
761 );
762 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
763 FloatPredicate::OGT,
764 value,
765 upper_bound,
766 "above_upper_bound",
767 ));
768 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
769 FloatPredicate::OLT,
770 value,
771 lower_bound,
772 "below_lower_bound",
773 ));
774 let not_representable = err!(self.builder.build_or(
775 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
776 below_lower_bound_cmp,
777 "not_representable_as_int",
778 ));
779 let value =
780 err!(
781 self.builder
782 .build_select(not_representable, zero, value, "safe_to_convert")
783 )
784 .into_float_value();
785 let value = if is_signed {
786 err!(
787 self.builder
788 .build_float_to_signed_int(value, int_ty, "as_int")
789 )
790 } else {
791 err!(
792 self.builder
793 .build_float_to_unsigned_int(value, int_ty, "as_int")
794 )
795 };
796 let value =
797 err!(
798 self.builder
799 .build_select(above_upper_bound_cmp, int_max_value, value, "")
800 )
801 .into_int_value();
802 let value =
803 err!(
804 self.builder
805 .build_select(below_lower_bound_cmp, int_min_value, value, "")
806 )
807 .into_int_value();
808
809 err_nt!(
810 self.builder
811 .build_bit_cast(value, int_ty, "")
812 .map(|v| v.into_int_value())
813 )
814 }
815
816 fn trap_if_not_representable_as_int(
817 &self,
818 lower_bound: u64, upper_bound: u64, value: FloatValue<'ctx>,
821 ) -> Result<(), CompileError> {
822 let float_ty = value.get_type();
823 let int_ty = if float_ty == self.intrinsics.f32_ty {
824 self.intrinsics.i32_ty
825 } else {
826 self.intrinsics.i64_ty
827 };
828
829 let lower_bound = err!(self.builder.build_bit_cast(
830 int_ty.const_int(lower_bound, false),
831 float_ty,
832 ""
833 ))
834 .into_float_value();
835 let upper_bound = err!(self.builder.build_bit_cast(
836 int_ty.const_int(upper_bound, false),
837 float_ty,
838 ""
839 ))
840 .into_float_value();
841
842 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
846 FloatPredicate::UGT,
847 value,
848 upper_bound,
849 "above_upper_bound",
850 ));
851 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
852 FloatPredicate::ULT,
853 value,
854 lower_bound,
855 "below_lower_bound",
856 ));
857 let out_of_bounds = err!(self.builder.build_or(
858 above_upper_bound_cmp,
859 below_lower_bound_cmp,
860 "out_of_bounds",
861 ));
862
863 let failure_block = self
864 .context
865 .append_basic_block(self.function, "conversion_failure_block");
866 let continue_block = self
867 .context
868 .append_basic_block(self.function, "conversion_success_block");
869
870 err!(
871 self.builder
872 .build_conditional_branch(out_of_bounds, failure_block, continue_block)
873 );
874 self.builder.position_at_end(failure_block);
875 let is_nan =
876 err!(
877 self.builder
878 .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
879 );
880 let trap_code = err!(self.builder.build_select(
881 is_nan,
882 self.intrinsics.trap_bad_conversion_to_integer,
883 self.intrinsics.trap_illegal_arithmetic,
884 "",
885 ));
886 self.build_call_with_param_attributes(
887 self.intrinsics.throw_trap,
888 &[trap_code.into()],
889 "throw",
890 )?;
891 err!(self.builder.build_unreachable());
892 self.builder.position_at_end(continue_block);
893
894 Ok(())
895 }
896
897 fn trap_if_zero_or_overflow(
898 &self,
899 left: IntValue<'ctx>,
900 right: IntValue<'ctx>,
901 ) -> Result<(), CompileError> {
902 let int_type = left.get_type();
903
904 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
905 let min_value = int_type.const_int(i32::MIN as u64, false);
906 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
907 (min_value, neg_one_value)
908 } else if int_type == self.intrinsics.i64_ty {
909 let min_value = int_type.const_int(i64::MIN as u64, false);
910 let neg_one_value = int_type.const_int(-1i64 as u64, false);
911 (min_value, neg_one_value)
912 } else {
913 unreachable!()
914 };
915
916 let divisor_is_zero = err!(self.builder.build_int_compare(
917 IntPredicate::EQ,
918 right,
919 int_type.const_zero(),
920 "divisor_is_zero",
921 ));
922 let should_trap = err!(self.builder.build_or(
923 divisor_is_zero,
924 err!(self.builder.build_and(
925 err!(self.builder.build_int_compare(
926 IntPredicate::EQ,
927 left,
928 min_value,
929 "left_is_min"
930 )),
931 err!(self.builder.build_int_compare(
932 IntPredicate::EQ,
933 right,
934 neg_one_value,
935 "right_is_neg_one",
936 )),
937 "div_will_overflow",
938 )),
939 "div_should_trap",
940 ));
941
942 let should_trap = self
943 .build_call_with_param_attributes(
944 self.intrinsics.expect_i1,
945 &[
946 should_trap.into(),
947 self.intrinsics.i1_ty.const_zero().into(),
948 ],
949 "should_trap_expect",
950 )?
951 .try_as_basic_value()
952 .unwrap_basic()
953 .into_int_value();
954
955 let shouldnt_trap_block = self
956 .context
957 .append_basic_block(self.function, "shouldnt_trap_block");
958 let should_trap_block = self
959 .context
960 .append_basic_block(self.function, "should_trap_block");
961 err!(self.builder.build_conditional_branch(
962 should_trap,
963 should_trap_block,
964 shouldnt_trap_block
965 ));
966 self.builder.position_at_end(should_trap_block);
967 let trap_code = err!(self.builder.build_select(
968 divisor_is_zero,
969 self.intrinsics.trap_integer_division_by_zero,
970 self.intrinsics.trap_illegal_arithmetic,
971 "",
972 ));
973 err!(
974 self.builder
975 .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
976 );
977 err!(self.builder.build_unreachable());
978 self.builder.position_at_end(shouldnt_trap_block);
979
980 Ok(())
981 }
982
983 fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
984 let int_type = value.get_type();
985 let should_trap = err!(self.builder.build_int_compare(
986 IntPredicate::EQ,
987 value,
988 int_type.const_zero(),
989 "divisor_is_zero",
990 ));
991
992 let should_trap = self
993 .build_call_with_param_attributes(
994 self.intrinsics.expect_i1,
995 &[
996 should_trap.into(),
997 self.intrinsics.i1_ty.const_zero().into(),
998 ],
999 "should_trap_expect",
1000 )?
1001 .try_as_basic_value()
1002 .unwrap_basic()
1003 .into_int_value();
1004
1005 let shouldnt_trap_block = self
1006 .context
1007 .append_basic_block(self.function, "shouldnt_trap_block");
1008 let should_trap_block = self
1009 .context
1010 .append_basic_block(self.function, "should_trap_block");
1011 err!(self.builder.build_conditional_branch(
1012 should_trap,
1013 should_trap_block,
1014 shouldnt_trap_block
1015 ));
1016 self.builder.position_at_end(should_trap_block);
1017 self.build_call_with_param_attributes(
1018 self.intrinsics.throw_trap,
1019 &[self.intrinsics.trap_integer_division_by_zero.into()],
1020 "throw",
1021 )?;
1022 err!(self.builder.build_unreachable());
1023 self.builder.position_at_end(shouldnt_trap_block);
1024
1025 Ok(())
1026 }
1027
1028 fn v128_into_int_vec(
1029 &self,
1030 value: BasicValueEnum<'ctx>,
1031 info: ExtraInfo,
1032 int_vec_ty: VectorType<'ctx>,
1033 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1034 let (value, info) = if self.config.enable_nan_canonicalization {
1035 if info.has_pending_f32_nan() {
1036 let value = err!(
1037 self.builder
1038 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1039 );
1040 (self.canonicalize_nans(value)?, info.strip_pending())
1041 } else if info.has_pending_f64_nan() {
1042 let value = err!(
1043 self.builder
1044 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1045 );
1046 (self.canonicalize_nans(value)?, info.strip_pending())
1047 } else {
1048 (value, info)
1049 }
1050 } else {
1051 (value, info)
1052 };
1053 Ok((
1054 err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1055 info,
1056 ))
1057 }
1058
1059 fn v128_into_i8x16(
1060 &self,
1061 value: BasicValueEnum<'ctx>,
1062 info: ExtraInfo,
1063 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1064 self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1065 }
1066
1067 fn v128_into_i16x8(
1068 &self,
1069 value: BasicValueEnum<'ctx>,
1070 info: ExtraInfo,
1071 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1072 self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1073 }
1074
1075 fn v128_into_i32x4(
1076 &self,
1077 value: BasicValueEnum<'ctx>,
1078 info: ExtraInfo,
1079 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1080 self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1081 }
1082
1083 fn v128_into_i64x2(
1084 &self,
1085 value: BasicValueEnum<'ctx>,
1086 info: ExtraInfo,
1087 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1088 self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1089 }
1090
1091 fn v128_into_f32x4(
1094 &self,
1095 value: BasicValueEnum<'ctx>,
1096 info: ExtraInfo,
1097 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1098 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1099 {
1100 let value = err!(
1101 self.builder
1102 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1103 );
1104 (self.canonicalize_nans(value)?, info.strip_pending())
1105 } else {
1106 (value, info)
1107 };
1108 Ok((
1109 err!(
1110 self.builder
1111 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1112 )
1113 .into_vector_value(),
1114 info,
1115 ))
1116 }
1117
1118 fn v128_into_f64x2(
1121 &self,
1122 value: BasicValueEnum<'ctx>,
1123 info: ExtraInfo,
1124 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1125 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1126 {
1127 let value = err!(
1128 self.builder
1129 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1130 );
1131 (self.canonicalize_nans(value)?, info.strip_pending())
1132 } else {
1133 (value, info)
1134 };
1135 Ok((
1136 err!(
1137 self.builder
1138 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1139 )
1140 .into_vector_value(),
1141 info,
1142 ))
1143 }
1144
1145 fn apply_pending_canonicalization(
1146 &self,
1147 value: BasicValueEnum<'ctx>,
1148 info: ExtraInfo,
1149 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1150 if !self.config.enable_nan_canonicalization {
1151 return Ok(value);
1152 }
1153
1154 if info.has_pending_f32_nan() {
1155 if value.get_type().is_vector_type()
1156 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1157 {
1158 let ty = value.get_type();
1159 let value = err!(
1160 self.builder
1161 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1162 );
1163 let value = self.canonicalize_nans(value)?;
1164 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1165 } else {
1166 self.canonicalize_nans(value)
1167 }
1168 } else if info.has_pending_f64_nan() {
1169 if value.get_type().is_vector_type()
1170 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1171 {
1172 let ty = value.get_type();
1173 let value = err!(
1174 self.builder
1175 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1176 );
1177 let value = self.canonicalize_nans(value)?;
1178 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1179 } else {
1180 self.canonicalize_nans(value)
1181 }
1182 } else {
1183 Ok(value)
1184 }
1185 }
1186
1187 fn canonicalize_nans(
1189 &self,
1190 value: BasicValueEnum<'ctx>,
1191 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1192 if !self.config.enable_nan_canonicalization {
1193 return Ok(value);
1194 }
1195
1196 let f_ty = value.get_type();
1197 if f_ty.is_vector_type() {
1198 let value = value.into_vector_value();
1199 let f_ty = f_ty.into_vector_type();
1200 let zero = f_ty.const_zero();
1201 let nan_cmp =
1202 err!(
1203 self.builder
1204 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1205 );
1206 let canonical_qnan = f_ty
1207 .get_element_type()
1208 .into_float_type()
1209 .const_float(f64::NAN);
1210 let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1211 err_nt!(
1212 self.builder
1213 .build_select(nan_cmp, canonical_qnan, value, "")
1214 .map(|v| v.as_basic_value_enum())
1215 )
1216 } else {
1217 let value = value.into_float_value();
1218 let f_ty = f_ty.into_float_type();
1219 let zero = f_ty.const_zero();
1220 let nan_cmp =
1221 err!(
1222 self.builder
1223 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1224 );
1225 let canonical_qnan = f_ty.const_float(f64::NAN);
1226 err_nt!(
1227 self.builder
1228 .build_select(nan_cmp, canonical_qnan, value, "")
1229 .map(|v| v.as_basic_value_enum())
1230 )
1231 }
1232 }
1233
1234 fn annotate_user_memaccess(
1235 &mut self,
1236 memory_index: MemoryIndex,
1237 _memarg: &MemArg,
1238 alignment: u32,
1239 memaccess: InstructionValue<'ctx>,
1240 ) -> Result<(), CompileError> {
1241 match memaccess.get_opcode() {
1242 InstructionOpcode::Load | InstructionOpcode::Store => {
1243 memaccess.set_alignment(alignment).unwrap();
1244 }
1245 _ => {}
1246 };
1247 if !self.non_volatile_memory_ops {
1248 if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1252 memory_index,
1253 self.intrinsics,
1254 self.module,
1255 self.memory_styles,
1256 )? {
1257 memaccess.set_volatile(true).map_err(|err| {
1259 CompileError::Codegen(format!(
1260 "could not set volatile on memory operation: {err}"
1261 ))
1262 })?;
1263 }
1264 }
1265 tbaa_label(
1266 self.module,
1267 self.intrinsics,
1268 format!("memory {}", memory_index.as_u32()),
1269 memaccess,
1270 );
1271 Ok(())
1272 }
1273
1274 fn build_annotated_load<T: BasicType<'ctx>>(
1275 &mut self,
1276 pointee_ty: T,
1277 offset: IntValue<'ctx>,
1278 memarg: &MemArg,
1279 alignment: u32,
1280 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1281 let memory_index = MemoryIndex::from_u32(memarg.memory);
1282 let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1283 .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1284 let effective_address = self.resolve_memory_ptr(
1285 memory_index,
1286 memarg,
1287 self.intrinsics.ptr_ty,
1288 offset,
1289 pointee_size,
1290 )?;
1291 let result = err!(self.builder.build_load(pointee_ty, effective_address, ""));
1292 self.annotate_user_memaccess(
1293 MemoryIndex::from_u32(memarg.memory),
1294 memarg,
1295 alignment,
1296 result.as_instruction_value().unwrap(),
1297 )?;
1298 Ok(result)
1299 }
1300
1301 fn build_annotated_atomic_load(
1302 &mut self,
1303 outer_ty: IntType<'ctx>,
1304 inner_ty: IntType<'ctx>,
1305 offset: IntValue<'ctx>,
1306 memarg: &MemArg,
1307 ) -> Result<IntValue<'ctx>, CompileError> {
1308 let alignment = 2u32.pow(memarg.align as u32);
1309 let memory_index = MemoryIndex::from_u32(memarg.memory);
1310 let inner_size =
1311 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1312 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1313 })?;
1314 let outer_size =
1315 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1316 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1317 })?;
1318
1319 let effective_address = self.resolve_memory_ptr(
1320 memory_index,
1321 memarg,
1322 self.intrinsics.ptr_ty,
1323 offset,
1324 inner_size,
1325 )?;
1326 self.trap_if_misaligned(
1327 memarg,
1328 effective_address,
1329 u8::try_from(inner_size).map_err(|_| {
1330 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1331 })?,
1332 )?;
1333
1334 let result = err!(
1335 self.builder
1336 .build_load(inner_ty, effective_address, "atomic_load")
1337 );
1338 let load = result.into_int_value();
1339 let load_inst = load.as_instruction_value().unwrap();
1340 self.annotate_user_memaccess(memory_index, memarg, alignment, load_inst)?;
1341 load_inst
1342 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1343 .unwrap();
1344
1345 if inner_size < outer_size {
1346 Ok(err_nt!(
1347 self.builder.build_int_z_extend(load, outer_ty, "")
1348 )?)
1349 } else {
1350 Ok(load)
1351 }
1352 }
1353
1354 fn build_annotated_store<T: BasicType<'ctx>>(
1355 &mut self,
1356 pointee_ty: T,
1357 offset: IntValue<'ctx>,
1358 value: BasicValueEnum<'ctx>,
1359 memarg: &MemArg,
1360 alignment: u32,
1361 ) -> Result<(), CompileError> {
1362 let memory_index = MemoryIndex::from_u32(memarg.memory);
1363 let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1364 .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1365 let effective_address = self.resolve_memory_ptr(
1366 memory_index,
1367 memarg,
1368 self.intrinsics.ptr_ty,
1369 offset,
1370 pointee_size,
1371 )?;
1372
1373 if !self.non_volatile_memory_ops {
1376 self.build_annotated_load(pointee_ty, offset, memarg, alignment)?;
1377 }
1378
1379 let store = err!(self.builder.build_store(effective_address, value));
1380 self.annotate_user_memaccess(memory_index, memarg, alignment, store)
1381 }
1382
1383 fn build_annotated_atomic_store(
1384 &mut self,
1385 outer_ty: IntType<'ctx>,
1386 inner_ty: IntType<'ctx>,
1387 offset: IntValue<'ctx>,
1388 value: IntValue<'ctx>,
1389 memarg: &MemArg,
1390 ) -> Result<(), CompileError> {
1391 let alignment = 2u32.pow(memarg.align as u32);
1392 let memory_index = MemoryIndex::from_u32(memarg.memory);
1393 let inner_size =
1394 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1395 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1396 })?;
1397 let outer_size =
1398 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1399 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1400 })?;
1401
1402 let effective_address = self.resolve_memory_ptr(
1403 memory_index,
1404 memarg,
1405 self.intrinsics.ptr_ty,
1406 offset,
1407 inner_size,
1408 )?;
1409 self.trap_if_misaligned(
1410 memarg,
1411 effective_address,
1412 u8::try_from(inner_size).map_err(|_| {
1413 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1414 })?,
1415 )?;
1416
1417 let value = if inner_size < outer_size {
1418 err!(self.builder.build_int_truncate(value, inner_ty, ""))
1419 } else {
1420 value
1421 };
1422 let store = err!(self.builder.build_store(effective_address, value));
1423 self.annotate_user_memaccess(memory_index, memarg, alignment, store)?;
1424 store
1425 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1426 .unwrap();
1427 Ok(())
1428 }
1429
1430 fn build_annotated_atomic_rmw(
1431 &mut self,
1432 outer_ty: IntType<'ctx>,
1433 inner_ty: IntType<'ctx>,
1434 offset: IntValue<'ctx>,
1435 value: IntValue<'ctx>,
1436 memarg: &MemArg,
1437 op: AtomicRMWBinOp,
1438 ) -> Result<IntValue<'ctx>, CompileError> {
1439 let alignment = 2u32.pow(memarg.align as u32);
1440 let memory_index = MemoryIndex::from_u32(memarg.memory);
1441 let inner_size =
1442 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1443 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1444 })?;
1445 let outer_size =
1446 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1447 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1448 })?;
1449
1450 let effective_address = self.resolve_memory_ptr(
1451 memory_index,
1452 memarg,
1453 self.intrinsics.ptr_ty,
1454 offset,
1455 inner_size,
1456 )?;
1457 self.trap_if_misaligned(
1458 memarg,
1459 effective_address,
1460 u8::try_from(inner_size).map_err(|_| {
1461 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1462 })?,
1463 )?;
1464 let value = if inner_size < outer_size {
1465 err!(self.builder.build_int_truncate(value, inner_ty, ""))
1466 } else {
1467 value
1468 };
1469 let old = self
1470 .builder
1471 .build_atomicrmw(
1472 op,
1473 effective_address,
1474 value,
1475 AtomicOrdering::SequentiallyConsistent,
1476 )
1477 .unwrap();
1478 self.annotate_user_memaccess(
1479 memory_index,
1480 memarg,
1481 alignment,
1482 old.as_instruction_value().unwrap(),
1483 )?;
1484
1485 let value = if inner_size < outer_size {
1486 err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1487 } else {
1488 old
1489 };
1490 Ok(value)
1491 }
1492
1493 fn build_annotated_atomic_rmw_cmpxchg(
1494 &mut self,
1495 outer_ty: IntType<'ctx>,
1496 inner_ty: IntType<'ctx>,
1497 offset: IntValue<'ctx>,
1498 cmp: IntValue<'ctx>,
1499 new: IntValue<'ctx>,
1500 memarg: &MemArg,
1501 ) -> Result<IntValue<'ctx>, CompileError> {
1502 let alignment = 2u32.pow(memarg.align as u32);
1503 let memory_index = MemoryIndex::from_u32(memarg.memory);
1504 let inner_size =
1505 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1506 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1507 })?;
1508 let outer_size =
1509 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1510 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1511 })?;
1512
1513 let effective_address = self.resolve_memory_ptr(
1514 memory_index,
1515 memarg,
1516 self.intrinsics.ptr_ty,
1517 offset,
1518 inner_size,
1519 )?;
1520 self.trap_if_misaligned(
1521 memarg,
1522 effective_address,
1523 u8::try_from(inner_size).map_err(|_| {
1524 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1525 })?,
1526 )?;
1527 let (cmp, new) = if inner_size < outer_size {
1528 (
1529 err!(self.builder.build_int_truncate(cmp, inner_ty, "")),
1530 err!(self.builder.build_int_truncate(new, inner_ty, "")),
1531 )
1532 } else {
1533 (cmp, new)
1534 };
1535 let old = self
1536 .builder
1537 .build_cmpxchg(
1538 effective_address,
1539 cmp,
1540 new,
1541 AtomicOrdering::SequentiallyConsistent,
1542 AtomicOrdering::SequentiallyConsistent,
1543 )
1544 .unwrap();
1545 self.annotate_user_memaccess(
1546 memory_index,
1547 memarg,
1548 alignment,
1549 old.as_instruction_value().unwrap(),
1550 )?;
1551 let old = self
1552 .builder
1553 .build_extract_value(old, 0, "")
1554 .unwrap()
1555 .into_int_value();
1556
1557 let value = if inner_size < outer_size {
1558 err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1559 } else {
1560 old
1561 };
1562 Ok(value)
1563 }
1564
1565 fn translate_atomic_rmw(
1566 &mut self,
1567 outer_ty: IntType<'ctx>,
1568 inner_ty: IntType<'ctx>,
1569 memarg: &MemArg,
1570 op: AtomicRMWBinOp,
1571 extra_info: Option<ExtraInfo>,
1572 ) -> Result<(), CompileError> {
1573 let value = self.state.pop1()?.into_int_value();
1574 let offset = self.state.pop1()?.into_int_value();
1575 let old = self.build_annotated_atomic_rmw(outer_ty, inner_ty, offset, value, memarg, op)?;
1576 if let Some(extra_info) = extra_info {
1577 self.state.push1_extra(old, extra_info);
1578 } else {
1579 self.state.push1(old);
1580 }
1581 Ok(())
1582 }
1583
1584 fn translate_atomic_rmw_cmpxchg(
1585 &mut self,
1586 outer_ty: IntType<'ctx>,
1587 inner_ty: IntType<'ctx>,
1588 memarg: &MemArg,
1589 extra_info: Option<ExtraInfo>,
1590 ) -> Result<(), CompileError> {
1591 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
1592 let cmp = self
1593 .apply_pending_canonicalization(cmp, cmp_info)?
1594 .into_int_value();
1595 let new = self
1596 .apply_pending_canonicalization(new, new_info)?
1597 .into_int_value();
1598 let offset = self.state.pop1()?.into_int_value();
1599 let old =
1600 self.build_annotated_atomic_rmw_cmpxchg(outer_ty, inner_ty, offset, cmp, new, memarg)?;
1601 if let Some(extra_info) = extra_info {
1602 self.state.push1_extra(old, extra_info);
1603 } else {
1604 self.state.push1(old);
1605 }
1606 Ok(())
1607 }
1608
1609 fn resolve_memory_ptr(
1610 &mut self,
1611 memory_index: MemoryIndex,
1612 memarg: &MemArg,
1613 ptr_ty: PointerType<'ctx>,
1614 var_offset: IntValue<'ctx>,
1615 value_size: usize,
1616 ) -> Result<PointerValue<'ctx>, CompileError> {
1617 let builder = &self.builder;
1618 let intrinsics = &self.intrinsics;
1619 let context = &self.context;
1620 let function = &self.function;
1621
1622 let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1624 let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1625 let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1626
1627 let base_ptr = if let Some(m0) = self.m0_param {
1629 m0
1630 } else {
1631 match self
1632 .ctx
1633 .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1634 {
1635 MemoryCache::Dynamic {
1636 ptr_to_base_ptr,
1637 ptr_to_current_length,
1638 } => {
1639 let minimum = self.wasm_module.memories[memory_index].minimum;
1641 let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1642 let ptr_in_bounds = if offset.is_const() {
1643 let load_offset_end =
1646 offset.const_add(value_size_v).get_zero_extended_constant();
1647 if load_offset_end.is_some_and(|load_offset_end| {
1648 load_offset_end <= minimum.bytes().0 as u64
1649 }) {
1650 Some(intrinsics.i64_ty.const_int(1, false))
1651 } else {
1652 None
1653 }
1654 } else {
1655 None
1656 };
1657
1658 let ptr_in_bounds = match ptr_in_bounds {
1659 Some(ptr) => ptr,
1660 None => {
1661 let load_offset_end = err!(builder.build_int_add(
1662 offset,
1663 value_size_v,
1664 "load_offset_end"
1665 ));
1666
1667 let current_length = err!(builder.build_load(
1668 self.intrinsics.i32_ty,
1669 ptr_to_current_length,
1670 "current_length"
1671 ))
1672 .into_int_value();
1673 tbaa_label(
1674 self.module,
1675 self.intrinsics,
1676 format!("memory {} length", memory_index.as_u32()),
1677 current_length.as_instruction_value().unwrap(),
1678 );
1679 let current_length = err!(builder.build_int_z_extend(
1680 current_length,
1681 intrinsics.i64_ty,
1682 "current_length_zextd"
1683 ));
1684
1685 err!(builder.build_int_compare(
1686 IntPredicate::ULE,
1687 load_offset_end,
1688 current_length,
1689 "ptr_in_bounds",
1690 ))
1691 }
1692 };
1693
1694 if !ptr_in_bounds.is_constant_int()
1695 || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1696 {
1697 let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1703 intrinsics.expect_i1,
1704 &[
1705 ptr_in_bounds.into(),
1706 intrinsics.i1_ty.const_int(1, true).into(),
1707 ],
1708 "ptr_in_bounds_expect",
1709 ))
1710 .try_as_basic_value()
1711 .unwrap_basic()
1712 .into_int_value();
1713
1714 let in_bounds_continue_block =
1715 context.append_basic_block(*function, "in_bounds_continue_block");
1716 let not_in_bounds_block =
1717 context.append_basic_block(*function, "not_in_bounds_block");
1718 err!(builder.build_conditional_branch(
1719 ptr_in_bounds,
1720 in_bounds_continue_block,
1721 not_in_bounds_block,
1722 ));
1723 builder.position_at_end(not_in_bounds_block);
1724 err!(self.build_call_with_param_attributes(
1725 intrinsics.throw_trap,
1726 &[intrinsics.trap_memory_oob.into()],
1727 "throw",
1728 ));
1729 err!(builder.build_unreachable());
1730 builder.position_at_end(in_bounds_continue_block);
1731 }
1732 let ptr_to_base =
1733 err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1734 .into_pointer_value();
1735 tbaa_label(
1736 self.module,
1737 self.intrinsics,
1738 format!("memory base_ptr {}", memory_index.as_u32()),
1739 ptr_to_base.as_instruction_value().unwrap(),
1740 );
1741 ptr_to_base
1742 }
1743 MemoryCache::Static { base_ptr } => base_ptr,
1744 }
1745 };
1746 let value_ptr = unsafe {
1747 err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1748 };
1749 err_nt!(
1750 builder
1751 .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1752 .map(|v| v.into_pointer_value())
1753 )
1754 }
1755
1756 fn trap_if_misaligned(
1757 &self,
1758 _memarg: &MemArg,
1759 ptr: PointerValue<'ctx>,
1760 align: u8,
1761 ) -> Result<(), CompileError> {
1762 if align <= 1 {
1763 return Ok(());
1764 }
1765 let value = err!(self.builder.build_ptr_to_int(
1766 ptr,
1767 self.intrinsics.i64_ty,
1768 "mischeck_value"
1769 ));
1770 let and = err!(self.builder.build_and(
1771 value,
1772 self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1773 "misaligncheck",
1774 ));
1775 let aligned = err!(self.builder.build_int_compare(
1776 IntPredicate::EQ,
1777 and,
1778 self.intrinsics.i64_zero,
1779 "is_aligned"
1780 ));
1781 let aligned = self
1782 .build_call_with_param_attributes(
1783 self.intrinsics.expect_i1,
1784 &[
1785 aligned.into(),
1786 self.intrinsics.i1_ty.const_int(1, false).into(),
1787 ],
1788 "is_aligned_expect",
1789 )?
1790 .try_as_basic_value()
1791 .unwrap_basic()
1792 .into_int_value();
1793
1794 let continue_block = self
1795 .context
1796 .append_basic_block(self.function, "aligned_access_continue_block");
1797 let not_aligned_block = self
1798 .context
1799 .append_basic_block(self.function, "misaligned_trap_block");
1800 err!(
1801 self.builder
1802 .build_conditional_branch(aligned, continue_block, not_aligned_block)
1803 );
1804
1805 self.builder.position_at_end(not_aligned_block);
1806 self.build_call_with_param_attributes(
1807 self.intrinsics.throw_trap,
1808 &[self.intrinsics.trap_unaligned_atomic.into()],
1809 "throw",
1810 )?;
1811 err!(self.builder.build_unreachable());
1812
1813 self.builder.position_at_end(continue_block);
1814 Ok(())
1815 }
1816
1817 fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1818 let func_type = self.function.get_type();
1819
1820 let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1821 let results = err!(
1822 results
1823 .into_iter()
1824 .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1825 .collect::<Result<Vec<_>, _>>()
1826 );
1827
1828 if wasm_fn_type.results().is_empty() {
1829 err!(self.builder.build_return(None));
1830 } else if self.abi.is_sret(wasm_fn_type)? {
1831 let sret = self
1832 .function
1833 .get_first_param()
1834 .unwrap()
1835 .into_pointer_value();
1836 let llvm_params: Vec<_> = wasm_fn_type
1837 .results()
1838 .iter()
1839 .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1840 .collect();
1841 let mut struct_value = self
1842 .context
1843 .struct_type(llvm_params.as_slice(), false)
1844 .get_undef();
1845 for (idx, value) in results.into_iter().enumerate() {
1846 let value = err!(self.builder.build_bit_cast(
1847 value,
1848 type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1849 "",
1850 ));
1851 struct_value =
1852 err!(
1853 self.builder
1854 .build_insert_value(struct_value, value, idx as u32, "")
1855 )
1856 .into_struct_value();
1857 }
1858 err!(self.builder.build_store(sret, struct_value));
1859 err!(self.builder.build_return(None));
1860 } else {
1861 err!(
1862 self.builder
1863 .build_return(Some(&self.abi.pack_values_for_register_return(
1864 self.intrinsics,
1865 &self.builder,
1866 &results,
1867 &func_type,
1868 )?))
1869 );
1870 }
1871 Ok(())
1872 }
1873
1874 fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1877 if let Some(tag) = self.tags_cache.get(&tag) {
1878 return *tag;
1879 }
1880
1881 let tag_ty = self
1882 .context
1883 .struct_type(&[self.intrinsics.i32_ty.into()], false);
1884 let tag_glbl = self.module.add_global(
1885 tag_ty,
1886 Some(AddressSpace::default()),
1887 &format!("__wasmer_eh_type_info_{tag}"),
1888 );
1889 tag_glbl.set_initializer(
1890 &tag_ty
1891 .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1892 .as_basic_value_enum(),
1893 );
1894
1895 tag_glbl.set_linkage(Linkage::External);
1896 tag_glbl.set_constant(true);
1897 if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1905 tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1906 }
1907
1908 let tag_glbl = tag_glbl.as_basic_value_enum();
1909
1910 self.tags_cache.insert(tag, tag_glbl);
1911 tag_glbl
1912 }
1913
1914 fn emit_return_call(
1915 &mut self,
1916 call_site: CallSiteValue<'ctx>,
1917 callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
1918 ) -> Result<(), CompileError> {
1919 let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
1926 LLVMTailCallKind::LLVMTailCallKindMustTail
1927 } else {
1928 LLVMTailCallKind::LLVMTailCallKindTail
1929 };
1930 call_site.set_tail_call_kind(tail_call_kind);
1931
1932 if self.function.get_type().get_return_type().is_none() {
1933 err!(self.builder.build_return(None));
1934 } else {
1935 let ret = call_site.try_as_basic_value();
1936 if ret.is_instruction() {
1937 return Err(CompileError::Codegen(
1938 "return_call expected a non-void call result".to_string(),
1939 ));
1940 }
1941 err!(self.builder.build_return(Some(&ret.unwrap_basic())));
1942 }
1943 Ok(())
1944 }
1945
1946 fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
1948 self.abi.is_sret(func_type).ok().map(|_| {
1949 self.function
1950 .get_first_param()
1951 .unwrap()
1952 .into_pointer_value()
1953 })
1954 }
1955
1956 fn build_m0_indirect_call(
1957 &mut self,
1958 table_index: u32,
1959 ctx_ptr: PointerValue<'ctx>,
1960 func_type: &FunctionType,
1961 func_ptr: PointerValue<'ctx>,
1962 func_index: IntValue<'ctx>,
1963 is_return_call: bool,
1964 ) -> Result<(), CompileError> {
1965 let Some(m0) = self.m0_param else {
1966 return Err(CompileError::Codegen(
1967 "Call to build_m0_indirect_call without m0 parameter!".to_string(),
1968 ));
1969 };
1970
1971 let params = self.state.popn_save_extra(func_type.params().len())?;
1972
1973 let mut local_func_indices = vec![];
1974 let mut foreign_func_indices = vec![];
1975
1976 for t in &self.wasm_module.table_initializers {
1977 if t.table_index.as_u32() == table_index {
1978 for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
1979 if self.wasm_module.local_func_index(*func_idx).is_some() {
1980 local_func_indices.push(func_in_table_idx)
1981 } else {
1982 foreign_func_indices.push(func_in_table_idx)
1983 }
1984 }
1985 break;
1986 }
1987 }
1988
1989 let needs_switch = self.m0_param.is_some()
1990 && !local_func_indices.is_empty()
1991 && !foreign_func_indices.is_empty();
1992
1993 if needs_switch {
1994 let foreign_idx_block = self
1995 .context
1996 .append_basic_block(self.function, "foreign_call_block");
1997 let local_idx_block = self
1998 .context
1999 .append_basic_block(self.function, "local_call_block");
2000 let unreachable_indirect_call_branch_block = self
2001 .context
2002 .append_basic_block(self.function, "unreachable_indirect_call_branch");
2003
2004 let cont =
2005 (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
2006
2007 err!(
2008 self.builder.build_switch(
2009 func_index,
2010 unreachable_indirect_call_branch_block,
2011 &local_func_indices
2012 .into_iter()
2013 .map(|v| (
2014 self.intrinsics.i32_ty.const_int(v as _, false),
2015 local_idx_block
2016 ))
2017 .chain(foreign_func_indices.into_iter().map(|v| (
2018 self.intrinsics.i32_ty.const_int(v as _, false),
2019 foreign_idx_block
2020 )))
2021 .collect::<Vec<_>>()
2022 )
2023 );
2024
2025 self.builder
2026 .position_at_end(unreachable_indirect_call_branch_block);
2027 err!(self.builder.build_unreachable());
2028
2029 self.builder.position_at_end(local_idx_block);
2031 let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
2032 ctx_ptr,
2033 func_type,
2034 func_ptr,
2035 Some(m0),
2036 is_return_call,
2037 ¶ms,
2038 )?;
2039
2040 let local_rets = if is_return_call {
2041 self.emit_return_call(local_call_site, local_llvm_func_type)?;
2042 Vec::new()
2043 } else {
2044 let rets = self.abi.rets_from_call(
2045 &self.builder,
2046 self.intrinsics,
2047 local_call_site,
2048 func_type,
2049 )?;
2050 err!(
2051 self.builder
2052 .build_unconditional_branch(cont.expect("non-return call requires cont"))
2053 );
2054 rets
2055 };
2056
2057 self.builder.position_at_end(foreign_idx_block);
2058 let (foreign_call_site, foreign_llvm_func_type) = self
2059 .build_indirect_call_with_params(
2060 ctx_ptr,
2061 func_type,
2062 func_ptr,
2063 None,
2064 is_return_call,
2065 ¶ms,
2066 )?;
2067
2068 let foreign_rets = if is_return_call {
2069 self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
2070 Vec::new()
2071 } else {
2072 let rets = self.abi.rets_from_call(
2073 &self.builder,
2074 self.intrinsics,
2075 foreign_call_site,
2076 func_type,
2077 )?;
2078 err!(
2079 self.builder
2080 .build_unconditional_branch(cont.expect("non-return call requires cont"))
2081 );
2082 rets
2083 };
2084
2085 if is_return_call {
2086 return Ok(());
2087 }
2088
2089 self.builder
2090 .position_at_end(cont.expect("non-return call requires cont"));
2091
2092 for i in 0..foreign_rets.len() {
2093 let f_i = foreign_rets[i];
2094 let l_i = local_rets[i];
2095 let ty = f_i.get_type();
2096 let v = err!(self.builder.build_phi(ty, ""));
2097 v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
2098 self.state.push1(v.as_basic_value());
2099 }
2100 } else if foreign_func_indices.is_empty() {
2101 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2102 ctx_ptr,
2103 func_type,
2104 func_ptr,
2105 Some(m0),
2106 is_return_call,
2107 ¶ms,
2108 )?;
2109
2110 if is_return_call {
2111 self.emit_return_call(call_site, llvm_func_type)?;
2112 } else {
2113 self.abi
2114 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2115 .iter()
2116 .for_each(|ret| self.state.push1(*ret));
2117 }
2118 } else {
2119 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2120 ctx_ptr,
2121 func_type,
2122 func_ptr,
2123 None,
2124 is_return_call,
2125 ¶ms,
2126 )?;
2127 if is_return_call {
2128 self.emit_return_call(call_site, llvm_func_type)?;
2129 } else {
2130 self.abi
2131 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2132 .iter()
2133 .for_each(|ret| self.state.push1(*ret));
2134 }
2135 }
2136
2137 Ok(())
2138 }
2139
2140 fn build_indirect_call(
2141 &mut self,
2142 ctx_ptr: PointerValue<'ctx>,
2143 func_type: &FunctionType,
2144 func_ptr: PointerValue<'ctx>,
2145 m0_param: Option<PointerValue<'ctx>>,
2146 is_return_call: bool,
2147 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2148 let params = self.state.popn_save_extra(func_type.params().len())?;
2149 self.build_indirect_call_with_params(
2150 ctx_ptr,
2151 func_type,
2152 func_ptr,
2153 m0_param,
2154 is_return_call,
2155 ¶ms,
2156 )
2157 }
2158
2159 fn build_indirect_call_with_params(
2160 &mut self,
2161 ctx_ptr: PointerValue<'ctx>,
2162 func_type: &FunctionType,
2163 func_ptr: PointerValue<'ctx>,
2164 m0_param: Option<PointerValue<'ctx>>,
2165 is_return_call: bool,
2166 params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
2167 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2168 let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
2169 self.context,
2170 self.intrinsics,
2171 Some(self.ctx.get_offsets()),
2172 func_type,
2173 m0_param.is_some(),
2174 )?;
2175
2176 let params = params
2178 .iter()
2179 .zip(func_type.params().iter())
2180 .map(|((v, info), wasm_ty)| match wasm_ty {
2181 Type::F32 => err_nt!(self.builder.build_bit_cast(
2182 self.apply_pending_canonicalization(*v, *info)?,
2183 self.intrinsics.f32_ty,
2184 "",
2185 )),
2186 Type::F64 => err_nt!(self.builder.build_bit_cast(
2187 self.apply_pending_canonicalization(*v, *info)?,
2188 self.intrinsics.f64_ty,
2189 "",
2190 )),
2191 Type::V128 => self.apply_pending_canonicalization(*v, *info),
2192 _ => Ok(*v),
2193 })
2194 .collect::<Result<Vec<_>, _>>()?;
2195
2196 let params = self.abi.args_to_call(
2197 &self.alloca_builder,
2198 func_type,
2199 &llvm_func_type,
2200 ctx_ptr,
2201 params.as_slice(),
2202 self.intrinsics,
2203 m0_param,
2204 is_return_call
2205 .then(|| self.current_sret_ptr(func_type))
2206 .flatten(),
2207 )?;
2208
2209 let typed_func_ptr = err!(self.builder.build_pointer_cast(
2210 func_ptr,
2211 self.context.ptr_type(AddressSpace::default()),
2212 "typed_func_ptr",
2213 ));
2214
2215 let call_site_local = self.build_indirect_call_or_invoke(
2216 llvm_func_type,
2217 typed_func_ptr,
2218 params.as_slice(),
2219 "then_block",
2220 is_return_call,
2221 )?;
2222 for (attr, attr_loc) in llvm_func_attrs {
2223 call_site_local.add_attribute(attr_loc, attr);
2224 }
2225
2226 Ok((call_site_local, llvm_func_type))
2227 }
2228
2229 fn build_indirect_call_or_invoke(
2230 &mut self,
2231 llvm_func_type: inkwell::types::FunctionType<'ctx>,
2232 func_ptr: PointerValue<'ctx>,
2233 params: &[BasicValueEnum<'ctx>],
2234 then_block_name: &str,
2235 is_return_call: bool,
2236 ) -> Result<CallSiteValue<'ctx>, CompileError> {
2237 if let Some(lpad) = self.state.get_innermost_landingpad()
2240 && !is_return_call
2241 {
2242 let then_block = self
2243 .context
2244 .append_basic_block(self.function, then_block_name);
2245
2246 let ret = err!(self.builder.build_indirect_invoke(
2247 llvm_func_type,
2248 func_ptr,
2249 params,
2250 then_block,
2251 lpad,
2252 "",
2253 ));
2254
2255 self.builder.position_at_end(then_block);
2256 Ok(ret)
2257 } else {
2258 let call_params = params
2259 .iter()
2260 .copied()
2261 .map(Into::into)
2262 .collect::<Vec<BasicMetadataValueEnum>>();
2263 Ok(err!(self.builder.build_indirect_call(
2264 llvm_func_type,
2265 func_ptr,
2266 call_params.as_slice(),
2267 ""
2268 )))
2269 }
2270 }
2271}
2272
2273pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
2274 m0_param: Option<PointerValue<'ctx>>,
2275 context: &'ctx Context,
2276 builder: Builder<'ctx>,
2277 alloca_builder: Builder<'ctx>,
2278 intrinsics: &'a Intrinsics<'ctx>,
2279 target_data: &'a TargetData,
2280 state: State<'ctx>,
2281 function: FunctionValue<'ctx>,
2282 locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, ctx: CtxType<'ctx, 'a>,
2284 unreachable_depth: usize,
2285 memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
2286 _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
2287 module: &'a Module<'ctx>,
2288 module_translation: &'a ModuleTranslationState,
2289 signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
2290 wasm_module: &'a ModuleInfo,
2291 symbol_registry: &'a dyn SymbolRegistry,
2292 abi: &'a dyn Abi,
2293 config: &'a LLVM,
2294 target_triple: Triple,
2295 tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
2296 binary_fmt: target_lexicon::BinaryFormat,
2297 cpu_features: EnumSet<CpuFeature>,
2298 non_volatile_memory_ops: bool,
2299}
2300
2301impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
2302 fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
2303 let intrinsic = if value
2304 .get_type()
2305 .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2306 {
2307 Some(self.intrinsics.add_f32)
2308 } else if value
2309 .get_type()
2310 .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2311 {
2312 Some(self.intrinsics.add_f64)
2313 } else if value
2314 .get_type()
2315 .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
2316 {
2317 Some(self.intrinsics.add_f32x4)
2318 } else if value
2319 .get_type()
2320 .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
2321 {
2322 Some(self.intrinsics.add_f64x2)
2323 } else {
2324 None
2325 };
2326
2327 match intrinsic {
2328 Some(intrinsic) => err_nt!(
2329 self.builder
2330 .build_call(
2331 intrinsic,
2332 &[
2333 value.into(),
2334 value.get_type().const_zero().into(),
2335 self.intrinsics.fp_rounding_md,
2336 self.intrinsics.fp_exception_md,
2337 ],
2338 "",
2339 )
2340 .map(|v| v.try_as_basic_value().unwrap_basic())
2341 ),
2342 None => Ok(value),
2343 }
2344 }
2345
2346 fn finalize_minmax_result(
2347 &self,
2348 value: BasicValueEnum<'ctx>,
2349 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2350 let ty = value.get_type();
2351 if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2352 || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2353 {
2354 let value = value.into_float_value();
2355 let is_nan = err!(self.builder.build_float_compare(
2356 FloatPredicate::UNO,
2357 value,
2358 value,
2359 "res_is_nan"
2360 ));
2361 let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2362 let result =
2363 err!(
2364 self.builder
2365 .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2366 );
2367 Ok(result.as_basic_value_enum())
2368 } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2369 let value = value.into_vector_value();
2370 let is_nan = self
2371 .build_call_with_param_attributes(
2372 self.intrinsics.cmp_f32x4,
2373 &[
2374 value.into(),
2375 value.into(),
2376 self.intrinsics.fp_uno_md,
2377 self.intrinsics.fp_exception_md,
2378 ],
2379 "",
2380 )?
2381 .try_as_basic_value()
2382 .unwrap_basic()
2383 .into_vector_value();
2384 let quiet = self
2385 .quiet_nan(value.as_basic_value_enum())?
2386 .into_vector_value();
2387 let result = err!(self.builder.build_select(
2388 is_nan,
2389 quiet.as_basic_value_enum(),
2390 value.as_basic_value_enum(),
2391 "",
2392 ));
2393 Ok(result.as_basic_value_enum())
2394 } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2395 let value = value.into_vector_value();
2396 let is_nan = self
2397 .build_call_with_param_attributes(
2398 self.intrinsics.cmp_f64x2,
2399 &[
2400 value.into(),
2401 value.into(),
2402 self.intrinsics.fp_uno_md,
2403 self.intrinsics.fp_exception_md,
2404 ],
2405 "",
2406 )?
2407 .try_as_basic_value()
2408 .unwrap_basic()
2409 .into_vector_value();
2410 let quiet = self
2411 .quiet_nan(value.as_basic_value_enum())?
2412 .into_vector_value();
2413 let result = err!(self.builder.build_select(
2414 is_nan,
2415 quiet.as_basic_value_enum(),
2416 value.as_basic_value_enum(),
2417 "",
2418 ));
2419 Ok(result.as_basic_value_enum())
2420 } else {
2421 Ok(value)
2422 }
2423 }
2424
2425 fn finalize_rounding_result(
2426 &self,
2427 value: BasicValueEnum<'ctx>,
2428 info: ExtraInfo,
2429 ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2430 let ty = value.get_type();
2431 let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2432 let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2433 let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2434 let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2435 debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2436
2437 if matches!(
2438 self.target_triple.architecture,
2439 Architecture::Riscv32(..) | Architecture::Riscv64(..)
2440 ) {
2441 if is_f32 || is_f64 {
2442 let input = value.into_float_value();
2443 let is_nan = err!(self.builder.build_float_compare(
2444 FloatPredicate::UNO,
2445 input,
2446 input,
2447 "res_is_nan",
2448 ));
2449 let canonical_nan_bits = if is_f32 {
2450 self.intrinsics
2451 .i32_ty
2452 .const_int(CANONICAL_NAN_F32 as _, false)
2453 } else {
2454 self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2455 };
2456 let canonical_nan = err!(self.builder.build_bit_cast(
2457 canonical_nan_bits,
2458 ty,
2459 "canonical_nan",
2460 ));
2461 let res =
2462 err!(
2463 self.builder
2464 .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2465 );
2466 Ok((res, info))
2467 } else if is_f32x4 {
2468 let value = value.into_vector_value();
2469 let is_nan = err!(self.builder.build_call(
2470 self.intrinsics.cmp_f32x4,
2471 &[
2472 value.into(),
2473 value.into(),
2474 self.intrinsics.fp_uno_md,
2475 self.intrinsics.fp_exception_md,
2476 ],
2477 "",
2478 ))
2479 .try_as_basic_value()
2480 .unwrap_basic()
2481 .into_vector_value();
2482 let canonical_nan_bits = self
2483 .intrinsics
2484 .i32_ty
2485 .const_int(CANONICAL_NAN_F32 as _, false);
2486 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2487 let canonical_nan = err!(self.builder.build_bit_cast(
2488 canonical_nan_bits,
2489 self.intrinsics.f32x4_ty,
2490 "canonical_nan",
2491 ));
2492 let res = err!(self.builder.build_select(
2493 is_nan,
2494 canonical_nan.as_basic_value_enum(),
2495 value.as_basic_value_enum(),
2496 "canonical_nan",
2497 ));
2498 Ok((res, info))
2499 } else {
2500 let value = value.into_vector_value();
2501 let is_nan = err!(self.builder.build_call(
2502 self.intrinsics.cmp_f64x2,
2503 &[
2504 value.into(),
2505 value.into(),
2506 self.intrinsics.fp_uno_md,
2507 self.intrinsics.fp_exception_md,
2508 ],
2509 "",
2510 ))
2511 .try_as_basic_value()
2512 .unwrap_basic()
2513 .into_vector_value();
2514 let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2515 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2516 let canonical_nan = err!(self.builder.build_bit_cast(
2517 canonical_nan_bits,
2518 self.intrinsics.f64x2_ty,
2519 "canonical_nan",
2520 ));
2521 let res = err!(self.builder.build_select(
2522 is_nan,
2523 canonical_nan.as_basic_value_enum(),
2524 value.as_basic_value_enum(),
2525 "canonical_nan",
2526 ));
2527 Ok((res, info))
2528 }
2529 } else {
2530 Ok((
2531 value,
2532 (info
2533 | if is_f32 || is_f32x4 {
2534 ExtraInfo::pending_f32_nan()
2535 } else {
2536 ExtraInfo::pending_f64_nan()
2537 })?,
2538 ))
2539 }
2540 }
2541
2542 fn translate_control_flow_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2545 match op {
2546 Operator::Block { blockty } => {
2547 let current_block = self
2548 .builder
2549 .get_insert_block()
2550 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2551
2552 let end_block = self.context.append_basic_block(self.function, "end");
2553 self.builder.position_at_end(end_block);
2554
2555 let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2556 .module_translation
2557 .blocktype_params_results(&blockty)?
2558 .1
2559 .iter()
2560 .map(|&wp_ty| {
2561 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2562 type_to_llvm(self.intrinsics, wasm_ty)
2563 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2564 })
2565 })
2566 .collect::<Result<_, _>>()?;
2567
2568 self.state.push_block(
2569 end_block,
2570 phis,
2571 self.module_translation
2572 .blocktype_params_results(&blockty)?
2573 .0
2574 .len(),
2575 );
2576 self.builder.position_at_end(current_block);
2577 }
2578 Operator::Loop { blockty } => {
2579 let loop_body = self.context.append_basic_block(self.function, "loop_body");
2580 let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2581 let pre_loop_block = self.builder.get_insert_block().unwrap();
2582
2583 let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2584
2585 self.builder.position_at_end(loop_next);
2586 let phis = blocktypes
2587 .1
2588 .iter()
2589 .map(|&wp_ty| {
2590 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2591 type_to_llvm(self.intrinsics, wasm_ty)
2592 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2593 })
2594 })
2595 .collect::<Result<_, _>>()?;
2596 self.builder.position_at_end(loop_body);
2597 let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2598 .0
2599 .iter()
2600 .map(|&wp_ty| {
2601 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2602 type_to_llvm(self.intrinsics, wasm_ty)
2603 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2604 })
2605 })
2606 .collect::<Result<_, _>>()?;
2607
2608 self.builder.position_at_end(pre_loop_block);
2612 for phi in loop_phis.iter().rev() {
2613 let (value, info) = self.state.pop1_extra()?;
2614 let value = self.apply_pending_canonicalization(value, info)?;
2615 phi.add_incoming(&[(&value, pre_loop_block)]);
2616 }
2617
2618 err!(self.builder.build_unconditional_branch(loop_body));
2619
2620 self.builder.position_at_end(loop_body);
2621 for phi in &loop_phis {
2622 self.state.push1(phi.as_basic_value());
2623 }
2624
2625 let num_inputs = loop_phis.len();
2626 self.state
2627 .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2628 }
2629 Operator::Br { relative_depth } => {
2630 let frame = self.state.frame_at_depth(relative_depth)?;
2631
2632 let current_block = self
2633 .builder
2634 .get_insert_block()
2635 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2636
2637 let phis = if frame.is_loop() {
2638 frame.loop_body_phis()
2639 } else {
2640 frame.phis()
2641 };
2642
2643 let len = phis.len();
2644 let values = self.state.peekn_extra(len)?;
2645 let values = values
2646 .iter()
2647 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2648 .collect::<Result<Vec<_>, _>>()?;
2649
2650 for (phi, value) in phis.iter().zip(values) {
2654 phi.add_incoming(&[(&value, current_block)]);
2655 }
2656
2657 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2658
2659 self.state.popn(len)?;
2660 self.state.reachable = false;
2661 }
2662 Operator::BrIf { relative_depth } => {
2663 let cond = self.state.pop1()?;
2664 let frame = self.state.frame_at_depth(relative_depth)?;
2665
2666 let current_block = self
2667 .builder
2668 .get_insert_block()
2669 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2670
2671 let phis = if frame.is_loop() {
2672 frame.loop_body_phis()
2673 } else {
2674 frame.phis()
2675 };
2676
2677 let param_stack = self.state.peekn_extra(phis.len())?;
2678 let param_stack = param_stack
2679 .iter()
2680 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2681 .collect::<Result<Vec<_>, _>>()?;
2682
2683 for (phi, value) in phis.iter().zip(param_stack) {
2684 phi.add_incoming(&[(&value, current_block)]);
2685 }
2686
2687 let else_block = self.context.append_basic_block(self.function, "else");
2688
2689 let cond_value = err!(self.builder.build_int_compare(
2690 IntPredicate::NE,
2691 cond.into_int_value(),
2692 self.intrinsics.i32_zero,
2693 "",
2694 ));
2695 err!(self.builder.build_conditional_branch(
2696 cond_value,
2697 *frame.br_dest(),
2698 else_block
2699 ));
2700 self.builder.position_at_end(else_block);
2701 }
2702 Operator::BrTable { ref targets } => {
2703 let current_block = self
2704 .builder
2705 .get_insert_block()
2706 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2707
2708 let index = self.state.pop1()?;
2709
2710 let default_frame = self.state.frame_at_depth(targets.default())?;
2711
2712 let phis = if default_frame.is_loop() {
2713 default_frame.loop_body_phis()
2714 } else {
2715 default_frame.phis()
2716 };
2717 let args = self.state.peekn(phis.len())?;
2718
2719 for (phi, value) in phis.iter().zip(args.iter()) {
2720 phi.add_incoming(&[(value, current_block)]);
2721 }
2722
2723 let cases: Vec<_> = targets
2724 .targets()
2725 .enumerate()
2726 .map(|(case_index, depth)| {
2727 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2728 let frame_result: Result<&ControlFrame, CompileError> =
2729 self.state.frame_at_depth(depth);
2730 let frame = match frame_result {
2731 Ok(v) => v,
2732 Err(e) => return Err(e),
2733 };
2734 let case_index_literal =
2735 self.context.i32_type().const_int(case_index as u64, false);
2736 let phis = if frame.is_loop() {
2737 frame.loop_body_phis()
2738 } else {
2739 frame.phis()
2740 };
2741 for (phi, value) in phis.iter().zip(args.iter()) {
2742 phi.add_incoming(&[(value, current_block)]);
2743 }
2744
2745 Ok((case_index_literal, *frame.br_dest()))
2746 })
2747 .collect::<Result<_, _>>()?;
2748
2749 err!(self.builder.build_switch(
2750 index.into_int_value(),
2751 *default_frame.br_dest(),
2752 &cases[..],
2753 ));
2754
2755 let args_len = args.len();
2756 self.state.popn(args_len)?;
2757 self.state.reachable = false;
2758 }
2759 Operator::If { blockty } => {
2760 let current_block = self
2761 .builder
2762 .get_insert_block()
2763 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2764 let if_then_block = self.context.append_basic_block(self.function, "if_then");
2765 let if_else_block = self.context.append_basic_block(self.function, "if_else");
2766 let end_block = self.context.append_basic_block(self.function, "if_end");
2767
2768 let end_phis = {
2769 self.builder.position_at_end(end_block);
2770
2771 let phis = self
2772 .module_translation
2773 .blocktype_params_results(&blockty)?
2774 .1
2775 .iter()
2776 .map(|&wp_ty| {
2777 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2778 type_to_llvm(self.intrinsics, wasm_ty)
2779 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2780 })
2781 })
2782 .collect::<Result<_, _>>()?;
2783
2784 self.builder.position_at_end(current_block);
2785 phis
2786 };
2787
2788 let block_param_types = self
2789 .module_translation
2790 .blocktype_params_results(&blockty)?
2791 .0
2792 .iter()
2793 .map(|&wp_ty| {
2794 err_nt!(wptype_to_type(wp_ty))
2795 .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2796 })
2797 .collect::<Result<Vec<_>, _>>()?;
2798
2799 self.builder.position_at_end(if_else_block);
2801 let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2802 .iter()
2803 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2804 .collect::<Result<SmallVec<_>, _>>()?;
2805 self.builder.position_at_end(if_then_block);
2806 let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2807 .iter()
2808 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2809 .collect::<Result<SmallVec<_>, _>>()?;
2810
2811 let cond = self.state.pop1()?;
2813
2814 self.builder.position_at_end(current_block);
2818 for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2819 let (value, info) = self.state.pop1_extra()?;
2820 let value = self.apply_pending_canonicalization(value, info)?;
2821 else_phi.add_incoming(&[(&value, current_block)]);
2822 then_phi.add_incoming(&[(&value, current_block)]);
2823 }
2824
2825 let cond_value = err!(self.builder.build_int_compare(
2826 IntPredicate::NE,
2827 cond.into_int_value(),
2828 self.intrinsics.i32_zero,
2829 "",
2830 ));
2831
2832 err!(self.builder.build_conditional_branch(
2833 cond_value,
2834 if_then_block,
2835 if_else_block
2836 ));
2837
2838 self.builder.position_at_end(if_then_block);
2839 for phi in then_phis.iter() {
2840 self.state.push1(phi.as_basic_value());
2841 }
2842
2843 self.state.push_if(
2844 if_then_block,
2845 if_else_block,
2846 end_block,
2847 then_phis,
2848 else_phis,
2849 end_phis,
2850 block_param_types.len(),
2851 );
2852 }
2853 Operator::Else => {
2854 if self.state.reachable {
2855 let frame = self.state.frame_at_depth(0)?;
2856 let current_block = self.builder.get_insert_block().ok_or_else(|| {
2857 CompileError::Codegen("not currently in a block".to_string())
2858 })?;
2859
2860 for phi in frame.phis().to_vec().iter().rev() {
2861 let (value, info) = self.state.pop1_extra()?;
2862 let value = self.apply_pending_canonicalization(value, info)?;
2863 phi.add_incoming(&[(&value, current_block)])
2864 }
2865
2866 let frame = self.state.frame_at_depth(0)?;
2867 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2868 }
2869
2870 let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2871 if_else,
2872 if_else_state,
2873 ..
2874 } = self.state.frame_at_depth_mut(0)?
2875 {
2876 (if_else, if_else_state)
2877 } else {
2878 unreachable!()
2879 };
2880
2881 *if_else_state = IfElseState::Else;
2882
2883 self.builder.position_at_end(*if_else_block);
2884 self.state.reachable = true;
2885
2886 if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2887 for phi in else_phis.clone().iter() {
2889 self.state.push1(phi.as_basic_value());
2890 }
2891 };
2892 }
2893
2894 Operator::End => {
2895 let frame = self.state.pop_frame()?;
2896 let current_block = self
2897 .builder
2898 .get_insert_block()
2899 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2900
2901 if self.state.reachable {
2902 for phi in frame.phis().iter().rev() {
2903 let (value, info) = self.state.pop1_extra()?;
2904 let value = self.apply_pending_canonicalization(value, info)?;
2905 phi.add_incoming(&[(&value, current_block)]);
2906 }
2907
2908 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2909 }
2910
2911 if let ControlFrame::IfElse {
2912 if_else,
2913 next,
2914 if_else_state: IfElseState::If,
2915 else_phis,
2916 ..
2917 } = &frame
2918 {
2919 for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
2920 phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
2921 }
2922 self.builder.position_at_end(*if_else);
2923 err!(self.builder.build_unconditional_branch(*next));
2924 } else if let ControlFrame::Landingpad { .. } = &frame {
2925 self.state.pop_landingpad();
2926 };
2927
2928 self.builder.position_at_end(*frame.code_after());
2929 self.state.reset_stack(&frame);
2930
2931 self.state.reachable = true;
2932
2933 for phi in frame.phis() {
2935 if phi.count_incoming() != 0 {
2936 self.state.push1(phi.as_basic_value());
2937 } else {
2938 let basic_ty = phi.as_basic_value().get_type();
2945 let placeholder_value = basic_ty.const_zero();
2946 self.state.push1(placeholder_value);
2947 phi.as_instruction().erase_from_basic_block();
2948 }
2949 }
2950 }
2951 Operator::Return => {
2952 let current_block = self
2953 .builder
2954 .get_insert_block()
2955 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2956
2957 let frame = self.state.outermost_frame()?;
2958 for phi in frame.phis().to_vec().iter().rev() {
2959 let (arg, info) = self.state.pop1_extra()?;
2960 let arg = self.apply_pending_canonicalization(arg, info)?;
2961 phi.add_incoming(&[(&arg, current_block)]);
2962 }
2963 let frame = self.state.outermost_frame()?;
2964 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2965
2966 self.state.reachable = false;
2967 }
2968
2969 Operator::Unreachable => {
2970 self.build_call_with_param_attributes(
2971 self.intrinsics.throw_trap,
2972 &[self.intrinsics.trap_unreachable.into()],
2973 "throw",
2974 )?;
2975 err!(self.builder.build_unreachable());
2976
2977 self.state.reachable = false;
2978 }
2979 _ => unreachable!(),
2980 }
2981
2982 Ok(())
2983 }
2984
2985 fn translate_basic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2988 let vmctx = &self.ctx.basic().into_pointer_value();
2989
2990 match op {
2991 Operator::Nop => {
2992 }
2994 Operator::Drop => {
2995 self.state.pop1()?;
2996 }
2997
2998 Operator::I32Const { value } => {
3000 let i = self.intrinsics.i32_ty.const_int(value as u64, false);
3001 let info = if is_f32_arithmetic(value as u32) {
3002 ExtraInfo::arithmetic_f32()
3003 } else {
3004 Default::default()
3005 };
3006 self.state.push1_extra(i, info);
3007 }
3008 Operator::I64Const { value } => {
3009 let i = self.intrinsics.i64_ty.const_int(value as u64, false);
3010 let info = if is_f64_arithmetic(value as u64) {
3011 ExtraInfo::arithmetic_f64()
3012 } else {
3013 Default::default()
3014 };
3015 self.state.push1_extra(i, info);
3016 }
3017 Operator::F32Const { value } => {
3018 let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
3019 let info = if is_f32_arithmetic(value.bits()) {
3020 ExtraInfo::arithmetic_f32()
3021 } else {
3022 Default::default()
3023 };
3024 let f = err!(
3025 self.builder
3026 .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
3027 );
3028 self.state.push1_extra(f, info);
3029 }
3030 Operator::F64Const { value } => {
3031 let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
3032 let info = if is_f64_arithmetic(value.bits()) {
3033 ExtraInfo::arithmetic_f64()
3034 } else {
3035 Default::default()
3036 };
3037 let f = err!(
3038 self.builder
3039 .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
3040 );
3041 self.state.push1_extra(f, info);
3042 }
3043 Operator::V128Const { value } => {
3044 let mut hi: [u8; 8] = Default::default();
3045 let mut lo: [u8; 8] = Default::default();
3046 hi.copy_from_slice(&value.bytes()[0..8]);
3047 lo.copy_from_slice(&value.bytes()[8..16]);
3048 let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
3049 let i = self
3050 .intrinsics
3051 .i128_ty
3052 .const_int_arbitrary_precision(&packed);
3053 let mut quad1: [u8; 4] = Default::default();
3054 let mut quad2: [u8; 4] = Default::default();
3055 let mut quad3: [u8; 4] = Default::default();
3056 let mut quad4: [u8; 4] = Default::default();
3057 quad1.copy_from_slice(&value.bytes()[0..4]);
3058 quad2.copy_from_slice(&value.bytes()[4..8]);
3059 quad3.copy_from_slice(&value.bytes()[8..12]);
3060 quad4.copy_from_slice(&value.bytes()[12..16]);
3061 let mut info: ExtraInfo = Default::default();
3062 if is_f32_arithmetic(u32::from_le_bytes(quad1))
3063 && is_f32_arithmetic(u32::from_le_bytes(quad2))
3064 && is_f32_arithmetic(u32::from_le_bytes(quad3))
3065 && is_f32_arithmetic(u32::from_le_bytes(quad4))
3066 {
3067 info |= ExtraInfo::arithmetic_f32();
3068 }
3069 if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
3070 info |= ExtraInfo::arithmetic_f64();
3071 }
3072 self.state.push1_extra(i, info);
3073 }
3074
3075 Operator::I8x16Splat => {
3076 let (v, i) = self.state.pop1_extra()?;
3077 let v = v.into_int_value();
3078 let v = err!(
3079 self.builder
3080 .build_int_truncate(v, self.intrinsics.i8_ty, "")
3081 );
3082 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
3083 let res = err!(
3084 self.builder
3085 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3086 );
3087 self.state.push1_extra(res, i);
3088 }
3089 Operator::I16x8Splat => {
3090 let (v, i) = self.state.pop1_extra()?;
3091 let v = v.into_int_value();
3092 let v = err!(
3093 self.builder
3094 .build_int_truncate(v, self.intrinsics.i16_ty, "")
3095 );
3096 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
3097 let res = err!(
3098 self.builder
3099 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3100 );
3101 self.state.push1_extra(res, i);
3102 }
3103 Operator::I32x4Splat => {
3104 let (v, i) = self.state.pop1_extra()?;
3105 let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
3106 let res = err!(
3107 self.builder
3108 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3109 );
3110 self.state.push1_extra(res, i);
3111 }
3112 Operator::I64x2Splat => {
3113 let (v, i) = self.state.pop1_extra()?;
3114 let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
3115 let res = err!(
3116 self.builder
3117 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3118 );
3119 self.state.push1_extra(res, i);
3120 }
3121 Operator::F32x4Splat => {
3122 let (v, i) = self.state.pop1_extra()?;
3123 let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
3124 let res = err!(
3125 self.builder
3126 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3127 );
3128 self.state.push1_extra(res, i);
3131 }
3132 Operator::F64x2Splat => {
3133 let (v, i) = self.state.pop1_extra()?;
3134 let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
3135 let res = err!(
3136 self.builder
3137 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3138 );
3139 self.state.push1_extra(res, i);
3142 }
3143
3144 Operator::LocalGet { local_index } => {
3146 let (type_value, pointer_value) = self.locals[local_index as usize];
3147 let v = err!(self.builder.build_load(
3148 type_value,
3149 pointer_value,
3150 &format!("local_{local_index}_get")
3151 ));
3152 tbaa_label(
3153 self.module,
3154 self.intrinsics,
3155 format!("local {local_index}"),
3156 v.as_instruction_value().unwrap(),
3157 );
3158 self.state.push1(v);
3159 }
3160 Operator::LocalSet { local_index } => {
3161 let pointer_value = self.locals[local_index as usize].1;
3162 let (v, i) = self.state.pop1_extra()?;
3163 let v = self.apply_pending_canonicalization(v, i)?;
3164 let store = err!(self.builder.build_store(pointer_value, v));
3165 tbaa_label(
3166 self.module,
3167 self.intrinsics,
3168 format!("local {local_index}"),
3169 store,
3170 );
3171 }
3172 Operator::LocalTee { local_index } => {
3173 let pointer_value = self.locals[local_index as usize].1;
3174 let (v, i) = self.state.peek1_extra()?;
3175 let v = self.apply_pending_canonicalization(v, i)?;
3176 let store = err!(self.builder.build_store(pointer_value, v));
3177 tbaa_label(
3178 self.module,
3179 self.intrinsics,
3180 format!("local {local_index}"),
3181 store,
3182 );
3183 }
3184
3185 Operator::GlobalGet { global_index } => {
3186 let global_index = GlobalIndex::from_u32(global_index);
3187 match self
3188 .ctx
3189 .global(global_index, self.intrinsics, self.module)?
3190 {
3191 GlobalCache::Const { value } => {
3192 self.state.push1(*value);
3193 }
3194 GlobalCache::Mut {
3195 ptr_to_value,
3196 value_type,
3197 } => {
3198 let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
3199 tbaa_label(
3200 self.module,
3201 self.intrinsics,
3202 format!("global {}", global_index.as_u32()),
3203 value.as_instruction_value().unwrap(),
3204 );
3205 self.state.push1(value);
3206 }
3207 }
3208 }
3209 Operator::GlobalSet { global_index } => {
3210 let global_index = GlobalIndex::from_u32(global_index);
3211 match self
3212 .ctx
3213 .global(global_index, self.intrinsics, self.module)?
3214 {
3215 GlobalCache::Const { value: _ } => {
3216 return Err(CompileError::Codegen(format!(
3217 "global.set on immutable global index {}",
3218 global_index.as_u32()
3219 )));
3220 }
3221 GlobalCache::Mut { ptr_to_value, .. } => {
3222 let ptr_to_value = *ptr_to_value;
3223 let (value, info) = self.state.pop1_extra()?;
3224 let value = self.apply_pending_canonicalization(value, info)?;
3225 let store = err!(self.builder.build_store(ptr_to_value, value));
3226 tbaa_label(
3227 self.module,
3228 self.intrinsics,
3229 format!("global {}", global_index.as_u32()),
3230 store,
3231 );
3232 }
3233 }
3234 }
3235
3236 Operator::TypedSelect { .. } | Operator::Select => {
3239 let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3240 let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
3248 || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
3249 {
3250 (
3251 self.apply_pending_canonicalization(v1, i1)?,
3252 i1.strip_pending(),
3253 self.apply_pending_canonicalization(v2, i2)?,
3254 i2.strip_pending(),
3255 )
3256 } else {
3257 (v1, i1, v2, i2)
3258 };
3259 let cond_value = err!(self.builder.build_int_compare(
3260 IntPredicate::NE,
3261 cond.into_int_value(),
3262 self.intrinsics.i32_zero,
3263 "",
3264 ));
3265 let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
3266 let info = {
3267 let mut info = (i1.strip_pending() & i2.strip_pending())?;
3268 if i1.has_pending_f32_nan() {
3269 debug_assert!(i2.has_pending_f32_nan());
3270 info = (info | ExtraInfo::pending_f32_nan())?;
3271 }
3272 if i1.has_pending_f64_nan() {
3273 debug_assert!(i2.has_pending_f64_nan());
3274 info = (info | ExtraInfo::pending_f64_nan())?;
3275 }
3276 info
3277 };
3278 self.state.push1_extra(res, info);
3279 }
3280 Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
3281 let is_return_call = matches!(op, Operator::ReturnCall { .. });
3282 let func_index = FunctionIndex::from_u32(function_index);
3283 let sigindex = &self.wasm_module.functions[func_index];
3284 let func_type = &self.wasm_module.signatures[*sigindex];
3285
3286 let FunctionCache {
3287 func,
3288 llvm_func_type,
3289 vmctx: callee_vmctx,
3290 imported_include_m0_param,
3291 attrs,
3292 } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
3293 let function_name = self
3294 .symbol_registry
3295 .symbol_to_name(Symbol::LocalFunction(local_func_index));
3296
3297 self.ctx.local_func(
3298 local_func_index,
3299 func_index,
3300 self.intrinsics,
3301 self.module,
3302 self.context,
3303 func_type,
3304 &function_name,
3305 )?
3306 } else {
3307 self.ctx
3308 .imported_func(func_index, self.intrinsics, self.context, func_type)?
3309 };
3310 let llvm_func_type = *llvm_func_type;
3311 let func = *func;
3312 let callee_vmctx = *callee_vmctx;
3313 let imported_include_m0_param = *imported_include_m0_param;
3314 let attrs = attrs.clone();
3315
3316 let params = self.state.popn_save_extra(func_type.params().len())?;
3322
3323 let params = params
3325 .iter()
3326 .zip(func_type.params().iter())
3327 .map(|((v, info), wasm_ty)| match wasm_ty {
3328 Type::F32 => err_nt!(self.builder.build_bit_cast(
3329 self.apply_pending_canonicalization(*v, *info)?,
3330 self.intrinsics.f32_ty,
3331 "",
3332 )),
3333 Type::F64 => err_nt!(self.builder.build_bit_cast(
3334 self.apply_pending_canonicalization(*v, *info)?,
3335 self.intrinsics.f64_ty,
3336 "",
3337 )),
3338 Type::V128 => self.apply_pending_canonicalization(*v, *info),
3339 _ => Ok(*v),
3340 })
3341 .collect::<Result<Vec<_>, _>>()?;
3342
3343 if let (Some(m0_param), Some(include_m0_param)) =
3344 (self.m0_param, imported_include_m0_param)
3345 {
3346 let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3350 self.abi.func_type_to_llvm(
3351 self.context,
3352 self.intrinsics,
3353 Some(self.ctx.get_offsets()),
3354 func_type,
3355 false,
3356 )?;
3357 let params_with_m0 = self.abi.args_to_call(
3358 &self.alloca_builder,
3359 func_type,
3360 &llvm_func_type,
3361 callee_vmctx.into_pointer_value(),
3362 params.as_slice(),
3363 self.intrinsics,
3364 Some(m0_param),
3365 is_return_call
3366 .then(|| self.current_sret_ptr(func_type))
3367 .flatten(),
3368 )?;
3369 let params_no_m0 = self.abi.args_to_call(
3370 &self.alloca_builder,
3371 func_type,
3372 &llvm_func_type_no_m0,
3373 callee_vmctx.into_pointer_value(),
3374 params.as_slice(),
3375 self.intrinsics,
3376 None,
3377 is_return_call
3378 .then(|| self.current_sret_ptr(func_type))
3379 .flatten(),
3380 )?;
3381
3382 let include_m0_call_block = self
3383 .context
3384 .append_basic_block(self.function, "call_block_with_m0");
3385 let skip_m0_call_block =
3386 self.context.append_basic_block(self.function, "call_block");
3387 let call_cont = self.context.append_basic_block(self.function, "call_cont");
3388 err!(self.builder.build_conditional_branch(
3389 include_m0_param,
3390 include_m0_call_block,
3391 skip_m0_call_block,
3392 ));
3393
3394 self.builder.position_at_end(include_m0_call_block);
3395 let call_site_with_m0 = self.build_indirect_call_or_invoke(
3396 llvm_func_type,
3397 func,
3398 params_with_m0.as_slice(),
3399 "then_block_with_m0",
3400 is_return_call,
3401 )?;
3402 for (attr, attr_loc) in &attrs {
3403 call_site_with_m0.add_attribute(*attr_loc, *attr);
3404 }
3405 let rets_with_m0 = self.abi.rets_from_call(
3406 &self.builder,
3407 self.intrinsics,
3408 call_site_with_m0,
3409 func_type,
3410 )?;
3411 let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3412 CompileError::Codegen(
3413 "missing insertion block after call with m0".to_string(),
3414 )
3415 })?;
3416 err!(self.builder.build_unconditional_branch(call_cont));
3417
3418 self.builder.position_at_end(skip_m0_call_block);
3419 let call_site_no_m0 = self.build_indirect_call_or_invoke(
3420 llvm_func_type_no_m0,
3421 func,
3422 params_no_m0.as_slice(),
3423 "then_block",
3424 is_return_call,
3425 )?;
3426 for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3427 call_site_no_m0.add_attribute(*attr_loc, *attr);
3428 }
3429 let rets_no_m0 = self.abi.rets_from_call(
3430 &self.builder,
3431 self.intrinsics,
3432 call_site_no_m0,
3433 func_type,
3434 )?;
3435 let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3436 CompileError::Codegen(
3437 "missing insertion block after call without m0".to_string(),
3438 )
3439 })?;
3440 err!(self.builder.build_unconditional_branch(call_cont));
3441
3442 self.builder.position_at_end(call_cont);
3443 for i in 0..rets_with_m0.len() {
3444 let with_m0 = rets_with_m0[i];
3445 let no_m0 = rets_no_m0[i];
3446 let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3447 phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3448 self.state.push1(phi.as_basic_value());
3449 }
3450 } else {
3451 let params = self.abi.args_to_call(
3452 &self.alloca_builder,
3453 func_type,
3454 &llvm_func_type,
3455 callee_vmctx.into_pointer_value(),
3456 params.as_slice(),
3457 self.intrinsics,
3458 self.m0_param,
3459 if is_return_call {
3460 self.current_sret_ptr(func_type)
3461 } else {
3462 None
3463 },
3464 )?;
3465
3466 let call_site = self.build_indirect_call_or_invoke(
3467 llvm_func_type,
3468 func,
3469 params.as_slice(),
3470 "then_block",
3471 is_return_call,
3472 )?;
3473 for (attr, attr_loc) in attrs {
3474 call_site.add_attribute(attr_loc, attr);
3475 }
3476
3477 if is_return_call {
3478 self.emit_return_call(call_site, llvm_func_type)?;
3479 self.state.reachable = false;
3480 } else {
3481 self.abi
3482 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3483 .iter()
3484 .for_each(|ret| self.state.push1(*ret));
3485 }
3486 }
3487 }
3488 Operator::CallIndirect {
3489 type_index,
3490 table_index,
3491 }
3492 | Operator::ReturnCallIndirect {
3493 type_index,
3494 table_index,
3495 } => {
3496 let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3497 let sigindex = SignatureIndex::from_u32(type_index);
3498 let table_index = TableIndex::from_u32(table_index);
3499 let func_type = &self.wasm_module.signatures[sigindex];
3500 let table = self.wasm_module.tables.get(table_index).unwrap();
3501 let local_fixed_funcref_table = self
3502 .wasm_module
3503 .local_table_index(table_index)
3504 .filter(|_| table.is_fixed_funcref_table());
3505 let expected_signature_hash = self
3506 .intrinsics
3507 .i32_ty
3508 .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3509
3510 let func_index = self.state.pop1()?.into_int_value();
3511 let generic_table = if local_fixed_funcref_table.is_none() {
3512 Some(self.ctx.table(
3513 table_index,
3514 self.intrinsics,
3515 self.module,
3516 &self.builder,
3517 )?)
3518 } else {
3519 None
3520 };
3521
3522 let table_bound = if local_fixed_funcref_table.is_some() {
3523 self.intrinsics
3524 .i32_ty
3525 .const_int(table.minimum.into(), false)
3526 } else {
3527 let (_, table_bound) = *generic_table.as_ref().unwrap();
3528 err!(self.builder.build_int_truncate(
3529 table_bound,
3530 self.intrinsics.i32_ty,
3531 "truncated_table_bounds",
3532 ))
3533 };
3534
3535 let index_in_bounds = err!(self.builder.build_int_compare(
3537 IntPredicate::ULT,
3538 func_index,
3539 table_bound,
3540 "index_in_bounds",
3541 ));
3542
3543 let index_in_bounds = self
3544 .build_call_with_param_attributes(
3545 self.intrinsics.expect_i1,
3546 &[
3547 index_in_bounds.into(),
3548 self.intrinsics.i1_ty.const_int(1, false).into(),
3549 ],
3550 "index_in_bounds_expect",
3551 )?
3552 .try_as_basic_value()
3553 .unwrap_basic()
3554 .into_int_value();
3555
3556 let in_bounds_continue_block = self
3557 .context
3558 .append_basic_block(self.function, "in_bounds_continue_block");
3559 let not_in_bounds_block = self
3560 .context
3561 .append_basic_block(self.function, "not_in_bounds_block");
3562 err!(self.builder.build_conditional_branch(
3563 index_in_bounds,
3564 in_bounds_continue_block,
3565 not_in_bounds_block,
3566 ));
3567 self.builder.position_at_end(not_in_bounds_block);
3568 self.build_call_with_param_attributes(
3569 self.intrinsics.throw_trap,
3570 &[self.intrinsics.trap_table_access_oob.into()],
3571 "throw",
3572 )?;
3573 err!(self.builder.build_unreachable());
3574 self.builder.position_at_end(in_bounds_continue_block);
3575
3576 let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3577 {
3578 let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3579 local_table_index,
3580 self.intrinsics,
3581 &self.builder,
3582 )?;
3583 unsafe {
3584 err!(self.builder.build_in_bounds_gep(
3585 self.intrinsics.anyfunc_ty,
3586 anyfuncs,
3587 &[func_index],
3588 "anyfunc_struct_ptr",
3589 ))
3590 }
3591 } else {
3592 let (table_base, _) = *generic_table.as_ref().unwrap();
3593
3594 let casted_table_base = err!(self.builder.build_pointer_cast(
3597 table_base,
3598 self.context.ptr_type(AddressSpace::default()),
3599 "casted_table_base",
3600 ));
3601
3602 let funcref_ptr = unsafe {
3603 err!(self.builder.build_in_bounds_gep(
3604 self.intrinsics.ptr_ty,
3605 casted_table_base,
3606 &[func_index],
3607 "funcref_ptr",
3608 ))
3609 };
3610
3611 let anyfunc_struct_ptr = err!(self.builder.build_load(
3613 self.intrinsics.ptr_ty,
3614 funcref_ptr,
3615 "anyfunc_struct_ptr",
3616 ))
3617 .into_pointer_value();
3618
3619 if !table.readonly {
3620 let funcref_not_null = err!(
3622 self.builder
3623 .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3624 );
3625
3626 let funcref_continue_deref_block = self
3627 .context
3628 .append_basic_block(self.function, "funcref_continue_deref_block");
3629
3630 let funcref_is_null_block = self
3631 .context
3632 .append_basic_block(self.function, "funcref_is_null_block");
3633 err!(self.builder.build_conditional_branch(
3634 funcref_not_null,
3635 funcref_continue_deref_block,
3636 funcref_is_null_block,
3637 ));
3638 self.builder.position_at_end(funcref_is_null_block);
3639 self.build_call_with_param_attributes(
3640 self.intrinsics.throw_trap,
3641 &[self.intrinsics.trap_call_indirect_null.into()],
3642 "throw",
3643 )?;
3644 err!(self.builder.build_unreachable());
3645 self.builder.position_at_end(funcref_continue_deref_block);
3646 }
3647
3648 anyfunc_struct_ptr
3649 };
3650
3651 let sig_hash_ptr = self
3653 .builder
3654 .build_struct_gep(
3655 self.intrinsics.anyfunc_ty,
3656 anyfunc_struct_ptr,
3657 1,
3658 "sig_hash_ptr",
3659 )
3660 .unwrap();
3661 let func_ptr_ptr = self
3662 .builder
3663 .build_struct_gep(
3664 self.intrinsics.anyfunc_ty,
3665 anyfunc_struct_ptr,
3666 0,
3667 "func_ptr_ptr",
3668 )
3669 .unwrap();
3670 let (func_ptr, found_signature_hash) = (
3671 err!(
3672 self.builder
3673 .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3674 )
3675 .into_pointer_value(),
3676 err!(
3677 self.builder
3678 .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3679 )
3680 .into_int_value(),
3681 );
3682
3683 let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3687
3688 let sig_hashes_equal = err!(self.builder.build_int_compare(
3691 IntPredicate::EQ,
3692 expected_signature_hash,
3693 found_signature_hash,
3694 "sig_hashes_equal",
3695 ));
3696
3697 let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3698 elem_initialized,
3699 sig_hashes_equal,
3700 ""
3701 ));
3702
3703 let initialized_and_sig_hashes_match = self
3705 .build_call_with_param_attributes(
3706 self.intrinsics.expect_i1,
3707 &[
3708 initialized_and_sig_hashes_match.into(),
3709 self.intrinsics.i1_ty.const_int(1, false).into(),
3710 ],
3711 "initialized_and_sig_hashes_match_expect",
3712 )?
3713 .try_as_basic_value()
3714 .unwrap_basic()
3715 .into_int_value();
3716
3717 let continue_block = self
3718 .context
3719 .append_basic_block(self.function, "continue_block");
3720 let sighashes_notequal_block = self
3721 .context
3722 .append_basic_block(self.function, "sighashes_notequal_block");
3723 err!(self.builder.build_conditional_branch(
3724 initialized_and_sig_hashes_match,
3725 continue_block,
3726 sighashes_notequal_block,
3727 ));
3728
3729 self.builder.position_at_end(sighashes_notequal_block);
3730 let trap_code = err!(self.builder.build_select(
3731 elem_initialized,
3732 self.intrinsics.trap_call_indirect_sig,
3733 self.intrinsics.trap_call_indirect_null,
3734 "",
3735 ));
3736 self.build_call_with_param_attributes(
3737 self.intrinsics.throw_trap,
3738 &[trap_code.into()],
3739 "throw",
3740 )?;
3741 err!(self.builder.build_unreachable());
3742 self.builder.position_at_end(continue_block);
3743
3744 let callee_vmctx = if table.readonly {
3745 *vmctx
3746 } else {
3747 let ctx_ptr_ptr = self
3748 .builder
3749 .build_struct_gep(
3750 self.intrinsics.anyfunc_ty,
3751 anyfunc_struct_ptr,
3752 2,
3753 "ctx_ptr_ptr",
3754 )
3755 .unwrap();
3756 err!(
3757 self.builder
3758 .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3759 )
3760 .into_pointer_value()
3761 };
3762
3763 if self.m0_param.is_some() {
3764 self.build_m0_indirect_call(
3765 table_index.as_u32(),
3766 callee_vmctx,
3767 func_type,
3768 func_ptr,
3769 func_index,
3770 is_return_call,
3771 )?;
3772 } else {
3773 let (call_site, llvm_func_type) = self.build_indirect_call(
3774 callee_vmctx,
3775 func_type,
3776 func_ptr,
3777 None,
3778 is_return_call,
3779 )?;
3780
3781 if is_return_call {
3782 self.emit_return_call(call_site, llvm_func_type)?;
3783 } else {
3784 self.abi
3785 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3786 .iter()
3787 .for_each(|ret| self.state.push1(*ret));
3788 }
3789 }
3790
3791 if is_return_call {
3792 self.state.reachable = false;
3793 }
3794 }
3795 _ => unreachable!(),
3796 }
3797 Ok(())
3798 }
3799
3800 fn translate_integer_arithmetic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3803 match op {
3804 Operator::I32Add | Operator::I64Add => {
3805 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3806 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3807 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3808 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3809 let res = err!(self.builder.build_int_add(v1, v2, ""));
3810 self.state.push1(res);
3811 }
3812 Operator::I8x16Add => {
3813 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3814 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3815 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3816 let res = err!(self.builder.build_int_add(v1, v2, ""));
3817 let res = err!(
3818 self.builder
3819 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3820 );
3821 self.state.push1(res);
3822 }
3823 Operator::I16x8Add => {
3824 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3825 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3826 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3827 let res = err!(self.builder.build_int_add(v1, v2, ""));
3828 let res = err!(
3829 self.builder
3830 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3831 );
3832 self.state.push1(res);
3833 }
3834 Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3835 let extend_op = match op {
3836 Operator::I16x8ExtAddPairwiseI8x16S => {
3837 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3838 }
3839 Operator::I16x8ExtAddPairwiseI8x16U => {
3840 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3841 }
3842 _ => unreachable!("Unhandled internal variant"),
3843 };
3844 let (v, i) = self.state.pop1_extra()?;
3845 let (v, _) = self.v128_into_i8x16(v, i)?;
3846
3847 let left = err!(self.builder.build_shuffle_vector(
3848 v,
3849 v.get_type().get_undef(),
3850 VectorType::const_vector(&[
3851 self.intrinsics.i32_consts[0],
3852 self.intrinsics.i32_consts[2],
3853 self.intrinsics.i32_consts[4],
3854 self.intrinsics.i32_consts[6],
3855 self.intrinsics.i32_consts[8],
3856 self.intrinsics.i32_consts[10],
3857 self.intrinsics.i32_consts[12],
3858 self.intrinsics.i32_consts[14],
3859 ]),
3860 "",
3861 ));
3862 let left = err!(extend_op(self, left));
3863 let right = err!(self.builder.build_shuffle_vector(
3864 v,
3865 v.get_type().get_undef(),
3866 VectorType::const_vector(&[
3867 self.intrinsics.i32_consts[1],
3868 self.intrinsics.i32_consts[3],
3869 self.intrinsics.i32_consts[5],
3870 self.intrinsics.i32_consts[7],
3871 self.intrinsics.i32_consts[9],
3872 self.intrinsics.i32_consts[11],
3873 self.intrinsics.i32_consts[13],
3874 self.intrinsics.i32_consts[15],
3875 ]),
3876 "",
3877 ));
3878 let right = err!(extend_op(self, right));
3879
3880 let res = err!(self.builder.build_int_add(left, right, ""));
3881 let res = err!(
3882 self.builder
3883 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3884 );
3885 self.state.push1(res);
3886 }
3887 Operator::I32x4Add => {
3888 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3889 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3890 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3891 let res = err!(self.builder.build_int_add(v1, v2, ""));
3892 let res = err!(
3893 self.builder
3894 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3895 );
3896 self.state.push1(res);
3897 }
3898 Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3899 let extend_op = match op {
3900 Operator::I32x4ExtAddPairwiseI16x8S => {
3901 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3902 }
3903 Operator::I32x4ExtAddPairwiseI16x8U => {
3904 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3905 }
3906 _ => unreachable!("Unhandled internal variant"),
3907 };
3908 let (v, i) = self.state.pop1_extra()?;
3909 let (v, _) = self.v128_into_i16x8(v, i)?;
3910
3911 let left = err!(self.builder.build_shuffle_vector(
3912 v,
3913 v.get_type().get_undef(),
3914 VectorType::const_vector(&[
3915 self.intrinsics.i32_consts[0],
3916 self.intrinsics.i32_consts[2],
3917 self.intrinsics.i32_consts[4],
3918 self.intrinsics.i32_consts[6],
3919 ]),
3920 "",
3921 ));
3922 let left = err!(extend_op(self, left));
3923 let right = err!(self.builder.build_shuffle_vector(
3924 v,
3925 v.get_type().get_undef(),
3926 VectorType::const_vector(&[
3927 self.intrinsics.i32_consts[1],
3928 self.intrinsics.i32_consts[3],
3929 self.intrinsics.i32_consts[5],
3930 self.intrinsics.i32_consts[7],
3931 ]),
3932 "",
3933 ));
3934 let right = err!(extend_op(self, right));
3935
3936 let res = err!(self.builder.build_int_add(left, right, ""));
3937 let res = err!(
3938 self.builder
3939 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3940 );
3941 self.state.push1(res);
3942 }
3943 Operator::I64x2Add => {
3944 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3945 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3946 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3947 let res = err!(self.builder.build_int_add(v1, v2, ""));
3948 let res = err!(
3949 self.builder
3950 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3951 );
3952 self.state.push1(res);
3953 }
3954 Operator::I8x16AddSatS => {
3955 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3956 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3957 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3958 let res = self
3959 .build_call_with_param_attributes(
3960 self.intrinsics.sadd_sat_i8x16,
3961 &[v1.into(), v2.into()],
3962 "",
3963 )?
3964 .try_as_basic_value()
3965 .unwrap_basic();
3966 let res = err!(
3967 self.builder
3968 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3969 );
3970 self.state.push1(res);
3971 }
3972 Operator::I16x8AddSatS => {
3973 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3974 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3975 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3976 let res = self
3977 .build_call_with_param_attributes(
3978 self.intrinsics.sadd_sat_i16x8,
3979 &[v1.into(), v2.into()],
3980 "",
3981 )?
3982 .try_as_basic_value()
3983 .unwrap_basic();
3984 let res = err!(
3985 self.builder
3986 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3987 );
3988 self.state.push1(res);
3989 }
3990 Operator::I8x16AddSatU => {
3991 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3992 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3993 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3994 let res = self
3995 .build_call_with_param_attributes(
3996 self.intrinsics.uadd_sat_i8x16,
3997 &[v1.into(), v2.into()],
3998 "",
3999 )?
4000 .try_as_basic_value()
4001 .unwrap_basic();
4002 let res = err!(
4003 self.builder
4004 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4005 );
4006 self.state.push1(res);
4007 }
4008 Operator::I16x8AddSatU => {
4009 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4010 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4011 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4012 let res = self
4013 .build_call_with_param_attributes(
4014 self.intrinsics.uadd_sat_i16x8,
4015 &[v1.into(), v2.into()],
4016 "",
4017 )?
4018 .try_as_basic_value()
4019 .unwrap_basic();
4020 let res = err!(
4021 self.builder
4022 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4023 );
4024 self.state.push1(res);
4025 }
4026 Operator::I32Sub | Operator::I64Sub => {
4027 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4028 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4029 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4030 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4031 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4032 self.state.push1(res);
4033 }
4034 Operator::I8x16Sub => {
4035 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4036 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4037 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4038 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4039 let res = err!(
4040 self.builder
4041 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4042 );
4043 self.state.push1(res);
4044 }
4045 Operator::I16x8Sub => {
4046 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4047 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4048 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4049 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4050 let res = err!(
4051 self.builder
4052 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4053 );
4054 self.state.push1(res);
4055 }
4056 Operator::I32x4Sub => {
4057 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4058 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4059 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4060 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4061 let res = err!(
4062 self.builder
4063 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4064 );
4065 self.state.push1(res);
4066 }
4067 Operator::I64x2Sub => {
4068 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4069 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4070 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4071 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4072 let res = err!(
4073 self.builder
4074 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4075 );
4076 self.state.push1(res);
4077 }
4078 Operator::I8x16SubSatS => {
4079 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4080 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4081 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4082 let res = self
4083 .build_call_with_param_attributes(
4084 self.intrinsics.ssub_sat_i8x16,
4085 &[v1.into(), v2.into()],
4086 "",
4087 )?
4088 .try_as_basic_value()
4089 .unwrap_basic();
4090 let res = err!(
4091 self.builder
4092 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4093 );
4094 self.state.push1(res);
4095 }
4096 Operator::I16x8SubSatS => {
4097 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4098 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4099 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4100 let res = self
4101 .build_call_with_param_attributes(
4102 self.intrinsics.ssub_sat_i16x8,
4103 &[v1.into(), v2.into()],
4104 "",
4105 )?
4106 .try_as_basic_value()
4107 .unwrap_basic();
4108 let res = err!(
4109 self.builder
4110 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4111 );
4112 self.state.push1(res);
4113 }
4114 Operator::I8x16SubSatU => {
4115 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4116 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4117 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4118 let res = self
4119 .build_call_with_param_attributes(
4120 self.intrinsics.usub_sat_i8x16,
4121 &[v1.into(), v2.into()],
4122 "",
4123 )?
4124 .try_as_basic_value()
4125 .unwrap_basic();
4126 let res = err!(
4127 self.builder
4128 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4129 );
4130 self.state.push1(res);
4131 }
4132 Operator::I16x8SubSatU => {
4133 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4134 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4135 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4136 let res = self
4137 .build_call_with_param_attributes(
4138 self.intrinsics.usub_sat_i16x8,
4139 &[v1.into(), v2.into()],
4140 "",
4141 )?
4142 .try_as_basic_value()
4143 .unwrap_basic();
4144 let res = err!(
4145 self.builder
4146 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4147 );
4148 self.state.push1(res);
4149 }
4150 Operator::I32Mul | Operator::I64Mul => {
4151 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4152 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4153 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4154 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4155 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4156 self.state.push1(res);
4157 }
4158 Operator::I16x8Mul => {
4159 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4160 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4161 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4162 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4163 let res = err!(
4164 self.builder
4165 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4166 );
4167 self.state.push1(res);
4168 }
4169 Operator::I32x4Mul => {
4170 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4171 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4172 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4173 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4174 let res = err!(
4175 self.builder
4176 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4177 );
4178 self.state.push1(res);
4179 }
4180 Operator::I64x2Mul => {
4181 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4182 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4183 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4184 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4185 let res = err!(
4186 self.builder
4187 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4188 );
4189 self.state.push1(res);
4190 }
4191 Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
4192 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4193 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4194 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4195 let res = self
4196 .build_call_with_param_attributes(
4197 self.intrinsics.x86_64.pmulhrsw128,
4198 &[v1.into(), v2.into()],
4199 "",
4200 )?
4201 .try_as_basic_value()
4202 .unwrap_basic();
4203 let res = err!(
4204 self.builder
4205 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4206 );
4207 self.state.push1(res);
4208 }
4209 Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
4210 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4211 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4212 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4213
4214 let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
4215 let max_values = VectorType::const_vector(&[max_value; 8]);
4216
4217 let v1 = err!(
4218 self.builder
4219 .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
4220 );
4221 let v2 = err!(
4222 self.builder
4223 .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
4224 );
4225 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4226
4227 let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
4229 let bits = VectorType::const_vector(&[bit; 8]);
4230
4231 let res = err!(self.builder.build_int_add(res, bits, ""));
4232
4233 let fifteen = self.intrinsics.i32_consts[15];
4234 let fifteens = VectorType::const_vector(&[fifteen; 8]);
4235
4236 let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
4237 let saturate_up = {
4238 let max_values = err!(self.builder.build_int_s_extend(
4239 max_values,
4240 self.intrinsics.i32x8_ty,
4241 ""
4242 ));
4243 err!(
4244 self.builder
4245 .build_int_compare(IntPredicate::SGT, res, max_values, "")
4246 )
4247 };
4248
4249 let res = err!(
4250 self.builder
4251 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
4252 );
4253
4254 let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
4255 .into_vector_value();
4256 let res = err!(
4257 self.builder
4258 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4259 );
4260 self.state.push1(res);
4261 }
4262 Operator::I16x8ExtMulLowI8x16S
4263 | Operator::I16x8ExtMulLowI8x16U
4264 | Operator::I16x8ExtMulHighI8x16S
4265 | Operator::I16x8ExtMulHighI8x16U => {
4266 let extend_op = match op {
4267 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
4268 |s: &Self, v| -> Result<VectorValue, CompileError> {
4269 err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
4270 }
4271 }
4272 Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
4273 |s: &Self, v| -> Result<VectorValue, CompileError> {
4274 err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
4275 }
4276 }
4277 _ => unreachable!("Unhandled internal variant"),
4278 };
4279 let shuffle_array = match op {
4280 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
4281 self.intrinsics.i32_consts[0],
4282 self.intrinsics.i32_consts[1],
4283 self.intrinsics.i32_consts[2],
4284 self.intrinsics.i32_consts[3],
4285 self.intrinsics.i32_consts[4],
4286 self.intrinsics.i32_consts[5],
4287 self.intrinsics.i32_consts[6],
4288 self.intrinsics.i32_consts[7],
4289 ],
4290 Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
4291 self.intrinsics.i32_consts[8],
4292 self.intrinsics.i32_consts[9],
4293 self.intrinsics.i32_consts[10],
4294 self.intrinsics.i32_consts[11],
4295 self.intrinsics.i32_consts[12],
4296 self.intrinsics.i32_consts[13],
4297 self.intrinsics.i32_consts[14],
4298 self.intrinsics.i32_consts[15],
4299 ],
4300 _ => unreachable!("Unhandled internal variant"),
4301 };
4302 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4303 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4304 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4305 let val1 = err!(self.builder.build_shuffle_vector(
4306 v1,
4307 v1.get_type().get_undef(),
4308 VectorType::const_vector(&shuffle_array),
4309 "",
4310 ));
4311 let val1 = err!(extend_op(self, val1));
4312 let val2 = err!(self.builder.build_shuffle_vector(
4313 v2,
4314 v2.get_type().get_undef(),
4315 VectorType::const_vector(&shuffle_array),
4316 "",
4317 ));
4318 let val2 = err!(extend_op(self, val2));
4319 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4320 let res = err!(
4321 self.builder
4322 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4323 );
4324 self.state.push1(res);
4325 }
4326 Operator::I32x4ExtMulLowI16x8S
4327 | Operator::I32x4ExtMulLowI16x8U
4328 | Operator::I32x4ExtMulHighI16x8S
4329 | Operator::I32x4ExtMulHighI16x8U => {
4330 let extend_op = match op {
4331 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4332 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4333 }
4334 Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4335 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4336 }
4337 _ => unreachable!("Unhandled internal variant"),
4338 };
4339 let shuffle_array = match op {
4340 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4341 self.intrinsics.i32_consts[0],
4342 self.intrinsics.i32_consts[1],
4343 self.intrinsics.i32_consts[2],
4344 self.intrinsics.i32_consts[3],
4345 ],
4346 Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4347 self.intrinsics.i32_consts[4],
4348 self.intrinsics.i32_consts[5],
4349 self.intrinsics.i32_consts[6],
4350 self.intrinsics.i32_consts[7],
4351 ],
4352 _ => unreachable!("Unhandled internal variant"),
4353 };
4354 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4355 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4356 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4357 let val1 = err!(self.builder.build_shuffle_vector(
4358 v1,
4359 v1.get_type().get_undef(),
4360 VectorType::const_vector(&shuffle_array),
4361 "",
4362 ));
4363 let val1 = err!(extend_op(self, val1));
4364 let val2 = err!(self.builder.build_shuffle_vector(
4365 v2,
4366 v2.get_type().get_undef(),
4367 VectorType::const_vector(&shuffle_array),
4368 "",
4369 ));
4370 let val2 = err!(extend_op(self, val2));
4371 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4372 let res = err!(
4373 self.builder
4374 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4375 );
4376 self.state.push1(res);
4377 }
4378 Operator::I64x2ExtMulLowI32x4S
4379 | Operator::I64x2ExtMulLowI32x4U
4380 | Operator::I64x2ExtMulHighI32x4S
4381 | Operator::I64x2ExtMulHighI32x4U => {
4382 let extend_op = match op {
4383 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4384 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4385 }
4386 Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4387 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4388 }
4389 _ => unreachable!("Unhandled internal variant"),
4390 };
4391 let shuffle_array = match op {
4392 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4393 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4394 }
4395 Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4396 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4397 }
4398 _ => unreachable!("Unhandled internal variant"),
4399 };
4400 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4401 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4402 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4403 let val1 = err!(self.builder.build_shuffle_vector(
4404 v1,
4405 v1.get_type().get_undef(),
4406 VectorType::const_vector(&shuffle_array),
4407 "",
4408 ));
4409 let val1 = err!(extend_op(self, val1));
4410 let val2 = err!(self.builder.build_shuffle_vector(
4411 v2,
4412 v2.get_type().get_undef(),
4413 VectorType::const_vector(&shuffle_array),
4414 "",
4415 ));
4416 let val2 = err!(extend_op(self, val2));
4417 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4418 let res = err!(
4419 self.builder
4420 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4421 );
4422 self.state.push1(res);
4423 }
4424 Operator::I32x4DotI16x8S => {
4425 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4426 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4427 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4428 let low_i16 = [
4429 self.intrinsics.i32_consts[0],
4430 self.intrinsics.i32_consts[2],
4431 self.intrinsics.i32_consts[4],
4432 self.intrinsics.i32_consts[6],
4433 ];
4434 let high_i16 = [
4435 self.intrinsics.i32_consts[1],
4436 self.intrinsics.i32_consts[3],
4437 self.intrinsics.i32_consts[5],
4438 self.intrinsics.i32_consts[7],
4439 ];
4440 let v1_low = err!(self.builder.build_shuffle_vector(
4441 v1,
4442 v1.get_type().get_undef(),
4443 VectorType::const_vector(&low_i16),
4444 "",
4445 ));
4446 let v1_low = err!(self.builder.build_int_s_extend(
4447 v1_low,
4448 self.intrinsics.i32x4_ty,
4449 ""
4450 ));
4451 let v1_high = err!(self.builder.build_shuffle_vector(
4452 v1,
4453 v1.get_type().get_undef(),
4454 VectorType::const_vector(&high_i16),
4455 "",
4456 ));
4457 let v1_high = err!(self.builder.build_int_s_extend(
4458 v1_high,
4459 self.intrinsics.i32x4_ty,
4460 ""
4461 ));
4462 let v2_low = err!(self.builder.build_shuffle_vector(
4463 v2,
4464 v2.get_type().get_undef(),
4465 VectorType::const_vector(&low_i16),
4466 "",
4467 ));
4468 let v2_low = err!(self.builder.build_int_s_extend(
4469 v2_low,
4470 self.intrinsics.i32x4_ty,
4471 ""
4472 ));
4473 let v2_high = err!(self.builder.build_shuffle_vector(
4474 v2,
4475 v2.get_type().get_undef(),
4476 VectorType::const_vector(&high_i16),
4477 "",
4478 ));
4479 let v2_high = err!(self.builder.build_int_s_extend(
4480 v2_high,
4481 self.intrinsics.i32x4_ty,
4482 ""
4483 ));
4484 let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4485 let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4486
4487 let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4488 let res = err!(
4489 self.builder
4490 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4491 );
4492 self.state.push1(res);
4493 }
4494 Operator::I16x8RelaxedDotI8x16I7x16S
4495 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4496 {
4497 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4498 let (a, _) = self.v128_into_i8x16(v1, i1)?;
4499 let (b, _) = self.v128_into_i8x16(v2, i2)?;
4500
4501 let res = self
4502 .build_call_with_param_attributes(
4503 self.intrinsics.x86_64.pmaddubsw128,
4504 &[b.into(), a.into()],
4505 "",
4506 )?
4507 .try_as_basic_value()
4508 .unwrap_basic()
4509 .into_vector_value();
4510 let res = err!(
4511 self.builder
4512 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4513 );
4514 self.state.push1(res);
4515 }
4516 Operator::I16x8RelaxedDotI8x16I7x16S => {
4517 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4518 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4519 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4520
4521 let left_indices = [
4522 self.intrinsics.i32_consts[0],
4523 self.intrinsics.i32_consts[2],
4524 self.intrinsics.i32_consts[4],
4525 self.intrinsics.i32_consts[6],
4526 self.intrinsics.i32_consts[8],
4527 self.intrinsics.i32_consts[10],
4528 self.intrinsics.i32_consts[12],
4529 self.intrinsics.i32_consts[14],
4530 ];
4531 let right_indices = [
4532 self.intrinsics.i32_consts[1],
4533 self.intrinsics.i32_consts[3],
4534 self.intrinsics.i32_consts[5],
4535 self.intrinsics.i32_consts[7],
4536 self.intrinsics.i32_consts[9],
4537 self.intrinsics.i32_consts[11],
4538 self.intrinsics.i32_consts[13],
4539 self.intrinsics.i32_consts[15],
4540 ];
4541
4542 let v1_left = err!(self.builder.build_shuffle_vector(
4543 v1,
4544 v1.get_type().get_undef(),
4545 VectorType::const_vector(&left_indices),
4546 "",
4547 ));
4548 let v1_left = err!(self.builder.build_int_s_extend(
4549 v1_left,
4550 self.intrinsics.i16x8_ty,
4551 ""
4552 ));
4553 let v1_right = err!(self.builder.build_shuffle_vector(
4554 v1,
4555 v1.get_type().get_undef(),
4556 VectorType::const_vector(&right_indices),
4557 "",
4558 ));
4559 let v1_right = err!(self.builder.build_int_s_extend(
4560 v1_right,
4561 self.intrinsics.i16x8_ty,
4562 ""
4563 ));
4564
4565 let v2_left = err!(self.builder.build_shuffle_vector(
4566 v2,
4567 v2.get_type().get_undef(),
4568 VectorType::const_vector(&left_indices),
4569 "",
4570 ));
4571 let v2_left = err!(self.builder.build_int_s_extend(
4572 v2_left,
4573 self.intrinsics.i16x8_ty,
4574 ""
4575 ));
4576 let v2_right = err!(self.builder.build_shuffle_vector(
4577 v2,
4578 v2.get_type().get_undef(),
4579 VectorType::const_vector(&right_indices),
4580 "",
4581 ));
4582 let v2_right = err!(self.builder.build_int_s_extend(
4583 v2_right,
4584 self.intrinsics.i16x8_ty,
4585 ""
4586 ));
4587
4588 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4589 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4590 let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4591 let res = err!(
4592 self.builder
4593 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4594 );
4595 self.state.push1(res);
4596 }
4597 Operator::I32x4RelaxedDotI8x16I7x16AddS
4598 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4599 {
4600 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4601 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4602 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4603 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4604
4605 let dot16 = self
4608 .build_call_with_param_attributes(
4609 self.intrinsics.x86_64.pmaddubsw128,
4610 &[v2.into(), v1.into()],
4611 "",
4612 )?
4613 .try_as_basic_value()
4614 .unwrap_basic()
4615 .into_vector_value();
4616 let ones =
4617 VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4618 let dot32 = self
4619 .build_call_with_param_attributes(
4620 self.intrinsics.x86_64.pmaddwd128,
4621 &[dot16.into(), ones.into()],
4622 "",
4623 )?
4624 .try_as_basic_value()
4625 .unwrap_basic()
4626 .into_vector_value();
4627 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4628 let res = err!(
4629 self.builder
4630 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4631 );
4632 self.state.push1(res);
4633 }
4634 Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4635 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4636 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4637 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4638 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4639
4640 let left_indices = [
4641 self.intrinsics.i32_consts[0],
4642 self.intrinsics.i32_consts[2],
4643 self.intrinsics.i32_consts[4],
4644 self.intrinsics.i32_consts[6],
4645 self.intrinsics.i32_consts[8],
4646 self.intrinsics.i32_consts[10],
4647 self.intrinsics.i32_consts[12],
4648 self.intrinsics.i32_consts[14],
4649 ];
4650 let right_indices = [
4651 self.intrinsics.i32_consts[1],
4652 self.intrinsics.i32_consts[3],
4653 self.intrinsics.i32_consts[5],
4654 self.intrinsics.i32_consts[7],
4655 self.intrinsics.i32_consts[9],
4656 self.intrinsics.i32_consts[11],
4657 self.intrinsics.i32_consts[13],
4658 self.intrinsics.i32_consts[15],
4659 ];
4660
4661 let v1_left = err!(self.builder.build_shuffle_vector(
4662 v1,
4663 v1.get_type().get_undef(),
4664 VectorType::const_vector(&left_indices),
4665 "",
4666 ));
4667 let v1_left = err!(self.builder.build_int_s_extend(
4668 v1_left,
4669 self.intrinsics.i16x8_ty,
4670 ""
4671 ));
4672 let v1_right = err!(self.builder.build_shuffle_vector(
4673 v1,
4674 v1.get_type().get_undef(),
4675 VectorType::const_vector(&right_indices),
4676 "",
4677 ));
4678 let v1_right = err!(self.builder.build_int_s_extend(
4679 v1_right,
4680 self.intrinsics.i16x8_ty,
4681 ""
4682 ));
4683
4684 let v2_left = err!(self.builder.build_shuffle_vector(
4685 v2,
4686 v2.get_type().get_undef(),
4687 VectorType::const_vector(&left_indices),
4688 "",
4689 ));
4690 let v2_left = err!(self.builder.build_int_s_extend(
4691 v2_left,
4692 self.intrinsics.i16x8_ty,
4693 ""
4694 ));
4695 let v2_right = err!(self.builder.build_shuffle_vector(
4696 v2,
4697 v2.get_type().get_undef(),
4698 VectorType::const_vector(&right_indices),
4699 "",
4700 ));
4701 let v2_right = err!(self.builder.build_int_s_extend(
4702 v2_right,
4703 self.intrinsics.i16x8_ty,
4704 ""
4705 ));
4706
4707 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4708 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4709 let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4710
4711 let pair_left = err!(self.builder.build_shuffle_vector(
4712 dot16,
4713 dot16.get_type().get_undef(),
4714 VectorType::const_vector(&[
4715 self.intrinsics.i32_consts[0],
4716 self.intrinsics.i32_consts[2],
4717 self.intrinsics.i32_consts[4],
4718 self.intrinsics.i32_consts[6],
4719 ]),
4720 "",
4721 ));
4722 let pair_left = err!(self.builder.build_int_s_extend(
4723 pair_left,
4724 self.intrinsics.i32x4_ty,
4725 ""
4726 ));
4727 let pair_right = err!(self.builder.build_shuffle_vector(
4728 dot16,
4729 dot16.get_type().get_undef(),
4730 VectorType::const_vector(&[
4731 self.intrinsics.i32_consts[1],
4732 self.intrinsics.i32_consts[3],
4733 self.intrinsics.i32_consts[5],
4734 self.intrinsics.i32_consts[7],
4735 ]),
4736 "",
4737 ));
4738 let pair_right = err!(self.builder.build_int_s_extend(
4739 pair_right,
4740 self.intrinsics.i32x4_ty,
4741 ""
4742 ));
4743 let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4744 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4745 let res = err!(
4746 self.builder
4747 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4748 );
4749 self.state.push1(res);
4750 }
4751 Operator::I32DivS | Operator::I64DivS => {
4752 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4753 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4754 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4755 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4756
4757 self.trap_if_zero_or_overflow(v1, v2)?;
4758
4759 let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4760 self.state.push1(res);
4761 }
4762 Operator::I32DivU | Operator::I64DivU => {
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
4768 self.trap_if_zero(v2)?;
4769
4770 let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4771 self.state.push1(res);
4772 }
4773 Operator::I32RemS | Operator::I64RemS => {
4774 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4775 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4776 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4777 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4778 let int_type = v1.get_type();
4779 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4780 let min_value = int_type.const_int(i32::MIN as u64, false);
4781 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4782 (min_value, neg_one_value)
4783 } else if int_type == self.intrinsics.i64_ty {
4784 let min_value = int_type.const_int(i64::MIN as u64, false);
4785 let neg_one_value = int_type.const_int(-1i64 as u64, false);
4786 (min_value, neg_one_value)
4787 } else {
4788 unreachable!()
4789 };
4790
4791 self.trap_if_zero(v2)?;
4792
4793 let will_overflow = err!(self.builder.build_and(
4805 err!(self.builder.build_int_compare(
4806 IntPredicate::EQ,
4807 v1,
4808 min_value,
4809 "left_is_min"
4810 )),
4811 err!(self.builder.build_int_compare(
4812 IntPredicate::EQ,
4813 v2,
4814 neg_one_value,
4815 "right_is_neg_one",
4816 )),
4817 "srem_will_overflow",
4818 ));
4819 let v1 =
4820 err!(
4821 self.builder
4822 .build_select(will_overflow, int_type.const_zero(), v1, "")
4823 )
4824 .into_int_value();
4825 let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4826 self.state.push1(res);
4827 }
4828 Operator::I32RemU | Operator::I64RemU => {
4829 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4830 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4831 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4832 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4833
4834 self.trap_if_zero(v2)?;
4835
4836 let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4837 self.state.push1(res);
4838 }
4839 Operator::I32And | Operator::I64And | Operator::V128And => {
4840 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4841 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4842 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4843 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4844 let res = err!(self.builder.build_and(v1, v2, ""));
4845 self.state.push1(res);
4846 }
4847 Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4848 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4849 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4850 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4851 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4852 let res = err!(self.builder.build_or(v1, v2, ""));
4853 self.state.push1(res);
4854 }
4855 Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4856 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4857 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4858 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4859 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4860 let res = err!(self.builder.build_xor(v1, v2, ""));
4861 self.state.push1(res);
4862 }
4863 Operator::V128AndNot => {
4864 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4865 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4866 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4867 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4868 let v2 = err!(self.builder.build_not(v2, ""));
4869 let res = err!(self.builder.build_and(v1, v2, ""));
4870 self.state.push1(res);
4871 }
4872 Operator::I8x16RelaxedLaneselect
4873 | Operator::I16x8RelaxedLaneselect
4874 | Operator::I32x4RelaxedLaneselect
4875 | Operator::I64x2RelaxedLaneselect
4876 if self.cpu_features.contains(CpuFeature::SSE41) =>
4877 {
4878 let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4879 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4880 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4881 let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4882
4883 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4884 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4885 let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4886 let res = self
4887 .build_call_with_param_attributes(
4888 self.intrinsics.x86_64.pblendvb,
4889 &[v2.into(), v1.into(), mask.into()],
4890 "",
4891 )?
4892 .try_as_basic_value()
4893 .unwrap_basic();
4894 let res = err!(
4895 self.builder
4896 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4897 );
4898 self.state.push1(res);
4899 }
4900 Operator::I8x16RelaxedLaneselect
4901 | Operator::I16x8RelaxedLaneselect
4902 | Operator::I32x4RelaxedLaneselect
4903 | Operator::I64x2RelaxedLaneselect
4904 | Operator::V128Bitselect => {
4905 let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4906 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4907 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4908 let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4909 let v1 = err!(
4910 self.builder
4911 .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
4912 )
4913 .into_vector_value();
4914 let v2 = err!(
4915 self.builder
4916 .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
4917 )
4918 .into_vector_value();
4919 let cond = err!(
4920 self.builder
4921 .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
4922 )
4923 .into_vector_value();
4924 let res = err!(self.builder.build_select(cond, v1, v2, ""));
4925 let res = err!(
4926 self.builder
4927 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4928 );
4929 self.state.push1(res);
4930 }
4931 Operator::I8x16Bitmask => {
4932 let (v, i) = self.state.pop1_extra()?;
4933 let (v, _) = self.v128_into_i8x16(v, i)?;
4934
4935 let zeros = self.intrinsics.i8x16_ty.const_zero();
4936 let res = err!(
4937 self.builder
4938 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4939 );
4940 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
4941 .into_int_value();
4942 let res = err!(
4943 self.builder
4944 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4945 );
4946 self.state.push1(res);
4947 }
4948 Operator::I16x8Bitmask => {
4949 let (v, i) = self.state.pop1_extra()?;
4950 let (v, _) = self.v128_into_i16x8(v, i)?;
4951
4952 let zeros = self.intrinsics.i16x8_ty.const_zero();
4953 let res = err!(
4954 self.builder
4955 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4956 );
4957 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
4958 .into_int_value();
4959 let res = err!(
4960 self.builder
4961 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4962 );
4963 self.state.push1(res);
4964 }
4965 Operator::I32x4Bitmask => {
4966 let (v, i) = self.state.pop1_extra()?;
4967 let (v, _) = self.v128_into_i32x4(v, i)?;
4968
4969 let zeros = self.intrinsics.i32x4_ty.const_zero();
4970 let res = err!(
4971 self.builder
4972 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4973 );
4974 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
4975 .into_int_value();
4976 let res = err!(
4977 self.builder
4978 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4979 );
4980 self.state.push1(res);
4981 }
4982 Operator::I64x2Bitmask => {
4983 let (v, i) = self.state.pop1_extra()?;
4984 let (v, _) = self.v128_into_i64x2(v, i)?;
4985
4986 let zeros = self.intrinsics.i64x2_ty.const_zero();
4987 let res = err!(
4988 self.builder
4989 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4990 );
4991 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
4992 .into_int_value();
4993 let res = err!(
4994 self.builder
4995 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4996 );
4997 self.state.push1(res);
4998 }
4999 Operator::I32Shl => {
5000 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5001 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5002 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5003 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5004 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5005 let v2 = err!(self.builder.build_and(v2, mask, ""));
5006 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5007 self.state.push1(res);
5008 }
5009 Operator::I64Shl => {
5010 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5011 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5012 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5013 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5014 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5015 let v2 = err!(self.builder.build_and(v2, mask, ""));
5016 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5017 self.state.push1(res);
5018 }
5019 Operator::I8x16Shl => {
5020 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5021 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5022 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5023 let v2 = v2.into_int_value();
5024 let v2 = err!(
5025 self.builder
5026 .build_and(v2, self.intrinsics.i32_consts[7], "")
5027 );
5028 let v2 = err!(
5029 self.builder
5030 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5031 );
5032 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5033 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5034 let res = err!(
5035 self.builder
5036 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5037 );
5038 self.state.push1(res);
5039 }
5040 Operator::I16x8Shl => {
5041 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5042 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5043 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5044 let v2 = v2.into_int_value();
5045 let v2 = err!(
5046 self.builder
5047 .build_and(v2, self.intrinsics.i32_consts[15], "")
5048 );
5049 let v2 = err!(
5050 self.builder
5051 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5052 );
5053 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5054 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5055 let res = err!(
5056 self.builder
5057 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5058 );
5059 self.state.push1(res);
5060 }
5061 Operator::I32x4Shl => {
5062 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5063 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5064 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5065 let v2 = v2.into_int_value();
5066 let v2 = err!(self.builder.build_and(
5067 v2,
5068 self.intrinsics.i32_ty.const_int(31, false),
5069 ""
5070 ));
5071 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5072 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5073 let res = err!(
5074 self.builder
5075 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5076 );
5077 self.state.push1(res);
5078 }
5079 Operator::I64x2Shl => {
5080 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5081 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5082 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5083 let v2 = v2.into_int_value();
5084 let v2 = err!(self.builder.build_and(
5085 v2,
5086 self.intrinsics.i32_ty.const_int(63, false),
5087 ""
5088 ));
5089 let v2 = err!(
5090 self.builder
5091 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5092 );
5093 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5094 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5095 let res = err!(
5096 self.builder
5097 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5098 );
5099 self.state.push1(res);
5100 }
5101 Operator::I32ShrS => {
5102 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5103 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5104 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5105 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5106 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5107 let v2 = err!(self.builder.build_and(v2, mask, ""));
5108 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5109 self.state.push1(res);
5110 }
5111 Operator::I64ShrS => {
5112 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5113 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5114 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5115 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5116 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5117 let v2 = err!(self.builder.build_and(v2, mask, ""));
5118 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5119 self.state.push1(res);
5120 }
5121 Operator::I8x16ShrS => {
5122 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5123 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5124 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5125 let v2 = v2.into_int_value();
5126 let v2 = err!(
5127 self.builder
5128 .build_and(v2, self.intrinsics.i32_consts[7], "")
5129 );
5130 let v2 = err!(
5131 self.builder
5132 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5133 );
5134 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5135 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5136 let res = err!(
5137 self.builder
5138 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5139 );
5140 self.state.push1(res);
5141 }
5142 Operator::I16x8ShrS => {
5143 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5144 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5145 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5146 let v2 = v2.into_int_value();
5147 let v2 = err!(
5148 self.builder
5149 .build_and(v2, self.intrinsics.i32_consts[15], "")
5150 );
5151 let v2 = err!(
5152 self.builder
5153 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5154 );
5155 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5156 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5157 let res = err!(
5158 self.builder
5159 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5160 );
5161 self.state.push1(res);
5162 }
5163 Operator::I32x4ShrS => {
5164 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5165 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5166 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5167 let v2 = v2.into_int_value();
5168 let v2 = err!(self.builder.build_and(
5169 v2,
5170 self.intrinsics.i32_ty.const_int(31, false),
5171 ""
5172 ));
5173 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5174 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5175 let res = err!(
5176 self.builder
5177 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5178 );
5179 self.state.push1(res);
5180 }
5181 Operator::I64x2ShrS => {
5182 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5183 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5184 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5185 let v2 = v2.into_int_value();
5186 let v2 = err!(self.builder.build_and(
5187 v2,
5188 self.intrinsics.i32_ty.const_int(63, false),
5189 ""
5190 ));
5191 let v2 = err!(
5192 self.builder
5193 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5194 );
5195 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5196 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5197 let res = err!(
5198 self.builder
5199 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5200 );
5201 self.state.push1(res);
5202 }
5203 Operator::I32ShrU => {
5204 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5205 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5206 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5207 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5208 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5209 let v2 = err!(self.builder.build_and(v2, mask, ""));
5210 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5211 self.state.push1(res);
5212 }
5213 Operator::I64ShrU => {
5214 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5215 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5216 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5217 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5218 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5219 let v2 = err!(self.builder.build_and(v2, mask, ""));
5220 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5221 self.state.push1(res);
5222 }
5223 Operator::I8x16ShrU => {
5224 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5225 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5226 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5227 let v2 = v2.into_int_value();
5228 let v2 = err!(
5229 self.builder
5230 .build_and(v2, self.intrinsics.i32_consts[7], "")
5231 );
5232 let v2 = err!(
5233 self.builder
5234 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5235 );
5236 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5237 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5238 let res = err!(
5239 self.builder
5240 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5241 );
5242 self.state.push1(res);
5243 }
5244 Operator::I16x8ShrU => {
5245 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5246 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5247 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5248 let v2 = v2.into_int_value();
5249 let v2 = err!(
5250 self.builder
5251 .build_and(v2, self.intrinsics.i32_consts[15], "")
5252 );
5253 let v2 = err!(
5254 self.builder
5255 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5256 );
5257 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5258 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5259 let res = err!(
5260 self.builder
5261 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5262 );
5263 self.state.push1(res);
5264 }
5265 Operator::I32x4ShrU => {
5266 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5267 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5268 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5269 let v2 = v2.into_int_value();
5270 let v2 = err!(self.builder.build_and(
5271 v2,
5272 self.intrinsics.i32_ty.const_int(31, false),
5273 ""
5274 ));
5275 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5276 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5277 let res = err!(
5278 self.builder
5279 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5280 );
5281 self.state.push1(res);
5282 }
5283 Operator::I64x2ShrU => {
5284 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5285 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5286 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5287 let v2 = v2.into_int_value();
5288 let v2 = err!(self.builder.build_and(
5289 v2,
5290 self.intrinsics.i32_ty.const_int(63, false),
5291 ""
5292 ));
5293 let v2 = err!(
5294 self.builder
5295 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5296 );
5297 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5298 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5299 let res = err!(
5300 self.builder
5301 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5302 );
5303 self.state.push1(res);
5304 }
5305 Operator::I32Rotl => {
5306 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5307 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5308 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5309 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5310 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5311 let v2 = err!(self.builder.build_and(v2, mask, ""));
5312 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5313 let rhs = {
5314 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5315 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5316 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5317 };
5318 let res = err!(self.builder.build_or(lhs, rhs, ""));
5319 self.state.push1(res);
5320 }
5321 Operator::I64Rotl => {
5322 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5323 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5324 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5325 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5326 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5327 let v2 = err!(self.builder.build_and(v2, mask, ""));
5328 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5329 let rhs = {
5330 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5331 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5332 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5333 };
5334 let res = err!(self.builder.build_or(lhs, rhs, ""));
5335 self.state.push1(res);
5336 }
5337 Operator::I32Rotr => {
5338 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5339 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5340 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5341 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5342 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5343 let v2 = err!(self.builder.build_and(v2, mask, ""));
5344 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5345 let rhs = {
5346 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5347 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5348 err!(self.builder.build_left_shift(v1, rhs, ""))
5349 };
5350 let res = err!(self.builder.build_or(lhs, rhs, ""));
5351 self.state.push1(res);
5352 }
5353 Operator::I64Rotr => {
5354 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5355 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5356 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5357 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5358 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5359 let v2 = err!(self.builder.build_and(v2, mask, ""));
5360 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5361 let rhs = {
5362 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5363 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5364 err!(self.builder.build_left_shift(v1, rhs, ""))
5365 };
5366 let res = err!(self.builder.build_or(lhs, rhs, ""));
5367 self.state.push1(res);
5368 }
5369 Operator::I32Clz => {
5370 let (input, info) = self.state.pop1_extra()?;
5371 let input = self.apply_pending_canonicalization(input, info)?;
5372 let is_zero_undef = self.intrinsics.i1_zero;
5373 let res = self
5374 .build_call_with_param_attributes(
5375 self.intrinsics.ctlz_i32,
5376 &[input.into(), is_zero_undef.into()],
5377 "",
5378 )?
5379 .try_as_basic_value()
5380 .unwrap_basic();
5381 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5382 }
5383 Operator::I64Clz => {
5384 let (input, info) = self.state.pop1_extra()?;
5385 let input = self.apply_pending_canonicalization(input, info)?;
5386 let is_zero_undef = self.intrinsics.i1_zero;
5387 let res = self
5388 .build_call_with_param_attributes(
5389 self.intrinsics.ctlz_i64,
5390 &[input.into(), is_zero_undef.into()],
5391 "",
5392 )?
5393 .try_as_basic_value()
5394 .unwrap_basic();
5395 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5396 }
5397 Operator::I32Ctz => {
5398 let (input, info) = self.state.pop1_extra()?;
5399 let input = self.apply_pending_canonicalization(input, info)?;
5400 let is_zero_undef = self.intrinsics.i1_zero;
5401 let res = self
5402 .build_call_with_param_attributes(
5403 self.intrinsics.cttz_i32,
5404 &[input.into(), is_zero_undef.into()],
5405 "",
5406 )?
5407 .try_as_basic_value()
5408 .unwrap_basic();
5409 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5410 }
5411 Operator::I64Ctz => {
5412 let (input, info) = self.state.pop1_extra()?;
5413 let input = self.apply_pending_canonicalization(input, info)?;
5414 let is_zero_undef = self.intrinsics.i1_zero;
5415 let res = self
5416 .build_call_with_param_attributes(
5417 self.intrinsics.cttz_i64,
5418 &[input.into(), is_zero_undef.into()],
5419 "",
5420 )?
5421 .try_as_basic_value()
5422 .unwrap_basic();
5423 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5424 }
5425 Operator::I8x16Popcnt => {
5426 let (v, i) = self.state.pop1_extra()?;
5427 let (v, _) = self.v128_into_i8x16(v, i)?;
5428 let res = self
5429 .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5430 .try_as_basic_value()
5431 .unwrap_basic();
5432 let res = err!(
5433 self.builder
5434 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5435 );
5436 self.state.push1(res);
5437 }
5438 Operator::I32Popcnt => {
5439 let (input, info) = self.state.pop1_extra()?;
5440 let input = self.apply_pending_canonicalization(input, info)?;
5441 let res = self
5442 .build_call_with_param_attributes(
5443 self.intrinsics.ctpop_i32,
5444 &[input.into()],
5445 "",
5446 )?
5447 .try_as_basic_value()
5448 .unwrap_basic();
5449 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5450 }
5451 Operator::I64Popcnt => {
5452 let (input, info) = self.state.pop1_extra()?;
5453 let input = self.apply_pending_canonicalization(input, info)?;
5454 let res = self
5455 .build_call_with_param_attributes(
5456 self.intrinsics.ctpop_i64,
5457 &[input.into()],
5458 "",
5459 )?
5460 .try_as_basic_value()
5461 .unwrap_basic();
5462 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5463 }
5464 Operator::I32Eqz => {
5465 let input = self.state.pop1()?.into_int_value();
5466 let cond = err!(self.builder.build_int_compare(
5467 IntPredicate::EQ,
5468 input,
5469 self.intrinsics.i32_zero,
5470 "",
5471 ));
5472 let res = err!(
5473 self.builder
5474 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5475 );
5476 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5477 }
5478 Operator::I64Eqz => {
5479 let input = self.state.pop1()?.into_int_value();
5480 let cond = err!(self.builder.build_int_compare(
5481 IntPredicate::EQ,
5482 input,
5483 self.intrinsics.i64_zero,
5484 "",
5485 ));
5486 let res = err!(
5487 self.builder
5488 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5489 );
5490 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5491 }
5492 Operator::I8x16Abs => {
5493 let (v, i) = self.state.pop1_extra()?;
5494 let (v, _) = self.v128_into_i8x16(v, i)?;
5495
5496 let seven = self.intrinsics.i8_ty.const_int(7, false);
5497 let seven = VectorType::const_vector(&[seven; 16]);
5498 let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5499 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5500 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5501 let res = err!(
5502 self.builder
5503 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5504 );
5505 self.state.push1(res);
5506 }
5507 Operator::I16x8Abs => {
5508 let (v, i) = self.state.pop1_extra()?;
5509 let (v, _) = self.v128_into_i16x8(v, i)?;
5510
5511 let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5512 let fifteen = VectorType::const_vector(&[fifteen; 8]);
5513 let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5514 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5515 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5516 let res = err!(
5517 self.builder
5518 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5519 );
5520 self.state.push1(res);
5521 }
5522 Operator::I32x4Abs => {
5523 let (v, i) = self.state.pop1_extra()?;
5524 let (v, _) = self.v128_into_i32x4(v, i)?;
5525
5526 let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5527 let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5528 let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5529 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5530 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5531 let res = err!(
5532 self.builder
5533 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5534 );
5535 self.state.push1(res);
5536 }
5537 Operator::I64x2Abs => {
5538 let (v, i) = self.state.pop1_extra()?;
5539 let (v, _) = self.v128_into_i64x2(v, i)?;
5540
5541 let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5542 let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5543 let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5544 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5545 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5546 let res = err!(
5547 self.builder
5548 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5549 );
5550 self.state.push1(res);
5551 }
5552 Operator::I8x16MinS => {
5553 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5554 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5555 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5556 let cmp = err!(
5557 self.builder
5558 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5559 );
5560 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5561 let res = err!(
5562 self.builder
5563 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5564 );
5565 self.state.push1(res);
5566 }
5567 Operator::I8x16MinU => {
5568 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5569 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5570 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5571 let cmp = err!(
5572 self.builder
5573 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5574 );
5575 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5576 let res = err!(
5577 self.builder
5578 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5579 );
5580 self.state.push1(res);
5581 }
5582 Operator::I8x16MaxS => {
5583 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5584 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5585 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5586 let cmp = err!(
5587 self.builder
5588 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5589 );
5590 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5591 let res = err!(
5592 self.builder
5593 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5594 );
5595 self.state.push1(res);
5596 }
5597 Operator::I8x16MaxU => {
5598 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5599 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5600 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5601 let cmp = err!(
5602 self.builder
5603 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5604 );
5605 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5606 let res = err!(
5607 self.builder
5608 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5609 );
5610 self.state.push1(res);
5611 }
5612 Operator::I16x8MinS => {
5613 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5614 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5615 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5616 let cmp = err!(
5617 self.builder
5618 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5619 );
5620 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5621 let res = err!(
5622 self.builder
5623 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5624 );
5625 self.state.push1(res);
5626 }
5627 Operator::I16x8MinU => {
5628 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5629 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5630 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5631 let cmp = err!(
5632 self.builder
5633 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5634 );
5635 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5636 let res = err!(
5637 self.builder
5638 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5639 );
5640 self.state.push1(res);
5641 }
5642 Operator::I16x8MaxS => {
5643 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5644 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5645 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5646 let cmp = err!(
5647 self.builder
5648 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5649 );
5650 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5651 let res = err!(
5652 self.builder
5653 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5654 );
5655 self.state.push1(res);
5656 }
5657 Operator::I16x8MaxU => {
5658 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5659 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5660 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5661 let cmp = err!(
5662 self.builder
5663 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5664 );
5665 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5666 let res = err!(
5667 self.builder
5668 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5669 );
5670 self.state.push1(res);
5671 }
5672 Operator::I32x4MinS => {
5673 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5674 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5675 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5676 let cmp = err!(
5677 self.builder
5678 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5679 );
5680 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5681 let res = err!(
5682 self.builder
5683 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5684 );
5685 self.state.push1(res);
5686 }
5687 Operator::I32x4MinU => {
5688 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5689 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5690 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5691 let cmp = err!(
5692 self.builder
5693 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5694 );
5695 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5696 let res = err!(
5697 self.builder
5698 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5699 );
5700 self.state.push1(res);
5701 }
5702 Operator::I32x4MaxS => {
5703 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5704 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5705 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5706 let cmp = err!(
5707 self.builder
5708 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5709 );
5710 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5711 let res = err!(
5712 self.builder
5713 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5714 );
5715 self.state.push1(res);
5716 }
5717 Operator::I32x4MaxU => {
5718 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5719 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5720 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5721 let cmp = err!(
5722 self.builder
5723 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5724 );
5725 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5726 let res = err!(
5727 self.builder
5728 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5729 );
5730 self.state.push1(res);
5731 }
5732 Operator::I8x16AvgrU => {
5733 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5734 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5735 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5736
5737 let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5748 let one = self.intrinsics.i16_ty.const_int(1, false);
5749 let one = VectorType::const_vector(&[one; 16]);
5750
5751 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5752 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5753 let res = err!(self.builder.build_int_add(
5754 err!(self.builder.build_int_add(one, v1, "")),
5755 v2,
5756 ""
5757 ));
5758 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5759 let res = err!(
5760 self.builder
5761 .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5762 );
5763 let res = err!(
5764 self.builder
5765 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5766 );
5767 self.state.push1(res);
5768 }
5769 Operator::I16x8AvgrU => {
5770 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5771 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5772 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5773
5774 let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5785 let one = self.intrinsics.i32_consts[1];
5786 let one = VectorType::const_vector(&[one; 8]);
5787
5788 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5789 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5790 let res = err!(self.builder.build_int_add(
5791 err!(self.builder.build_int_add(one, v1, "")),
5792 v2,
5793 ""
5794 ));
5795 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5796 let res = err!(
5797 self.builder
5798 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5799 );
5800 let res = err!(
5801 self.builder
5802 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5803 );
5804 self.state.push1(res);
5805 }
5806 Operator::I64Add128 | Operator::I64Sub128 => {
5807 let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
5808 let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
5809 let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
5810 let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
5811
5812 let lhs_lo = self
5813 .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
5814 .into_int_value();
5815 let lhs_hi = self
5816 .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
5817 .into_int_value();
5818 let rhs_lo = self
5819 .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
5820 .into_int_value();
5821 let rhs_hi = self
5822 .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
5823 .into_int_value();
5824
5825 let idx0 = self.intrinsics.i32_ty.const_zero();
5826 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5827
5828 let lhs = self.intrinsics.i64x2_ty.get_undef();
5829 let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
5830 let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
5831 let lhs = err!(
5832 self.builder
5833 .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
5834 )
5835 .into_int_value();
5836
5837 let rhs = self.intrinsics.i64x2_ty.get_undef();
5838 let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
5839 let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
5840 let rhs = err!(
5841 self.builder
5842 .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
5843 )
5844 .into_int_value();
5845
5846 let result = err!(match op {
5847 Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
5848 Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
5849 _ => unreachable!(),
5850 });
5851 let result = err!(self.builder.build_bit_cast(
5852 result,
5853 self.intrinsics.i64x2_ty,
5854 ""
5855 ))
5856 .into_vector_value();
5857 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5858 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5859
5860 self.state.push1(result_lo);
5861 self.state.push1(result_hi);
5862 }
5863 Operator::I64MulWideS | Operator::I64MulWideU => {
5864 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5865 let lhs = self
5866 .apply_pending_canonicalization(lhs, lhs_info)?
5867 .into_int_value();
5868 let rhs = self
5869 .apply_pending_canonicalization(rhs, rhs_info)?
5870 .into_int_value();
5871
5872 let lhs = err!(match op {
5873 Operator::I64MulWideS => {
5874 self.builder
5875 .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
5876 }
5877 Operator::I64MulWideU => {
5878 self.builder
5879 .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
5880 }
5881 _ => unreachable!(),
5882 });
5883 let rhs = err!(match op {
5884 Operator::I64MulWideS => {
5885 self.builder
5886 .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
5887 }
5888 Operator::I64MulWideU => {
5889 self.builder
5890 .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
5891 }
5892 _ => unreachable!(),
5893 });
5894
5895 let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
5896 let result = err!(self.builder.build_bit_cast(
5897 result,
5898 self.intrinsics.i64x2_ty,
5899 ""
5900 ))
5901 .into_vector_value();
5902 let idx0 = self.intrinsics.i32_ty.const_zero();
5903 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5904 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5905 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5906
5907 self.state.push1(result_lo);
5908 self.state.push1(result_hi);
5909 }
5910 _ => unreachable!(),
5911 }
5912 Ok(())
5913 }
5914
5915 fn translate_floating_point_arithmetic_operator(
5918 &mut self,
5919 op: Operator,
5920 ) -> Result<(), CompileError> {
5921 match op {
5922 Operator::F32Add => {
5923 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5924 let res = self
5925 .build_call_with_param_attributes(
5926 self.intrinsics.add_f32,
5927 &[
5928 v1.into(),
5929 v2.into(),
5930 self.intrinsics.fp_rounding_md,
5931 self.intrinsics.fp_exception_md,
5932 ],
5933 "",
5934 )?
5935 .try_as_basic_value()
5936 .unwrap_basic();
5937 self.state.push1_extra(
5938 res,
5939 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5940 );
5941 }
5942 Operator::F64Add => {
5943 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5944 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5945 let res = self
5946 .build_call_with_param_attributes(
5947 self.intrinsics.add_f64,
5948 &[
5949 v1.into(),
5950 v2.into(),
5951 self.intrinsics.fp_rounding_md,
5952 self.intrinsics.fp_exception_md,
5953 ],
5954 "",
5955 )?
5956 .try_as_basic_value()
5957 .unwrap_basic();
5958 self.state.push1_extra(
5959 res,
5960 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5961 );
5962 }
5963 Operator::F32x4Add => {
5964 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5965 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5966 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5967 let res = self
5968 .build_call_with_param_attributes(
5969 self.intrinsics.add_f32x4,
5970 &[
5971 v1.into(),
5972 v2.into(),
5973 self.intrinsics.fp_rounding_md,
5974 self.intrinsics.fp_exception_md,
5975 ],
5976 "",
5977 )?
5978 .try_as_basic_value()
5979 .unwrap_basic();
5980 let res = err!(
5981 self.builder
5982 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5983 );
5984 self.state.push1_extra(
5985 res,
5986 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5987 );
5988 }
5989 Operator::F64x2Add => {
5990 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5991 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5992 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5993 let res = self
5994 .build_call_with_param_attributes(
5995 self.intrinsics.add_f64x2,
5996 &[
5997 v1.into(),
5998 v2.into(),
5999 self.intrinsics.fp_rounding_md,
6000 self.intrinsics.fp_exception_md,
6001 ],
6002 "",
6003 )?
6004 .try_as_basic_value()
6005 .unwrap_basic();
6006 let res = err!(
6007 self.builder
6008 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6009 );
6010 self.state.push1_extra(
6011 res,
6012 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6013 );
6014 }
6015 Operator::F32Sub => {
6016 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6017 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6018 let res = self
6019 .build_call_with_param_attributes(
6020 self.intrinsics.sub_f32,
6021 &[
6022 v1.into(),
6023 v2.into(),
6024 self.intrinsics.fp_rounding_md,
6025 self.intrinsics.fp_exception_md,
6026 ],
6027 "",
6028 )?
6029 .try_as_basic_value()
6030 .unwrap_basic();
6031 self.state.push1_extra(
6032 res,
6033 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6034 );
6035 }
6036 Operator::F64Sub => {
6037 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6038 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6039 let res = self
6040 .build_call_with_param_attributes(
6041 self.intrinsics.sub_f64,
6042 &[
6043 v1.into(),
6044 v2.into(),
6045 self.intrinsics.fp_rounding_md,
6046 self.intrinsics.fp_exception_md,
6047 ],
6048 "",
6049 )?
6050 .try_as_basic_value()
6051 .unwrap_basic();
6052 self.state.push1_extra(
6053 res,
6054 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6055 );
6056 }
6057 Operator::F32x4Sub => {
6058 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6059 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6060 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6061 let res = self
6062 .build_call_with_param_attributes(
6063 self.intrinsics.sub_f32x4,
6064 &[
6065 v1.into(),
6066 v2.into(),
6067 self.intrinsics.fp_rounding_md,
6068 self.intrinsics.fp_exception_md,
6069 ],
6070 "",
6071 )?
6072 .try_as_basic_value()
6073 .unwrap_basic();
6074 let res = err!(
6075 self.builder
6076 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6077 );
6078 self.state.push1_extra(
6079 res,
6080 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6081 );
6082 }
6083 Operator::F64x2Sub => {
6084 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6085 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6086 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6087 let res = self
6088 .build_call_with_param_attributes(
6089 self.intrinsics.sub_f64x2,
6090 &[
6091 v1.into(),
6092 v2.into(),
6093 self.intrinsics.fp_rounding_md,
6094 self.intrinsics.fp_exception_md,
6095 ],
6096 "",
6097 )?
6098 .try_as_basic_value()
6099 .unwrap_basic();
6100 let res = err!(
6101 self.builder
6102 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6103 );
6104 self.state.push1_extra(
6105 res,
6106 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6107 );
6108 }
6109 Operator::F32Mul => {
6110 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6111 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6112 let res = self
6113 .build_call_with_param_attributes(
6114 self.intrinsics.mul_f32,
6115 &[
6116 v1.into(),
6117 v2.into(),
6118 self.intrinsics.fp_rounding_md,
6119 self.intrinsics.fp_exception_md,
6120 ],
6121 "",
6122 )?
6123 .try_as_basic_value()
6124 .unwrap_basic();
6125 self.state.push1_extra(
6126 res,
6127 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6128 );
6129 }
6130 Operator::F64Mul => {
6131 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6132 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6133 let res = self
6134 .build_call_with_param_attributes(
6135 self.intrinsics.mul_f64,
6136 &[
6137 v1.into(),
6138 v2.into(),
6139 self.intrinsics.fp_rounding_md,
6140 self.intrinsics.fp_exception_md,
6141 ],
6142 "",
6143 )?
6144 .try_as_basic_value()
6145 .unwrap_basic();
6146 self.state.push1_extra(
6147 res,
6148 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6149 );
6150 }
6151 Operator::F32x4Mul => {
6152 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6153 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6154 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6155 let res = self
6156 .build_call_with_param_attributes(
6157 self.intrinsics.mul_f32x4,
6158 &[
6159 v1.into(),
6160 v2.into(),
6161 self.intrinsics.fp_rounding_md,
6162 self.intrinsics.fp_exception_md,
6163 ],
6164 "",
6165 )?
6166 .try_as_basic_value()
6167 .unwrap_basic();
6168 let res = err!(
6169 self.builder
6170 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6171 );
6172 self.state.push1_extra(
6173 res,
6174 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6175 );
6176 }
6177 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
6178 if self.cpu_features.contains(CpuFeature::FMA) =>
6179 {
6180 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6181 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6182 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6183 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6184
6185 let v1 = match op {
6186 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6187 _ => v1,
6188 };
6189 let res = self
6190 .build_call_with_param_attributes(
6191 self.intrinsics.muladd_f32x4,
6192 &[
6193 v1.into(),
6194 v2.into(),
6195 v3.into(),
6196 self.intrinsics.fp_rounding_md,
6197 self.intrinsics.fp_exception_md,
6198 ],
6199 "",
6200 )?
6201 .try_as_basic_value()
6202 .unwrap_basic();
6203 let res = err!(
6204 self.builder
6205 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6206 );
6207 let info = (i1.strip_pending() & i2.strip_pending())?;
6208 let info = (info & i3.strip_pending())?;
6209 let info = (info | ExtraInfo::pending_f32_nan())?;
6210 self.state.push1_extra(res, info);
6211 }
6212 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
6213 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6214 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6215 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6216 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6217
6218 let v1 = match op {
6219 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6220 _ => v1,
6221 };
6222 let mul = self
6223 .build_call_with_param_attributes(
6224 self.intrinsics.mul_f32x4,
6225 &[
6226 v1.into(),
6227 v2.into(),
6228 self.intrinsics.fp_rounding_md,
6229 self.intrinsics.fp_exception_md,
6230 ],
6231 "",
6232 )?
6233 .try_as_basic_value()
6234 .unwrap_basic();
6235 let mul = mul.into_vector_value();
6236 let res = self
6237 .build_call_with_param_attributes(
6238 self.intrinsics.add_f32x4,
6239 &[
6240 mul.into(),
6241 v3.into(),
6242 self.intrinsics.fp_rounding_md,
6243 self.intrinsics.fp_exception_md,
6244 ],
6245 "",
6246 )?
6247 .try_as_basic_value()
6248 .unwrap_basic();
6249 let res = err!(
6250 self.builder
6251 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6252 );
6253 let info = (i1.strip_pending() & i2.strip_pending())?;
6254 let info = (info & i3.strip_pending())?;
6255 let info = (info | ExtraInfo::pending_f32_nan())?;
6256 self.state.push1_extra(res, info);
6257 }
6258 Operator::F64x2Mul => {
6259 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6260 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6261 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6262 let res = self
6263 .build_call_with_param_attributes(
6264 self.intrinsics.mul_f64x2,
6265 &[
6266 v1.into(),
6267 v2.into(),
6268 self.intrinsics.fp_rounding_md,
6269 self.intrinsics.fp_exception_md,
6270 ],
6271 "",
6272 )?
6273 .try_as_basic_value()
6274 .unwrap_basic();
6275 let res = err!(
6276 self.builder
6277 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6278 );
6279 self.state.push1_extra(
6280 res,
6281 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6282 );
6283 }
6284 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
6285 if self.cpu_features.contains(CpuFeature::FMA) =>
6286 {
6287 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6288 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6289 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6290 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6291
6292 let v1 = match op {
6293 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6294 _ => v1,
6295 };
6296 let res = self
6297 .build_call_with_param_attributes(
6298 self.intrinsics.muladd_f64x2,
6299 &[
6300 v1.into(),
6301 v2.into(),
6302 v3.into(),
6303 self.intrinsics.fp_rounding_md,
6304 self.intrinsics.fp_exception_md,
6305 ],
6306 "",
6307 )?
6308 .try_as_basic_value()
6309 .unwrap_basic();
6310 let res = err!(
6311 self.builder
6312 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6313 );
6314 let info = (i1.strip_pending() & i2.strip_pending())?;
6315 let info = (info & i3.strip_pending())?;
6316 let info = (info | ExtraInfo::pending_f64_nan())?;
6317 self.state.push1_extra(res, info);
6318 }
6319 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
6320 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6321 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6322 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6323 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6324
6325 let v1 = match op {
6326 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6327 _ => v1,
6328 };
6329 let mul = self
6330 .build_call_with_param_attributes(
6331 self.intrinsics.mul_f64x2,
6332 &[
6333 v1.into(),
6334 v2.into(),
6335 self.intrinsics.fp_rounding_md,
6336 self.intrinsics.fp_exception_md,
6337 ],
6338 "",
6339 )?
6340 .try_as_basic_value()
6341 .unwrap_basic();
6342 let mul = mul.into_vector_value();
6343 let res = self
6344 .build_call_with_param_attributes(
6345 self.intrinsics.add_f64x2,
6346 &[
6347 mul.into(),
6348 v3.into(),
6349 self.intrinsics.fp_rounding_md,
6350 self.intrinsics.fp_exception_md,
6351 ],
6352 "",
6353 )?
6354 .try_as_basic_value()
6355 .unwrap_basic();
6356 let res = err!(
6357 self.builder
6358 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6359 );
6360 let info = (i1.strip_pending() & i2.strip_pending())?;
6361 let info = (info & i3.strip_pending())?;
6362 let info = (info | ExtraInfo::pending_f64_nan())?;
6363 self.state.push1_extra(res, info);
6364 }
6365 Operator::F32Div => {
6366 let (v1, v2) = self.state.pop2()?;
6367 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6368 let res = self
6369 .build_call_with_param_attributes(
6370 self.intrinsics.div_f32,
6371 &[
6372 v1.into(),
6373 v2.into(),
6374 self.intrinsics.fp_rounding_md,
6375 self.intrinsics.fp_exception_md,
6376 ],
6377 "",
6378 )?
6379 .try_as_basic_value()
6380 .unwrap_basic();
6381 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6382 }
6383 Operator::F64Div => {
6384 let (v1, v2) = self.state.pop2()?;
6385 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6386 let res = self
6387 .build_call_with_param_attributes(
6388 self.intrinsics.div_f64,
6389 &[
6390 v1.into(),
6391 v2.into(),
6392 self.intrinsics.fp_rounding_md,
6393 self.intrinsics.fp_exception_md,
6394 ],
6395 "",
6396 )?
6397 .try_as_basic_value()
6398 .unwrap_basic();
6399 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6400 }
6401 Operator::F32x4Div => {
6402 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6403 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
6404 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
6405 let res = self
6406 .build_call_with_param_attributes(
6407 self.intrinsics.div_f32x4,
6408 &[
6409 v1.into(),
6410 v2.into(),
6411 self.intrinsics.fp_rounding_md,
6412 self.intrinsics.fp_exception_md,
6413 ],
6414 "",
6415 )?
6416 .try_as_basic_value()
6417 .unwrap_basic();
6418 let res = err!(
6419 self.builder
6420 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6421 );
6422 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6423 }
6424 Operator::F64x2Div => {
6425 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6426 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
6427 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
6428 let res = self
6429 .build_call_with_param_attributes(
6430 self.intrinsics.div_f64x2,
6431 &[
6432 v1.into(),
6433 v2.into(),
6434 self.intrinsics.fp_rounding_md,
6435 self.intrinsics.fp_exception_md,
6436 ],
6437 "",
6438 )?
6439 .try_as_basic_value()
6440 .unwrap_basic();
6441 let res = err!(
6442 self.builder
6443 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6444 );
6445 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6446 }
6447 Operator::F32Sqrt => {
6448 let input = self.state.pop1()?;
6449 let res = self
6450 .build_call_with_param_attributes(
6451 self.intrinsics.sqrt_f32,
6452 &[input.into()],
6453 "",
6454 )?
6455 .try_as_basic_value()
6456 .unwrap_basic();
6457 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6458 }
6459 Operator::F64Sqrt => {
6460 let input = self.state.pop1()?;
6461 let res = self
6462 .build_call_with_param_attributes(
6463 self.intrinsics.sqrt_f64,
6464 &[input.into()],
6465 "",
6466 )?
6467 .try_as_basic_value()
6468 .unwrap_basic();
6469 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6470 }
6471 Operator::F32x4Sqrt => {
6472 let (v, i) = self.state.pop1_extra()?;
6473 let (v, _) = self.v128_into_f32x4(v, i)?;
6474 let res = self
6475 .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6476 .try_as_basic_value()
6477 .unwrap_basic();
6478 let bits = err!(
6479 self.builder
6480 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6481 );
6482 self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6483 }
6484 Operator::F64x2Sqrt => {
6485 let (v, i) = self.state.pop1_extra()?;
6486 let (v, _) = self.v128_into_f64x2(v, i)?;
6487 let res = self
6488 .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6489 .try_as_basic_value()
6490 .unwrap_basic();
6491 let bits = err!(
6492 self.builder
6493 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6494 );
6495 self.state.push1(bits);
6496 }
6497 Operator::F32Min => {
6498 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6499 let lhs = self
6500 .apply_pending_canonicalization(lhs, lhs_info)?
6501 .into_float_value();
6502 let rhs = self
6503 .apply_pending_canonicalization(rhs, rhs_info)?
6504 .into_float_value();
6505
6506 let res = self
6507 .build_call_with_param_attributes(
6508 self.intrinsics.minimum_f32,
6509 &[lhs.into(), rhs.into()],
6510 "",
6511 )?
6512 .try_as_basic_value()
6513 .unwrap_basic();
6514
6515 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6516 let res = res.into_float_value();
6517
6518 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6519 }
6520 Operator::F64Min => {
6521 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6522 let lhs = self
6523 .apply_pending_canonicalization(lhs, lhs_info)?
6524 .into_float_value();
6525 let rhs = self
6526 .apply_pending_canonicalization(rhs, rhs_info)?
6527 .into_float_value();
6528
6529 let res = self
6530 .build_call_with_param_attributes(
6531 self.intrinsics.minimum_f64,
6532 &[lhs.into(), rhs.into()],
6533 "",
6534 )?
6535 .try_as_basic_value()
6536 .unwrap_basic();
6537
6538 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6539 let res = res.into_float_value();
6540
6541 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6542 }
6543 Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6544 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6545 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6546 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6547 let res = self
6548 .build_call_with_param_attributes(
6549 self.intrinsics.x86_64.min_ps,
6550 &[v1.into(), v2.into()],
6551 "",
6552 )?
6553 .try_as_basic_value()
6554 .unwrap_basic();
6555 let res = err!(
6556 self.builder
6557 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6558 );
6559 self.state.push1_extra(
6560 res,
6561 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6562 );
6563 }
6564 Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6565 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6566 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6567 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6568 let res = self
6569 .build_call_with_param_attributes(
6570 self.intrinsics.minimum_f32x4,
6571 &[v1.into(), v2.into()],
6572 "",
6573 )?
6574 .try_as_basic_value()
6575 .unwrap_basic();
6576
6577 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6578 let res = res.into_vector_value();
6579
6580 let res = err!(
6581 self.builder
6582 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6583 );
6584 self.state.push1_extra(
6585 res,
6586 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6587 );
6588 }
6589 Operator::F32x4PMin => {
6590 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6592 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6593 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6594 let cmp = err!(
6595 self.builder
6596 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6597 );
6598 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6599 let res = err!(
6600 self.builder
6601 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6602 );
6603 self.state.push1(res);
6604 }
6605 Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6606 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6607 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6608 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6609 let res = self
6610 .build_call_with_param_attributes(
6611 self.intrinsics.x86_64.min_pd,
6612 &[v1.into(), v2.into()],
6613 "",
6614 )?
6615 .try_as_basic_value()
6616 .unwrap_basic();
6617 let res = err!(
6618 self.builder
6619 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6620 );
6621 self.state.push1_extra(
6622 res,
6623 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6624 );
6625 }
6626 Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6627 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6628 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6629 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6630 let res = self
6631 .build_call_with_param_attributes(
6632 self.intrinsics.minimum_f64x2,
6633 &[v1.into(), v2.into()],
6634 "",
6635 )?
6636 .try_as_basic_value()
6637 .unwrap_basic();
6638
6639 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6640 let res = res.into_vector_value();
6641
6642 let res = err!(
6643 self.builder
6644 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6645 );
6646 self.state.push1_extra(
6647 res,
6648 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6649 );
6650 }
6651 Operator::F64x2PMin => {
6652 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6654 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6655 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6656 let cmp = err!(
6657 self.builder
6658 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6659 );
6660 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6661 let res = err!(
6662 self.builder
6663 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6664 );
6665 self.state.push1(res);
6666 }
6667 Operator::F32Max => {
6668 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6669 let lhs = self
6670 .apply_pending_canonicalization(lhs, lhs_info)?
6671 .into_float_value();
6672 let rhs = self
6673 .apply_pending_canonicalization(rhs, rhs_info)?
6674 .into_float_value();
6675
6676 let res = self
6677 .build_call_with_param_attributes(
6678 self.intrinsics.maximum_f32,
6679 &[lhs.into(), rhs.into()],
6680 "",
6681 )?
6682 .try_as_basic_value()
6683 .unwrap_basic();
6684
6685 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6686 let res = res.into_float_value();
6687
6688 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6689 }
6690 Operator::F64Max => {
6691 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6692 let lhs = self
6693 .apply_pending_canonicalization(lhs, lhs_info)?
6694 .into_float_value();
6695 let rhs = self
6696 .apply_pending_canonicalization(rhs, rhs_info)?
6697 .into_float_value();
6698
6699 let res = self
6700 .build_call_with_param_attributes(
6701 self.intrinsics.maximum_f64,
6702 &[lhs.into(), rhs.into()],
6703 "",
6704 )?
6705 .try_as_basic_value()
6706 .unwrap_basic();
6707
6708 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6709 let res = res.into_float_value();
6710
6711 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6712 }
6713 Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6714 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6715 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6716 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6717 let res = self
6718 .build_call_with_param_attributes(
6719 self.intrinsics.x86_64.max_ps,
6720 &[v1.into(), v2.into()],
6721 "",
6722 )?
6723 .try_as_basic_value()
6724 .unwrap_basic();
6725 let res = err!(
6726 self.builder
6727 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6728 );
6729 self.state.push1_extra(
6730 res,
6731 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6732 );
6733 }
6734 Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6735 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6736 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6737 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6738 let res = self
6739 .build_call_with_param_attributes(
6740 self.intrinsics.maximum_f32x4,
6741 &[v1.into(), v2.into()],
6742 "",
6743 )?
6744 .try_as_basic_value()
6745 .unwrap_basic();
6746
6747 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6748 let res = res.into_vector_value();
6749
6750 let res = err!(
6751 self.builder
6752 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6753 );
6754 self.state.push1_extra(
6755 res,
6756 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6757 );
6758 }
6759 Operator::F32x4PMax => {
6760 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6762 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6763 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6764 let cmp = err!(
6765 self.builder
6766 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6767 );
6768 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6769
6770 let res = err!(
6771 self.builder
6772 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6773 );
6774 self.state.push1(res);
6775 }
6776 Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6777 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6778 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6779 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6780 let res = self
6781 .build_call_with_param_attributes(
6782 self.intrinsics.x86_64.max_pd,
6783 &[v1.into(), v2.into()],
6784 "",
6785 )?
6786 .try_as_basic_value()
6787 .unwrap_basic();
6788 let res = err!(
6789 self.builder
6790 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6791 );
6792 self.state.push1_extra(
6793 res,
6794 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6795 );
6796 }
6797 Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6798 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6799 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6800 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6801 let res = self
6802 .build_call_with_param_attributes(
6803 self.intrinsics.maximum_f64x2,
6804 &[v1.into(), v2.into()],
6805 "",
6806 )?
6807 .try_as_basic_value()
6808 .unwrap_basic();
6809
6810 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6811 let res = res.into_vector_value();
6812
6813 let res = err!(
6814 self.builder
6815 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6816 );
6817 self.state.push1_extra(
6818 res,
6819 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6820 );
6821 }
6822 Operator::F64x2PMax => {
6823 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6825 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6826 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6827 let cmp = err!(
6828 self.builder
6829 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6830 );
6831 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6832 let res = err!(
6833 self.builder
6834 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6835 );
6836 self.state.push1(res);
6837 }
6838 Operator::F32Ceil => {
6839 let (input, info) = self.state.pop1_extra()?;
6840 let res = err!(self.build_call_with_param_attributes(
6841 self.intrinsics.ceil_f32,
6842 &[input.into()],
6843 ""
6844 ))
6845 .try_as_basic_value()
6846 .unwrap_basic();
6847 let (res, info) = self.finalize_rounding_result(res, info)?;
6848 self.state.push1_extra(res, info);
6849 }
6850 Operator::F32x4Ceil => {
6851 let (v, i) = self.state.pop1_extra()?;
6852 let (v, _) = self.v128_into_f32x4(v, i)?;
6853 let res = err!(self.build_call_with_param_attributes(
6854 self.intrinsics.ceil_f32x4,
6855 &[v.into()],
6856 ""
6857 ))
6858 .try_as_basic_value()
6859 .unwrap_basic();
6860 let (res, info) = self.finalize_rounding_result(res, i)?;
6861 let res = err!(
6862 self.builder
6863 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6864 );
6865 self.state.push1_extra(res, info);
6866 }
6867 Operator::F64Ceil => {
6868 let (input, info) = self.state.pop1_extra()?;
6869 let res = err!(self.build_call_with_param_attributes(
6870 self.intrinsics.ceil_f64,
6871 &[input.into()],
6872 ""
6873 ))
6874 .try_as_basic_value()
6875 .unwrap_basic();
6876 let (res, info) = self.finalize_rounding_result(res, info)?;
6877 self.state.push1_extra(res, info);
6878 }
6879 Operator::F64x2Ceil => {
6880 let (v, i) = self.state.pop1_extra()?;
6881 let (v, _) = self.v128_into_f64x2(v, i)?;
6882 let res = err!(self.build_call_with_param_attributes(
6883 self.intrinsics.ceil_f64x2,
6884 &[v.into()],
6885 ""
6886 ))
6887 .try_as_basic_value()
6888 .unwrap_basic();
6889 let (res, info) = self.finalize_rounding_result(res, i)?;
6890 let res = err!(
6891 self.builder
6892 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6893 );
6894 self.state.push1_extra(res, info);
6895 }
6896 Operator::F32Floor => {
6897 let (input, info) = self.state.pop1_extra()?;
6898 let res = err!(self.build_call_with_param_attributes(
6899 self.intrinsics.floor_f32,
6900 &[input.into()],
6901 ""
6902 ))
6903 .try_as_basic_value()
6904 .unwrap_basic();
6905 let (res, info) = self.finalize_rounding_result(res, info)?;
6906 self.state.push1_extra(res, info);
6907 }
6908 Operator::F32x4Floor => {
6909 let (v, i) = self.state.pop1_extra()?;
6910 let (v, _) = self.v128_into_f32x4(v, i)?;
6911 let res = err!(self.build_call_with_param_attributes(
6912 self.intrinsics.floor_f32x4,
6913 &[v.into()],
6914 ""
6915 ))
6916 .try_as_basic_value()
6917 .unwrap_basic();
6918 let (res, info) = self.finalize_rounding_result(res, i)?;
6919 let res = err!(
6920 self.builder
6921 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6922 );
6923 self.state.push1_extra(res, info);
6924 }
6925 Operator::F64Floor => {
6926 let (input, info) = self.state.pop1_extra()?;
6927 let res = err!(self.build_call_with_param_attributes(
6928 self.intrinsics.floor_f64,
6929 &[input.into()],
6930 ""
6931 ))
6932 .try_as_basic_value()
6933 .unwrap_basic();
6934 let (res, info) = self.finalize_rounding_result(res, info)?;
6935 self.state.push1_extra(res, info);
6936 }
6937 Operator::F64x2Floor => {
6938 let (v, i) = self.state.pop1_extra()?;
6939 let (v, _) = self.v128_into_f64x2(v, i)?;
6940 let res = err!(self.build_call_with_param_attributes(
6941 self.intrinsics.floor_f64x2,
6942 &[v.into()],
6943 ""
6944 ))
6945 .try_as_basic_value()
6946 .unwrap_basic();
6947 let (res, info) = self.finalize_rounding_result(res, i)?;
6948 let res = err!(
6949 self.builder
6950 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6951 );
6952 self.state.push1_extra(res, info);
6953 }
6954 Operator::F32Trunc => {
6955 let (v, info) = self.state.pop1_extra()?;
6956 let res = err!(
6957 self.builder
6958 .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
6959 )
6960 .try_as_basic_value()
6961 .unwrap_basic();
6962 let (res, info) = self.finalize_rounding_result(res, info)?;
6963 self.state.push1_extra(res, info);
6964 }
6965 Operator::F32x4Trunc => {
6966 let (v, i) = self.state.pop1_extra()?;
6967 let (v, _) = self.v128_into_f32x4(v, i)?;
6968 let res = err!(self.build_call_with_param_attributes(
6969 self.intrinsics.trunc_f32x4,
6970 &[v.into()],
6971 ""
6972 ))
6973 .try_as_basic_value()
6974 .unwrap_basic();
6975 let (res, info) = self.finalize_rounding_result(res, i)?;
6976 let res = err!(
6977 self.builder
6978 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6979 );
6980 self.state.push1_extra(res, info);
6981 }
6982 Operator::F64Trunc => {
6983 let (v, info) = self.state.pop1_extra()?;
6984 let res = err!(
6985 self.builder
6986 .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
6987 )
6988 .try_as_basic_value()
6989 .unwrap_basic();
6990 let (res, info) = self.finalize_rounding_result(res, info)?;
6991 self.state.push1_extra(res, info);
6992 }
6993 Operator::F64x2Trunc => {
6994 let (v, i) = self.state.pop1_extra()?;
6995 let (v, _) = self.v128_into_f64x2(v, i)?;
6996 let res = err!(self.build_call_with_param_attributes(
6997 self.intrinsics.trunc_f64x2,
6998 &[v.into()],
6999 ""
7000 ))
7001 .try_as_basic_value()
7002 .unwrap_basic();
7003 let (res, info) = self.finalize_rounding_result(res, i)?;
7004 let res = err!(
7005 self.builder
7006 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7007 );
7008 self.state.push1_extra(res, info);
7009 }
7010 Operator::F32Nearest => {
7011 let (v, info) = self.state.pop1_extra()?;
7012 let res = err!(self.build_call_with_param_attributes(
7013 self.intrinsics.nearbyint_f32,
7014 &[v.into()],
7015 ""
7016 ))
7017 .try_as_basic_value()
7018 .unwrap_basic();
7019 let (res, info) = self.finalize_rounding_result(res, info)?;
7020 self.state.push1_extra(res, info);
7021 }
7022 Operator::F32x4Nearest => {
7023 let (v, i) = self.state.pop1_extra()?;
7024 let (v, _) = self.v128_into_f32x4(v, i)?;
7025 let res = err!(self.build_call_with_param_attributes(
7026 self.intrinsics.nearbyint_f32x4,
7027 &[v.into()],
7028 ""
7029 ))
7030 .try_as_basic_value()
7031 .unwrap_basic();
7032 let (res, info) = self.finalize_rounding_result(res, i)?;
7033 let res = err!(
7034 self.builder
7035 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7036 );
7037 self.state.push1_extra(res, info);
7038 }
7039 Operator::F64Nearest => {
7040 let (v, info) = self.state.pop1_extra()?;
7041 let res = err!(self.build_call_with_param_attributes(
7042 self.intrinsics.nearbyint_f64,
7043 &[v.into()],
7044 ""
7045 ))
7046 .try_as_basic_value()
7047 .unwrap_basic();
7048 let (res, info) = self.finalize_rounding_result(res, info)?;
7049 self.state.push1_extra(res, info);
7050 }
7051 Operator::F64x2Nearest => {
7052 let (v, i) = self.state.pop1_extra()?;
7053 let (v, _) = self.v128_into_f64x2(v, i)?;
7054 let res = err!(self.build_call_with_param_attributes(
7055 self.intrinsics.nearbyint_f64x2,
7056 &[v.into()],
7057 ""
7058 ))
7059 .try_as_basic_value()
7060 .unwrap_basic();
7061 let (res, info) = self.finalize_rounding_result(res, i)?;
7062 let res = err!(
7063 self.builder
7064 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7065 );
7066 self.state.push1_extra(res, info);
7067 }
7068 Operator::F32Abs => {
7069 let (v, i) = self.state.pop1_extra()?;
7070 let v = self.apply_pending_canonicalization(v, i)?;
7071 let res = err!(
7072 self.builder
7073 .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
7074 )
7075 .try_as_basic_value()
7076 .unwrap_basic();
7077 self.state.push1_extra(res, i.strip_pending());
7080 }
7081 Operator::F64Abs => {
7082 let (v, i) = self.state.pop1_extra()?;
7083 let v = self.apply_pending_canonicalization(v, i)?;
7084 let res = err!(
7085 self.builder
7086 .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
7087 )
7088 .try_as_basic_value()
7089 .unwrap_basic();
7090 self.state.push1_extra(res, i.strip_pending());
7093 }
7094 Operator::F32x4Abs => {
7095 let (v, i) = self.state.pop1_extra()?;
7096 let v = err!(self.builder.build_bit_cast(
7097 v.into_int_value(),
7098 self.intrinsics.f32x4_ty,
7099 ""
7100 ));
7101 let v = self.apply_pending_canonicalization(v, i)?;
7102 let res = self
7103 .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
7104 .try_as_basic_value()
7105 .unwrap_basic();
7106 let res = err!(
7107 self.builder
7108 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7109 );
7110 self.state.push1_extra(res, i.strip_pending());
7113 }
7114 Operator::F64x2Abs => {
7115 let (v, i) = self.state.pop1_extra()?;
7116 let v = err!(self.builder.build_bit_cast(
7117 v.into_int_value(),
7118 self.intrinsics.f64x2_ty,
7119 ""
7120 ));
7121 let v = self.apply_pending_canonicalization(v, i)?;
7122 let res = self
7123 .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
7124 .try_as_basic_value()
7125 .unwrap_basic();
7126 let res = err!(
7127 self.builder
7128 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7129 );
7130 self.state.push1_extra(res, i.strip_pending());
7133 }
7134 Operator::F32x4Neg => {
7135 let (v, i) = self.state.pop1_extra()?;
7136 let v = err!(self.builder.build_bit_cast(
7137 v.into_int_value(),
7138 self.intrinsics.f32x4_ty,
7139 ""
7140 ));
7141 let v = self
7142 .apply_pending_canonicalization(v, i)?
7143 .into_vector_value();
7144 let res = err!(self.builder.build_float_neg(v, ""));
7145 let res = err!(
7146 self.builder
7147 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7148 );
7149 self.state.push1_extra(res, i.strip_pending());
7152 }
7153 Operator::F64x2Neg => {
7154 let (v, i) = self.state.pop1_extra()?;
7155 let v = err!(self.builder.build_bit_cast(
7156 v.into_int_value(),
7157 self.intrinsics.f64x2_ty,
7158 ""
7159 ));
7160 let v = self
7161 .apply_pending_canonicalization(v, i)?
7162 .into_vector_value();
7163 let res = err!(self.builder.build_float_neg(v, ""));
7164 let res = err!(
7165 self.builder
7166 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7167 );
7168 self.state.push1_extra(res, i.strip_pending());
7171 }
7172 Operator::F32Neg | Operator::F64Neg => {
7173 let (v, i) = self.state.pop1_extra()?;
7174 let v = self
7175 .apply_pending_canonicalization(v, i)?
7176 .into_float_value();
7177 let res = err!(self.builder.build_float_neg(v, ""));
7178 self.state.push1_extra(res, i.strip_pending());
7181 }
7182 Operator::F32Copysign => {
7183 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7184 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7185 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7186 let res = self
7187 .build_call_with_param_attributes(
7188 self.intrinsics.copysign_f32,
7189 &[mag.into(), sgn.into()],
7190 "",
7191 )?
7192 .try_as_basic_value()
7193 .unwrap_basic();
7194 self.state.push1_extra(res, mag_info.strip_pending());
7197 }
7198 Operator::F64Copysign => {
7199 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7200 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7201 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7202 let res = self
7203 .build_call_with_param_attributes(
7204 self.intrinsics.copysign_f64,
7205 &[mag.into(), sgn.into()],
7206 "",
7207 )?
7208 .try_as_basic_value()
7209 .unwrap_basic();
7210 self.state.push1_extra(res, mag_info.strip_pending());
7213 }
7214 _ => unreachable!(),
7215 }
7216 Ok(())
7217 }
7218
7219 fn translate_integer_comparison_operator(&mut self, op: Operator) -> Result<(), CompileError> {
7222 match op {
7223 Operator::I32Eq | Operator::I64Eq => {
7224 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7225 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7226 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7227 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7228 let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7229 let res = err!(
7230 self.builder
7231 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7232 );
7233 self.state.push1_extra(
7234 res,
7235 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7236 );
7237 }
7238 Operator::I8x16Eq => {
7239 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7240 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7241 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7242 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7243 let res = err!(
7244 self.builder
7245 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7246 );
7247 let res = err!(
7248 self.builder
7249 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7250 );
7251 self.state.push1(res);
7252 }
7253 Operator::I16x8Eq => {
7254 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7255 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7256 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7257 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7258 let res = err!(
7259 self.builder
7260 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7261 );
7262 let res = err!(
7263 self.builder
7264 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7265 );
7266 self.state.push1(res);
7267 }
7268 Operator::I32x4Eq => {
7269 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7270 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7271 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7272 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7273 let res = err!(
7274 self.builder
7275 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7276 );
7277 let res = err!(
7278 self.builder
7279 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7280 );
7281 self.state.push1(res);
7282 }
7283 Operator::I64x2Eq => {
7284 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7285 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7286 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7287 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7288 let res = err!(
7289 self.builder
7290 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7291 );
7292 let res = err!(
7293 self.builder
7294 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7295 );
7296 self.state.push1(res);
7297 }
7298 Operator::I32Ne | Operator::I64Ne => {
7299 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7300 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7301 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7302 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7303 let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7304 let res = err!(
7305 self.builder
7306 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7307 );
7308 self.state.push1_extra(
7309 res,
7310 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7311 );
7312 }
7313 Operator::I8x16Ne => {
7314 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7315 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7316 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7317 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7318 let res = err!(
7319 self.builder
7320 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7321 );
7322 let res = err!(
7323 self.builder
7324 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7325 );
7326 self.state.push1(res);
7327 }
7328 Operator::I16x8Ne => {
7329 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7330 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7331 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7332 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7333 let res = err!(
7334 self.builder
7335 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7336 );
7337 let res = err!(
7338 self.builder
7339 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7340 );
7341 self.state.push1(res);
7342 }
7343 Operator::I32x4Ne => {
7344 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7345 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7346 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7347 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7348 let res = err!(
7349 self.builder
7350 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7351 );
7352 let res = err!(
7353 self.builder
7354 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7355 );
7356 self.state.push1(res);
7357 }
7358 Operator::I64x2Ne => {
7359 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7360 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7361 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7362 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7363 let res = err!(
7364 self.builder
7365 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7366 );
7367 let res = err!(
7368 self.builder
7369 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7370 );
7371 self.state.push1(res);
7372 }
7373 Operator::I32LtS | Operator::I64LtS => {
7374 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7375 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7376 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7377 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7378 let cond = err!(
7379 self.builder
7380 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7381 );
7382 let res = err!(
7383 self.builder
7384 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7385 );
7386 self.state.push1_extra(
7387 res,
7388 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7389 );
7390 }
7391 Operator::I8x16LtS => {
7392 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7393 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7394 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7395 let res = err!(
7396 self.builder
7397 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7398 );
7399 let res = err!(
7400 self.builder
7401 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7402 );
7403 let res = err!(
7404 self.builder
7405 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7406 );
7407 self.state.push1(res);
7408 }
7409 Operator::I16x8LtS => {
7410 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7411 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7412 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7413 let res = err!(
7414 self.builder
7415 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7416 );
7417 let res = err!(
7418 self.builder
7419 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7420 );
7421 let res = err!(
7422 self.builder
7423 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7424 );
7425 self.state.push1(res);
7426 }
7427 Operator::I32x4LtS => {
7428 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7429 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7430 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7431 let res = err!(
7432 self.builder
7433 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7434 );
7435 let res = err!(
7436 self.builder
7437 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7438 );
7439 let res = err!(
7440 self.builder
7441 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7442 );
7443 self.state.push1(res);
7444 }
7445 Operator::I64x2LtS => {
7446 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7447 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7448 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7449 let res = err!(
7450 self.builder
7451 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7452 );
7453 let res = err!(
7454 self.builder
7455 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7456 );
7457 let res = err!(
7458 self.builder
7459 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7460 );
7461 self.state.push1(res);
7462 }
7463 Operator::I32LtU | Operator::I64LtU => {
7464 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7465 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7466 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7467 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7468 let cond = err!(
7469 self.builder
7470 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7471 );
7472 let res = err!(
7473 self.builder
7474 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7475 );
7476 self.state.push1(res);
7477 }
7478 Operator::I8x16LtU => {
7479 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7480 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7481 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7482 let res = err!(
7483 self.builder
7484 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7485 );
7486 let res = err!(
7487 self.builder
7488 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7489 );
7490 let res = err!(
7491 self.builder
7492 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7493 );
7494 self.state.push1(res);
7495 }
7496 Operator::I16x8LtU => {
7497 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7498 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7499 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7500 let res = err!(
7501 self.builder
7502 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7503 );
7504 let res = err!(
7505 self.builder
7506 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7507 );
7508 let res = err!(
7509 self.builder
7510 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7511 );
7512 self.state.push1(res);
7513 }
7514 Operator::I32x4LtU => {
7515 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7516 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7517 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7518 let res = err!(
7519 self.builder
7520 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7521 );
7522 let res = err!(
7523 self.builder
7524 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7525 );
7526 let res = err!(
7527 self.builder
7528 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7529 );
7530 self.state.push1(res);
7531 }
7532 Operator::I32LeS | Operator::I64LeS => {
7533 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7534 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7535 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7536 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7537 let cond = err!(
7538 self.builder
7539 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7540 );
7541 let res = err!(
7542 self.builder
7543 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7544 );
7545 self.state.push1_extra(
7546 res,
7547 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7548 );
7549 }
7550 Operator::I8x16LeS => {
7551 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7552 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7553 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7554 let res = err!(
7555 self.builder
7556 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7557 );
7558 let res = err!(
7559 self.builder
7560 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7561 );
7562 let res = err!(
7563 self.builder
7564 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7565 );
7566 self.state.push1(res);
7567 }
7568 Operator::I16x8LeS => {
7569 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7570 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7571 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7572 let res = err!(
7573 self.builder
7574 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7575 );
7576 let res = err!(
7577 self.builder
7578 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7579 );
7580 let res = err!(
7581 self.builder
7582 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7583 );
7584 self.state.push1(res);
7585 }
7586 Operator::I32x4LeS => {
7587 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7588 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7589 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7590 let res = err!(
7591 self.builder
7592 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7593 );
7594 let res = err!(
7595 self.builder
7596 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7597 );
7598 let res = err!(
7599 self.builder
7600 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7601 );
7602 self.state.push1(res);
7603 }
7604 Operator::I64x2LeS => {
7605 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7606 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7607 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7608 let res = err!(
7609 self.builder
7610 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7611 );
7612 let res = err!(
7613 self.builder
7614 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7615 );
7616 let res = err!(
7617 self.builder
7618 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7619 );
7620 self.state.push1(res);
7621 }
7622 Operator::I32LeU | Operator::I64LeU => {
7623 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7624 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7625 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7626 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7627 let cond = err!(
7628 self.builder
7629 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7630 );
7631 let res = err!(
7632 self.builder
7633 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7634 );
7635 self.state.push1_extra(
7636 res,
7637 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7638 );
7639 }
7640 Operator::I8x16LeU => {
7641 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7642 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7643 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7644 let res = err!(
7645 self.builder
7646 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7647 );
7648 let res = err!(
7649 self.builder
7650 .build_int_s_extend(res, self.intrinsics.i8x16_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 Operator::I16x8LeU => {
7659 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7660 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7661 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7662 let res = err!(
7663 self.builder
7664 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7665 );
7666 let res = err!(
7667 self.builder
7668 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7669 );
7670 let res = err!(
7671 self.builder
7672 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7673 );
7674 self.state.push1(res);
7675 }
7676 Operator::I32x4LeU => {
7677 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7678 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7679 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7680 let res = err!(
7681 self.builder
7682 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7683 );
7684 let res = err!(
7685 self.builder
7686 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7687 );
7688 let res = err!(
7689 self.builder
7690 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7691 );
7692 self.state.push1(res);
7693 }
7694 Operator::I32GtS | Operator::I64GtS => {
7695 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7696 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7697 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7698 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7699 let cond = err!(
7700 self.builder
7701 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7702 );
7703 let res = err!(
7704 self.builder
7705 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7706 );
7707 self.state.push1_extra(
7708 res,
7709 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7710 );
7711 }
7712 Operator::I8x16GtS => {
7713 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7714 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7715 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7716 let res = err!(
7717 self.builder
7718 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7719 );
7720 let res = err!(
7721 self.builder
7722 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7723 );
7724 let res = err!(
7725 self.builder
7726 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7727 );
7728 self.state.push1(res);
7729 }
7730 Operator::I16x8GtS => {
7731 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7732 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7733 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7734 let res = err!(
7735 self.builder
7736 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7737 );
7738 let res = err!(
7739 self.builder
7740 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7741 );
7742 let res = err!(
7743 self.builder
7744 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7745 );
7746 self.state.push1(res);
7747 }
7748 Operator::I32x4GtS => {
7749 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7750 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7751 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7752 let res = err!(
7753 self.builder
7754 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7755 );
7756 let res = err!(
7757 self.builder
7758 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7759 );
7760 let res = err!(
7761 self.builder
7762 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7763 );
7764 self.state.push1(res);
7765 }
7766 Operator::I64x2GtS => {
7767 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7768 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7769 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7770 let res = err!(
7771 self.builder
7772 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7773 );
7774 let res = err!(
7775 self.builder
7776 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7777 );
7778 let res = err!(
7779 self.builder
7780 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7781 );
7782 self.state.push1(res);
7783 }
7784 Operator::I32GtU | Operator::I64GtU => {
7785 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7786 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7787 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7788 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7789 let cond = err!(
7790 self.builder
7791 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7792 );
7793 let res = err!(
7794 self.builder
7795 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7796 );
7797 self.state.push1_extra(
7798 res,
7799 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7800 );
7801 }
7802 Operator::I8x16GtU => {
7803 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7804 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7805 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7806 let res = err!(
7807 self.builder
7808 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7809 );
7810 let res = err!(
7811 self.builder
7812 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7813 );
7814 let res = err!(
7815 self.builder
7816 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7817 );
7818 self.state.push1(res);
7819 }
7820 Operator::I16x8GtU => {
7821 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7822 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7823 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7824 let res = err!(
7825 self.builder
7826 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7827 );
7828 let res = err!(
7829 self.builder
7830 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7831 );
7832 let res = err!(
7833 self.builder
7834 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7835 );
7836 self.state.push1(res);
7837 }
7838 Operator::I32x4GtU => {
7839 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7840 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7841 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7842 let res = err!(
7843 self.builder
7844 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7845 );
7846 let res = err!(
7847 self.builder
7848 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7849 );
7850 let res = err!(
7851 self.builder
7852 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7853 );
7854 self.state.push1(res);
7855 }
7856 Operator::I32GeS | Operator::I64GeS => {
7857 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7858 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7859 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7860 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7861 let cond = err!(
7862 self.builder
7863 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7864 );
7865 let res = err!(
7866 self.builder
7867 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7868 );
7869 self.state.push1(res);
7870 }
7871 Operator::I8x16GeS => {
7872 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7873 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7874 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7875 let res = err!(
7876 self.builder
7877 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7878 );
7879 let res = err!(
7880 self.builder
7881 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7882 );
7883 let res = err!(
7884 self.builder
7885 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7886 );
7887 self.state.push1(res);
7888 }
7889 Operator::I16x8GeS => {
7890 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7891 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7892 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7893 let res = err!(
7894 self.builder
7895 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7896 );
7897 let res = err!(
7898 self.builder
7899 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7900 );
7901 let res = err!(
7902 self.builder
7903 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7904 );
7905 self.state.push1(res);
7906 }
7907 Operator::I32x4GeS => {
7908 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7909 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7910 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7911 let res = err!(
7912 self.builder
7913 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7914 );
7915 let res = err!(
7916 self.builder
7917 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7918 );
7919 let res = err!(
7920 self.builder
7921 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7922 );
7923 self.state.push1(res);
7924 }
7925 Operator::I64x2GeS => {
7926 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7927 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7928 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7929 let res = err!(
7930 self.builder
7931 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7932 );
7933 let res = err!(
7934 self.builder
7935 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7936 );
7937 let res = err!(
7938 self.builder
7939 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7940 );
7941 self.state.push1(res);
7942 }
7943 Operator::I32GeU | Operator::I64GeU => {
7944 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7945 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7946 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7947 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7948 let cond = err!(
7949 self.builder
7950 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7951 );
7952 let res = err!(
7953 self.builder
7954 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7955 );
7956 self.state.push1_extra(
7957 res,
7958 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7959 );
7960 }
7961 Operator::I8x16GeU => {
7962 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7963 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7964 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7965 let res = err!(
7966 self.builder
7967 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7968 );
7969 let res = err!(
7970 self.builder
7971 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7972 );
7973 let res = err!(
7974 self.builder
7975 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7976 );
7977 self.state.push1(res);
7978 }
7979 Operator::I16x8GeU => {
7980 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7981 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7982 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7983 let res = err!(
7984 self.builder
7985 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7986 );
7987 let res = err!(
7988 self.builder
7989 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7990 );
7991 let res = err!(
7992 self.builder
7993 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7994 );
7995 self.state.push1(res);
7996 }
7997 Operator::I32x4GeU => {
7998 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7999 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8000 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8001 let res = err!(
8002 self.builder
8003 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8004 );
8005 let res = err!(
8006 self.builder
8007 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8008 );
8009 let res = err!(
8010 self.builder
8011 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8012 );
8013 self.state.push1(res);
8014 }
8015 _ => unreachable!(),
8016 }
8017 Ok(())
8018 }
8019
8020 fn translate_floating_point_comparison_operator(
8023 &mut self,
8024 op: Operator,
8025 ) -> Result<(), CompileError> {
8026 match op {
8027 Operator::F32Eq | Operator::F64Eq => {
8028 let (v1, v2) = self.state.pop2()?;
8029 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8030 let cond = err!(
8031 self.builder
8032 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8033 );
8034 let res = err!(
8035 self.builder
8036 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8037 );
8038 self.state.push1_extra(
8039 res,
8040 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8041 );
8042 }
8043 Operator::F32x4Eq => {
8044 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8045 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8046 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8047 let res = err!(
8048 self.builder
8049 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8050 );
8051 let res = err!(
8052 self.builder
8053 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8054 );
8055 let res = err!(
8056 self.builder
8057 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8058 );
8059 self.state.push1(res);
8060 }
8061 Operator::F64x2Eq => {
8062 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8063 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8064 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8065 let res = err!(
8066 self.builder
8067 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8068 );
8069 let res = err!(
8070 self.builder
8071 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8072 );
8073 let res = err!(
8074 self.builder
8075 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8076 );
8077 self.state.push1(res);
8078 }
8079 Operator::F32Ne | Operator::F64Ne => {
8080 let (v1, v2) = self.state.pop2()?;
8081 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8082 let cond = err!(
8083 self.builder
8084 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8085 );
8086 let res = err!(
8087 self.builder
8088 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8089 );
8090 self.state.push1_extra(
8091 res,
8092 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8093 );
8094 }
8095 Operator::F32x4Ne => {
8096 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8097 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8098 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8099 let res = err!(
8100 self.builder
8101 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8102 );
8103 let res = err!(
8104 self.builder
8105 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8106 );
8107 let res = err!(
8108 self.builder
8109 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8110 );
8111 self.state.push1(res);
8112 }
8113 Operator::F64x2Ne => {
8114 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8115 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8116 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8117 let res = err!(
8118 self.builder
8119 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8120 );
8121 let res = err!(
8122 self.builder
8123 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8124 );
8125 let res = err!(
8126 self.builder
8127 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8128 );
8129 self.state.push1(res);
8130 }
8131 Operator::F32Lt | Operator::F64Lt => {
8132 let (v1, v2) = self.state.pop2()?;
8133 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8134 let cond = err!(
8135 self.builder
8136 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8137 );
8138 let res = err!(
8139 self.builder
8140 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8141 );
8142 self.state.push1_extra(
8143 res,
8144 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8145 );
8146 }
8147 Operator::F32x4Lt => {
8148 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8149 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8150 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8151 let res = err!(
8152 self.builder
8153 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8154 );
8155 let res = err!(
8156 self.builder
8157 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8158 );
8159 let res = err!(
8160 self.builder
8161 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8162 );
8163 self.state.push1(res);
8164 }
8165 Operator::F64x2Lt => {
8166 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8167 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8168 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8169 let res = err!(
8170 self.builder
8171 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8172 );
8173 let res = err!(
8174 self.builder
8175 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8176 );
8177 let res = err!(
8178 self.builder
8179 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8180 );
8181 self.state.push1(res);
8182 }
8183 Operator::F32Le | Operator::F64Le => {
8184 let (v1, v2) = self.state.pop2()?;
8185 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8186 let cond = err!(
8187 self.builder
8188 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8189 );
8190 let res = err!(
8191 self.builder
8192 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8193 );
8194 self.state.push1_extra(
8195 res,
8196 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8197 );
8198 }
8199 Operator::F32x4Le => {
8200 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8201 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8202 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8203 let res = err!(
8204 self.builder
8205 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8206 );
8207 let res = err!(
8208 self.builder
8209 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8210 );
8211 let res = err!(
8212 self.builder
8213 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8214 );
8215 self.state.push1(res);
8216 }
8217 Operator::F64x2Le => {
8218 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8219 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8220 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8221 let res = err!(
8222 self.builder
8223 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8224 );
8225 let res = err!(
8226 self.builder
8227 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8228 );
8229 let res = err!(
8230 self.builder
8231 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8232 );
8233 self.state.push1(res);
8234 }
8235 Operator::F32Gt | Operator::F64Gt => {
8236 let (v1, v2) = self.state.pop2()?;
8237 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8238 let cond = err!(
8239 self.builder
8240 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8241 );
8242 let res = err!(
8243 self.builder
8244 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8245 );
8246 self.state.push1_extra(
8247 res,
8248 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8249 );
8250 }
8251 Operator::F32x4Gt => {
8252 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8253 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8254 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8255 let res = err!(
8256 self.builder
8257 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8258 );
8259 let res = err!(
8260 self.builder
8261 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8262 );
8263 let res = err!(
8264 self.builder
8265 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8266 );
8267 self.state.push1(res);
8268 }
8269 Operator::F64x2Gt => {
8270 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8271 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8272 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8273 let res = err!(
8274 self.builder
8275 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8276 );
8277 let res = err!(
8278 self.builder
8279 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8280 );
8281 let res = err!(
8282 self.builder
8283 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8284 );
8285 self.state.push1(res);
8286 }
8287 Operator::F32Ge | Operator::F64Ge => {
8288 let (v1, v2) = self.state.pop2()?;
8289 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8290 let cond = err!(
8291 self.builder
8292 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8293 );
8294 let res = err!(
8295 self.builder
8296 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8297 );
8298 self.state.push1_extra(
8299 res,
8300 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8301 );
8302 }
8303 Operator::F32x4Ge => {
8304 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8305 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8306 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8307 let res = err!(
8308 self.builder
8309 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8310 );
8311 let res = err!(
8312 self.builder
8313 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8314 );
8315 let res = err!(
8316 self.builder
8317 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8318 );
8319 self.state.push1(res);
8320 }
8321 Operator::F64x2Ge => {
8322 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8323 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8324 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8325 let res = err!(
8326 self.builder
8327 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8328 );
8329 let res = err!(
8330 self.builder
8331 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8332 );
8333 let res = err!(
8334 self.builder
8335 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8336 );
8337 self.state.push1(res);
8338 }
8339 _ => unreachable!(),
8340 }
8341 Ok(())
8342 }
8343
8344 fn translate_conversion_operator(&mut self, op: Operator) -> Result<(), CompileError> {
8347 match op {
8348 Operator::I32WrapI64 => {
8349 let (v, i) = self.state.pop1_extra()?;
8350 let v = self.apply_pending_canonicalization(v, i)?;
8351 let v = v.into_int_value();
8352 let res = err!(
8353 self.builder
8354 .build_int_truncate(v, self.intrinsics.i32_ty, "")
8355 );
8356 self.state.push1(res);
8357 }
8358 Operator::I64ExtendI32S => {
8359 let (v, i) = self.state.pop1_extra()?;
8360 let v = self.apply_pending_canonicalization(v, i)?;
8361 let v = v.into_int_value();
8362 let res = err!(
8363 self.builder
8364 .build_int_s_extend(v, self.intrinsics.i64_ty, "")
8365 );
8366 self.state.push1(res);
8367 }
8368 Operator::I64ExtendI32U => {
8369 let (v, i) = self.state.pop1_extra()?;
8370 let v = self.apply_pending_canonicalization(v, i)?;
8371 let v = v.into_int_value();
8372 let res = err!(
8373 self.builder
8374 .build_int_z_extend(v, self.intrinsics.i64_ty, "")
8375 );
8376 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
8377 }
8378 Operator::I16x8ExtendLowI8x16S => {
8379 let (v, i) = self.state.pop1_extra()?;
8380 let (v, _) = self.v128_into_i8x16(v, i)?;
8381 let low = err!(self.builder.build_shuffle_vector(
8382 v,
8383 v.get_type().get_undef(),
8384 VectorType::const_vector(&[
8385 self.intrinsics.i32_consts[0],
8386 self.intrinsics.i32_consts[1],
8387 self.intrinsics.i32_consts[2],
8388 self.intrinsics.i32_consts[3],
8389 self.intrinsics.i32_consts[4],
8390 self.intrinsics.i32_consts[5],
8391 self.intrinsics.i32_consts[6],
8392 self.intrinsics.i32_consts[7],
8393 ]),
8394 "",
8395 ));
8396 let res = err!(
8397 self.builder
8398 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8399 );
8400 let res = err!(
8401 self.builder
8402 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8403 );
8404 self.state.push1(res);
8405 }
8406 Operator::I16x8ExtendHighI8x16S => {
8407 let (v, i) = self.state.pop1_extra()?;
8408 let (v, _) = self.v128_into_i8x16(v, i)?;
8409 let low = err!(self.builder.build_shuffle_vector(
8410 v,
8411 v.get_type().get_undef(),
8412 VectorType::const_vector(&[
8413 self.intrinsics.i32_consts[8],
8414 self.intrinsics.i32_consts[9],
8415 self.intrinsics.i32_consts[10],
8416 self.intrinsics.i32_consts[11],
8417 self.intrinsics.i32_consts[12],
8418 self.intrinsics.i32_consts[13],
8419 self.intrinsics.i32_consts[14],
8420 self.intrinsics.i32_consts[15],
8421 ]),
8422 "",
8423 ));
8424 let res = err!(
8425 self.builder
8426 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8427 );
8428 let res = err!(
8429 self.builder
8430 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8431 );
8432 self.state.push1(res);
8433 }
8434 Operator::I16x8ExtendLowI8x16U => {
8435 let (v, i) = self.state.pop1_extra()?;
8436 let (v, _) = self.v128_into_i8x16(v, i)?;
8437 let low = err!(self.builder.build_shuffle_vector(
8438 v,
8439 v.get_type().get_undef(),
8440 VectorType::const_vector(&[
8441 self.intrinsics.i32_consts[0],
8442 self.intrinsics.i32_consts[1],
8443 self.intrinsics.i32_consts[2],
8444 self.intrinsics.i32_consts[3],
8445 self.intrinsics.i32_consts[4],
8446 self.intrinsics.i32_consts[5],
8447 self.intrinsics.i32_consts[6],
8448 self.intrinsics.i32_consts[7],
8449 ]),
8450 "",
8451 ));
8452 let res = err!(
8453 self.builder
8454 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8455 );
8456 let res = err!(
8457 self.builder
8458 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8459 );
8460 self.state.push1(res);
8461 }
8462 Operator::I16x8ExtendHighI8x16U => {
8463 let (v, i) = self.state.pop1_extra()?;
8464 let (v, _) = self.v128_into_i8x16(v, i)?;
8465 let low = err!(self.builder.build_shuffle_vector(
8466 v,
8467 v.get_type().get_undef(),
8468 VectorType::const_vector(&[
8469 self.intrinsics.i32_consts[8],
8470 self.intrinsics.i32_consts[9],
8471 self.intrinsics.i32_consts[10],
8472 self.intrinsics.i32_consts[11],
8473 self.intrinsics.i32_consts[12],
8474 self.intrinsics.i32_consts[13],
8475 self.intrinsics.i32_consts[14],
8476 self.intrinsics.i32_consts[15],
8477 ]),
8478 "",
8479 ));
8480 let res = err!(
8481 self.builder
8482 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8483 );
8484 let res = err!(
8485 self.builder
8486 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8487 );
8488 self.state.push1(res);
8489 }
8490 Operator::I32x4ExtendLowI16x8S => {
8491 let (v, i) = self.state.pop1_extra()?;
8492 let (v, _) = self.v128_into_i16x8(v, i)?;
8493 let low = err!(self.builder.build_shuffle_vector(
8494 v,
8495 v.get_type().get_undef(),
8496 VectorType::const_vector(&[
8497 self.intrinsics.i32_consts[0],
8498 self.intrinsics.i32_consts[1],
8499 self.intrinsics.i32_consts[2],
8500 self.intrinsics.i32_consts[3],
8501 ]),
8502 "",
8503 ));
8504 let res = err!(
8505 self.builder
8506 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8507 );
8508 let res = err!(
8509 self.builder
8510 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8511 );
8512 self.state.push1(res);
8513 }
8514 Operator::I32x4ExtendHighI16x8S => {
8515 let (v, i) = self.state.pop1_extra()?;
8516 let (v, _) = self.v128_into_i16x8(v, i)?;
8517 let low = err!(self.builder.build_shuffle_vector(
8518 v,
8519 v.get_type().get_undef(),
8520 VectorType::const_vector(&[
8521 self.intrinsics.i32_consts[4],
8522 self.intrinsics.i32_consts[5],
8523 self.intrinsics.i32_consts[6],
8524 self.intrinsics.i32_consts[7],
8525 ]),
8526 "",
8527 ));
8528 let res = err!(
8529 self.builder
8530 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8531 );
8532 let res = err!(
8533 self.builder
8534 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8535 );
8536 self.state.push1(res);
8537 }
8538 Operator::I32x4ExtendLowI16x8U => {
8539 let (v, i) = self.state.pop1_extra()?;
8540 let (v, _) = self.v128_into_i16x8(v, i)?;
8541 let low = err!(self.builder.build_shuffle_vector(
8542 v,
8543 v.get_type().get_undef(),
8544 VectorType::const_vector(&[
8545 self.intrinsics.i32_consts[0],
8546 self.intrinsics.i32_consts[1],
8547 self.intrinsics.i32_consts[2],
8548 self.intrinsics.i32_consts[3],
8549 ]),
8550 "",
8551 ));
8552 let res = err!(
8553 self.builder
8554 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8555 );
8556 let res = err!(
8557 self.builder
8558 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8559 );
8560 self.state.push1(res);
8561 }
8562 Operator::I32x4ExtendHighI16x8U => {
8563 let (v, i) = self.state.pop1_extra()?;
8564 let (v, _) = self.v128_into_i16x8(v, i)?;
8565 let low = err!(self.builder.build_shuffle_vector(
8566 v,
8567 v.get_type().get_undef(),
8568 VectorType::const_vector(&[
8569 self.intrinsics.i32_consts[4],
8570 self.intrinsics.i32_consts[5],
8571 self.intrinsics.i32_consts[6],
8572 self.intrinsics.i32_consts[7],
8573 ]),
8574 "",
8575 ));
8576 let res = err!(
8577 self.builder
8578 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8579 );
8580 let res = err!(
8581 self.builder
8582 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8583 );
8584 self.state.push1(res);
8585 }
8586 Operator::I64x2ExtendLowI32x4U
8587 | Operator::I64x2ExtendLowI32x4S
8588 | Operator::I64x2ExtendHighI32x4U
8589 | Operator::I64x2ExtendHighI32x4S => {
8590 let extend = match op {
8591 Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8592 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8593 }
8594 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8595 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8596 }
8597 _ => unreachable!("Unhandled inner case"),
8598 };
8599 let indices = match op {
8600 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8601 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8602 }
8603 Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8604 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8605 }
8606 _ => unreachable!("Unhandled inner case"),
8607 };
8608 let (v, i) = self.state.pop1_extra()?;
8609 let (v, _) = self.v128_into_i32x4(v, i)?;
8610 let low = err!(self.builder.build_shuffle_vector(
8611 v,
8612 v.get_type().get_undef(),
8613 VectorType::const_vector(&indices),
8614 "",
8615 ));
8616 let res = err!(extend(self, low));
8617 let res = err!(
8618 self.builder
8619 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8620 );
8621 self.state.push1(res);
8622 }
8623 Operator::I8x16NarrowI16x8S => {
8624 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8625 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8626 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8627 let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8628 let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8629 let min = VectorType::const_vector(&[min; 8]);
8630 let max = VectorType::const_vector(&[max; 8]);
8631 let apply_min_clamp_v1 =
8632 err!(
8633 self.builder
8634 .build_int_compare(IntPredicate::SLT, v1, min, "")
8635 );
8636 let apply_max_clamp_v1 =
8637 err!(
8638 self.builder
8639 .build_int_compare(IntPredicate::SGT, v1, max, "")
8640 );
8641 let apply_min_clamp_v2 =
8642 err!(
8643 self.builder
8644 .build_int_compare(IntPredicate::SLT, v2, min, "")
8645 );
8646 let apply_max_clamp_v2 =
8647 err!(
8648 self.builder
8649 .build_int_compare(IntPredicate::SGT, v2, max, "")
8650 );
8651 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8652 .into_vector_value();
8653 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8654 .into_vector_value();
8655 let v1 = err!(self.builder.build_int_truncate(
8656 v1,
8657 self.intrinsics.i8_ty.vec_type(8),
8658 ""
8659 ));
8660 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8661 .into_vector_value();
8662 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8663 .into_vector_value();
8664 let v2 = err!(self.builder.build_int_truncate(
8665 v2,
8666 self.intrinsics.i8_ty.vec_type(8),
8667 ""
8668 ));
8669 let res = err!(self.builder.build_shuffle_vector(
8670 v1,
8671 v2,
8672 VectorType::const_vector(&[
8673 self.intrinsics.i32_consts[0],
8674 self.intrinsics.i32_consts[1],
8675 self.intrinsics.i32_consts[2],
8676 self.intrinsics.i32_consts[3],
8677 self.intrinsics.i32_consts[4],
8678 self.intrinsics.i32_consts[5],
8679 self.intrinsics.i32_consts[6],
8680 self.intrinsics.i32_consts[7],
8681 self.intrinsics.i32_consts[8],
8682 self.intrinsics.i32_consts[9],
8683 self.intrinsics.i32_consts[10],
8684 self.intrinsics.i32_consts[11],
8685 self.intrinsics.i32_consts[12],
8686 self.intrinsics.i32_consts[13],
8687 self.intrinsics.i32_consts[14],
8688 self.intrinsics.i32_consts[15],
8689 ]),
8690 "",
8691 ));
8692 let res = err!(
8693 self.builder
8694 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8695 );
8696 self.state.push1(res);
8697 }
8698 Operator::I8x16NarrowI16x8U => {
8699 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8700 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8701 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8702 let min = self.intrinsics.i16x8_ty.const_zero();
8703 let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8704 let max = VectorType::const_vector(&[max; 8]);
8705 let apply_min_clamp_v1 =
8706 err!(
8707 self.builder
8708 .build_int_compare(IntPredicate::SLT, v1, min, "")
8709 );
8710 let apply_max_clamp_v1 =
8711 err!(
8712 self.builder
8713 .build_int_compare(IntPredicate::SGT, v1, max, "")
8714 );
8715 let apply_min_clamp_v2 =
8716 err!(
8717 self.builder
8718 .build_int_compare(IntPredicate::SLT, v2, min, "")
8719 );
8720 let apply_max_clamp_v2 =
8721 err!(
8722 self.builder
8723 .build_int_compare(IntPredicate::SGT, v2, max, "")
8724 );
8725 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8726 .into_vector_value();
8727 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8728 .into_vector_value();
8729 let v1 = err!(self.builder.build_int_truncate(
8730 v1,
8731 self.intrinsics.i8_ty.vec_type(8),
8732 ""
8733 ));
8734 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8735 .into_vector_value();
8736 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8737 .into_vector_value();
8738 let v2 = err!(self.builder.build_int_truncate(
8739 v2,
8740 self.intrinsics.i8_ty.vec_type(8),
8741 ""
8742 ));
8743 let res = err!(self.builder.build_shuffle_vector(
8744 v1,
8745 v2,
8746 VectorType::const_vector(&[
8747 self.intrinsics.i32_consts[0],
8748 self.intrinsics.i32_consts[1],
8749 self.intrinsics.i32_consts[2],
8750 self.intrinsics.i32_consts[3],
8751 self.intrinsics.i32_consts[4],
8752 self.intrinsics.i32_consts[5],
8753 self.intrinsics.i32_consts[6],
8754 self.intrinsics.i32_consts[7],
8755 self.intrinsics.i32_consts[8],
8756 self.intrinsics.i32_consts[9],
8757 self.intrinsics.i32_consts[10],
8758 self.intrinsics.i32_consts[11],
8759 self.intrinsics.i32_consts[12],
8760 self.intrinsics.i32_consts[13],
8761 self.intrinsics.i32_consts[14],
8762 self.intrinsics.i32_consts[15],
8763 ]),
8764 "",
8765 ));
8766 let res = err!(
8767 self.builder
8768 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8769 );
8770 self.state.push1(res);
8771 }
8772 Operator::I16x8NarrowI32x4S => {
8773 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8774 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8775 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8776 let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8777 let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8778 let min = VectorType::const_vector(&[min; 4]);
8779 let max = VectorType::const_vector(&[max; 4]);
8780 let apply_min_clamp_v1 =
8781 err!(
8782 self.builder
8783 .build_int_compare(IntPredicate::SLT, v1, min, "")
8784 );
8785 let apply_max_clamp_v1 =
8786 err!(
8787 self.builder
8788 .build_int_compare(IntPredicate::SGT, v1, max, "")
8789 );
8790 let apply_min_clamp_v2 =
8791 err!(
8792 self.builder
8793 .build_int_compare(IntPredicate::SLT, v2, min, "")
8794 );
8795 let apply_max_clamp_v2 =
8796 err!(
8797 self.builder
8798 .build_int_compare(IntPredicate::SGT, v2, max, "")
8799 );
8800 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8801 .into_vector_value();
8802 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8803 .into_vector_value();
8804 let v1 = err!(self.builder.build_int_truncate(
8805 v1,
8806 self.intrinsics.i16_ty.vec_type(4),
8807 ""
8808 ));
8809 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8810 .into_vector_value();
8811 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8812 .into_vector_value();
8813 let v2 = err!(self.builder.build_int_truncate(
8814 v2,
8815 self.intrinsics.i16_ty.vec_type(4),
8816 ""
8817 ));
8818 let res = err!(self.builder.build_shuffle_vector(
8819 v1,
8820 v2,
8821 VectorType::const_vector(&[
8822 self.intrinsics.i32_consts[0],
8823 self.intrinsics.i32_consts[1],
8824 self.intrinsics.i32_consts[2],
8825 self.intrinsics.i32_consts[3],
8826 self.intrinsics.i32_consts[4],
8827 self.intrinsics.i32_consts[5],
8828 self.intrinsics.i32_consts[6],
8829 self.intrinsics.i32_consts[7],
8830 ]),
8831 "",
8832 ));
8833 let res = err!(
8834 self.builder
8835 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8836 );
8837 self.state.push1(res);
8838 }
8839 Operator::I16x8NarrowI32x4U => {
8840 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8841 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8842 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8843 let min = self.intrinsics.i32x4_ty.const_zero();
8844 let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8845 let max = VectorType::const_vector(&[max; 4]);
8846 let apply_min_clamp_v1 =
8847 err!(
8848 self.builder
8849 .build_int_compare(IntPredicate::SLT, v1, min, "")
8850 );
8851 let apply_max_clamp_v1 =
8852 err!(
8853 self.builder
8854 .build_int_compare(IntPredicate::SGT, v1, max, "")
8855 );
8856 let apply_min_clamp_v2 =
8857 err!(
8858 self.builder
8859 .build_int_compare(IntPredicate::SLT, v2, min, "")
8860 );
8861 let apply_max_clamp_v2 =
8862 err!(
8863 self.builder
8864 .build_int_compare(IntPredicate::SGT, v2, max, "")
8865 );
8866 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8867 .into_vector_value();
8868 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8869 .into_vector_value();
8870 let v1 = err!(self.builder.build_int_truncate(
8871 v1,
8872 self.intrinsics.i16_ty.vec_type(4),
8873 ""
8874 ));
8875 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8876 .into_vector_value();
8877 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8878 .into_vector_value();
8879 let v2 = err!(self.builder.build_int_truncate(
8880 v2,
8881 self.intrinsics.i16_ty.vec_type(4),
8882 ""
8883 ));
8884 let res = err!(self.builder.build_shuffle_vector(
8885 v1,
8886 v2,
8887 VectorType::const_vector(&[
8888 self.intrinsics.i32_consts[0],
8889 self.intrinsics.i32_consts[1],
8890 self.intrinsics.i32_consts[2],
8891 self.intrinsics.i32_consts[3],
8892 self.intrinsics.i32_consts[4],
8893 self.intrinsics.i32_consts[5],
8894 self.intrinsics.i32_consts[6],
8895 self.intrinsics.i32_consts[7],
8896 ]),
8897 "",
8898 ));
8899 let res = err!(
8900 self.builder
8901 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8902 );
8903 self.state.push1(res);
8904 }
8905 Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8906 let (v, i) = self.state.pop1_extra()?;
8907 let (v, _) = self.v128_into_f32x4(v, i)?;
8908 let res = self
8909 .build_call_with_param_attributes(
8910 self.intrinsics.x86_64.cvttps2dq,
8911 &[v.into()],
8912 "",
8913 )?
8914 .try_as_basic_value()
8915 .unwrap_basic();
8916 let res = err!(
8917 self.builder
8918 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8919 );
8920 self.state.push1(res);
8921 }
8922 Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
8923 let (v, i) = self.state.pop1_extra()?;
8924 let v = self.apply_pending_canonicalization(v, i)?;
8925 let v = v.into_int_value();
8926 let res = self.trunc_sat_into_int(
8927 self.intrinsics.f32x4_ty,
8928 self.intrinsics.i32x4_ty,
8929 LEF32_GEQ_I32_MIN,
8930 GEF32_LEQ_I32_MAX,
8931 i32::MIN as u64,
8932 i32::MAX as u64,
8933 v,
8934 )?;
8935 self.state.push1(res);
8936 }
8937 Operator::I32x4RelaxedTruncF32x4U
8938 if self.cpu_features.contains(CpuFeature::AVX512F)
8939 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8940 {
8941 let (v, i) = self.state.pop1_extra()?;
8942 let (v, _) = self.v128_into_f32x4(v, i)?;
8943 let res = self
8944 .build_call_with_param_attributes(
8945 self.intrinsics.x86_64.cvtps2udq128,
8946 &[
8947 v.into(),
8948 self.intrinsics.i32x4_ty.const_zero().into(),
8949 self.intrinsics.i8_ty.const_int(0xff, false).into(),
8950 ],
8951 "",
8952 )?
8953 .try_as_basic_value()
8954 .unwrap_basic();
8955 let res = err!(
8956 self.builder
8957 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8958 );
8959 self.state.push1(res);
8960 }
8961 Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
8962 let (v, i) = self.state.pop1_extra()?;
8963 let v = self.apply_pending_canonicalization(v, i)?;
8964 let v = v.into_int_value();
8965 let res = self.trunc_sat_into_int(
8966 self.intrinsics.f32x4_ty,
8967 self.intrinsics.i32x4_ty,
8968 LEF32_GEQ_U32_MIN,
8969 GEF32_LEQ_U32_MAX,
8970 u32::MIN as u64,
8971 u32::MAX as u64,
8972 v,
8973 )?;
8974 self.state.push1(res);
8975 }
8976 Operator::I32x4RelaxedTruncF64x2SZero
8977 if self.cpu_features.contains(CpuFeature::SSE2) =>
8978 {
8979 let (v, i) = self.state.pop1_extra()?;
8980 let (v, _) = self.v128_into_f64x2(v, i)?;
8981 let res = self
8982 .build_call_with_param_attributes(
8983 self.intrinsics.x86_64.cvtpd2dq,
8984 &[v.into()],
8985 "",
8986 )?
8987 .try_as_basic_value()
8988 .unwrap_basic();
8989 let res = err!(
8990 self.builder
8991 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8992 );
8993 self.state.push1(res);
8994 }
8995 Operator::I32x4RelaxedTruncF64x2UZero
8996 if self.cpu_features.contains(CpuFeature::AVX512F)
8997 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8998 {
8999 let (v, i) = self.state.pop1_extra()?;
9000 let (v, _) = self.v128_into_f64x2(v, i)?;
9001 let res = self
9002 .build_call_with_param_attributes(
9003 self.intrinsics.x86_64.cvtpd2udq128,
9004 &[
9005 v.into(),
9006 self.intrinsics.i32x4_ty.const_zero().into(),
9007 self.intrinsics.i8_ty.const_int(0xff, false).into(),
9008 ],
9009 "",
9010 )?
9011 .try_as_basic_value()
9012 .unwrap_basic();
9013 let res = err!(
9014 self.builder
9015 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9016 );
9017 self.state.push1(res);
9018 }
9019 Operator::I32x4TruncSatF64x2SZero
9020 | Operator::I32x4TruncSatF64x2UZero
9021 | Operator::I32x4RelaxedTruncF64x2SZero
9022 | Operator::I32x4RelaxedTruncF64x2UZero => {
9023 let ((min, max), (cmp_min, cmp_max)) = match op {
9024 Operator::I32x4TruncSatF64x2SZero => (
9025 (i32::MIN as u64, i32::MAX as u64),
9026 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9027 ),
9028 Operator::I32x4TruncSatF64x2UZero => (
9029 (u32::MIN as u64, u32::MAX as u64),
9030 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9031 ),
9032 Operator::I32x4RelaxedTruncF64x2SZero => (
9033 (i32::MIN as u64, i32::MAX as u64),
9034 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9035 ),
9036 Operator::I32x4RelaxedTruncF64x2UZero => (
9037 (u32::MIN as u64, u32::MAX as u64),
9038 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9039 ),
9040 _ => unreachable!("Unhandled internal variant"),
9041 };
9042 let (v, i) = self.state.pop1_extra()?;
9043 let v = self.apply_pending_canonicalization(v, i)?;
9044 let v = v.into_int_value();
9045 let res = self.trunc_sat(
9046 self.intrinsics.f64x2_ty,
9047 self.intrinsics.i32_ty.vec_type(2),
9048 cmp_min,
9049 cmp_max,
9050 min,
9051 max,
9052 v,
9053 )?;
9054
9055 let zero = self.intrinsics.i32_consts[0];
9056 let zeros = VectorType::const_vector(&[zero; 2]);
9057 let res = err!(self.builder.build_shuffle_vector(
9058 res,
9059 zeros,
9060 VectorType::const_vector(&[
9061 self.intrinsics.i32_consts[0],
9062 self.intrinsics.i32_consts[1],
9063 self.intrinsics.i32_consts[2],
9064 self.intrinsics.i32_consts[3],
9065 ]),
9066 "",
9067 ));
9068 let res = err!(
9069 self.builder
9070 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9071 );
9072 self.state.push1(res);
9073 }
9074 Operator::I32TruncF32S => {
9105 let v1 = self.state.pop1()?.into_float_value();
9106 self.trap_if_not_representable_as_int(
9107 0xcf000000, 0x4effffff, v1,
9110 )?;
9111 let res = err!(self.builder.build_float_to_signed_int(
9112 v1,
9113 self.intrinsics.i32_ty,
9114 ""
9115 ));
9116 self.state.push1(res);
9117 }
9118 Operator::I32TruncF64S => {
9119 let v1 = self.state.pop1()?.into_float_value();
9120 self.trap_if_not_representable_as_int(
9121 0xc1e00000001fffff, 0x41dfffffffffffff, v1,
9124 )?;
9125 let res = err!(self.builder.build_float_to_signed_int(
9126 v1,
9127 self.intrinsics.i32_ty,
9128 ""
9129 ));
9130 self.state.push1(res);
9131 }
9132 Operator::I32TruncSatF32S => {
9133 let (v, i) = self.state.pop1_extra()?;
9134 let v = self.apply_pending_canonicalization(v, i)?;
9135 let v = v.into_float_value();
9136 let res = self.trunc_sat_scalar(
9137 self.intrinsics.i32_ty,
9138 LEF32_GEQ_I32_MIN,
9139 GEF32_LEQ_I32_MAX,
9140 i32::MIN as u32 as u64,
9141 i32::MAX as u32 as u64,
9142 v,
9143 )?;
9144 self.state.push1(res);
9145 }
9146 Operator::I32TruncSatF64S => {
9147 let (v, i) = self.state.pop1_extra()?;
9148 let v = self.apply_pending_canonicalization(v, i)?;
9149 let v = v.into_float_value();
9150 let res = self.trunc_sat_scalar(
9151 self.intrinsics.i32_ty,
9152 LEF64_GEQ_I32_MIN,
9153 GEF64_LEQ_I32_MAX,
9154 i32::MIN as u64,
9155 i32::MAX as u64,
9156 v,
9157 )?;
9158 self.state.push1(res);
9159 }
9160 Operator::I64TruncF32S => {
9161 let v1 = self.state.pop1()?.into_float_value();
9162 self.trap_if_not_representable_as_int(
9163 0xdf000000, 0x5effffff, v1,
9166 )?;
9167 let res = err!(self.builder.build_float_to_signed_int(
9168 v1,
9169 self.intrinsics.i64_ty,
9170 ""
9171 ));
9172 self.state.push1(res);
9173 }
9174 Operator::I64TruncF64S => {
9175 let v1 = self.state.pop1()?.into_float_value();
9176 self.trap_if_not_representable_as_int(
9177 0xc3e0000000000000, 0x43dfffffffffffff, v1,
9180 )?;
9181 let res = err!(self.builder.build_float_to_signed_int(
9182 v1,
9183 self.intrinsics.i64_ty,
9184 ""
9185 ));
9186 self.state.push1(res);
9187 }
9188 Operator::I64TruncSatF32S => {
9189 let (v, i) = self.state.pop1_extra()?;
9190 let v = self.apply_pending_canonicalization(v, i)?;
9191 let v = v.into_float_value();
9192 let res = self.trunc_sat_scalar(
9193 self.intrinsics.i64_ty,
9194 LEF32_GEQ_I64_MIN,
9195 GEF32_LEQ_I64_MAX,
9196 i64::MIN as u64,
9197 i64::MAX as u64,
9198 v,
9199 )?;
9200 self.state.push1(res);
9201 }
9202 Operator::I64TruncSatF64S => {
9203 let (v, i) = self.state.pop1_extra()?;
9204 let v = self.apply_pending_canonicalization(v, i)?;
9205 let v = v.into_float_value();
9206 let res = self.trunc_sat_scalar(
9207 self.intrinsics.i64_ty,
9208 LEF64_GEQ_I64_MIN,
9209 GEF64_LEQ_I64_MAX,
9210 i64::MIN as u64,
9211 i64::MAX as u64,
9212 v,
9213 )?;
9214 self.state.push1(res);
9215 }
9216 Operator::I32TruncF32U => {
9217 let v1 = self.state.pop1()?.into_float_value();
9218 self.trap_if_not_representable_as_int(
9219 0xbf7fffff, 0x4f7fffff, v1,
9222 )?;
9223 let res = err!(self.builder.build_float_to_unsigned_int(
9224 v1,
9225 self.intrinsics.i32_ty,
9226 ""
9227 ));
9228 self.state.push1(res);
9229 }
9230 Operator::I32TruncF64U => {
9231 let v1 = self.state.pop1()?.into_float_value();
9232 self.trap_if_not_representable_as_int(
9233 0xbfefffffffffffff, 0x41efffffffffffff, v1,
9236 )?;
9237 let res = err!(self.builder.build_float_to_unsigned_int(
9238 v1,
9239 self.intrinsics.i32_ty,
9240 ""
9241 ));
9242 self.state.push1(res);
9243 }
9244 Operator::I32TruncSatF32U => {
9245 let (v, i) = self.state.pop1_extra()?;
9246 let v = self.apply_pending_canonicalization(v, i)?;
9247 let v = v.into_float_value();
9248 let res = self.trunc_sat_scalar(
9249 self.intrinsics.i32_ty,
9250 LEF32_GEQ_U32_MIN,
9251 GEF32_LEQ_U32_MAX,
9252 u32::MIN as u64,
9253 u32::MAX as u64,
9254 v,
9255 )?;
9256 self.state.push1(res);
9257 }
9258 Operator::I32TruncSatF64U => {
9259 let (v, i) = self.state.pop1_extra()?;
9260 let v = self.apply_pending_canonicalization(v, i)?;
9261 let v = v.into_float_value();
9262 let res = self.trunc_sat_scalar(
9263 self.intrinsics.i32_ty,
9264 LEF64_GEQ_U32_MIN,
9265 GEF64_LEQ_U32_MAX,
9266 u32::MIN as u64,
9267 u32::MAX as u64,
9268 v,
9269 )?;
9270 self.state.push1(res);
9271 }
9272 Operator::I64TruncF32U => {
9273 let v1 = self.state.pop1()?.into_float_value();
9274 self.trap_if_not_representable_as_int(
9275 0xbf7fffff, 0x5f7fffff, v1,
9278 )?;
9279 let res = err!(self.builder.build_float_to_unsigned_int(
9280 v1,
9281 self.intrinsics.i64_ty,
9282 ""
9283 ));
9284 self.state.push1(res);
9285 }
9286 Operator::I64TruncF64U => {
9287 let v1 = self.state.pop1()?.into_float_value();
9288 self.trap_if_not_representable_as_int(
9289 0xbfefffffffffffff, 0x43efffffffffffff, v1,
9292 )?;
9293 let res = err!(self.builder.build_float_to_unsigned_int(
9294 v1,
9295 self.intrinsics.i64_ty,
9296 ""
9297 ));
9298 self.state.push1(res);
9299 }
9300 Operator::I64TruncSatF32U => {
9301 let (v, i) = self.state.pop1_extra()?;
9302 let v = self.apply_pending_canonicalization(v, i)?;
9303 let v = v.into_float_value();
9304 let res = self.trunc_sat_scalar(
9305 self.intrinsics.i64_ty,
9306 LEF32_GEQ_U64_MIN,
9307 GEF32_LEQ_U64_MAX,
9308 u64::MIN,
9309 u64::MAX,
9310 v,
9311 )?;
9312 self.state.push1(res);
9313 }
9314 Operator::I64TruncSatF64U => {
9315 let (v, i) = self.state.pop1_extra()?;
9316 let v = self.apply_pending_canonicalization(v, i)?;
9317 let v = v.into_float_value();
9318 let res = self.trunc_sat_scalar(
9319 self.intrinsics.i64_ty,
9320 LEF64_GEQ_U64_MIN,
9321 GEF64_LEQ_U64_MAX,
9322 u64::MIN,
9323 u64::MAX,
9324 v,
9325 )?;
9326 self.state.push1(res);
9327 }
9328 Operator::F32DemoteF64 => {
9329 let v = self.state.pop1()?;
9330 let v = v.into_float_value();
9331 let res = self
9332 .build_call_with_param_attributes(
9333 self.intrinsics.fptrunc_f64,
9334 &[
9335 v.into(),
9336 self.intrinsics.fp_rounding_md,
9337 self.intrinsics.fp_exception_md,
9338 ],
9339 "",
9340 )?
9341 .try_as_basic_value()
9342 .unwrap_basic();
9343 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9344 }
9345 Operator::F64PromoteF32 => {
9346 let v = self.state.pop1()?;
9347 let v = v.into_float_value();
9348 let res = self
9349 .build_call_with_param_attributes(
9350 self.intrinsics.fpext_f32,
9351 &[v.into(), self.intrinsics.fp_exception_md],
9352 "",
9353 )?
9354 .try_as_basic_value()
9355 .unwrap_basic();
9356 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9357 }
9358 Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
9359 let (v, i) = self.state.pop1_extra()?;
9360 let v = self.apply_pending_canonicalization(v, i)?;
9361 let v = v.into_int_value();
9362 let res = err!(self.builder.build_signed_int_to_float(
9363 v,
9364 self.intrinsics.f32_ty,
9365 ""
9366 ));
9367 self.state.push1(res);
9368 }
9369 Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
9370 let (v, i) = self.state.pop1_extra()?;
9371 let v = self.apply_pending_canonicalization(v, i)?;
9372 let v = v.into_int_value();
9373 let res = err!(self.builder.build_signed_int_to_float(
9374 v,
9375 self.intrinsics.f64_ty,
9376 ""
9377 ));
9378 self.state.push1(res);
9379 }
9380 Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
9381 let (v, i) = self.state.pop1_extra()?;
9382 let v = self.apply_pending_canonicalization(v, i)?;
9383 let v = v.into_int_value();
9384 let res = err!(self.builder.build_unsigned_int_to_float(
9385 v,
9386 self.intrinsics.f32_ty,
9387 ""
9388 ));
9389 self.state.push1(res);
9390 }
9391 Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
9392 let (v, i) = self.state.pop1_extra()?;
9393 let v = self.apply_pending_canonicalization(v, i)?;
9394 let v = v.into_int_value();
9395 let res = err!(self.builder.build_unsigned_int_to_float(
9396 v,
9397 self.intrinsics.f64_ty,
9398 ""
9399 ));
9400 self.state.push1(res);
9401 }
9402 Operator::F32x4ConvertI32x4S => {
9403 let v = self.state.pop1()?;
9404 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9405 .into_vector_value();
9406 let res = err!(self.builder.build_signed_int_to_float(
9407 v,
9408 self.intrinsics.f32x4_ty,
9409 ""
9410 ));
9411 let res = err!(
9412 self.builder
9413 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9414 );
9415 self.state.push1(res);
9416 }
9417 Operator::F32x4ConvertI32x4U => {
9418 let v = self.state.pop1()?;
9419 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9420 .into_vector_value();
9421 let res = err!(self.builder.build_unsigned_int_to_float(
9422 v,
9423 self.intrinsics.f32x4_ty,
9424 ""
9425 ));
9426 let res = err!(
9427 self.builder
9428 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9429 );
9430 self.state.push1(res);
9431 }
9432 Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
9433 let extend = match op {
9434 Operator::F64x2ConvertLowI32x4U => {
9435 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
9436 }
9437 Operator::F64x2ConvertLowI32x4S => {
9438 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
9439 }
9440 _ => unreachable!("Unhandled inner case"),
9441 };
9442 let (v, i) = self.state.pop1_extra()?;
9443 let (v, _) = self.v128_into_i32x4(v, i)?;
9444 let low = err!(self.builder.build_shuffle_vector(
9445 v,
9446 v.get_type().get_undef(),
9447 VectorType::const_vector(&[
9448 self.intrinsics.i32_consts[0],
9449 self.intrinsics.i32_consts[1],
9450 ]),
9451 "",
9452 ));
9453 let res = err!(extend(self, low));
9454 let res = err!(self.builder.build_signed_int_to_float(
9455 res,
9456 self.intrinsics.f64x2_ty,
9457 ""
9458 ));
9459 let res = err!(
9460 self.builder
9461 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9462 );
9463 self.state.push1(res);
9464 }
9465 Operator::F64x2PromoteLowF32x4 => {
9466 let (v, i) = self.state.pop1_extra()?;
9467 let (v, _) = self.v128_into_f32x4(v, i)?;
9468 let low = err!(self.builder.build_shuffle_vector(
9469 v,
9470 v.get_type().get_undef(),
9471 VectorType::const_vector(&[
9472 self.intrinsics.i32_consts[0],
9473 self.intrinsics.i32_consts[1],
9474 ]),
9475 "",
9476 ));
9477 let res = err!(
9478 self.builder
9479 .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9480 );
9481 let res = err!(
9482 self.builder
9483 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9484 );
9485 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9486 }
9487 Operator::F32x4DemoteF64x2Zero => {
9488 let (v, i) = self.state.pop1_extra()?;
9489 let (v, _) = self.v128_into_f64x2(v, i)?;
9490 let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9491 let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9492 let zeros = f32x2_ty.const_zero();
9493 let res = err!(self.builder.build_shuffle_vector(
9494 res,
9495 zeros,
9496 VectorType::const_vector(&[
9497 self.intrinsics.i32_consts[0],
9498 self.intrinsics.i32_consts[1],
9499 self.intrinsics.i32_consts[2],
9500 self.intrinsics.i32_consts[3],
9501 ]),
9502 "",
9503 ));
9504 let res = err!(
9505 self.builder
9506 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9507 );
9508 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9509 }
9510 Operator::I32ReinterpretF32 => {
9535 let (v, i) = self.state.pop1_extra()?;
9536 let v = self.apply_pending_canonicalization(v, i)?;
9537 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9538 self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9539 }
9540 Operator::I64ReinterpretF64 => {
9541 let (v, i) = self.state.pop1_extra()?;
9542 let v = self.apply_pending_canonicalization(v, i)?;
9543 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9544 self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9545 }
9546 Operator::F32ReinterpretI32 => {
9547 let (v, i) = self.state.pop1_extra()?;
9548 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9549 self.state.push1_extra(ret, i);
9550 }
9551 Operator::F64ReinterpretI64 => {
9552 let (v, i) = self.state.pop1_extra()?;
9553 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9554 self.state.push1_extra(ret, i);
9555 }
9556 _ => unreachable!(),
9557 }
9558 Ok(())
9559 }
9560
9561 fn translate_sign_extension_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9564 match op {
9565 Operator::I32Extend8S => {
9566 let value = self.state.pop1()?.into_int_value();
9567 let narrow_value = err!(self.builder.build_int_truncate(
9568 value,
9569 self.intrinsics.i8_ty,
9570 ""
9571 ));
9572 let extended_value = err!(self.builder.build_int_s_extend(
9573 narrow_value,
9574 self.intrinsics.i32_ty,
9575 ""
9576 ));
9577 self.state.push1(extended_value);
9578 }
9579 Operator::I32Extend16S => {
9580 let value = self.state.pop1()?.into_int_value();
9581 let narrow_value = err!(self.builder.build_int_truncate(
9582 value,
9583 self.intrinsics.i16_ty,
9584 ""
9585 ));
9586 let extended_value = err!(self.builder.build_int_s_extend(
9587 narrow_value,
9588 self.intrinsics.i32_ty,
9589 ""
9590 ));
9591 self.state.push1(extended_value);
9592 }
9593 Operator::I64Extend8S => {
9594 let value = self.state.pop1()?.into_int_value();
9595 let narrow_value = err!(self.builder.build_int_truncate(
9596 value,
9597 self.intrinsics.i8_ty,
9598 ""
9599 ));
9600 let extended_value = err!(self.builder.build_int_s_extend(
9601 narrow_value,
9602 self.intrinsics.i64_ty,
9603 ""
9604 ));
9605 self.state.push1(extended_value);
9606 }
9607 Operator::I64Extend16S => {
9608 let value = self.state.pop1()?.into_int_value();
9609 let narrow_value = err!(self.builder.build_int_truncate(
9610 value,
9611 self.intrinsics.i16_ty,
9612 ""
9613 ));
9614 let extended_value = err!(self.builder.build_int_s_extend(
9615 narrow_value,
9616 self.intrinsics.i64_ty,
9617 ""
9618 ));
9619 self.state.push1(extended_value);
9620 }
9621 Operator::I64Extend32S => {
9622 let value = self.state.pop1()?.into_int_value();
9623 let narrow_value = err!(self.builder.build_int_truncate(
9624 value,
9625 self.intrinsics.i32_ty,
9626 ""
9627 ));
9628 let extended_value = err!(self.builder.build_int_s_extend(
9629 narrow_value,
9630 self.intrinsics.i64_ty,
9631 ""
9632 ));
9633 self.state.push1(extended_value);
9634 }
9635 _ => unreachable!(),
9636 }
9637 Ok(())
9638 }
9639
9640 fn translate_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9643 let vmctx = &self.ctx.basic().into_pointer_value();
9644
9645 match op {
9646 Operator::I32Load { ref memarg } => {
9647 let offset = self.state.pop1()?.into_int_value();
9648 let result =
9649 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9650 self.state.push1(result);
9651 }
9652 Operator::I64Load { ref memarg } => {
9653 let offset = self.state.pop1()?.into_int_value();
9654 let result =
9655 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9656 self.state.push1(result);
9657 }
9658 Operator::F32Load { ref memarg } => {
9659 let offset = self.state.pop1()?.into_int_value();
9660 let result =
9661 self.build_annotated_load(self.intrinsics.f32_ty, offset, memarg, 1)?;
9662 self.state.push1(result);
9663 }
9664 Operator::F64Load { ref memarg } => {
9665 let offset = self.state.pop1()?.into_int_value();
9666 let result =
9667 self.build_annotated_load(self.intrinsics.f64_ty, offset, memarg, 1)?;
9668 self.state.push1(result);
9669 }
9670 Operator::V128Load { ref memarg } => {
9671 let offset = self.state.pop1()?.into_int_value();
9672 let result =
9673 self.build_annotated_load(self.intrinsics.i128_ty, offset, memarg, 1)?;
9674 self.state.push1(result);
9675 }
9676 Operator::V128Load8Lane { ref memarg, lane } => {
9677 let (v, i) = self.state.pop1_extra()?;
9678 let (v, _i) = self.v128_into_i8x16(v, i)?;
9679 let offset = self.state.pop1()?.into_int_value();
9680 let element =
9681 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9682 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9683 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9684 let res = err!(
9685 self.builder
9686 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9687 );
9688 self.state.push1(res);
9689 }
9690 Operator::V128Load16Lane { ref memarg, lane } => {
9691 let (v, i) = self.state.pop1_extra()?;
9692 let (v, i) = self.v128_into_i16x8(v, i)?;
9693 let offset = self.state.pop1()?.into_int_value();
9694 let element =
9695 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9696 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9697 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9698 let res = err!(
9699 self.builder
9700 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9701 );
9702 self.state.push1_extra(res, i);
9703 }
9704 Operator::V128Load32Lane { ref memarg, lane } => {
9705 let (v, i) = self.state.pop1_extra()?;
9706 let (v, i) = self.v128_into_i32x4(v, i)?;
9707 let offset = self.state.pop1()?.into_int_value();
9708 let element =
9709 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9710 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9711 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9712 let res = err!(
9713 self.builder
9714 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9715 );
9716 self.state.push1_extra(res, i);
9717 }
9718 Operator::V128Load64Lane { ref memarg, lane } => {
9719 let (v, i) = self.state.pop1_extra()?;
9720 let (v, i) = self.v128_into_i64x2(v, i)?;
9721 let offset = self.state.pop1()?.into_int_value();
9722 let element =
9723 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9724 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9725 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9726 let res = err!(
9727 self.builder
9728 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9729 );
9730 self.state.push1_extra(res, i);
9731 }
9732
9733 Operator::I32Store { ref memarg } => {
9734 let value = self.state.pop1()?;
9735 let offset = self.state.pop1()?.into_int_value();
9736 self.build_annotated_store(self.intrinsics.i32_ty, offset, value, memarg, 1)?;
9737 }
9738 Operator::I64Store { ref memarg } => {
9739 let value = self.state.pop1()?;
9740 let offset = self.state.pop1()?.into_int_value();
9741 self.build_annotated_store(self.intrinsics.i64_ty, offset, value, memarg, 1)?;
9742 }
9743 Operator::F32Store { ref memarg } => {
9744 let (v, i) = self.state.pop1_extra()?;
9745 let v = self.apply_pending_canonicalization(v, i)?;
9746 let offset = self.state.pop1()?.into_int_value();
9747 self.build_annotated_store(self.intrinsics.f32_ty, offset, v, memarg, 1)?;
9748 }
9749 Operator::F64Store { ref memarg } => {
9750 let (v, i) = self.state.pop1_extra()?;
9751 let v = self.apply_pending_canonicalization(v, i)?;
9752 let offset = self.state.pop1()?.into_int_value();
9753 self.build_annotated_store(self.intrinsics.f64_ty, offset, v, memarg, 1)?;
9754 }
9755 Operator::V128Store { ref memarg } => {
9756 let (v, i) = self.state.pop1_extra()?;
9757 let v = self.apply_pending_canonicalization(v, i)?;
9758 let offset = self.state.pop1()?.into_int_value();
9759 self.build_annotated_store(self.intrinsics.i128_ty, offset, v, memarg, 1)?;
9760 }
9761 Operator::V128Store8Lane { ref memarg, lane } => {
9762 let (v, i) = self.state.pop1_extra()?;
9763 let (v, _i) = self.v128_into_i8x16(v, i)?;
9764 let offset = self.state.pop1()?.into_int_value();
9765 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9766 let val = err!(self.builder.build_extract_element(v, idx, ""));
9767 self.build_annotated_store(self.intrinsics.i8_ty, offset, val, memarg, 1)?;
9768 }
9769 Operator::V128Store16Lane { ref memarg, lane } => {
9770 let (v, i) = self.state.pop1_extra()?;
9771 let (v, _i) = self.v128_into_i16x8(v, i)?;
9772 let offset = self.state.pop1()?.into_int_value();
9773 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9774 let val = err!(self.builder.build_extract_element(v, idx, ""));
9775 self.build_annotated_store(self.intrinsics.i16_ty, offset, val, memarg, 1)?;
9776 }
9777 Operator::V128Store32Lane { ref memarg, lane } => {
9778 let (v, i) = self.state.pop1_extra()?;
9779 let (v, _i) = self.v128_into_i32x4(v, i)?;
9780 let offset = self.state.pop1()?.into_int_value();
9781 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9782 let val = err!(self.builder.build_extract_element(v, idx, ""));
9783 self.build_annotated_store(self.intrinsics.i32_ty, offset, val, memarg, 1)?;
9784 }
9785 Operator::V128Store64Lane { ref memarg, lane } => {
9786 let (v, i) = self.state.pop1_extra()?;
9787 let (v, _i) = self.v128_into_i64x2(v, i)?;
9788 let offset = self.state.pop1()?.into_int_value();
9789 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9790 let val = err!(self.builder.build_extract_element(v, idx, ""));
9791 self.build_annotated_store(self.intrinsics.i64_ty, offset, val, memarg, 1)?;
9792 }
9793 Operator::I32Load8S { ref memarg } => {
9794 let offset = self.state.pop1()?.into_int_value();
9795 let narrow_result =
9796 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9797 let result = err!(self.builder.build_int_s_extend(
9798 narrow_result.into_int_value(),
9799 self.intrinsics.i32_ty,
9800 "",
9801 ));
9802 self.state.push1(result);
9803 }
9804 Operator::I32Load16S { ref memarg } => {
9805 let offset = self.state.pop1()?.into_int_value();
9806 let narrow_result =
9807 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9808 let result = err!(self.builder.build_int_s_extend(
9809 narrow_result.into_int_value(),
9810 self.intrinsics.i32_ty,
9811 "",
9812 ));
9813 self.state.push1(result);
9814 }
9815 Operator::I64Load8S { ref memarg } => {
9816 let offset = self.state.pop1()?.into_int_value();
9817 let narrow_result =
9818 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9819 let result = err!(self.builder.build_int_s_extend(
9820 narrow_result.into_int_value(),
9821 self.intrinsics.i64_ty,
9822 ""
9823 ));
9824 self.state.push1(result);
9825 }
9826 Operator::I64Load16S { ref memarg } => {
9827 let offset = self.state.pop1()?.into_int_value();
9828 let narrow_result =
9829 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9830 let result = err!(self.builder.build_int_s_extend(
9831 narrow_result.into_int_value(),
9832 self.intrinsics.i64_ty,
9833 ""
9834 ));
9835 self.state.push1(result);
9836 }
9837 Operator::I64Load32S { ref memarg } => {
9838 let offset = self.state.pop1()?.into_int_value();
9839 let narrow_result =
9840 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9841 let result = err!(self.builder.build_int_s_extend(
9842 narrow_result.into_int_value(),
9843 self.intrinsics.i64_ty,
9844 "",
9845 ));
9846 self.state.push1(result);
9847 }
9848
9849 Operator::I32Load8U { ref memarg } => {
9850 let offset = self.state.pop1()?.into_int_value();
9851 let narrow_result =
9852 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9853 let result = err!(self.builder.build_int_z_extend(
9854 narrow_result.into_int_value(),
9855 self.intrinsics.i32_ty,
9856 "",
9857 ));
9858 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9859 }
9860 Operator::I32Load16U { ref memarg } => {
9861 let offset = self.state.pop1()?.into_int_value();
9862 let narrow_result =
9863 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9864 let result = err!(self.builder.build_int_z_extend(
9865 narrow_result.into_int_value(),
9866 self.intrinsics.i32_ty,
9867 "",
9868 ));
9869 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9870 }
9871 Operator::I64Load8U { ref memarg } => {
9872 let offset = self.state.pop1()?.into_int_value();
9873 let narrow_result =
9874 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9875 let result = err!(self.builder.build_int_z_extend(
9876 narrow_result.into_int_value(),
9877 self.intrinsics.i64_ty,
9878 "",
9879 ));
9880 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9881 }
9882 Operator::I64Load16U { ref memarg } => {
9883 let offset = self.state.pop1()?.into_int_value();
9884 let narrow_result =
9885 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9886 let result = err!(self.builder.build_int_z_extend(
9887 narrow_result.into_int_value(),
9888 self.intrinsics.i64_ty,
9889 "",
9890 ));
9891 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9892 }
9893 Operator::I64Load32U { ref memarg } => {
9894 let offset = self.state.pop1()?.into_int_value();
9895 let narrow_result =
9896 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9897 let result = err!(self.builder.build_int_z_extend(
9898 narrow_result.into_int_value(),
9899 self.intrinsics.i64_ty,
9900 "",
9901 ));
9902 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9903 }
9904
9905 Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9906 let value = self.state.pop1()?.into_int_value();
9907 let offset = self.state.pop1()?.into_int_value();
9908 let narrow_value = err!(self.builder.build_int_truncate(
9909 value,
9910 self.intrinsics.i8_ty,
9911 ""
9912 ));
9913 self.build_annotated_store(
9914 self.intrinsics.i8_ty,
9915 offset,
9916 narrow_value.into(),
9917 memarg,
9918 1,
9919 )?;
9920 }
9921 Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
9922 let value = self.state.pop1()?.into_int_value();
9923 let offset = self.state.pop1()?.into_int_value();
9924 let narrow_value = err!(self.builder.build_int_truncate(
9925 value,
9926 self.intrinsics.i16_ty,
9927 ""
9928 ));
9929 self.build_annotated_store(
9930 self.intrinsics.i16_ty,
9931 offset,
9932 narrow_value.into(),
9933 memarg,
9934 1,
9935 )?;
9936 }
9937 Operator::I64Store32 { ref memarg } => {
9938 let value = self.state.pop1()?.into_int_value();
9939 let offset = self.state.pop1()?.into_int_value();
9940 let narrow_value = err!(self.builder.build_int_truncate(
9941 value,
9942 self.intrinsics.i32_ty,
9943 ""
9944 ));
9945 self.build_annotated_store(
9946 self.intrinsics.i32_ty,
9947 offset,
9948 narrow_value.into(),
9949 memarg,
9950 1,
9951 )?;
9952 }
9953 Operator::I8x16Neg => {
9954 let (v, i) = self.state.pop1_extra()?;
9955 let (v, _) = self.v128_into_i8x16(v, i)?;
9956 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9957 let res = err!(
9958 self.builder
9959 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9960 );
9961 self.state.push1(res);
9962 }
9963 Operator::I16x8Neg => {
9964 let (v, i) = self.state.pop1_extra()?;
9965 let (v, _) = self.v128_into_i16x8(v, i)?;
9966 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9967 let res = err!(
9968 self.builder
9969 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9970 );
9971 self.state.push1(res);
9972 }
9973 Operator::I32x4Neg => {
9974 let (v, i) = self.state.pop1_extra()?;
9975 let (v, _) = self.v128_into_i32x4(v, i)?;
9976 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9977 let res = err!(
9978 self.builder
9979 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9980 );
9981 self.state.push1(res);
9982 }
9983 Operator::I64x2Neg => {
9984 let (v, i) = self.state.pop1_extra()?;
9985 let (v, _) = self.v128_into_i64x2(v, i)?;
9986 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9987 let res = err!(
9988 self.builder
9989 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9990 );
9991 self.state.push1(res);
9992 }
9993 Operator::V128Not => {
9994 let (v, i) = self.state.pop1_extra()?;
9995 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
9996 let res = err!(self.builder.build_not(v, ""));
9997 self.state.push1(res);
9998 }
9999 Operator::V128AnyTrue => {
10000 let v = self.state.pop1()?.into_int_value();
10003 let res = err!(self.builder.build_int_compare(
10004 IntPredicate::NE,
10005 v,
10006 v.get_type().const_zero(),
10007 "",
10008 ));
10009 let res = err!(
10010 self.builder
10011 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10012 );
10013 self.state.push1_extra(
10014 res,
10015 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10016 );
10017 }
10018 Operator::I8x16AllTrue
10019 | Operator::I16x8AllTrue
10020 | Operator::I32x4AllTrue
10021 | Operator::I64x2AllTrue => {
10022 let vec_ty = match op {
10023 Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10024 Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10025 Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10026 Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10027 _ => unreachable!(),
10028 };
10029 let (v, i) = self.state.pop1_extra()?;
10030 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10031 let lane_int_ty = self
10032 .context
10033 .custom_width_int_type(NonZero::new(vec_ty.get_size()).unwrap())
10034 .unwrap();
10035 let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10036 let mask = err!(self.builder.build_int_compare(
10037 IntPredicate::NE,
10038 vec,
10039 vec_ty.const_zero(),
10040 "mask",
10041 ));
10042 let cmask =
10043 err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10044 let res = err!(self.builder.build_int_compare(
10045 IntPredicate::EQ,
10046 cmask,
10047 lane_int_ty.const_int(u64::MAX, true),
10048 "",
10049 ));
10050 let res = err!(
10051 self.builder
10052 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10053 );
10054 self.state.push1_extra(
10055 res,
10056 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10057 );
10058 }
10059 Operator::I8x16ExtractLaneS { lane } => {
10060 let (v, i) = self.state.pop1_extra()?;
10061 let (v, _) = self.v128_into_i8x16(v, i)?;
10062 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10063 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10064 let res = err!(
10065 self.builder
10066 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10067 );
10068 self.state.push1(res);
10069 }
10070 Operator::I8x16ExtractLaneU { lane } => {
10071 let (v, i) = self.state.pop1_extra()?;
10072 let (v, _) = self.v128_into_i8x16(v, i)?;
10073 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10074 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10075 let res = err!(
10076 self.builder
10077 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10078 );
10079 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10080 }
10081 Operator::I16x8ExtractLaneS { lane } => {
10082 let (v, i) = self.state.pop1_extra()?;
10083 let (v, _) = self.v128_into_i16x8(v, i)?;
10084 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10085 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10086 let res = err!(
10087 self.builder
10088 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10089 );
10090 self.state.push1(res);
10091 }
10092 Operator::I16x8ExtractLaneU { lane } => {
10093 let (v, i) = self.state.pop1_extra()?;
10094 let (v, _) = self.v128_into_i16x8(v, i)?;
10095 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10096 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10097 let res = err!(
10098 self.builder
10099 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10100 );
10101 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10102 }
10103 Operator::I32x4ExtractLane { lane } => {
10104 let (v, i) = self.state.pop1_extra()?;
10105 let (v, i) = self.v128_into_i32x4(v, i)?;
10106 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10107 let res = err!(self.builder.build_extract_element(v, idx, ""));
10108 self.state.push1_extra(res, i);
10109 }
10110 Operator::I64x2ExtractLane { lane } => {
10111 let (v, i) = self.state.pop1_extra()?;
10112 let (v, i) = self.v128_into_i64x2(v, i)?;
10113 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10114 let res = err!(self.builder.build_extract_element(v, idx, ""));
10115 self.state.push1_extra(res, i);
10116 }
10117 Operator::F32x4ExtractLane { lane } => {
10118 let (v, i) = self.state.pop1_extra()?;
10119 let (v, i) = self.v128_into_f32x4(v, i)?;
10120 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10121 let res = err!(self.builder.build_extract_element(v, idx, ""));
10122 self.state.push1_extra(res, i);
10123 }
10124 Operator::F64x2ExtractLane { lane } => {
10125 let (v, i) = self.state.pop1_extra()?;
10126 let (v, i) = self.v128_into_f64x2(v, i)?;
10127 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10128 let res = err!(self.builder.build_extract_element(v, idx, ""));
10129 self.state.push1_extra(res, i);
10130 }
10131 Operator::I8x16ReplaceLane { lane } => {
10132 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10133 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10134 let v2 = v2.into_int_value();
10135 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10136 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10137 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10138 let res = err!(
10139 self.builder
10140 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10141 );
10142 self.state.push1(res);
10143 }
10144 Operator::I16x8ReplaceLane { lane } => {
10145 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10146 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10147 let v2 = v2.into_int_value();
10148 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10149 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10150 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10151 let res = err!(
10152 self.builder
10153 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10154 );
10155 self.state.push1(res);
10156 }
10157 Operator::I32x4ReplaceLane { lane } => {
10158 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10159 let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10160 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10161 let v2 = v2.into_int_value();
10162 let i2 = i2.strip_pending();
10163 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10164 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10165 let res = err!(
10166 self.builder
10167 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10168 );
10169 self.state
10170 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10171 }
10172 Operator::I64x2ReplaceLane { lane } => {
10173 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10174 let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10175 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10176 let v2 = v2.into_int_value();
10177 let i2 = i2.strip_pending();
10178 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10179 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10180 let res = err!(
10181 self.builder
10182 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10183 );
10184 self.state
10185 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10186 }
10187 Operator::F32x4ReplaceLane { lane } => {
10188 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10189 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10190 let push_pending_f32_nan_to_result =
10191 i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10192 let (v1, v2) = if !push_pending_f32_nan_to_result {
10193 (
10194 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10195 .into_vector_value(),
10196 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10197 .into_float_value(),
10198 )
10199 } else {
10200 (v1, v2.into_float_value())
10201 };
10202 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10203 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10204 let res = err!(
10205 self.builder
10206 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10207 );
10208 let info = if push_pending_f32_nan_to_result {
10209 ExtraInfo::pending_f32_nan()
10210 } else {
10211 (i1.strip_pending() & i2.strip_pending())?
10212 };
10213 self.state.push1_extra(res, info);
10214 }
10215 Operator::F64x2ReplaceLane { lane } => {
10216 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10217 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10218 let push_pending_f64_nan_to_result =
10219 i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10220 let (v1, v2) = if !push_pending_f64_nan_to_result {
10221 (
10222 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10223 .into_vector_value(),
10224 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10225 .into_float_value(),
10226 )
10227 } else {
10228 (v1, v2.into_float_value())
10229 };
10230 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10231 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10232 let res = err!(
10233 self.builder
10234 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10235 );
10236 let info = if push_pending_f64_nan_to_result {
10237 ExtraInfo::pending_f64_nan()
10238 } else {
10239 (i1.strip_pending() & i2.strip_pending())?
10240 };
10241 self.state.push1_extra(res, info);
10242 }
10243 Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10244 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10245 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10246 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10247
10248 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10249 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10250 let res = self
10251 .build_call_with_param_attributes(
10252 self.intrinsics.x86_64.pshufb128,
10253 &[v1.into(), v2.into()],
10254 "",
10255 )?
10256 .try_as_basic_value()
10257 .unwrap_basic();
10258 let res = err!(
10259 self.builder
10260 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10261 );
10262 self.state.push1(res);
10263 }
10264 Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10265 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10266 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10267 let v1 = err!(
10268 self.builder
10269 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10270 )
10271 .into_vector_value();
10272 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10273 let v2 = err!(
10274 self.builder
10275 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10276 )
10277 .into_vector_value();
10278 let lanes = self.intrinsics.i8_ty.const_int(16, false);
10279 let lanes =
10280 self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10281 let mut res = self.intrinsics.i8x16_ty.get_undef();
10282 let idx_out_of_range = err!(self.builder.build_int_compare(
10283 IntPredicate::UGE,
10284 v2,
10285 lanes,
10286 "idx_out_of_range",
10287 ));
10288 let idx_clamped = err!(self.builder.build_select(
10289 idx_out_of_range,
10290 self.intrinsics.i8x16_ty.const_zero(),
10291 v2,
10292 "idx_clamped",
10293 ))
10294 .into_vector_value();
10295 for i in 0..16 {
10296 let idx = err!(self.builder.build_extract_element(
10297 idx_clamped,
10298 self.intrinsics.i32_ty.const_int(i, false),
10299 "idx",
10300 ))
10301 .into_int_value();
10302 let replace_with_zero = err!(self.builder.build_extract_element(
10303 idx_out_of_range,
10304 self.intrinsics.i32_ty.const_int(i, false),
10305 "replace_with_zero",
10306 ))
10307 .into_int_value();
10308 let elem =
10309 err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10310 let elem_or_zero = err!(self.builder.build_select(
10311 replace_with_zero,
10312 self.intrinsics.i8_zero,
10313 elem,
10314 "elem_or_zero",
10315 ));
10316 res = err!(self.builder.build_insert_element(
10317 res,
10318 elem_or_zero,
10319 self.intrinsics.i32_ty.const_int(i, false),
10320 "",
10321 ));
10322 }
10323 let res = err!(
10324 self.builder
10325 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10326 );
10327 self.state.push1(res);
10328 }
10329 Operator::I8x16Shuffle { lanes } => {
10330 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10331 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10332 let v1 = err!(
10333 self.builder
10334 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10335 )
10336 .into_vector_value();
10337 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10338 let v2 = err!(
10339 self.builder
10340 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10341 )
10342 .into_vector_value();
10343 let mask = VectorType::const_vector(
10344 lanes
10345 .iter()
10346 .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10347 .collect::<Vec<IntValue>>()
10348 .as_slice(),
10349 );
10350 let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10351 let res = err!(
10352 self.builder
10353 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10354 );
10355 self.state.push1(res);
10356 }
10357 Operator::V128Load8x8S { ref memarg } => {
10358 let offset = self.state.pop1()?.into_int_value();
10359 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10360 let v = err!(
10361 self.builder
10362 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10363 )
10364 .into_vector_value();
10365 let res = err!(
10366 self.builder
10367 .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10368 );
10369 let res = err!(
10370 self.builder
10371 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10372 );
10373 self.state.push1(res);
10374 }
10375 Operator::V128Load8x8U { ref memarg } => {
10376 let offset = self.state.pop1()?.into_int_value();
10377 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10378 let v = err!(
10379 self.builder
10380 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10381 )
10382 .into_vector_value();
10383 let res = err!(
10384 self.builder
10385 .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10386 );
10387 let res = err!(
10388 self.builder
10389 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10390 );
10391 self.state.push1(res);
10392 }
10393 Operator::V128Load16x4S { ref memarg } => {
10394 let offset = self.state.pop1()?.into_int_value();
10395 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10396 let v = err!(self.builder.build_bit_cast(
10397 v,
10398 self.intrinsics.i16_ty.vec_type(4),
10399 ""
10400 ))
10401 .into_vector_value();
10402 let res = err!(
10403 self.builder
10404 .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10405 );
10406 let res = err!(
10407 self.builder
10408 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10409 );
10410 self.state.push1(res);
10411 }
10412 Operator::V128Load16x4U { ref memarg } => {
10413 let offset = self.state.pop1()?.into_int_value();
10414 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10415 let v = err!(self.builder.build_bit_cast(
10416 v,
10417 self.intrinsics.i16_ty.vec_type(4),
10418 ""
10419 ))
10420 .into_vector_value();
10421 let res = err!(
10422 self.builder
10423 .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10424 );
10425 let res = err!(
10426 self.builder
10427 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10428 );
10429 self.state.push1(res);
10430 }
10431 Operator::V128Load32x2S { ref memarg } => {
10432 let offset = self.state.pop1()?.into_int_value();
10433 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10434 let v = err!(self.builder.build_bit_cast(
10435 v,
10436 self.intrinsics.i32_ty.vec_type(2),
10437 ""
10438 ))
10439 .into_vector_value();
10440 let res = err!(
10441 self.builder
10442 .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10443 );
10444 let res = err!(
10445 self.builder
10446 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10447 );
10448 self.state.push1(res);
10449 }
10450 Operator::V128Load32x2U { ref memarg } => {
10451 let offset = self.state.pop1()?.into_int_value();
10452 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10453 let v = err!(self.builder.build_bit_cast(
10454 v,
10455 self.intrinsics.i32_ty.vec_type(2),
10456 ""
10457 ))
10458 .into_vector_value();
10459 let res = err!(
10460 self.builder
10461 .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10462 );
10463 let res = err!(
10464 self.builder
10465 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10466 );
10467 self.state.push1(res);
10468 }
10469 Operator::V128Load32Zero { ref memarg } => {
10470 let offset = self.state.pop1()?.into_int_value();
10471 let element =
10472 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10473 let res = err!(self.builder.build_int_z_extend(
10474 element.into_int_value(),
10475 self.intrinsics.i128_ty,
10476 "",
10477 ));
10478 self.state.push1(res);
10479 }
10480 Operator::V128Load64Zero { ref memarg } => {
10481 let offset = self.state.pop1()?.into_int_value();
10482 let element =
10483 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10484 let res = err!(self.builder.build_int_z_extend(
10485 element.into_int_value(),
10486 self.intrinsics.i128_ty,
10487 "",
10488 ));
10489 self.state.push1(res);
10490 }
10491 Operator::V128Load8Splat { ref memarg } => {
10492 let offset = self.state.pop1()?.into_int_value();
10493 let element =
10494 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10495 let res = self.splat_vector(element, self.intrinsics.i8x16_ty)?;
10496 let res = err!(
10497 self.builder
10498 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10499 );
10500 self.state.push1(res);
10501 }
10502 Operator::V128Load16Splat { ref memarg } => {
10503 let offset = self.state.pop1()?.into_int_value();
10504 let element =
10505 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10506 let res = self.splat_vector(element, self.intrinsics.i16x8_ty)?;
10507 let res = err!(
10508 self.builder
10509 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10510 );
10511 self.state.push1(res);
10512 }
10513 Operator::V128Load32Splat { ref memarg } => {
10514 let offset = self.state.pop1()?.into_int_value();
10515 let element =
10516 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10517 let res = self.splat_vector(element, self.intrinsics.i32x4_ty)?;
10518 let res = err!(
10519 self.builder
10520 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10521 );
10522 self.state.push1(res);
10523 }
10524 Operator::V128Load64Splat { ref memarg } => {
10525 let offset = self.state.pop1()?.into_int_value();
10526 let element =
10527 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10528 let res = self.splat_vector(element, self.intrinsics.i64x2_ty)?;
10529 let res = err!(
10530 self.builder
10531 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10532 );
10533 self.state.push1(res);
10534 }
10535
10536 Operator::MemoryGrow { mem } => {
10537 let memory_index = MemoryIndex::from_u32(mem);
10538 let delta = self.state.pop1()?;
10539 let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
10540 let grow = err!(self.builder.build_indirect_call(
10541 self.intrinsics.memory_grow_ty,
10542 grow_fn_ptr,
10543 &[
10544 vmctx.as_basic_value_enum().into(),
10545 delta.into(),
10546 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10547 ],
10548 "",
10549 ));
10550 self.state.push1(grow.try_as_basic_value().unwrap_basic());
10551 }
10552 Operator::MemorySize { mem } => {
10553 let memory_index = MemoryIndex::from_u32(mem);
10554 let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
10555 let size = err!(self.builder.build_indirect_call(
10556 self.intrinsics.memory_size_ty,
10557 size_fn_ptr,
10558 &[
10559 vmctx.as_basic_value_enum().into(),
10560 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10561 ],
10562 "",
10563 ));
10564 self.state.push1(size.try_as_basic_value().unwrap_basic());
10566 }
10567 Operator::MemoryInit { data_index, mem } => {
10568 let (dest, src, len) = self.state.pop3()?;
10569 let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
10570 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10571 self.build_call_with_param_attributes(
10572 self.intrinsics.memory_init,
10573 &[
10574 vmctx.as_basic_value_enum().into(),
10575 mem.into(),
10576 segment.into(),
10577 dest.into(),
10578 src.into(),
10579 len.into(),
10580 ],
10581 "",
10582 )?;
10583 }
10584 Operator::DataDrop { data_index } => {
10585 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10586 self.build_call_with_param_attributes(
10587 self.intrinsics.data_drop,
10588 &[vmctx.as_basic_value_enum().into(), segment.into()],
10589 "",
10590 )?;
10591 }
10592 Operator::MemoryCopy { dst_mem, src_mem } => {
10593 let _dst = dst_mem;
10595 let (memory_copy, src) = if let Some(local_memory_index) = self
10596 .wasm_module
10597 .local_memory_index(MemoryIndex::from_u32(src_mem))
10598 {
10599 (self.intrinsics.memory_copy, local_memory_index.as_u32())
10600 } else {
10601 (self.intrinsics.imported_memory_copy, src_mem)
10602 };
10603
10604 let (dest_pos, src_pos, len) = self.state.pop3()?;
10605 let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
10606 self.build_call_with_param_attributes(
10607 memory_copy,
10608 &[
10609 vmctx.as_basic_value_enum().into(),
10610 src_index.into(),
10611 dest_pos.into(),
10612 src_pos.into(),
10613 len.into(),
10614 ],
10615 "",
10616 )?;
10617 }
10618 Operator::MemoryFill { mem } => {
10619 let (memory_fill, mem) = if let Some(local_memory_index) = self
10620 .wasm_module
10621 .local_memory_index(MemoryIndex::from_u32(mem))
10622 {
10623 (self.intrinsics.memory_fill, local_memory_index.as_u32())
10624 } else {
10625 (self.intrinsics.imported_memory_fill, mem)
10626 };
10627
10628 let (dst, val, len) = self.state.pop3()?;
10629 let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
10630 self.build_call_with_param_attributes(
10631 memory_fill,
10632 &[
10633 vmctx.as_basic_value_enum().into(),
10634 mem_index.into(),
10635 dst.into(),
10636 val.into(),
10637 len.into(),
10638 ],
10639 "",
10640 )?;
10641 }
10642 _ => unreachable!(),
10643 }
10644 Ok(())
10645 }
10646
10647 fn translate_atomic_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
10649 let vmctx = &self.ctx.basic().into_pointer_value();
10650
10651 match op {
10652 Operator::AtomicFence => {
10653 }
10661 Operator::I32AtomicLoad { ref memarg } => {
10662 let offset = self.state.pop1()?.into_int_value();
10663 let result = self.build_annotated_atomic_load(
10664 self.intrinsics.i32_ty,
10665 self.intrinsics.i32_ty,
10666 offset,
10667 memarg,
10668 )?;
10669 self.state.push1(result);
10670 }
10671 Operator::I64AtomicLoad { ref memarg } => {
10672 let offset = self.state.pop1()?.into_int_value();
10673 let result = self.build_annotated_atomic_load(
10674 self.intrinsics.i64_ty,
10675 self.intrinsics.i64_ty,
10676 offset,
10677 memarg,
10678 )?;
10679 self.state.push1(result);
10680 }
10681 Operator::I32AtomicLoad8U { ref memarg } => {
10682 let offset = self.state.pop1()?.into_int_value();
10683 let result = self.build_annotated_atomic_load(
10684 self.intrinsics.i32_ty,
10685 self.intrinsics.i8_ty,
10686 offset,
10687 memarg,
10688 )?;
10689 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10690 }
10691 Operator::I32AtomicLoad16U { ref memarg } => {
10692 let offset = self.state.pop1()?.into_int_value();
10693 let result = self.build_annotated_atomic_load(
10694 self.intrinsics.i32_ty,
10695 self.intrinsics.i16_ty,
10696 offset,
10697 memarg,
10698 )?;
10699 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10700 }
10701 Operator::I64AtomicLoad8U { ref memarg } => {
10702 let offset = self.state.pop1()?.into_int_value();
10703 let result = self.build_annotated_atomic_load(
10704 self.intrinsics.i64_ty,
10705 self.intrinsics.i8_ty,
10706 offset,
10707 memarg,
10708 )?;
10709 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10710 }
10711 Operator::I64AtomicLoad16U { ref memarg } => {
10712 let offset = self.state.pop1()?.into_int_value();
10713 let result = self.build_annotated_atomic_load(
10714 self.intrinsics.i64_ty,
10715 self.intrinsics.i16_ty,
10716 offset,
10717 memarg,
10718 )?;
10719 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10720 }
10721 Operator::I64AtomicLoad32U { ref memarg } => {
10722 let offset = self.state.pop1()?.into_int_value();
10723 let result = self.build_annotated_atomic_load(
10724 self.intrinsics.i64_ty,
10725 self.intrinsics.i32_ty,
10726 offset,
10727 memarg,
10728 )?;
10729 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10730 }
10731 Operator::I32AtomicStore { ref memarg } => {
10732 let value = self.state.pop1()?.into_int_value();
10733 let offset = self.state.pop1()?.into_int_value();
10734 self.build_annotated_atomic_store(
10735 self.intrinsics.i32_ty,
10736 self.intrinsics.i32_ty,
10737 offset,
10738 value,
10739 memarg,
10740 )?;
10741 }
10742 Operator::I64AtomicStore { ref memarg } => {
10743 let value = self.state.pop1()?.into_int_value();
10744 let offset = self.state.pop1()?.into_int_value();
10745 self.build_annotated_atomic_store(
10746 self.intrinsics.i64_ty,
10747 self.intrinsics.i64_ty,
10748 offset,
10749 value,
10750 memarg,
10751 )?;
10752 }
10753 Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10754 let value = self.state.pop1()?.into_int_value();
10755 let offset = self.state.pop1()?.into_int_value();
10756 self.build_annotated_atomic_store(
10757 value.get_type(),
10758 self.intrinsics.i8_ty,
10759 offset,
10760 value,
10761 memarg,
10762 )?;
10763 }
10764 Operator::I32AtomicStore16 { ref memarg }
10765 | Operator::I64AtomicStore16 { ref memarg } => {
10766 let value = self.state.pop1()?.into_int_value();
10767 let offset = self.state.pop1()?.into_int_value();
10768 self.build_annotated_atomic_store(
10769 value.get_type(),
10770 self.intrinsics.i16_ty,
10771 offset,
10772 value,
10773 memarg,
10774 )?;
10775 }
10776 Operator::I64AtomicStore32 { ref memarg } => {
10777 let value = self.state.pop1()?.into_int_value();
10778 let offset = self.state.pop1()?.into_int_value();
10779 self.build_annotated_atomic_store(
10780 self.intrinsics.i64_ty,
10781 self.intrinsics.i32_ty,
10782 offset,
10783 value,
10784 memarg,
10785 )?;
10786 }
10787 Operator::I32AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10788 self.intrinsics.i32_ty,
10789 self.intrinsics.i8_ty,
10790 memarg,
10791 AtomicRMWBinOp::Add,
10792 Some(ExtraInfo::arithmetic_f32()),
10793 )?,
10794 Operator::I32AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10795 self.intrinsics.i32_ty,
10796 self.intrinsics.i16_ty,
10797 memarg,
10798 AtomicRMWBinOp::Add,
10799 Some(ExtraInfo::arithmetic_f32()),
10800 )?,
10801 Operator::I32AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10802 self.intrinsics.i32_ty,
10803 self.intrinsics.i32_ty,
10804 memarg,
10805 AtomicRMWBinOp::Add,
10806 None,
10807 )?,
10808 Operator::I64AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10809 self.intrinsics.i64_ty,
10810 self.intrinsics.i8_ty,
10811 memarg,
10812 AtomicRMWBinOp::Add,
10813 Some(ExtraInfo::arithmetic_f64()),
10814 )?,
10815 Operator::I64AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10816 self.intrinsics.i64_ty,
10817 self.intrinsics.i16_ty,
10818 memarg,
10819 AtomicRMWBinOp::Add,
10820 Some(ExtraInfo::arithmetic_f64()),
10821 )?,
10822 Operator::I64AtomicRmw32AddU { ref memarg } => self.translate_atomic_rmw(
10823 self.intrinsics.i64_ty,
10824 self.intrinsics.i32_ty,
10825 memarg,
10826 AtomicRMWBinOp::Add,
10827 Some(ExtraInfo::arithmetic_f64()),
10828 )?,
10829 Operator::I64AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10830 self.intrinsics.i64_ty,
10831 self.intrinsics.i64_ty,
10832 memarg,
10833 AtomicRMWBinOp::Add,
10834 None,
10835 )?,
10836 Operator::I32AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10837 self.intrinsics.i32_ty,
10838 self.intrinsics.i8_ty,
10839 memarg,
10840 AtomicRMWBinOp::Sub,
10841 Some(ExtraInfo::arithmetic_f32()),
10842 )?,
10843 Operator::I32AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10844 self.intrinsics.i32_ty,
10845 self.intrinsics.i16_ty,
10846 memarg,
10847 AtomicRMWBinOp::Sub,
10848 Some(ExtraInfo::arithmetic_f32()),
10849 )?,
10850 Operator::I32AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10851 self.intrinsics.i32_ty,
10852 self.intrinsics.i32_ty,
10853 memarg,
10854 AtomicRMWBinOp::Sub,
10855 None,
10856 )?,
10857 Operator::I64AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10858 self.intrinsics.i64_ty,
10859 self.intrinsics.i8_ty,
10860 memarg,
10861 AtomicRMWBinOp::Sub,
10862 Some(ExtraInfo::arithmetic_f32()),
10863 )?,
10864 Operator::I64AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10865 self.intrinsics.i64_ty,
10866 self.intrinsics.i16_ty,
10867 memarg,
10868 AtomicRMWBinOp::Sub,
10869 Some(ExtraInfo::arithmetic_f64()),
10870 )?,
10871 Operator::I64AtomicRmw32SubU { ref memarg } => self.translate_atomic_rmw(
10872 self.intrinsics.i64_ty,
10873 self.intrinsics.i32_ty,
10874 memarg,
10875 AtomicRMWBinOp::Sub,
10876 Some(ExtraInfo::arithmetic_f64()),
10877 )?,
10878 Operator::I64AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10879 self.intrinsics.i64_ty,
10880 self.intrinsics.i64_ty,
10881 memarg,
10882 AtomicRMWBinOp::Sub,
10883 None,
10884 )?,
10885 Operator::I32AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10886 self.intrinsics.i32_ty,
10887 self.intrinsics.i8_ty,
10888 memarg,
10889 AtomicRMWBinOp::And,
10890 Some(ExtraInfo::arithmetic_f32()),
10891 )?,
10892 Operator::I32AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
10893 self.intrinsics.i32_ty,
10894 self.intrinsics.i16_ty,
10895 memarg,
10896 AtomicRMWBinOp::And,
10897 Some(ExtraInfo::arithmetic_f32()),
10898 )?,
10899 Operator::I32AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
10900 self.intrinsics.i32_ty,
10901 self.intrinsics.i32_ty,
10902 memarg,
10903 AtomicRMWBinOp::And,
10904 None,
10905 )?,
10906 Operator::I64AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10907 self.intrinsics.i64_ty,
10908 self.intrinsics.i8_ty,
10909 memarg,
10910 AtomicRMWBinOp::And,
10911 Some(ExtraInfo::arithmetic_f64()),
10912 )?,
10913 Operator::I64AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
10914 self.intrinsics.i64_ty,
10915 self.intrinsics.i16_ty,
10916 memarg,
10917 AtomicRMWBinOp::And,
10918 Some(ExtraInfo::arithmetic_f64()),
10919 )?,
10920 Operator::I64AtomicRmw32AndU { ref memarg } => self.translate_atomic_rmw(
10921 self.intrinsics.i64_ty,
10922 self.intrinsics.i32_ty,
10923 memarg,
10924 AtomicRMWBinOp::And,
10925 Some(ExtraInfo::arithmetic_f64()),
10926 )?,
10927 Operator::I64AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
10928 self.intrinsics.i64_ty,
10929 self.intrinsics.i64_ty,
10930 memarg,
10931 AtomicRMWBinOp::And,
10932 None,
10933 )?,
10934 Operator::I32AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
10935 self.intrinsics.i32_ty,
10936 self.intrinsics.i8_ty,
10937 memarg,
10938 AtomicRMWBinOp::Or,
10939 Some(ExtraInfo::arithmetic_f32()),
10940 )?,
10941 Operator::I32AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
10942 self.intrinsics.i32_ty,
10943 self.intrinsics.i16_ty,
10944 memarg,
10945 AtomicRMWBinOp::Or,
10946 Some(ExtraInfo::arithmetic_f32()),
10947 )?,
10948 Operator::I32AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
10949 self.intrinsics.i32_ty,
10950 self.intrinsics.i32_ty,
10951 memarg,
10952 AtomicRMWBinOp::Or,
10953 Some(ExtraInfo::arithmetic_f32()),
10954 )?,
10955 Operator::I64AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
10956 self.intrinsics.i64_ty,
10957 self.intrinsics.i8_ty,
10958 memarg,
10959 AtomicRMWBinOp::Or,
10960 Some(ExtraInfo::arithmetic_f64()),
10961 )?,
10962 Operator::I64AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
10963 self.intrinsics.i64_ty,
10964 self.intrinsics.i16_ty,
10965 memarg,
10966 AtomicRMWBinOp::Or,
10967 Some(ExtraInfo::arithmetic_f64()),
10968 )?,
10969 Operator::I64AtomicRmw32OrU { ref memarg } => self.translate_atomic_rmw(
10970 self.intrinsics.i64_ty,
10971 self.intrinsics.i32_ty,
10972 memarg,
10973 AtomicRMWBinOp::Or,
10974 Some(ExtraInfo::arithmetic_f64()),
10975 )?,
10976 Operator::I64AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
10977 self.intrinsics.i64_ty,
10978 self.intrinsics.i64_ty,
10979 memarg,
10980 AtomicRMWBinOp::Or,
10981 None,
10982 )?,
10983 Operator::I32AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
10984 self.intrinsics.i32_ty,
10985 self.intrinsics.i8_ty,
10986 memarg,
10987 AtomicRMWBinOp::Xor,
10988 Some(ExtraInfo::arithmetic_f32()),
10989 )?,
10990 Operator::I32AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
10991 self.intrinsics.i32_ty,
10992 self.intrinsics.i16_ty,
10993 memarg,
10994 AtomicRMWBinOp::Xor,
10995 Some(ExtraInfo::arithmetic_f32()),
10996 )?,
10997 Operator::I32AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
10998 self.intrinsics.i32_ty,
10999 self.intrinsics.i32_ty,
11000 memarg,
11001 AtomicRMWBinOp::Xor,
11002 None,
11003 )?,
11004 Operator::I64AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11005 self.intrinsics.i64_ty,
11006 self.intrinsics.i8_ty,
11007 memarg,
11008 AtomicRMWBinOp::Xor,
11009 Some(ExtraInfo::arithmetic_f64()),
11010 )?,
11011 Operator::I64AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11012 self.intrinsics.i64_ty,
11013 self.intrinsics.i16_ty,
11014 memarg,
11015 AtomicRMWBinOp::Xor,
11016 Some(ExtraInfo::arithmetic_f64()),
11017 )?,
11018 Operator::I64AtomicRmw32XorU { ref memarg } => self.translate_atomic_rmw(
11019 self.intrinsics.i64_ty,
11020 self.intrinsics.i32_ty,
11021 memarg,
11022 AtomicRMWBinOp::Xor,
11023 Some(ExtraInfo::arithmetic_f64()),
11024 )?,
11025 Operator::I64AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11026 self.intrinsics.i64_ty,
11027 self.intrinsics.i64_ty,
11028 memarg,
11029 AtomicRMWBinOp::Xor,
11030 None,
11031 )?,
11032 Operator::I32AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11033 self.intrinsics.i32_ty,
11034 self.intrinsics.i8_ty,
11035 memarg,
11036 AtomicRMWBinOp::Xchg,
11037 Some(ExtraInfo::arithmetic_f32()),
11038 )?,
11039 Operator::I32AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11040 self.intrinsics.i32_ty,
11041 self.intrinsics.i16_ty,
11042 memarg,
11043 AtomicRMWBinOp::Xchg,
11044 Some(ExtraInfo::arithmetic_f32()),
11045 )?,
11046 Operator::I32AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11047 self.intrinsics.i32_ty,
11048 self.intrinsics.i32_ty,
11049 memarg,
11050 AtomicRMWBinOp::Xchg,
11051 None,
11052 )?,
11053 Operator::I64AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11054 self.intrinsics.i64_ty,
11055 self.intrinsics.i8_ty,
11056 memarg,
11057 AtomicRMWBinOp::Xchg,
11058 Some(ExtraInfo::arithmetic_f64()),
11059 )?,
11060 Operator::I64AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11061 self.intrinsics.i64_ty,
11062 self.intrinsics.i16_ty,
11063 memarg,
11064 AtomicRMWBinOp::Xchg,
11065 Some(ExtraInfo::arithmetic_f64()),
11066 )?,
11067 Operator::I64AtomicRmw32XchgU { ref memarg } => self.translate_atomic_rmw(
11068 self.intrinsics.i64_ty,
11069 self.intrinsics.i32_ty,
11070 memarg,
11071 AtomicRMWBinOp::Xchg,
11072 Some(ExtraInfo::arithmetic_f64()),
11073 )?,
11074 Operator::I64AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11075 self.intrinsics.i64_ty,
11076 self.intrinsics.i64_ty,
11077 memarg,
11078 AtomicRMWBinOp::Xchg,
11079 None,
11080 )?,
11081 Operator::I32AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11082 self.intrinsics.i32_ty,
11083 self.intrinsics.i8_ty,
11084 memarg,
11085 Some(ExtraInfo::arithmetic_f32()),
11086 )?,
11087 Operator::I32AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11088 self.intrinsics.i32_ty,
11089 self.intrinsics.i16_ty,
11090 memarg,
11091 Some(ExtraInfo::arithmetic_f32()),
11092 )?,
11093 Operator::I32AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11094 self.intrinsics.i32_ty,
11095 self.intrinsics.i32_ty,
11096 memarg,
11097 None,
11098 )?,
11099 Operator::I64AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11100 self.intrinsics.i64_ty,
11101 self.intrinsics.i8_ty,
11102 memarg,
11103 Some(ExtraInfo::arithmetic_f64()),
11104 )?,
11105 Operator::I64AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11106 self.intrinsics.i64_ty,
11107 self.intrinsics.i16_ty,
11108 memarg,
11109 Some(ExtraInfo::arithmetic_f64()),
11110 )?,
11111 Operator::I64AtomicRmw32CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11112 self.intrinsics.i64_ty,
11113 self.intrinsics.i32_ty,
11114 memarg,
11115 Some(ExtraInfo::arithmetic_f64()),
11116 )?,
11117 Operator::I64AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11118 self.intrinsics.i64_ty,
11119 self.intrinsics.i64_ty,
11120 memarg,
11121 None,
11122 )?,
11123 Operator::MemoryAtomicWait32 { memarg } => {
11124 let memory_index = MemoryIndex::from_u32(memarg.memory);
11125 let (dst, val, timeout) = self.state.pop3()?;
11126 let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
11127 let ret = err!(
11128 self.builder.build_indirect_call(
11129 self.intrinsics.memory_wait32_ty,
11130 wait32_fn_ptr,
11131 &[
11132 vmctx.as_basic_value_enum().into(),
11133 self.intrinsics
11134 .i32_ty
11135 .const_int(memarg.memory as u64, false)
11136 .into(),
11137 dst.into(),
11138 val.into(),
11139 timeout.into(),
11140 ],
11141 "",
11142 )
11143 );
11144 self.state.push1(ret.try_as_basic_value().unwrap_basic());
11145 }
11146 Operator::MemoryAtomicWait64 { memarg } => {
11147 let memory_index = MemoryIndex::from_u32(memarg.memory);
11148 let (dst, val, timeout) = self.state.pop3()?;
11149 let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
11150 let ret = err!(
11151 self.builder.build_indirect_call(
11152 self.intrinsics.memory_wait64_ty,
11153 wait64_fn_ptr,
11154 &[
11155 vmctx.as_basic_value_enum().into(),
11156 self.intrinsics
11157 .i32_ty
11158 .const_int(memarg.memory as u64, false)
11159 .into(),
11160 dst.into(),
11161 val.into(),
11162 timeout.into(),
11163 ],
11164 "",
11165 )
11166 );
11167 self.state.push1(ret.try_as_basic_value().unwrap_basic());
11168 }
11169 Operator::MemoryAtomicNotify { memarg } => {
11170 let memory_index = MemoryIndex::from_u32(memarg.memory);
11171 let (dst, count) = self.state.pop2()?;
11172 let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
11173 let cnt = err!(
11174 self.builder.build_indirect_call(
11175 self.intrinsics.memory_notify_ty,
11176 notify_fn_ptr,
11177 &[
11178 vmctx.as_basic_value_enum().into(),
11179 self.intrinsics
11180 .i32_ty
11181 .const_int(memarg.memory as u64, false)
11182 .into(),
11183 dst.into(),
11184 count.into(),
11185 ],
11186 "",
11187 )
11188 );
11189 self.state.push1(cnt.try_as_basic_value().unwrap_basic());
11190 }
11191 _ => unreachable!(),
11192 }
11193 Ok(())
11194 }
11195
11196 fn translate_reference_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11199 match op {
11200 Operator::RefNull { hty } => {
11201 let ty = err!(wpheaptype_to_type(hty));
11202 let ty = type_to_llvm(self.intrinsics, ty)?;
11203 self.state.push1(ty.const_zero());
11204 }
11205 Operator::RefIsNull => {
11206 let value = self.state.pop1()?;
11207 let is_null = match value {
11208 BasicValueEnum::IntValue(value) => err!(self.builder.build_int_compare(
11209 IntPredicate::EQ,
11210 value,
11211 value.get_type().const_zero(),
11212 "",
11213 )),
11214 BasicValueEnum::PointerValue(value) => {
11215 err!(self.builder.build_is_null(value, ""))
11216 }
11217 _ => unreachable!("ref.is_null only accepts reference types"),
11218 };
11219 let is_null = err!(self.builder.build_int_z_extend(
11220 is_null,
11221 self.intrinsics.i32_ty,
11222 ""
11223 ));
11224 self.state.push1(is_null);
11225 }
11226 Operator::RefFunc { function_index } => {
11227 let index = self
11228 .intrinsics
11229 .i32_ty
11230 .const_int(function_index.into(), false);
11231 let value = self
11232 .build_call_with_param_attributes(
11233 self.intrinsics.func_ref,
11234 &[self.ctx.basic().into(), index.into()],
11235 "",
11236 )?
11237 .try_as_basic_value()
11238 .unwrap_basic();
11239 self.state.push1(value);
11240 }
11241 _ => unreachable!(),
11242 }
11243 Ok(())
11244 }
11245
11246 fn translate_table_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11248 match op {
11249 Operator::TableGet { table } => {
11250 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11251 let elem = self.state.pop1()?;
11252 let table_get = if self
11253 .wasm_module
11254 .local_table_index(TableIndex::from_u32(table))
11255 .is_some()
11256 {
11257 self.intrinsics.table_get
11258 } else {
11259 self.intrinsics.imported_table_get
11260 };
11261 let value = self
11262 .build_call_with_param_attributes(
11263 table_get,
11264 &[self.ctx.basic().into(), table_index.into(), elem.into()],
11265 "",
11266 )?
11267 .try_as_basic_value()
11268 .unwrap_basic();
11269 let value = err!(
11270 self.builder.build_bit_cast(
11271 value,
11272 type_to_llvm(
11273 self.intrinsics,
11274 self.wasm_module
11275 .tables
11276 .get(TableIndex::from_u32(table))
11277 .unwrap()
11278 .ty,
11279 )?,
11280 "",
11281 )
11282 );
11283 self.state.push1(value);
11284 }
11285 Operator::TableSet { table } => {
11286 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11287 let (elem, value) = self.state.pop2()?;
11288 let value = err!(
11289 self.builder
11290 .build_bit_cast(value, self.intrinsics.ptr_ty, "")
11291 );
11292 let table_set = if self
11293 .wasm_module
11294 .local_table_index(TableIndex::from_u32(table))
11295 .is_some()
11296 {
11297 self.intrinsics.table_set
11298 } else {
11299 self.intrinsics.imported_table_set
11300 };
11301 self.build_call_with_param_attributes(
11302 table_set,
11303 &[
11304 self.ctx.basic().into(),
11305 table_index.into(),
11306 elem.into(),
11307 value.into(),
11308 ],
11309 "",
11310 )?;
11311 }
11312 Operator::TableCopy {
11313 dst_table,
11314 src_table,
11315 } => {
11316 let (dst, src, len) = self.state.pop3()?;
11317 let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
11318 let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
11319 self.build_call_with_param_attributes(
11320 self.intrinsics.table_copy,
11321 &[
11322 self.ctx.basic().into(),
11323 dst_table.into(),
11324 src_table.into(),
11325 dst.into(),
11326 src.into(),
11327 len.into(),
11328 ],
11329 "",
11330 )?;
11331 }
11332 Operator::TableInit { elem_index, table } => {
11333 let (dst, src, len) = self.state.pop3()?;
11334 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11335 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11336 self.build_call_with_param_attributes(
11337 self.intrinsics.table_init,
11338 &[
11339 self.ctx.basic().into(),
11340 table.into(),
11341 segment.into(),
11342 dst.into(),
11343 src.into(),
11344 len.into(),
11345 ],
11346 "",
11347 )?;
11348 }
11349 Operator::ElemDrop { elem_index } => {
11350 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11351 self.build_call_with_param_attributes(
11352 self.intrinsics.elem_drop,
11353 &[self.ctx.basic().into(), segment.into()],
11354 "",
11355 )?;
11356 }
11357 Operator::TableFill { table } => {
11358 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11359 let (start, elem, len) = self.state.pop3()?;
11360 let elem = err!(
11361 self.builder
11362 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11363 );
11364 self.build_call_with_param_attributes(
11365 self.intrinsics.table_fill,
11366 &[
11367 self.ctx.basic().into(),
11368 table.into(),
11369 start.into(),
11370 elem.into(),
11371 len.into(),
11372 ],
11373 "",
11374 )?;
11375 }
11376 Operator::TableGrow { table } => {
11377 let (elem, delta) = self.state.pop2()?;
11378 let elem = err!(
11379 self.builder
11380 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11381 );
11382 let (table_grow, table_index) = if let Some(local_table_index) = self
11383 .wasm_module
11384 .local_table_index(TableIndex::from_u32(table))
11385 {
11386 (self.intrinsics.table_grow, local_table_index.as_u32())
11387 } else {
11388 (self.intrinsics.imported_table_grow, table)
11389 };
11390 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11391 let size = self
11392 .build_call_with_param_attributes(
11393 table_grow,
11394 &[
11395 self.ctx.basic().into(),
11396 elem.into(),
11397 delta.into(),
11398 table_index.into(),
11399 ],
11400 "",
11401 )?
11402 .try_as_basic_value()
11403 .unwrap_basic();
11404 self.state.push1(size);
11405 }
11406 Operator::TableSize { table } => {
11407 let (table_size, table_index) = if let Some(local_table_index) = self
11408 .wasm_module
11409 .local_table_index(TableIndex::from_u32(table))
11410 {
11411 (self.intrinsics.table_size, local_table_index.as_u32())
11412 } else {
11413 (self.intrinsics.imported_table_size, table)
11414 };
11415 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11416 let size = self
11417 .build_call_with_param_attributes(
11418 table_size,
11419 &[self.ctx.basic().into(), table_index.into()],
11420 "",
11421 )?
11422 .try_as_basic_value()
11423 .unwrap_basic();
11424 self.state.push1(size);
11425 }
11426 _ => unreachable!(),
11427 }
11428 Ok(())
11429 }
11430
11431 fn translate_eh_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11434 match op {
11435 Operator::TryTable { try_table } => {
11436 let current_block = self
11437 .builder
11438 .get_insert_block()
11439 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11440
11441 self.builder.position_at_end(current_block);
11442
11443 let end_block = self.context.append_basic_block(self.function, "try_end");
11444
11445 let end_phis = {
11446 self.builder.position_at_end(end_block);
11447
11448 let phis = self
11449 .module_translation
11450 .blocktype_params_results(&try_table.ty)?
11451 .1
11452 .iter()
11453 .map(|&wp_ty| {
11454 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
11455 type_to_llvm(self.intrinsics, wasm_ty)
11456 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
11457 })
11458 })
11459 .collect::<Result<_, _>>()?;
11460
11461 self.builder.position_at_end(current_block);
11462 phis
11463 };
11464
11465 let catches: Vec<_> = try_table
11469 .catches
11470 .into_iter()
11471 .unique_by(|v| match v {
11472 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
11473 Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
11474 })
11475 .collect();
11476
11477 let null = self.intrinsics.ptr_ty.const_zero();
11479
11480 let mut catch_tag_values = vec![];
11481 let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
11482 .iter()
11483 .map(|catch| match catch {
11484 Catch::All { .. } | Catch::AllRef { .. } => {
11485 catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
11486 Ok(null.into())
11487 }
11488 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
11489 catch_tag_values.push(*tag);
11490 Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
11491 }
11492 })
11493 .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
11494
11495 let mut outer_catch_blocks = vec![];
11499 for outer_landingpad in self.state.landingpads.iter().rev() {
11500 for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
11501 if !catch_tag_values.contains(tag) {
11502 catch_tag_values.push(*tag);
11503 lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
11504 null.into()
11505 } else {
11506 *self.tags_cache.get(&(*tag as i32)).expect(
11507 "If a previous try_table encountered a tag, \
11508 it should be in the cache",
11509 )
11510 });
11511 outer_catch_blocks.push(*catch_info);
11512 }
11513 }
11514 }
11515
11516 let mut maybe_lpad_block = None;
11520 let mut catch_blocks = vec![];
11521 if !lpad_clauses.is_empty() {
11522 let lpad_block = self.context.append_basic_block(self.function, "catch");
11523 let catch_all_block =
11524 self.context.append_basic_block(self.function, "catch_all");
11525 let catch_specific_block = self
11526 .context
11527 .append_basic_block(self.function, "catch_specific");
11528 let catch_end_block =
11529 self.context.append_basic_block(self.function, "catch_end");
11530 let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
11531
11532 self.builder.position_at_end(lpad_block);
11533
11534 let res = err!(self.builder.build_landing_pad(
11535 self.intrinsics.lpad_exception_ty,
11536 self.intrinsics.personality,
11537 &lpad_clauses,
11538 false,
11539 "exc_struct",
11540 ));
11541
11542 let res = res.into_struct_value();
11543
11544 let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
11545 let pre_selector =
11546 err!(self.builder.build_extract_value(res, 1, "pre_selector"));
11547
11548 let pre_selector_is_zero = err!(self.builder.build_int_compare(
11551 IntPredicate::EQ,
11552 pre_selector.into_int_value(),
11553 self.intrinsics.i32_zero,
11554 "pre_selector_is_zero"
11555 ));
11556 err!(self.builder.build_conditional_branch(
11557 pre_selector_is_zero,
11558 catch_all_block,
11559 catch_specific_block
11560 ));
11561
11562 self.builder.position_at_end(catch_all_block);
11563 err!(self.builder.build_unconditional_branch(catch_end_block));
11564
11565 self.builder.position_at_end(catch_specific_block);
11566 let selector_value = self.build_call_with_param_attributes(
11567 self.intrinsics.personality2,
11568 &[self.ctx.basic().into(), uw_exc.into()],
11569 "selector",
11570 )?;
11571 err!(self.builder.build_unconditional_branch(catch_end_block));
11572
11573 self.builder.position_at_end(catch_end_block);
11574 let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
11575 selector.add_incoming(&[
11576 (
11577 &self
11578 .intrinsics
11579 .i32_ty
11580 .const_int(CATCH_ALL_TAG_VALUE as u64, false),
11581 catch_all_block,
11582 ),
11583 (
11584 &selector_value
11585 .try_as_basic_value()
11586 .unwrap_basic()
11587 .into_int_value(),
11588 catch_specific_block,
11589 ),
11590 ]);
11591
11592 let uw_exc = uw_exc.into_pointer_value();
11637 let exnref = self.build_call_with_param_attributes(
11638 self.intrinsics.exception_into_exnref,
11639 &[uw_exc.into()],
11640 "exnref",
11641 )?;
11642
11643 let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
11644 let selector = selector.as_basic_value().into_int_value();
11645
11646 for catch in catches.iter() {
11647 match catch {
11648 Catch::All { label } => {
11649 let b = self
11650 .context
11651 .append_basic_block(self.function, "catch_all_clause");
11652 self.builder.position_at_end(b);
11653 let frame = self.state.frame_at_depth(*label)?;
11654
11655 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11656
11657 self.builder.position_at_end(catch_end_block);
11658 catch_blocks.push((b, None));
11659 }
11660 Catch::One { tag, label } => {
11661 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11662 let signature = &self.wasm_module.signatures[tag_idx];
11663 let params = signature.params();
11664
11665 let b = self.context.append_basic_block(
11666 self.function,
11667 format!("catch_one_clause_{tag}").as_str(),
11668 );
11669 self.builder.position_at_end(b);
11670
11671 let exnref_phi = err!(
11672 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11673 );
11674 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11675
11676 let exn_payload_ptr = err!(self.builder.build_direct_call(
11678 self.intrinsics.read_exnref,
11679 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11680 "exn_ptr",
11681 ));
11682 let exn_payload_ptr = exn_payload_ptr
11683 .try_as_basic_value()
11684 .unwrap_basic()
11685 .into_pointer_value();
11686
11687 let values = params
11689 .iter()
11690 .enumerate()
11691 .map(|(i, v)| {
11692 let name = format!("value_{i}");
11693 let ptr = err!(unsafe {
11694 self.builder.build_gep(
11695 self.intrinsics.i128_ty,
11696 exn_payload_ptr,
11697 &[self
11698 .intrinsics
11699 .i32_ty
11700 .const_int(i as u64, false)],
11701 format!("{name}_ptr").as_str(),
11702 )
11703 });
11704 err_nt!(self.builder.build_load(
11705 type_to_llvm(self.intrinsics, *v)?,
11706 ptr,
11707 &name,
11708 ))
11709 })
11710 .collect::<Result<Vec<_>, CompileError>>()?;
11711
11712 let frame = self.state.frame_at_depth(*label)?;
11713
11714 for (phi, value) in frame.phis().iter().zip(values.iter()) {
11715 phi.add_incoming(&[(value, b)])
11716 }
11717
11718 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11719
11720 self.builder.position_at_end(catch_end_block);
11721 catch_blocks.push((b, Some(exnref_phi)));
11722 }
11723 Catch::OneRef { label, tag } => {
11724 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11725 let signature = &self.wasm_module.signatures[tag_idx];
11726 let params = signature.params();
11727
11728 let b = self.context.append_basic_block(
11729 self.function,
11730 format!("catch_one_ref_clause_{tag}").as_str(),
11731 );
11732 self.builder.position_at_end(b);
11733
11734 let exnref_phi = err!(
11735 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11736 );
11737 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11738
11739 let exn_payload_ptr = err!(self.builder.build_direct_call(
11741 self.intrinsics.read_exnref,
11742 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11743 "exn_ptr",
11744 ));
11745 let exn_payload_ptr = exn_payload_ptr
11746 .try_as_basic_value()
11747 .unwrap_basic()
11748 .into_pointer_value();
11749
11750 let mut values = params
11752 .iter()
11753 .enumerate()
11754 .map(|(i, v)| {
11755 let name = format!("value_{i}");
11756 let ptr = err!(unsafe {
11757 self.builder.build_gep(
11758 self.intrinsics.i128_ty,
11759 exn_payload_ptr,
11760 &[self
11761 .intrinsics
11762 .i32_ty
11763 .const_int(i as u64, false)],
11764 format!("{name}_ptr").as_str(),
11765 )
11766 });
11767 err_nt!(self.builder.build_load(
11768 type_to_llvm(self.intrinsics, *v)?,
11769 ptr,
11770 &name,
11771 ))
11772 })
11773 .collect::<Result<Vec<_>, CompileError>>()?;
11774
11775 values.push(exnref_phi.as_basic_value());
11776
11777 let frame = self.state.frame_at_depth(*label)?;
11778
11779 for (phi, value) in frame.phis().iter().zip(values.iter()) {
11780 phi.add_incoming(&[(value, b)])
11781 }
11782
11783 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11784
11785 self.builder.position_at_end(catch_end_block);
11786 catch_blocks.push((b, Some(exnref_phi)));
11787 }
11788 Catch::AllRef { label } => {
11789 let b = self
11790 .context
11791 .append_basic_block(self.function, "catch_all_ref_clause");
11792 self.builder.position_at_end(b);
11793
11794 let exnref_phi = err!(
11795 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11796 );
11797 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11798
11799 let frame = self.state.frame_at_depth(*label)?;
11800
11801 let phis = frame.phis();
11802
11803 assert_eq!(phis.len(), 1);
11804 phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
11805
11806 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11807
11808 self.builder.position_at_end(catch_end_block);
11809 catch_blocks.push((b, Some(exnref_phi)));
11810 }
11811 }
11812 }
11813
11814 for catch_info in &outer_catch_blocks {
11815 if let Some(phi) = catch_info.exnref_phi {
11816 phi.add_incoming(&[(&exnref, catch_end_block)]);
11817 }
11818 }
11819
11820 err!(
11821 self.builder.build_switch(
11822 selector,
11823 rethrow_block,
11824 catch_blocks
11825 .iter()
11826 .enumerate()
11827 .map(|(i, v)| (
11828 self.intrinsics
11829 .i32_ty
11830 .const_int(catch_tag_values[i] as _, false),
11831 v.0
11832 ))
11833 .chain(outer_catch_blocks.iter().map(|catch_info| (
11834 self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
11835 catch_info.catch_block
11836 )))
11837 .collect::<Vec<_>>()
11838 .as_slice()
11839 )
11840 );
11841
11842 self.builder.position_at_end(rethrow_block);
11846
11847 self.build_call_with_param_attributes(
11848 self.intrinsics.throw,
11849 &[self.ctx.basic().into(), exnref.into()],
11850 "rethrow",
11851 )?;
11852 err!(self.builder.build_unreachable());
11854
11855 maybe_lpad_block = Some(lpad_block);
11856 }
11857
11858 self.builder.position_at_end(current_block);
11860
11861 let catch_tags_and_blocks = catch_tag_values
11864 .into_iter()
11865 .zip(catch_blocks)
11866 .map(|(tag, (block, exnref_phi))| TagCatchInfo {
11867 tag,
11868 catch_block: block,
11869 exnref_phi,
11870 })
11871 .collect::<Vec<_>>();
11872 self.state.push_landingpad(
11873 maybe_lpad_block,
11874 end_block,
11875 end_phis,
11876 &catch_tags_and_blocks,
11877 self.module_translation
11878 .blocktype_params_results(&try_table.ty)?
11879 .0
11880 .len(),
11881 );
11882 }
11883 Operator::Throw { tag_index } => {
11884 let current_block = self
11885 .builder
11886 .get_insert_block()
11887 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11888
11889 let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
11890 let signature = &self.wasm_module.signatures[sig_index];
11891 let params = signature.params();
11892 let values = self.state.popn_save_extra(params.len())?;
11893
11894 values.iter().enumerate().try_for_each(|(i, (v, _))| {
11895 let t = type_to_llvm(self.intrinsics, params[i])?;
11896 if t != v.get_type() {
11897 return Err(CompileError::Codegen(format!(
11898 "Incompatible types: {:?} != {:?}",
11899 t,
11900 v.get_type()
11901 )));
11902 }
11903
11904 Ok(())
11905 })?;
11906
11907 let exnref = err!(
11909 self.builder.build_direct_call(
11910 self.intrinsics.alloc_exception,
11911 &[
11912 self.ctx.basic().into(),
11913 self.intrinsics
11914 .i32_ty
11915 .const_int(tag_index as _, false)
11916 .into()
11917 ],
11918 "exnref",
11919 )
11920 );
11921 let exnref = exnref.try_as_basic_value().unwrap_basic();
11922
11923 let exn_payload_ptr = err!(self.builder.build_direct_call(
11924 self.intrinsics.read_exnref,
11925 &[self.ctx.basic().into(), exnref.into()],
11926 "exn_ptr",
11927 ));
11928 let exn_payload_ptr = exn_payload_ptr
11929 .try_as_basic_value()
11930 .unwrap_basic()
11931 .into_pointer_value();
11932
11933 for (i, value) in values.into_iter().enumerate() {
11934 let ptr = err!(unsafe {
11935 self.builder.build_gep(
11936 self.intrinsics.i128_ty,
11937 exn_payload_ptr,
11938 &[self.intrinsics.i32_ty.const_int(i as u64, false)],
11939 format!("value_{i}_ptr").as_str(),
11940 )
11941 });
11942 err!(self.builder.build_store(ptr, value.0));
11943 }
11944
11945 if let Some(pad) = self.state.get_innermost_landingpad() {
11946 let unreachable_block = self
11947 .context
11948 .append_basic_block(self.function, "_throw_unreachable");
11949
11950 err!(self.builder.build_invoke(
11951 self.intrinsics.throw,
11952 &[self.ctx.basic(), exnref],
11953 unreachable_block,
11954 pad,
11955 "throw",
11956 ));
11957
11958 self.builder.position_at_end(unreachable_block);
11959 err!(self.builder.build_unreachable());
11961
11962 self.builder.position_at_end(current_block);
11963 } else {
11964 self.build_call_with_param_attributes(
11965 self.intrinsics.throw,
11966 &[self.ctx.basic().into(), exnref.into()],
11967 "throw",
11968 )?;
11969 err!(self.builder.build_unreachable());
11971 }
11972
11973 self.state.reachable = false;
11974 }
11975 Operator::ThrowRef => {
11976 let current_block = self
11977 .builder
11978 .get_insert_block()
11979 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11980
11981 let exnref = self.state.pop1()?;
11982
11983 if let Some(pad) = self.state.get_innermost_landingpad() {
11984 let unreachable_block = self
11985 .context
11986 .append_basic_block(self.function, "_rethrow_unreachable");
11987
11988 err!(self.builder.build_invoke(
11989 self.intrinsics.throw,
11990 &[self.ctx.basic(), exnref],
11991 unreachable_block,
11992 pad,
11993 "throw",
11994 ));
11995
11996 self.builder.position_at_end(unreachable_block);
11997 err!(self.builder.build_unreachable());
11999
12000 self.builder.position_at_end(current_block);
12001 } else {
12002 self.build_call_with_param_attributes(
12003 self.intrinsics.throw,
12004 &[self.ctx.basic().into(), exnref.into()],
12005 "throw",
12006 )?;
12007 err!(self.builder.build_unreachable());
12009 }
12010
12011 self.state.reachable = false;
12012 }
12013 _ => unreachable!(),
12014 }
12015 Ok(())
12016 }
12017
12018 fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
12019 if !self.state.reachable {
12022 match op {
12023 Operator::Block { blockty: _ }
12024 | Operator::Loop { blockty: _ }
12025 | Operator::If { blockty: _ }
12026 | Operator::TryTable { .. } => {
12027 self.unreachable_depth += 1;
12028 return Ok(());
12029 }
12030 Operator::Else => {
12031 if self.unreachable_depth != 0 {
12032 return Ok(());
12033 }
12034 }
12035 Operator::End => {
12036 if self.unreachable_depth != 0 {
12037 self.unreachable_depth -= 1;
12038 return Ok(());
12039 }
12040 }
12041 _ => {
12042 return Ok(());
12043 }
12044 }
12045 }
12046
12047 match op {
12048 Operator::Block { .. }
12049 | Operator::Loop { .. }
12050 | Operator::Br { .. }
12051 | Operator::BrIf { .. }
12052 | Operator::BrTable { .. }
12053 | Operator::If { .. }
12054 | Operator::Else
12055 | Operator::End
12056 | Operator::Return
12057 | Operator::Unreachable => {
12058 self.translate_control_flow_operator(op)?;
12059 }
12060 Operator::Nop
12061 | Operator::Drop
12062 | Operator::I32Const { .. }
12063 | Operator::I64Const { .. }
12064 | Operator::F32Const { .. }
12065 | Operator::F64Const { .. }
12066 | Operator::V128Const { .. }
12067 | Operator::I8x16Splat
12068 | Operator::I16x8Splat
12069 | Operator::I32x4Splat
12070 | Operator::I64x2Splat
12071 | Operator::F32x4Splat
12072 | Operator::F64x2Splat
12073 | Operator::LocalGet { .. }
12074 | Operator::LocalSet { .. }
12075 | Operator::LocalTee { .. }
12076 | Operator::GlobalGet { .. }
12077 | Operator::GlobalSet { .. }
12078 | Operator::Call { .. }
12079 | Operator::ReturnCall { .. }
12080 | Operator::CallIndirect { .. }
12081 | Operator::ReturnCallIndirect { .. }
12082 | Operator::TypedSelect { .. }
12083 | Operator::Select => {
12084 self.translate_basic_operator(op)?;
12085 }
12086 Operator::I32Add
12087 | Operator::I64Add
12088 | Operator::I8x16Add
12089 | Operator::I16x8Add
12090 | Operator::I16x8ExtAddPairwiseI8x16S
12091 | Operator::I16x8ExtAddPairwiseI8x16U
12092 | Operator::I32x4Add
12093 | Operator::I32x4ExtAddPairwiseI16x8S
12094 | Operator::I32x4ExtAddPairwiseI16x8U
12095 | Operator::I64x2Add
12096 | Operator::I8x16AddSatS
12097 | Operator::I16x8AddSatS
12098 | Operator::I8x16AddSatU
12099 | Operator::I16x8AddSatU
12100 | Operator::I32Sub
12101 | Operator::I64Sub
12102 | Operator::I8x16Sub
12103 | Operator::I16x8Sub
12104 | Operator::I32x4Sub
12105 | Operator::I64x2Sub
12106 | Operator::I8x16SubSatS
12107 | Operator::I16x8SubSatS
12108 | Operator::I8x16SubSatU
12109 | Operator::I16x8SubSatU
12110 | Operator::I32Mul
12111 | Operator::I64Mul
12112 | Operator::I16x8Mul
12113 | Operator::I32x4Mul
12114 | Operator::I64x2Mul
12115 | Operator::I16x8RelaxedQ15mulrS
12116 | Operator::I16x8Q15MulrSatS
12117 | Operator::I16x8ExtMulLowI8x16S
12118 | Operator::I16x8ExtMulLowI8x16U
12119 | Operator::I16x8ExtMulHighI8x16S
12120 | Operator::I16x8ExtMulHighI8x16U
12121 | Operator::I32x4ExtMulLowI16x8S
12122 | Operator::I32x4ExtMulLowI16x8U
12123 | Operator::I32x4ExtMulHighI16x8S
12124 | Operator::I32x4ExtMulHighI16x8U
12125 | Operator::I64x2ExtMulLowI32x4S
12126 | Operator::I64x2ExtMulLowI32x4U
12127 | Operator::I64x2ExtMulHighI32x4S
12128 | Operator::I64x2ExtMulHighI32x4U
12129 | Operator::I32x4DotI16x8S
12130 | Operator::I16x8RelaxedDotI8x16I7x16S
12131 | Operator::I32x4RelaxedDotI8x16I7x16AddS
12132 | Operator::I32DivS
12133 | Operator::I64DivS
12134 | Operator::I32DivU
12135 | Operator::I64DivU
12136 | Operator::I32RemS
12137 | Operator::I64RemS
12138 | Operator::I32RemU
12139 | Operator::I64RemU
12140 | Operator::I32And
12141 | Operator::I64And
12142 | Operator::V128And
12143 | Operator::I32Or
12144 | Operator::I64Or
12145 | Operator::V128Or
12146 | Operator::I32Xor
12147 | Operator::I64Xor
12148 | Operator::V128Xor
12149 | Operator::V128AndNot
12150 | Operator::I8x16RelaxedLaneselect
12151 | Operator::I16x8RelaxedLaneselect
12152 | Operator::I32x4RelaxedLaneselect
12153 | Operator::I64x2RelaxedLaneselect
12154 | Operator::V128Bitselect
12155 | Operator::I8x16Bitmask
12156 | Operator::I16x8Bitmask
12157 | Operator::I32x4Bitmask
12158 | Operator::I64x2Bitmask
12159 | Operator::I32Shl
12160 | Operator::I64Shl
12161 | Operator::I8x16Shl
12162 | Operator::I16x8Shl
12163 | Operator::I32x4Shl
12164 | Operator::I64x2Shl
12165 | Operator::I32ShrS
12166 | Operator::I64ShrS
12167 | Operator::I8x16ShrS
12168 | Operator::I16x8ShrS
12169 | Operator::I32x4ShrS
12170 | Operator::I64x2ShrS
12171 | Operator::I32ShrU
12172 | Operator::I64ShrU
12173 | Operator::I8x16ShrU
12174 | Operator::I16x8ShrU
12175 | Operator::I32x4ShrU
12176 | Operator::I64x2ShrU
12177 | Operator::I32Rotl
12178 | Operator::I64Rotl
12179 | Operator::I32Rotr
12180 | Operator::I64Rotr
12181 | Operator::I32Clz
12182 | Operator::I64Clz
12183 | Operator::I32Ctz
12184 | Operator::I64Ctz
12185 | Operator::I8x16Popcnt
12186 | Operator::I32Popcnt
12187 | Operator::I64Popcnt
12188 | Operator::I32Eqz
12189 | Operator::I64Eqz
12190 | Operator::I8x16Abs
12191 | Operator::I16x8Abs
12192 | Operator::I32x4Abs
12193 | Operator::I64x2Abs
12194 | Operator::I8x16MinS
12195 | Operator::I8x16MinU
12196 | Operator::I8x16MaxS
12197 | Operator::I8x16MaxU
12198 | Operator::I16x8MinS
12199 | Operator::I16x8MinU
12200 | Operator::I16x8MaxS
12201 | Operator::I16x8MaxU
12202 | Operator::I32x4MinS
12203 | Operator::I32x4MinU
12204 | Operator::I32x4MaxS
12205 | Operator::I32x4MaxU
12206 | Operator::I8x16AvgrU
12207 | Operator::I16x8AvgrU
12208 | Operator::I64Add128
12209 | Operator::I64Sub128
12210 | Operator::I64MulWideS
12211 | Operator::I64MulWideU => self.translate_integer_arithmetic_operator(op)?,
12212 Operator::F32Add
12213 | Operator::F64Add
12214 | Operator::F32x4Add
12215 | Operator::F64x2Add
12216 | Operator::F32Sub
12217 | Operator::F64Sub
12218 | Operator::F32x4Sub
12219 | Operator::F64x2Sub
12220 | Operator::F32Mul
12221 | Operator::F64Mul
12222 | Operator::F32x4Mul
12223 | Operator::F32x4RelaxedMadd
12224 | Operator::F32x4RelaxedNmadd
12225 | Operator::F64x2Mul
12226 | Operator::F64x2RelaxedMadd
12227 | Operator::F64x2RelaxedNmadd
12228 | Operator::F32Div
12229 | Operator::F64Div
12230 | Operator::F32x4Div
12231 | Operator::F64x2Div
12232 | Operator::F32Sqrt
12233 | Operator::F64Sqrt
12234 | Operator::F32x4Sqrt
12235 | Operator::F64x2Sqrt
12236 | Operator::F32Min
12237 | Operator::F64Min
12238 | Operator::F32x4RelaxedMin
12239 | Operator::F32x4Min
12240 | Operator::F32x4PMin
12241 | Operator::F64x2RelaxedMin
12242 | Operator::F64x2Min
12243 | Operator::F64x2PMin
12244 | Operator::F32Max
12245 | Operator::F64Max
12246 | Operator::F32x4RelaxedMax
12247 | Operator::F32x4Max
12248 | Operator::F32x4PMax
12249 | Operator::F64x2RelaxedMax
12250 | Operator::F64x2Max
12251 | Operator::F64x2PMax
12252 | Operator::F32Ceil
12253 | Operator::F32x4Ceil
12254 | Operator::F64Ceil
12255 | Operator::F64x2Ceil
12256 | Operator::F32Floor
12257 | Operator::F32x4Floor
12258 | Operator::F64Floor
12259 | Operator::F64x2Floor
12260 | Operator::F32Trunc
12261 | Operator::F32x4Trunc
12262 | Operator::F64Trunc
12263 | Operator::F64x2Trunc
12264 | Operator::F32Nearest
12265 | Operator::F32x4Nearest
12266 | Operator::F64Nearest
12267 | Operator::F64x2Nearest
12268 | Operator::F32Abs
12269 | Operator::F64Abs
12270 | Operator::F32x4Abs
12271 | Operator::F64x2Abs
12272 | Operator::F32x4Neg
12273 | Operator::F64x2Neg
12274 | Operator::F32Neg
12275 | Operator::F64Neg
12276 | Operator::F32Copysign
12277 | Operator::F64Copysign => self.translate_floating_point_arithmetic_operator(op)?,
12278 Operator::I32Eq
12279 | Operator::I64Eq
12280 | Operator::I8x16Eq
12281 | Operator::I16x8Eq
12282 | Operator::I32x4Eq
12283 | Operator::I64x2Eq
12284 | Operator::I32Ne
12285 | Operator::I64Ne
12286 | Operator::I8x16Ne
12287 | Operator::I16x8Ne
12288 | Operator::I32x4Ne
12289 | Operator::I64x2Ne
12290 | Operator::I32LtS
12291 | Operator::I64LtS
12292 | Operator::I8x16LtS
12293 | Operator::I16x8LtS
12294 | Operator::I32x4LtS
12295 | Operator::I64x2LtS
12296 | Operator::I32LtU
12297 | Operator::I64LtU
12298 | Operator::I8x16LtU
12299 | Operator::I16x8LtU
12300 | Operator::I32x4LtU
12301 | Operator::I32LeS
12302 | Operator::I64LeS
12303 | Operator::I8x16LeS
12304 | Operator::I16x8LeS
12305 | Operator::I32x4LeS
12306 | Operator::I64x2LeS
12307 | Operator::I32LeU
12308 | Operator::I64LeU
12309 | Operator::I8x16LeU
12310 | Operator::I16x8LeU
12311 | Operator::I32x4LeU
12312 | Operator::I32GtS
12313 | Operator::I64GtS
12314 | Operator::I8x16GtS
12315 | Operator::I16x8GtS
12316 | Operator::I32x4GtS
12317 | Operator::I64x2GtS
12318 | Operator::I32GtU
12319 | Operator::I64GtU
12320 | Operator::I8x16GtU
12321 | Operator::I16x8GtU
12322 | Operator::I32x4GtU
12323 | Operator::I32GeS
12324 | Operator::I64GeS
12325 | Operator::I8x16GeS
12326 | Operator::I16x8GeS
12327 | Operator::I32x4GeS
12328 | Operator::I64x2GeS
12329 | Operator::I32GeU
12330 | Operator::I64GeU
12331 | Operator::I8x16GeU
12332 | Operator::I16x8GeU
12333 | Operator::I32x4GeU => self.translate_integer_comparison_operator(op)?,
12334 Operator::F32Eq
12335 | Operator::F64Eq
12336 | Operator::F32x4Eq
12337 | Operator::F64x2Eq
12338 | Operator::F32Ne
12339 | Operator::F64Ne
12340 | Operator::F32x4Ne
12341 | Operator::F64x2Ne
12342 | Operator::F32Lt
12343 | Operator::F64Lt
12344 | Operator::F32x4Lt
12345 | Operator::F64x2Lt
12346 | Operator::F32Le
12347 | Operator::F64Le
12348 | Operator::F32x4Le
12349 | Operator::F64x2Le
12350 | Operator::F32Gt
12351 | Operator::F64Gt
12352 | Operator::F32x4Gt
12353 | Operator::F64x2Gt
12354 | Operator::F32Ge
12355 | Operator::F64Ge
12356 | Operator::F32x4Ge
12357 | Operator::F64x2Ge => self.translate_floating_point_comparison_operator(op)?,
12358 Operator::I32WrapI64
12359 | Operator::I64ExtendI32S
12360 | Operator::I64ExtendI32U
12361 | Operator::I16x8ExtendLowI8x16S
12362 | Operator::I16x8ExtendHighI8x16S
12363 | Operator::I16x8ExtendLowI8x16U
12364 | Operator::I16x8ExtendHighI8x16U
12365 | Operator::I32x4ExtendLowI16x8S
12366 | Operator::I32x4ExtendHighI16x8S
12367 | Operator::I32x4ExtendLowI16x8U
12368 | Operator::I32x4ExtendHighI16x8U
12369 | Operator::I64x2ExtendLowI32x4U
12370 | Operator::I64x2ExtendLowI32x4S
12371 | Operator::I64x2ExtendHighI32x4U
12372 | Operator::I64x2ExtendHighI32x4S
12373 | Operator::I8x16NarrowI16x8S
12374 | Operator::I8x16NarrowI16x8U
12375 | Operator::I16x8NarrowI32x4S
12376 | Operator::I16x8NarrowI32x4U
12377 | Operator::I32x4RelaxedTruncF32x4S
12378 | Operator::I32x4TruncSatF32x4S
12379 | Operator::I32x4RelaxedTruncF32x4U
12380 | Operator::I32x4TruncSatF32x4U
12381 | Operator::I32x4RelaxedTruncF64x2SZero
12382 | Operator::I32x4RelaxedTruncF64x2UZero
12383 | Operator::I32x4TruncSatF64x2SZero
12384 | Operator::I32x4TruncSatF64x2UZero
12385 | Operator::I32TruncF32S
12386 | Operator::I32TruncF64S
12387 | Operator::I32TruncSatF32S
12388 | Operator::I32TruncSatF64S
12389 | Operator::I64TruncF32S
12390 | Operator::I64TruncF64S
12391 | Operator::I64TruncSatF32S
12392 | Operator::I64TruncSatF64S
12393 | Operator::I32TruncF32U
12394 | Operator::I32TruncF64U
12395 | Operator::I32TruncSatF32U
12396 | Operator::I32TruncSatF64U
12397 | Operator::I64TruncF32U
12398 | Operator::I64TruncF64U
12399 | Operator::I64TruncSatF32U
12400 | Operator::I64TruncSatF64U
12401 | Operator::F32DemoteF64
12402 | Operator::F64PromoteF32
12403 | Operator::F32ConvertI32S
12404 | Operator::F32ConvertI64S
12405 | Operator::F64ConvertI32S
12406 | Operator::F64ConvertI64S
12407 | Operator::F32ConvertI32U
12408 | Operator::F32ConvertI64U
12409 | Operator::F64ConvertI32U
12410 | Operator::F64ConvertI64U
12411 | Operator::F32x4ConvertI32x4S
12412 | Operator::F32x4ConvertI32x4U
12413 | Operator::F64x2ConvertLowI32x4S
12414 | Operator::F64x2ConvertLowI32x4U
12415 | Operator::F64x2PromoteLowF32x4
12416 | Operator::F32x4DemoteF64x2Zero
12417 | Operator::I32ReinterpretF32
12418 | Operator::I64ReinterpretF64
12419 | Operator::F32ReinterpretI32
12420 | Operator::F64ReinterpretI64 => self.translate_conversion_operator(op)?,
12421 Operator::I32Extend8S
12422 | Operator::I32Extend16S
12423 | Operator::I64Extend8S
12424 | Operator::I64Extend16S
12425 | Operator::I64Extend32S => self.translate_sign_extension_operator(op)?,
12426 Operator::I32Load { .. }
12427 | Operator::I64Load { .. }
12428 | Operator::F32Load { .. }
12429 | Operator::F64Load { .. }
12430 | Operator::V128Load { .. }
12431 | Operator::V128Load8Lane { .. }
12432 | Operator::V128Load16Lane { .. }
12433 | Operator::V128Load32Lane { .. }
12434 | Operator::V128Load64Lane { .. }
12435 | Operator::I32Store { .. }
12436 | Operator::I64Store { .. }
12437 | Operator::F32Store { .. }
12438 | Operator::F64Store { .. }
12439 | Operator::V128Store { .. }
12440 | Operator::V128Store8Lane { .. }
12441 | Operator::V128Store16Lane { .. }
12442 | Operator::V128Store32Lane { .. }
12443 | Operator::V128Store64Lane { .. }
12444 | Operator::I32Load8S { .. }
12445 | Operator::I32Load16S { .. }
12446 | Operator::I64Load8S { .. }
12447 | Operator::I64Load16S { .. }
12448 | Operator::I64Load32S { .. }
12449 | Operator::I32Load8U { .. }
12450 | Operator::I32Load16U { .. }
12451 | Operator::I64Load8U { .. }
12452 | Operator::I64Load16U { .. }
12453 | Operator::I64Load32U { .. }
12454 | Operator::I32Store8 { .. }
12455 | Operator::I64Store8 { .. }
12456 | Operator::I32Store16 { .. }
12457 | Operator::I64Store16 { .. }
12458 | Operator::I64Store32 { .. }
12459 | Operator::I8x16Neg
12460 | Operator::I16x8Neg
12461 | Operator::I32x4Neg
12462 | Operator::I64x2Neg
12463 | Operator::V128Not
12464 | Operator::V128AnyTrue
12465 | Operator::I8x16AllTrue
12466 | Operator::I16x8AllTrue
12467 | Operator::I32x4AllTrue
12468 | Operator::I64x2AllTrue
12469 | Operator::I8x16ExtractLaneS { .. }
12470 | Operator::I8x16ExtractLaneU { .. }
12471 | Operator::I16x8ExtractLaneS { .. }
12472 | Operator::I16x8ExtractLaneU { .. }
12473 | Operator::I32x4ExtractLane { .. }
12474 | Operator::I64x2ExtractLane { .. }
12475 | Operator::F32x4ExtractLane { .. }
12476 | Operator::F64x2ExtractLane { .. }
12477 | Operator::I8x16ReplaceLane { .. }
12478 | Operator::I16x8ReplaceLane { .. }
12479 | Operator::I32x4ReplaceLane { .. }
12480 | Operator::I64x2ReplaceLane { .. }
12481 | Operator::F32x4ReplaceLane { .. }
12482 | Operator::F64x2ReplaceLane { .. }
12483 | Operator::I8x16RelaxedSwizzle
12484 | Operator::I8x16Swizzle
12485 | Operator::I8x16Shuffle { .. }
12486 | Operator::V128Load8x8S { .. }
12487 | Operator::V128Load8x8U { .. }
12488 | Operator::V128Load16x4S { .. }
12489 | Operator::V128Load16x4U { .. }
12490 | Operator::V128Load32x2S { .. }
12491 | Operator::V128Load32x2U { .. }
12492 | Operator::V128Load32Zero { .. }
12493 | Operator::V128Load64Zero { .. }
12494 | Operator::V128Load8Splat { .. }
12495 | Operator::V128Load16Splat { .. }
12496 | Operator::V128Load32Splat { .. }
12497 | Operator::V128Load64Splat { .. }
12498 | Operator::MemoryGrow { .. }
12499 | Operator::MemorySize { .. }
12500 | Operator::MemoryInit { .. }
12501 | Operator::DataDrop { .. }
12502 | Operator::MemoryCopy { .. }
12503 | Operator::MemoryFill { .. } => self.translate_memory_operator(op)?,
12504 Operator::AtomicFence { .. }
12505 | Operator::I32AtomicLoad { .. }
12506 | Operator::I64AtomicLoad { .. }
12507 | Operator::I32AtomicLoad8U { .. }
12508 | Operator::I32AtomicLoad16U { .. }
12509 | Operator::I64AtomicLoad8U { .. }
12510 | Operator::I64AtomicLoad16U { .. }
12511 | Operator::I64AtomicLoad32U { .. }
12512 | Operator::I32AtomicStore { .. }
12513 | Operator::I64AtomicStore { .. }
12514 | Operator::I32AtomicStore8 { .. }
12515 | Operator::I64AtomicStore8 { .. }
12516 | Operator::I32AtomicStore16 { .. }
12517 | Operator::I64AtomicStore16 { .. }
12518 | Operator::I64AtomicStore32 { .. }
12519 | Operator::I32AtomicRmw8AddU { .. }
12520 | Operator::I32AtomicRmw16AddU { .. }
12521 | Operator::I32AtomicRmwAdd { .. }
12522 | Operator::I64AtomicRmw8AddU { .. }
12523 | Operator::I64AtomicRmw16AddU { .. }
12524 | Operator::I64AtomicRmw32AddU { .. }
12525 | Operator::I64AtomicRmwAdd { .. }
12526 | Operator::I32AtomicRmw8SubU { .. }
12527 | Operator::I32AtomicRmw16SubU { .. }
12528 | Operator::I32AtomicRmwSub { .. }
12529 | Operator::I64AtomicRmw8SubU { .. }
12530 | Operator::I64AtomicRmw16SubU { .. }
12531 | Operator::I64AtomicRmw32SubU { .. }
12532 | Operator::I64AtomicRmwSub { .. }
12533 | Operator::I32AtomicRmw8AndU { .. }
12534 | Operator::I32AtomicRmw16AndU { .. }
12535 | Operator::I32AtomicRmwAnd { .. }
12536 | Operator::I64AtomicRmw8AndU { .. }
12537 | Operator::I64AtomicRmw16AndU { .. }
12538 | Operator::I64AtomicRmw32AndU { .. }
12539 | Operator::I64AtomicRmwAnd { .. }
12540 | Operator::I32AtomicRmw8OrU { .. }
12541 | Operator::I32AtomicRmw16OrU { .. }
12542 | Operator::I32AtomicRmwOr { .. }
12543 | Operator::I64AtomicRmw8OrU { .. }
12544 | Operator::I64AtomicRmw16OrU { .. }
12545 | Operator::I64AtomicRmw32OrU { .. }
12546 | Operator::I64AtomicRmwOr { .. }
12547 | Operator::I32AtomicRmw8XorU { .. }
12548 | Operator::I32AtomicRmw16XorU { .. }
12549 | Operator::I32AtomicRmwXor { .. }
12550 | Operator::I64AtomicRmw8XorU { .. }
12551 | Operator::I64AtomicRmw16XorU { .. }
12552 | Operator::I64AtomicRmw32XorU { .. }
12553 | Operator::I64AtomicRmwXor { .. }
12554 | Operator::I32AtomicRmw8XchgU { .. }
12555 | Operator::I32AtomicRmw16XchgU { .. }
12556 | Operator::I32AtomicRmwXchg { .. }
12557 | Operator::I64AtomicRmw8XchgU { .. }
12558 | Operator::I64AtomicRmw16XchgU { .. }
12559 | Operator::I64AtomicRmw32XchgU { .. }
12560 | Operator::I64AtomicRmwXchg { .. }
12561 | Operator::I32AtomicRmw8CmpxchgU { .. }
12562 | Operator::I32AtomicRmw16CmpxchgU { .. }
12563 | Operator::I32AtomicRmwCmpxchg { .. }
12564 | Operator::I64AtomicRmw8CmpxchgU { .. }
12565 | Operator::I64AtomicRmw16CmpxchgU { .. }
12566 | Operator::I64AtomicRmw32CmpxchgU { .. }
12567 | Operator::I64AtomicRmwCmpxchg { .. }
12568 | Operator::MemoryAtomicWait32 { .. }
12569 | Operator::MemoryAtomicWait64 { .. }
12570 | Operator::MemoryAtomicNotify { .. } => self.translate_atomic_memory_operator(op)?,
12571 Operator::RefNull { .. } | Operator::RefIsNull | Operator::RefFunc { .. } => {
12572 self.translate_reference_operator(op)?;
12573 }
12574 Operator::TableGet { .. }
12575 | Operator::TableSet { .. }
12576 | Operator::TableCopy { .. }
12577 | Operator::TableInit { .. }
12578 | Operator::ElemDrop { .. }
12579 | Operator::TableFill { .. }
12580 | Operator::TableGrow { .. }
12581 | Operator::TableSize { .. } => self.translate_table_operator(op)?,
12582 Operator::TryTable { .. } | Operator::Throw { .. } | Operator::ThrowRef => {
12583 self.translate_eh_operator(op)?;
12584 }
12585 _ => {
12586 return Err(CompileError::Codegen(format!(
12587 "Operator {op:?} unimplemented",
12588 )));
12589 }
12590 }
12591
12592 Ok(())
12593 }
12594
12595 fn build_call_with_param_attributes(
12596 &self,
12597 function: FunctionValue<'ctx>,
12598 args: &[BasicMetadataValueEnum<'ctx>],
12599 name: &str,
12600 ) -> Result<CallSiteValue<'ctx>, CompileError> {
12601 let call = self
12602 .builder
12603 .build_call(function, args, name)
12604 .map_err(|e| CompileError::Codegen(e.to_string()))?;
12605
12606 if matches!(
12611 self.target_triple.architecture,
12612 Architecture::Riscv32(..) | Architecture::Riscv64(..)
12613 ) {
12614 let param_types = function.get_type().get_param_types();
12615 for (i, ty) in param_types.into_iter().enumerate() {
12616 if ty == self.context.i32_type().into() {
12617 call.add_attribute(
12618 AttributeLoc::Param(i as u32),
12619 self.context
12620 .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
12621 );
12622 call.add_attribute(
12623 AttributeLoc::Param(i as u32),
12624 self.context
12625 .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
12626 );
12627 }
12628 }
12629 }
12630
12631 Ok(call)
12632 }
12633}
12634
12635fn is_f32_arithmetic(bits: u32) -> bool {
12636 let bits = bits & 0x7FFF_FFFF;
12638 bits < 0x7FC0_0000
12639}
12640
12641fn is_f64_arithmetic(bits: u64) -> bool {
12642 let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12644 bits < 0x7FF8_0000_0000_0000
12645}