1use std::num::NonZero;
2use std::{collections::HashMap, path::Path};
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::{
12 compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle, object_file::CompiledFunction,
13};
14use enumset::EnumSet;
15use inkwell::{
16 AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
17 attributes::{Attribute, AttributeLoc},
18 builder::Builder,
19 context::Context,
20 debug_info::{AsDIScope, DIFlags, DIFlagsConstants, DWARFEmissionKind, DWARFSourceLanguage},
21 module::{FlagBehavior, Linkage, Module},
22 passes::PassBuilderOptions,
23 targets::{FileType, TargetData, TargetMachine},
24 types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
25 values::{
26 BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
27 FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
28 PointerValue, VectorValue,
29 },
30};
31use itertools::Itertools;
32use smallvec::SmallVec;
33use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
34use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
35
36use crate::{
37 abi::{Abi, get_abi},
38 config::LLVM,
39 error::{err, err_nt},
40 object_file::load_object_file,
41};
42use wasmer_compiler::{
43 CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
44 GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
45 GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
46 LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
47 LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
48 from_binaryreadererror_wasmerror,
49 misc::{CompiledFunctionExt, CompiledKind},
50 types::{
51 relocation::RelocationTarget,
52 symbols::{Symbol, SymbolRegistry},
53 },
54 wasmparser::{Catch, MemArg, Operator},
55 wpheaptype_to_type, wptype_to_type,
56};
57use wasmer_types::{
58 CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
59 ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
60};
61use wasmer_types::{TagIndex, entity::PrimaryMap};
62use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
63
64const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
65const FUNCTION_SECTION_MACHO: &str = "__TEXT";
66const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
67
68const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
74
75pub struct FuncTranslator {
76 ctx: Context,
77 target_triple: Triple,
78 target_machines: HashMap<OptimizationStyle, TargetMachine>,
79 abi: Box<dyn Abi>,
80 binary_fmt: BinaryFormat,
81 func_section: String,
82 pointer_width: u8,
83 cpu_features: EnumSet<CpuFeature>,
84 non_volatile_memory_ops: bool,
85 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
86}
87
88impl wasmer_compiler::FuncTranslator for FuncTranslator {}
89
90impl FuncTranslator {
91 pub fn new(
92 target_triple: Triple,
93 target_machines: HashMap<OptimizationStyle, TargetMachine>,
94 binary_fmt: BinaryFormat,
95 pointer_width: u8,
96 cpu_features: EnumSet<CpuFeature>,
97 non_volatile_memory_ops: bool,
98 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
99 ) -> Result<Self, CompileError> {
100 let abi_source_tm = target_machines
101 .get(&OptimizationStyle::ForSpeed)
102 .expect("target_machines must contain OptimizationStyle::ForSpeed");
103 let abi = get_abi(abi_source_tm);
104 Ok(Self {
105 ctx: Context::create(),
106 target_triple,
107 target_machines,
108 abi,
109 func_section: match binary_fmt {
110 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
111 BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
112 _ => {
113 return Err(CompileError::UnsupportedTarget(format!(
114 "Unsupported binary format: {binary_fmt:?}"
115 )));
116 }
117 },
118 binary_fmt,
119 pointer_width,
120 cpu_features,
121 non_volatile_memory_ops,
122 wasm_apply_data_relocs_fn_index,
123 })
124 }
125
126 #[allow(clippy::too_many_arguments)]
127 pub fn translate_to_module(
128 &self,
129 wasm_module: &ModuleInfo,
130 module_translation: &ModuleTranslationState,
131 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
132 local_func_index: &LocalFunctionIndex,
133 function_body: &FunctionBodyData,
134 config: &LLVM,
135 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
136 _table_styles: &PrimaryMap<TableIndex, TableStyle>,
137 symbol_registry: &dyn SymbolRegistry,
138 target: &Triple,
139 opt_style: OptimizationStyle,
140 ) -> Result<Module<'_>, CompileError> {
141 let func_index = wasm_module.func_index(*local_func_index);
143 let function =
144 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
145
146 let m0_is_enabled = memory_styles
149 .get(MemoryIndex::from_u32(0))
150 .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
151
152 let (function_name, module_name) = if cfg!(feature = "experimental-artifact") {
153 (function.linkage_name(), String::new())
154 } else {
155 let function_name =
156 symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
157 let module_name = match wasm_module.name.as_ref() {
158 None => format!("<anonymous module> function {function_name}"),
159 Some(module_name) => format!("module {module_name} function {function_name}"),
160 };
161 (function_name, module_name)
162 };
163
164 let module = self.ctx.create_module(module_name.as_str());
165
166 let target_machine = &self.target_machines.values().next().unwrap();
167 let target_triple = target_machine.get_triple();
168 let target_data = target_machine.get_target_data();
169 module.set_triple(&target_triple);
170 module.set_data_layout(&target_data.get_data_layout());
171 let wasm_fn_type = wasm_module
172 .signatures
173 .get(wasm_module.functions[func_index])
174 .unwrap();
175
176 let offsets = VMOffsets::new(self.pointer_width, wasm_module);
177 let intrinsics = Intrinsics::declare(
178 &module,
179 &self.ctx,
180 &target_data,
181 &self.target_triple,
182 &self.binary_fmt,
183 );
184 let (func_type, func_attrs) = self.abi.func_type_to_llvm(
185 &self.ctx,
186 &intrinsics,
187 Some(&offsets),
188 wasm_fn_type,
189 m0_is_enabled,
190 )?;
191
192 let func = module.add_function(&function_name, func_type, Some(Linkage::External));
193 let debug_info = if cfg!(feature = "experimental-artifact") {
194 let debug_metadata_version = self
195 .ctx
196 .i32_type()
197 .const_int(inkwell::debug_info::debug_metadata_version().into(), false);
198 module.add_basic_value_flag(
199 "Debug Info Version",
200 FlagBehavior::Warning,
201 debug_metadata_version,
202 );
203 module.add_basic_value_flag(
204 "Dwarf Version",
205 FlagBehavior::Warning,
206 self.ctx.i32_type().const_int(4, false),
207 );
208
209 let (dibuilder, compile_unit) = module.create_debug_info_builder(
210 true,
211 DWARFSourceLanguage::C,
212 &wasm_module.name(),
213 ".",
214 "wasmer",
215 true,
216 "",
217 0,
218 "",
219 DWARFEmissionKind::Full,
220 0,
221 false,
222 false,
223 "",
224 "",
225 );
226 let subroutine_type = dibuilder.create_subroutine_type(
227 compile_unit.get_file(),
228 None,
229 &[],
230 DIFlags::PUBLIC,
231 );
232 let function_name = wasm_module.get_function_name(func_index);
233 let start_line = (function_body.module_offset as u32).saturating_add(1);
234 let subprogram = dibuilder.create_function(
235 compile_unit.as_debug_info_scope(),
236 &function_name,
237 None,
238 compile_unit.get_file(),
239 start_line,
240 subroutine_type,
241 false,
242 true,
243 start_line,
244 DIFlags::PUBLIC,
245 true,
246 );
247 func.set_subprogram(subprogram);
248 Some((dibuilder, subprogram))
249 } else {
250 None
251 };
252 for (attr, attr_loc) in &func_attrs {
253 func.add_attribute(*attr_loc, *attr);
254 }
255
256 if !matches!(target.operating_system, OperatingSystem::Windows) {
257 func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
258 }
259
260 func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
261 func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
262
263 let section = match self.binary_fmt {
264 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
265 BinaryFormat::Macho => {
266 format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
267 }
268 _ => {
269 return Err(CompileError::UnsupportedTarget(format!(
270 "Unsupported binary format: {:?}",
271 self.binary_fmt
272 )));
273 }
274 };
275
276 func.set_personality_function(intrinsics.personality);
277 if !cfg!(feature = "experimental-artifact") {
278 func.as_global_value().set_section(Some(§ion));
279 }
280
281 func.set_linkage(Linkage::DLLExport);
282 func.as_global_value()
283 .set_dll_storage_class(DLLStorageClass::Export);
284
285 let entry = self.ctx.append_basic_block(func, "entry");
286 let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
287 let return_ = self.ctx.append_basic_block(func, "return");
288 let alloca_builder = self.ctx.create_builder();
289 let cache_builder = self.ctx.create_builder();
290 let builder = self.ctx.create_builder();
291 cache_builder.position_at_end(entry);
292 let br = err!(cache_builder.build_unconditional_branch(start_of_code));
293 alloca_builder.position_before(&br);
294 cache_builder.position_before(&br);
295 builder.position_at_end(start_of_code);
296
297 let mut state = State::new();
298 builder.position_at_end(return_);
299 let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
300 .results()
301 .iter()
302 .map(|&wasm_ty| {
303 type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
304 })
305 .collect::<Result<_, _>>()?;
306 state.push_block(return_, phis, 0);
307 builder.position_at_end(start_of_code);
308
309 let mut reader = MiddlewareBinaryReader::new_with_offset(
310 function_body.data,
311 function_body.module_offset,
312 );
313 reader.set_middleware_chain(
314 config
315 .middlewares
316 .generate_function_middleware_chain(*local_func_index),
317 );
318
319 let mut params = vec![];
320 let first_param =
321 if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
322 if m0_is_enabled { 3 } else { 2 }
323 } else if m0_is_enabled {
324 2
325 } else {
326 1
327 };
328 let mut is_first_alloca = true;
329 let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
330 let alloca = err!(alloca_builder.build_alloca(ty, &name));
331 if is_first_alloca {
332 alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
333 is_first_alloca = false;
334 }
335 Ok(alloca)
336 };
337
338 for idx in 0..wasm_fn_type.params().len() {
356 let ty = wasm_fn_type.params()[idx];
357 let ty = type_to_llvm(&intrinsics, ty)?;
358 let value = func
359 .get_nth_param((idx as u32).checked_add(first_param).unwrap())
360 .unwrap();
361 let alloca = insert_alloca(ty, format!("param_{idx}"))?;
362 err!(cache_builder.build_store(alloca, value));
363 params.push((ty, alloca));
364 }
365
366 let mut locals = vec![];
367 let num_locals = reader.read_local_count()?;
368 for idx in 0..num_locals {
369 let (count, ty) = reader.read_local_decl()?;
370 let ty = err!(wptype_to_type(ty));
371 let ty = type_to_llvm(&intrinsics, ty)?;
372 for _ in 0..count {
373 let alloca = insert_alloca(ty, format!("local_{idx}"))?;
374 err!(cache_builder.build_store(alloca, ty.const_zero()));
375 locals.push((ty, alloca));
376 }
377 }
378
379 let mut params_locals = params.clone();
380 params_locals.extend(locals.iter().cloned());
381
382 let mut m0_param = None;
383
384 if m0_is_enabled {
385 let m0 = self.abi.get_m0_ptr_param(&func);
386 m0.set_name("m0_base_ptr");
387 m0_param = Some(m0);
388 }
389
390 let mut fcg = LLVMFunctionCodeGenerator {
391 m0_param,
392 context: &self.ctx,
393 builder,
394 alloca_builder,
395 intrinsics: &intrinsics,
396 target_data: &target_data,
397 state,
398 function: func,
399 locals: params_locals,
400 ctx: CtxType::new(
401 wasm_module,
402 &func,
403 &cache_builder,
404 &*self.abi,
405 self.pointer_width,
406 m0_param,
407 ),
408 unreachable_depth: 0,
409 memory_styles,
410 _table_styles,
411 module: &module,
412 module_translation,
413 signature_hashes,
414 wasm_module,
415 symbol_registry,
416 abi: &*self.abi,
417 config,
418 target_triple: self.target_triple.clone(),
419 tags_cache: HashMap::new(),
420 binary_fmt: self.binary_fmt,
421 cpu_features: self.cpu_features,
422 non_volatile_memory_ops: self.non_volatile_memory_ops,
423 };
424
425 fcg.ctx.add_func(
426 func_index,
427 func.as_global_value().as_pointer_value(),
428 func_type,
429 fcg.ctx.basic(),
430 &func_attrs,
431 );
432
433 while fcg.state.has_control_frames() {
434 let pos = reader.current_position() as u32;
435 let original_pos = reader.original_position() as u32;
436 let op = reader.read_operator()?;
437 if let Some((dibuilder, subprogram)) = debug_info.as_ref() {
438 let line = original_pos.saturating_add(1);
439 let loc = dibuilder.create_debug_location(
440 &self.ctx,
441 line,
442 1,
443 subprogram.as_debug_info_scope(),
444 None,
445 );
446 fcg.builder.set_current_debug_location(loc);
447 }
448 fcg.translate_operator(op, pos)?;
449 }
450
451 fcg.finalize(wasm_fn_type)?;
452 if let Some((dibuilder, _)) = debug_info {
453 dibuilder.finalize();
454 }
455
456 if let Some(ref callbacks) = config.callbacks {
457 callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
458 }
459
460 let mut passes = vec![];
461 if config.enable_verifier {
462 passes.push("verify");
463 }
464
465 match opt_style {
466 OptimizationStyle::Disabled => {
467 passes.push("default<O0>");
468 }
469 OptimizationStyle::ForSize => {
470 passes.push("default<O1>");
472 }
473 OptimizationStyle::ForSpeed => {
474 passes.push("sccp");
475 passes.push("early-cse");
476 passes.push("adce");
478 passes.push("sroa");
479 passes.push("aggressive-instcombine");
480 passes.push("jump-threading");
481 passes.push("simplifycfg");
483 passes.push("reassociate");
484 passes.push("loop-rotate");
485 passes.push("indvars");
486 passes.push("sccp");
490 passes.push("reassociate");
491 passes.push("simplifycfg");
492 passes.push("gvn");
493 passes.push("memcpyopt");
494 passes.push("dse");
495 passes.push("dce");
496 passes.push("reassociate");
498 passes.push("simplifycfg");
499 passes.push("mem2reg");
500 }
501 }
502
503 module
504 .run_passes(
505 &passes.join(","),
506 target_machine,
507 PassBuilderOptions::create(),
508 )
509 .unwrap();
510
511 if let Some(ref callbacks) = config.callbacks {
512 callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
513 }
514
515 Ok(module)
516 }
517
518 #[allow(clippy::too_many_arguments)]
519 pub fn translate(
520 &self,
521 wasm_module: &ModuleInfo,
522 module_translation: &ModuleTranslationState,
523 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
524 local_func_index: &LocalFunctionIndex,
525 function_body: &FunctionBodyData,
526 config: &LLVM,
527 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
528 table_styles: &PrimaryMap<TableIndex, TableStyle>,
529 symbol_registry: &ModuleBasedSymbolRegistry,
530 target: &Triple,
531 build_directory: &Path,
532 ) -> Result<CompiledFunction, CompileError> {
533 let func_index = wasm_module.func_index(*local_func_index);
534 let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
535 OptimizationStyle::Disabled
539 } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
540 OptimizationStyle::ForSize
541 } else {
542 OptimizationStyle::ForSpeed
543 };
544 let module = self.translate_to_module(
545 wasm_module,
546 module_translation,
547 signature_hashes,
548 local_func_index,
549 function_body,
550 config,
551 memory_styles,
552 table_styles,
553 symbol_registry,
554 target,
555 opt_style,
556 )?;
557 let function =
558 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
559
560 let target_machine = self.target_machines.get(&opt_style).unwrap();
561 let memory_buffer = target_machine
562 .write_to_memory_buffer(&module, FileType::Object)
563 .unwrap();
564
565 if let Some(ref callbacks) = config.callbacks {
566 let module_hash = wasm_module.hash().map(|m| m.to_string());
567 callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
568 let asm_buffer = target_machine
569 .write_to_memory_buffer(&module, FileType::Assembly)
570 .unwrap();
571 callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
572 }
573
574 if cfg!(feature = "experimental-artifact") {
575 let object_path = build_directory
576 .to_path_buf()
577 .join(function.object_filename());
578 std::fs::write(&object_path, memory_buffer.as_slice())
579 .map_err(|e| CompileError::Codegen(format!("Cannot save LLVM object file: {e}")))?;
580 Ok(CompiledFunction::Elf(object_path))
581 } else {
582 Ok(CompiledFunction::Rkyv(Box::new(load_object_file(
583 memory_buffer.as_slice(),
584 &self.func_section,
585 RelocationTarget::LocalFunc(*local_func_index),
586 |name: &str| {
587 Ok({
588 let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
589 name.strip_prefix("_").unwrap_or(name)
590 } else {
591 name
592 }
593 .to_string();
594 if let Some(Symbol::LocalFunction(local_func_index)) =
595 symbol_registry.name_to_symbol(&name)
596 {
597 Some(RelocationTarget::LocalFunc(local_func_index))
598 } else {
599 None
600 }
601 })
602 },
603 self.binary_fmt,
604 &self.target_triple,
605 )?)))
606 }
607 }
608}
609
610impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
611 fn splat_vector(
613 &self,
614 value: BasicValueEnum<'ctx>,
615 vec_ty: VectorType<'ctx>,
616 ) -> Result<VectorValue<'ctx>, CompileError> {
617 err_nt!(
620 self.builder.build_shuffle_vector(
621 err!(self.builder.build_insert_element(
622 vec_ty.get_undef(),
623 value,
624 self.intrinsics.i32_zero,
625 "",
626 )),
627 vec_ty.get_undef(),
628 self.intrinsics
629 .i32_ty
630 .vec_type(vec_ty.get_size())
631 .const_zero(),
632 "",
633 )
634 )
635 }
636
637 #[allow(clippy::too_many_arguments)]
640 fn trunc_sat<T: FloatMathType<'ctx>>(
641 &self,
642 fvec_ty: T,
643 ivec_ty: T::MathConvType,
644 lower_bound: u64, upper_bound: u64, int_min_value: u64,
647 int_max_value: u64,
648 value: IntValue<'ctx>,
649 ) -> Result<VectorValue<'ctx>, CompileError> {
650 let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
664 let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
665 let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
666 let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
667
668 let is_signed = int_min_value != 0;
669 let int_min_value = self.splat_vector(
670 ivec_element_ty
671 .const_int(int_min_value, is_signed)
672 .as_basic_value_enum(),
673 ivec_ty,
674 )?;
675 let int_max_value = self.splat_vector(
676 ivec_element_ty
677 .const_int(int_max_value, is_signed)
678 .as_basic_value_enum(),
679 ivec_ty,
680 )?;
681 let lower_bound = if is_signed {
682 err!(self.builder.build_signed_int_to_float(
683 ivec_element_ty.const_int(lower_bound, is_signed),
684 fvec_element_ty,
685 "",
686 ))
687 } else {
688 err!(self.builder.build_unsigned_int_to_float(
689 ivec_element_ty.const_int(lower_bound, is_signed),
690 fvec_element_ty,
691 "",
692 ))
693 };
694 let upper_bound = if is_signed {
695 err!(self.builder.build_signed_int_to_float(
696 ivec_element_ty.const_int(upper_bound, is_signed),
697 fvec_element_ty,
698 "",
699 ))
700 } else {
701 err!(self.builder.build_unsigned_int_to_float(
702 ivec_element_ty.const_int(upper_bound, is_signed),
703 fvec_element_ty,
704 "",
705 ))
706 };
707
708 let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
709 let zero = fvec_ty.const_zero();
710 let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
711 let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
712 let nan_cmp =
713 err!(
714 self.builder
715 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
716 );
717 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
718 FloatPredicate::OGT,
719 value,
720 upper_bound,
721 "above_upper_bound",
722 ));
723 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
724 FloatPredicate::OLT,
725 value,
726 lower_bound,
727 "below_lower_bound",
728 ));
729 let not_representable = err!(self.builder.build_or(
730 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
731 below_lower_bound_cmp,
732 "not_representable_as_int",
733 ));
734 let value =
735 err!(
736 self.builder
737 .build_select(not_representable, zero, value, "safe_to_convert")
738 )
739 .into_vector_value();
740 let value = if is_signed {
741 self.builder
742 .build_float_to_signed_int(value, ivec_ty, "as_int")
743 } else {
744 self.builder
745 .build_float_to_unsigned_int(value, ivec_ty, "as_int")
746 };
747
748 let value = err!(value);
749 let value =
750 err!(
751 self.builder
752 .build_select(above_upper_bound_cmp, int_max_value, value, "")
753 )
754 .into_vector_value();
755 err_nt!(
756 self.builder
757 .build_select(below_lower_bound_cmp, int_min_value, value, "")
758 .map(|v| v.into_vector_value())
759 )
760 }
761
762 #[allow(clippy::too_many_arguments)]
765 fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
766 &self,
767 fvec_ty: T,
768 ivec_ty: T::MathConvType,
769 lower_bound: u64, upper_bound: u64, int_min_value: u64,
772 int_max_value: u64,
773 value: IntValue<'ctx>,
774 ) -> Result<IntValue<'ctx>, CompileError> {
775 let res = self.trunc_sat(
776 fvec_ty,
777 ivec_ty,
778 lower_bound,
779 upper_bound,
780 int_min_value,
781 int_max_value,
782 value,
783 )?;
784 err_nt!(
785 self.builder
786 .build_bit_cast(res, self.intrinsics.i128_ty, "")
787 .map(|v| v.into_int_value())
788 )
789 }
790
791 fn trunc_sat_scalar(
794 &self,
795 int_ty: IntType<'ctx>,
796 lower_bound: u64, upper_bound: u64, int_min_value: u64,
799 int_max_value: u64,
800 value: FloatValue<'ctx>,
801 ) -> Result<IntValue<'ctx>, CompileError> {
802 let is_signed = int_min_value != 0;
818 let int_min_value = int_ty.const_int(int_min_value, is_signed);
819 let int_max_value = int_ty.const_int(int_max_value, is_signed);
820
821 let lower_bound = if is_signed {
822 err!(self.builder.build_signed_int_to_float(
823 int_ty.const_int(lower_bound, is_signed),
824 value.get_type(),
825 "",
826 ))
827 } else {
828 err!(self.builder.build_unsigned_int_to_float(
829 int_ty.const_int(lower_bound, is_signed),
830 value.get_type(),
831 "",
832 ))
833 };
834 let upper_bound = if is_signed {
835 err!(self.builder.build_signed_int_to_float(
836 int_ty.const_int(upper_bound, is_signed),
837 value.get_type(),
838 "",
839 ))
840 } else {
841 err!(self.builder.build_unsigned_int_to_float(
842 int_ty.const_int(upper_bound, is_signed),
843 value.get_type(),
844 "",
845 ))
846 };
847
848 let zero = value.get_type().const_zero();
849
850 let nan_cmp =
851 err!(
852 self.builder
853 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
854 );
855 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
856 FloatPredicate::OGT,
857 value,
858 upper_bound,
859 "above_upper_bound",
860 ));
861 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
862 FloatPredicate::OLT,
863 value,
864 lower_bound,
865 "below_lower_bound",
866 ));
867 let not_representable = err!(self.builder.build_or(
868 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
869 below_lower_bound_cmp,
870 "not_representable_as_int",
871 ));
872 let value =
873 err!(
874 self.builder
875 .build_select(not_representable, zero, value, "safe_to_convert")
876 )
877 .into_float_value();
878 let value = if is_signed {
879 err!(
880 self.builder
881 .build_float_to_signed_int(value, int_ty, "as_int")
882 )
883 } else {
884 err!(
885 self.builder
886 .build_float_to_unsigned_int(value, int_ty, "as_int")
887 )
888 };
889 let value =
890 err!(
891 self.builder
892 .build_select(above_upper_bound_cmp, int_max_value, value, "")
893 )
894 .into_int_value();
895 let value =
896 err!(
897 self.builder
898 .build_select(below_lower_bound_cmp, int_min_value, value, "")
899 )
900 .into_int_value();
901
902 err_nt!(
903 self.builder
904 .build_bit_cast(value, int_ty, "")
905 .map(|v| v.into_int_value())
906 )
907 }
908
909 fn trap_if_not_representable_as_int(
910 &self,
911 lower_bound: u64, upper_bound: u64, value: FloatValue<'ctx>,
914 ) -> Result<(), CompileError> {
915 let float_ty = value.get_type();
916 let int_ty = if float_ty == self.intrinsics.f32_ty {
917 self.intrinsics.i32_ty
918 } else {
919 self.intrinsics.i64_ty
920 };
921
922 let lower_bound = err!(self.builder.build_bit_cast(
923 int_ty.const_int(lower_bound, false),
924 float_ty,
925 ""
926 ))
927 .into_float_value();
928 let upper_bound = err!(self.builder.build_bit_cast(
929 int_ty.const_int(upper_bound, false),
930 float_ty,
931 ""
932 ))
933 .into_float_value();
934
935 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
939 FloatPredicate::UGT,
940 value,
941 upper_bound,
942 "above_upper_bound",
943 ));
944 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
945 FloatPredicate::ULT,
946 value,
947 lower_bound,
948 "below_lower_bound",
949 ));
950 let out_of_bounds = err!(self.builder.build_or(
951 above_upper_bound_cmp,
952 below_lower_bound_cmp,
953 "out_of_bounds",
954 ));
955
956 let failure_block = self
957 .context
958 .append_basic_block(self.function, "conversion_failure_block");
959 let continue_block = self
960 .context
961 .append_basic_block(self.function, "conversion_success_block");
962
963 err!(
964 self.builder
965 .build_conditional_branch(out_of_bounds, failure_block, continue_block)
966 );
967 self.builder.position_at_end(failure_block);
968 let is_nan =
969 err!(
970 self.builder
971 .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
972 );
973 let trap_code = err!(self.builder.build_select(
974 is_nan,
975 self.intrinsics.trap_bad_conversion_to_integer,
976 self.intrinsics.trap_illegal_arithmetic,
977 "",
978 ));
979 self.build_call_with_param_attributes(
980 self.intrinsics.throw_trap,
981 &[trap_code.into()],
982 "throw",
983 )?;
984 err!(self.builder.build_unreachable());
985 self.builder.position_at_end(continue_block);
986
987 Ok(())
988 }
989
990 fn trap_if_zero_or_overflow(
991 &self,
992 left: IntValue<'ctx>,
993 right: IntValue<'ctx>,
994 ) -> Result<(), CompileError> {
995 let int_type = left.get_type();
996
997 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
998 let min_value = int_type.const_int(i32::MIN as u64, false);
999 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
1000 (min_value, neg_one_value)
1001 } else if int_type == self.intrinsics.i64_ty {
1002 let min_value = int_type.const_int(i64::MIN as u64, false);
1003 let neg_one_value = int_type.const_int(-1i64 as u64, false);
1004 (min_value, neg_one_value)
1005 } else {
1006 unreachable!()
1007 };
1008
1009 let divisor_is_zero = err!(self.builder.build_int_compare(
1010 IntPredicate::EQ,
1011 right,
1012 int_type.const_zero(),
1013 "divisor_is_zero",
1014 ));
1015 let should_trap = err!(self.builder.build_or(
1016 divisor_is_zero,
1017 err!(self.builder.build_and(
1018 err!(self.builder.build_int_compare(
1019 IntPredicate::EQ,
1020 left,
1021 min_value,
1022 "left_is_min"
1023 )),
1024 err!(self.builder.build_int_compare(
1025 IntPredicate::EQ,
1026 right,
1027 neg_one_value,
1028 "right_is_neg_one",
1029 )),
1030 "div_will_overflow",
1031 )),
1032 "div_should_trap",
1033 ));
1034
1035 let should_trap = self
1036 .build_call_with_param_attributes(
1037 self.intrinsics.expect_i1,
1038 &[
1039 should_trap.into(),
1040 self.intrinsics.i1_ty.const_zero().into(),
1041 ],
1042 "should_trap_expect",
1043 )?
1044 .try_as_basic_value()
1045 .unwrap_basic()
1046 .into_int_value();
1047
1048 let shouldnt_trap_block = self
1049 .context
1050 .append_basic_block(self.function, "shouldnt_trap_block");
1051 let should_trap_block = self
1052 .context
1053 .append_basic_block(self.function, "should_trap_block");
1054 err!(self.builder.build_conditional_branch(
1055 should_trap,
1056 should_trap_block,
1057 shouldnt_trap_block
1058 ));
1059 self.builder.position_at_end(should_trap_block);
1060 let trap_code = err!(self.builder.build_select(
1061 divisor_is_zero,
1062 self.intrinsics.trap_integer_division_by_zero,
1063 self.intrinsics.trap_illegal_arithmetic,
1064 "",
1065 ));
1066 err!(
1067 self.builder
1068 .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
1069 );
1070 err!(self.builder.build_unreachable());
1071 self.builder.position_at_end(shouldnt_trap_block);
1072
1073 Ok(())
1074 }
1075
1076 fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
1077 let int_type = value.get_type();
1078 let should_trap = err!(self.builder.build_int_compare(
1079 IntPredicate::EQ,
1080 value,
1081 int_type.const_zero(),
1082 "divisor_is_zero",
1083 ));
1084
1085 let should_trap = self
1086 .build_call_with_param_attributes(
1087 self.intrinsics.expect_i1,
1088 &[
1089 should_trap.into(),
1090 self.intrinsics.i1_ty.const_zero().into(),
1091 ],
1092 "should_trap_expect",
1093 )?
1094 .try_as_basic_value()
1095 .unwrap_basic()
1096 .into_int_value();
1097
1098 let shouldnt_trap_block = self
1099 .context
1100 .append_basic_block(self.function, "shouldnt_trap_block");
1101 let should_trap_block = self
1102 .context
1103 .append_basic_block(self.function, "should_trap_block");
1104 err!(self.builder.build_conditional_branch(
1105 should_trap,
1106 should_trap_block,
1107 shouldnt_trap_block
1108 ));
1109 self.builder.position_at_end(should_trap_block);
1110 self.build_call_with_param_attributes(
1111 self.intrinsics.throw_trap,
1112 &[self.intrinsics.trap_integer_division_by_zero.into()],
1113 "throw",
1114 )?;
1115 err!(self.builder.build_unreachable());
1116 self.builder.position_at_end(shouldnt_trap_block);
1117
1118 Ok(())
1119 }
1120
1121 fn v128_into_int_vec(
1122 &self,
1123 value: BasicValueEnum<'ctx>,
1124 info: ExtraInfo,
1125 int_vec_ty: VectorType<'ctx>,
1126 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1127 let (value, info) = if self.config.enable_nan_canonicalization {
1128 if info.has_pending_f32_nan() {
1129 let value = err!(
1130 self.builder
1131 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1132 );
1133 (self.canonicalize_nans(value)?, info.strip_pending())
1134 } else if info.has_pending_f64_nan() {
1135 let value = err!(
1136 self.builder
1137 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1138 );
1139 (self.canonicalize_nans(value)?, info.strip_pending())
1140 } else {
1141 (value, info)
1142 }
1143 } else {
1144 (value, info)
1145 };
1146 Ok((
1147 err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1148 info,
1149 ))
1150 }
1151
1152 fn v128_into_i8x16(
1153 &self,
1154 value: BasicValueEnum<'ctx>,
1155 info: ExtraInfo,
1156 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1157 self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1158 }
1159
1160 fn v128_into_i16x8(
1161 &self,
1162 value: BasicValueEnum<'ctx>,
1163 info: ExtraInfo,
1164 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1165 self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1166 }
1167
1168 fn v128_into_i32x4(
1169 &self,
1170 value: BasicValueEnum<'ctx>,
1171 info: ExtraInfo,
1172 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1173 self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1174 }
1175
1176 fn v128_into_i64x2(
1177 &self,
1178 value: BasicValueEnum<'ctx>,
1179 info: ExtraInfo,
1180 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1181 self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1182 }
1183
1184 fn v128_into_f32x4(
1187 &self,
1188 value: BasicValueEnum<'ctx>,
1189 info: ExtraInfo,
1190 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1191 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1192 {
1193 let value = err!(
1194 self.builder
1195 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1196 );
1197 (self.canonicalize_nans(value)?, info.strip_pending())
1198 } else {
1199 (value, info)
1200 };
1201 Ok((
1202 err!(
1203 self.builder
1204 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1205 )
1206 .into_vector_value(),
1207 info,
1208 ))
1209 }
1210
1211 fn v128_into_f64x2(
1214 &self,
1215 value: BasicValueEnum<'ctx>,
1216 info: ExtraInfo,
1217 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1218 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1219 {
1220 let value = err!(
1221 self.builder
1222 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1223 );
1224 (self.canonicalize_nans(value)?, info.strip_pending())
1225 } else {
1226 (value, info)
1227 };
1228 Ok((
1229 err!(
1230 self.builder
1231 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1232 )
1233 .into_vector_value(),
1234 info,
1235 ))
1236 }
1237
1238 fn apply_pending_canonicalization(
1239 &self,
1240 value: BasicValueEnum<'ctx>,
1241 info: ExtraInfo,
1242 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1243 if !self.config.enable_nan_canonicalization {
1244 return Ok(value);
1245 }
1246
1247 if info.has_pending_f32_nan() {
1248 if value.get_type().is_vector_type()
1249 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1250 {
1251 let ty = value.get_type();
1252 let value = err!(
1253 self.builder
1254 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1255 );
1256 let value = self.canonicalize_nans(value)?;
1257 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1258 } else {
1259 self.canonicalize_nans(value)
1260 }
1261 } else if info.has_pending_f64_nan() {
1262 if value.get_type().is_vector_type()
1263 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1264 {
1265 let ty = value.get_type();
1266 let value = err!(
1267 self.builder
1268 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1269 );
1270 let value = self.canonicalize_nans(value)?;
1271 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1272 } else {
1273 self.canonicalize_nans(value)
1274 }
1275 } else {
1276 Ok(value)
1277 }
1278 }
1279
1280 fn canonicalize_nans(
1282 &self,
1283 value: BasicValueEnum<'ctx>,
1284 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1285 if !self.config.enable_nan_canonicalization {
1286 return Ok(value);
1287 }
1288
1289 let f_ty = value.get_type();
1290 if f_ty.is_vector_type() {
1291 let value = value.into_vector_value();
1292 let f_ty = f_ty.into_vector_type();
1293 let zero = f_ty.const_zero();
1294 let nan_cmp =
1295 err!(
1296 self.builder
1297 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1298 );
1299 let canonical_qnan = f_ty
1300 .get_element_type()
1301 .into_float_type()
1302 .const_float(f64::NAN);
1303 let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1304 err_nt!(
1305 self.builder
1306 .build_select(nan_cmp, canonical_qnan, value, "")
1307 .map(|v| v.as_basic_value_enum())
1308 )
1309 } else {
1310 let value = value.into_float_value();
1311 let f_ty = f_ty.into_float_type();
1312 let zero = f_ty.const_zero();
1313 let nan_cmp =
1314 err!(
1315 self.builder
1316 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1317 );
1318 let canonical_qnan = f_ty.const_float(f64::NAN);
1319 err_nt!(
1320 self.builder
1321 .build_select(nan_cmp, canonical_qnan, value, "")
1322 .map(|v| v.as_basic_value_enum())
1323 )
1324 }
1325 }
1326
1327 fn annotate_user_memaccess(
1328 &mut self,
1329 memory_index: MemoryIndex,
1330 _memarg: &MemArg,
1331 alignment: u32,
1332 memaccess: InstructionValue<'ctx>,
1333 ) -> Result<(), CompileError> {
1334 match memaccess.get_opcode() {
1335 InstructionOpcode::Load | InstructionOpcode::Store => {
1336 memaccess.set_alignment(alignment).unwrap();
1337 }
1338 _ => {}
1339 };
1340 if !self.non_volatile_memory_ops {
1341 if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1345 memory_index,
1346 self.intrinsics,
1347 self.module,
1348 self.memory_styles,
1349 )? {
1350 memaccess.set_volatile(true).map_err(|err| {
1352 CompileError::Codegen(format!(
1353 "could not set volatile on memory operation: {err}"
1354 ))
1355 })?;
1356 }
1357 }
1358 tbaa_label(
1359 self.module,
1360 self.intrinsics,
1361 format!("memory {}", memory_index.as_u32()),
1362 memaccess,
1363 );
1364 Ok(())
1365 }
1366
1367 fn build_annotated_load<T: BasicType<'ctx>>(
1368 &mut self,
1369 pointee_ty: T,
1370 offset: IntValue<'ctx>,
1371 memarg: &MemArg,
1372 alignment: u32,
1373 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1374 let memory_index = MemoryIndex::from_u32(memarg.memory);
1375 let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1376 .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1377 let effective_address = self.resolve_memory_ptr(
1378 memory_index,
1379 memarg,
1380 self.intrinsics.ptr_ty,
1381 offset,
1382 pointee_size,
1383 )?;
1384 let result = err!(self.builder.build_load(pointee_ty, effective_address, ""));
1385 self.annotate_user_memaccess(
1386 MemoryIndex::from_u32(memarg.memory),
1387 memarg,
1388 alignment,
1389 result.as_instruction_value().unwrap(),
1390 )?;
1391 Ok(result)
1392 }
1393
1394 fn build_annotated_atomic_load(
1395 &mut self,
1396 outer_ty: IntType<'ctx>,
1397 inner_ty: IntType<'ctx>,
1398 offset: IntValue<'ctx>,
1399 memarg: &MemArg,
1400 ) -> Result<IntValue<'ctx>, CompileError> {
1401 let alignment = 2u32.pow(memarg.align as u32);
1402 let memory_index = MemoryIndex::from_u32(memarg.memory);
1403 let inner_size =
1404 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1405 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1406 })?;
1407 let outer_size =
1408 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1409 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1410 })?;
1411
1412 let effective_address = self.resolve_memory_ptr(
1413 memory_index,
1414 memarg,
1415 self.intrinsics.ptr_ty,
1416 offset,
1417 inner_size,
1418 )?;
1419 self.trap_if_misaligned(
1420 memarg,
1421 effective_address,
1422 u8::try_from(inner_size).map_err(|_| {
1423 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1424 })?,
1425 )?;
1426
1427 let result = err!(
1428 self.builder
1429 .build_load(inner_ty, effective_address, "atomic_load")
1430 );
1431 let load = result.into_int_value();
1432 let load_inst = load.as_instruction_value().unwrap();
1433 self.annotate_user_memaccess(memory_index, memarg, alignment, load_inst)?;
1434 load_inst
1435 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1436 .unwrap();
1437
1438 if inner_size < outer_size {
1439 Ok(err_nt!(
1440 self.builder.build_int_z_extend(load, outer_ty, "")
1441 )?)
1442 } else {
1443 Ok(load)
1444 }
1445 }
1446
1447 fn build_annotated_store<T: BasicType<'ctx>>(
1448 &mut self,
1449 pointee_ty: T,
1450 offset: IntValue<'ctx>,
1451 value: BasicValueEnum<'ctx>,
1452 memarg: &MemArg,
1453 alignment: u32,
1454 ) -> Result<(), CompileError> {
1455 let memory_index = MemoryIndex::from_u32(memarg.memory);
1456 let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1457 .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1458 let effective_address = self.resolve_memory_ptr(
1459 memory_index,
1460 memarg,
1461 self.intrinsics.ptr_ty,
1462 offset,
1463 pointee_size,
1464 )?;
1465
1466 if !self.non_volatile_memory_ops {
1469 self.build_annotated_load(pointee_ty, offset, memarg, alignment)?;
1470 }
1471
1472 let store = err!(self.builder.build_store(effective_address, value));
1473 self.annotate_user_memaccess(memory_index, memarg, alignment, store)
1474 }
1475
1476 fn build_annotated_atomic_store(
1477 &mut self,
1478 outer_ty: IntType<'ctx>,
1479 inner_ty: IntType<'ctx>,
1480 offset: IntValue<'ctx>,
1481 value: IntValue<'ctx>,
1482 memarg: &MemArg,
1483 ) -> Result<(), CompileError> {
1484 let alignment = 2u32.pow(memarg.align as u32);
1485 let memory_index = MemoryIndex::from_u32(memarg.memory);
1486 let inner_size =
1487 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1488 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1489 })?;
1490 let outer_size =
1491 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1492 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1493 })?;
1494
1495 let effective_address = self.resolve_memory_ptr(
1496 memory_index,
1497 memarg,
1498 self.intrinsics.ptr_ty,
1499 offset,
1500 inner_size,
1501 )?;
1502 self.trap_if_misaligned(
1503 memarg,
1504 effective_address,
1505 u8::try_from(inner_size).map_err(|_| {
1506 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1507 })?,
1508 )?;
1509
1510 let value = if inner_size < outer_size {
1511 err!(self.builder.build_int_truncate(value, inner_ty, ""))
1512 } else {
1513 value
1514 };
1515 let store = err!(self.builder.build_store(effective_address, value));
1516 self.annotate_user_memaccess(memory_index, memarg, alignment, store)?;
1517 store
1518 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1519 .unwrap();
1520 Ok(())
1521 }
1522
1523 fn build_annotated_atomic_rmw(
1524 &mut self,
1525 outer_ty: IntType<'ctx>,
1526 inner_ty: IntType<'ctx>,
1527 offset: IntValue<'ctx>,
1528 value: IntValue<'ctx>,
1529 memarg: &MemArg,
1530 op: AtomicRMWBinOp,
1531 ) -> Result<IntValue<'ctx>, CompileError> {
1532 let alignment = 2u32.pow(memarg.align as u32);
1533 let memory_index = MemoryIndex::from_u32(memarg.memory);
1534 let inner_size =
1535 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1536 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1537 })?;
1538 let outer_size =
1539 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1540 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1541 })?;
1542
1543 let effective_address = self.resolve_memory_ptr(
1544 memory_index,
1545 memarg,
1546 self.intrinsics.ptr_ty,
1547 offset,
1548 inner_size,
1549 )?;
1550 self.trap_if_misaligned(
1551 memarg,
1552 effective_address,
1553 u8::try_from(inner_size).map_err(|_| {
1554 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1555 })?,
1556 )?;
1557 let value = if inner_size < outer_size {
1558 err!(self.builder.build_int_truncate(value, inner_ty, ""))
1559 } else {
1560 value
1561 };
1562 let old = self
1563 .builder
1564 .build_atomicrmw(
1565 op,
1566 effective_address,
1567 value,
1568 AtomicOrdering::SequentiallyConsistent,
1569 )
1570 .unwrap();
1571 self.annotate_user_memaccess(
1572 memory_index,
1573 memarg,
1574 alignment,
1575 old.as_instruction_value().unwrap(),
1576 )?;
1577
1578 let value = if inner_size < outer_size {
1579 err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1580 } else {
1581 old
1582 };
1583 Ok(value)
1584 }
1585
1586 fn build_annotated_atomic_rmw_cmpxchg(
1587 &mut self,
1588 outer_ty: IntType<'ctx>,
1589 inner_ty: IntType<'ctx>,
1590 offset: IntValue<'ctx>,
1591 cmp: IntValue<'ctx>,
1592 new: IntValue<'ctx>,
1593 memarg: &MemArg,
1594 ) -> Result<IntValue<'ctx>, CompileError> {
1595 let alignment = 2u32.pow(memarg.align as u32);
1596 let memory_index = MemoryIndex::from_u32(memarg.memory);
1597 let inner_size =
1598 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1599 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1600 })?;
1601 let outer_size =
1602 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1603 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1604 })?;
1605
1606 let effective_address = self.resolve_memory_ptr(
1607 memory_index,
1608 memarg,
1609 self.intrinsics.ptr_ty,
1610 offset,
1611 inner_size,
1612 )?;
1613 self.trap_if_misaligned(
1614 memarg,
1615 effective_address,
1616 u8::try_from(inner_size).map_err(|_| {
1617 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1618 })?,
1619 )?;
1620 let (cmp, new) = if inner_size < outer_size {
1621 (
1622 err!(self.builder.build_int_truncate(cmp, inner_ty, "")),
1623 err!(self.builder.build_int_truncate(new, inner_ty, "")),
1624 )
1625 } else {
1626 (cmp, new)
1627 };
1628 let old = self
1629 .builder
1630 .build_cmpxchg(
1631 effective_address,
1632 cmp,
1633 new,
1634 AtomicOrdering::SequentiallyConsistent,
1635 AtomicOrdering::SequentiallyConsistent,
1636 )
1637 .unwrap();
1638 self.annotate_user_memaccess(
1639 memory_index,
1640 memarg,
1641 alignment,
1642 old.as_instruction_value().unwrap(),
1643 )?;
1644 let old = self
1645 .builder
1646 .build_extract_value(old, 0, "")
1647 .unwrap()
1648 .into_int_value();
1649
1650 let value = if inner_size < outer_size {
1651 err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1652 } else {
1653 old
1654 };
1655 Ok(value)
1656 }
1657
1658 fn translate_atomic_rmw(
1659 &mut self,
1660 outer_ty: IntType<'ctx>,
1661 inner_ty: IntType<'ctx>,
1662 memarg: &MemArg,
1663 op: AtomicRMWBinOp,
1664 extra_info: Option<ExtraInfo>,
1665 ) -> Result<(), CompileError> {
1666 let value = self.state.pop1()?.into_int_value();
1667 let offset = self.state.pop1()?.into_int_value();
1668 let old = self.build_annotated_atomic_rmw(outer_ty, inner_ty, offset, value, memarg, op)?;
1669 if let Some(extra_info) = extra_info {
1670 self.state.push1_extra(old, extra_info);
1671 } else {
1672 self.state.push1(old);
1673 }
1674 Ok(())
1675 }
1676
1677 fn translate_atomic_rmw_cmpxchg(
1678 &mut self,
1679 outer_ty: IntType<'ctx>,
1680 inner_ty: IntType<'ctx>,
1681 memarg: &MemArg,
1682 extra_info: Option<ExtraInfo>,
1683 ) -> Result<(), CompileError> {
1684 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
1685 let cmp = self
1686 .apply_pending_canonicalization(cmp, cmp_info)?
1687 .into_int_value();
1688 let new = self
1689 .apply_pending_canonicalization(new, new_info)?
1690 .into_int_value();
1691 let offset = self.state.pop1()?.into_int_value();
1692 let old =
1693 self.build_annotated_atomic_rmw_cmpxchg(outer_ty, inner_ty, offset, cmp, new, memarg)?;
1694 if let Some(extra_info) = extra_info {
1695 self.state.push1_extra(old, extra_info);
1696 } else {
1697 self.state.push1(old);
1698 }
1699 Ok(())
1700 }
1701
1702 fn resolve_memory_ptr(
1703 &mut self,
1704 memory_index: MemoryIndex,
1705 memarg: &MemArg,
1706 ptr_ty: PointerType<'ctx>,
1707 var_offset: IntValue<'ctx>,
1708 value_size: usize,
1709 ) -> Result<PointerValue<'ctx>, CompileError> {
1710 let builder = &self.builder;
1711 let intrinsics = &self.intrinsics;
1712 let context = &self.context;
1713 let function = &self.function;
1714
1715 let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1717 let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1718 let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1719
1720 let base_ptr = if let Some(m0) = self.m0_param {
1722 m0
1723 } else {
1724 match self
1725 .ctx
1726 .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1727 {
1728 MemoryCache::Dynamic {
1729 ptr_to_base_ptr,
1730 ptr_to_current_length,
1731 } => {
1732 let minimum = self.wasm_module.memories[memory_index].minimum;
1734 let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1735 let ptr_in_bounds = if offset.is_const() {
1736 let load_offset_end =
1739 offset.const_add(value_size_v).get_zero_extended_constant();
1740 if load_offset_end.is_some_and(|load_offset_end| {
1741 load_offset_end <= minimum.bytes().0 as u64
1742 }) {
1743 Some(intrinsics.i64_ty.const_int(1, false))
1744 } else {
1745 None
1746 }
1747 } else {
1748 None
1749 };
1750
1751 let ptr_in_bounds = match ptr_in_bounds {
1752 Some(ptr) => ptr,
1753 None => {
1754 let load_offset_end = err!(builder.build_int_add(
1755 offset,
1756 value_size_v,
1757 "load_offset_end"
1758 ));
1759
1760 let current_length = err!(builder.build_load(
1761 self.intrinsics.i32_ty,
1762 ptr_to_current_length,
1763 "current_length"
1764 ))
1765 .into_int_value();
1766 tbaa_label(
1767 self.module,
1768 self.intrinsics,
1769 format!("memory {} length", memory_index.as_u32()),
1770 current_length.as_instruction_value().unwrap(),
1771 );
1772 let current_length = err!(builder.build_int_z_extend(
1773 current_length,
1774 intrinsics.i64_ty,
1775 "current_length_zextd"
1776 ));
1777
1778 err!(builder.build_int_compare(
1779 IntPredicate::ULE,
1780 load_offset_end,
1781 current_length,
1782 "ptr_in_bounds",
1783 ))
1784 }
1785 };
1786
1787 if !ptr_in_bounds.is_constant_int()
1788 || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1789 {
1790 let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1796 intrinsics.expect_i1,
1797 &[
1798 ptr_in_bounds.into(),
1799 intrinsics.i1_ty.const_int(1, true).into(),
1800 ],
1801 "ptr_in_bounds_expect",
1802 ))
1803 .try_as_basic_value()
1804 .unwrap_basic()
1805 .into_int_value();
1806
1807 let in_bounds_continue_block =
1808 context.append_basic_block(*function, "in_bounds_continue_block");
1809 let not_in_bounds_block =
1810 context.append_basic_block(*function, "not_in_bounds_block");
1811 err!(builder.build_conditional_branch(
1812 ptr_in_bounds,
1813 in_bounds_continue_block,
1814 not_in_bounds_block,
1815 ));
1816 builder.position_at_end(not_in_bounds_block);
1817 err!(self.build_call_with_param_attributes(
1818 intrinsics.throw_trap,
1819 &[intrinsics.trap_memory_oob.into()],
1820 "throw",
1821 ));
1822 err!(builder.build_unreachable());
1823 builder.position_at_end(in_bounds_continue_block);
1824 }
1825 let ptr_to_base =
1826 err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1827 .into_pointer_value();
1828 tbaa_label(
1829 self.module,
1830 self.intrinsics,
1831 format!("memory base_ptr {}", memory_index.as_u32()),
1832 ptr_to_base.as_instruction_value().unwrap(),
1833 );
1834 ptr_to_base
1835 }
1836 MemoryCache::Static { base_ptr } => base_ptr,
1837 }
1838 };
1839 let value_ptr = unsafe {
1840 err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1841 };
1842 err_nt!(
1843 builder
1844 .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1845 .map(|v| v.into_pointer_value())
1846 )
1847 }
1848
1849 fn trap_if_misaligned(
1850 &self,
1851 _memarg: &MemArg,
1852 ptr: PointerValue<'ctx>,
1853 align: u8,
1854 ) -> Result<(), CompileError> {
1855 if align <= 1 {
1856 return Ok(());
1857 }
1858 let value = err!(self.builder.build_ptr_to_int(
1859 ptr,
1860 self.intrinsics.i64_ty,
1861 "mischeck_value"
1862 ));
1863 let and = err!(self.builder.build_and(
1864 value,
1865 self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1866 "misaligncheck",
1867 ));
1868 let aligned = err!(self.builder.build_int_compare(
1869 IntPredicate::EQ,
1870 and,
1871 self.intrinsics.i64_zero,
1872 "is_aligned"
1873 ));
1874 let aligned = self
1875 .build_call_with_param_attributes(
1876 self.intrinsics.expect_i1,
1877 &[
1878 aligned.into(),
1879 self.intrinsics.i1_ty.const_int(1, false).into(),
1880 ],
1881 "is_aligned_expect",
1882 )?
1883 .try_as_basic_value()
1884 .unwrap_basic()
1885 .into_int_value();
1886
1887 let continue_block = self
1888 .context
1889 .append_basic_block(self.function, "aligned_access_continue_block");
1890 let not_aligned_block = self
1891 .context
1892 .append_basic_block(self.function, "misaligned_trap_block");
1893 err!(
1894 self.builder
1895 .build_conditional_branch(aligned, continue_block, not_aligned_block)
1896 );
1897
1898 self.builder.position_at_end(not_aligned_block);
1899 self.build_call_with_param_attributes(
1900 self.intrinsics.throw_trap,
1901 &[self.intrinsics.trap_unaligned_atomic.into()],
1902 "throw",
1903 )?;
1904 err!(self.builder.build_unreachable());
1905
1906 self.builder.position_at_end(continue_block);
1907 Ok(())
1908 }
1909
1910 fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1911 let func_type = self.function.get_type();
1912
1913 let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1914 let results = err!(
1915 results
1916 .into_iter()
1917 .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1918 .collect::<Result<Vec<_>, _>>()
1919 );
1920
1921 if wasm_fn_type.results().is_empty() {
1922 err!(self.builder.build_return(None));
1923 } else if self.abi.is_sret(wasm_fn_type)? {
1924 let sret = self
1925 .function
1926 .get_first_param()
1927 .unwrap()
1928 .into_pointer_value();
1929 let llvm_params: Vec<_> = wasm_fn_type
1930 .results()
1931 .iter()
1932 .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1933 .collect();
1934 let mut struct_value = self
1935 .context
1936 .struct_type(llvm_params.as_slice(), false)
1937 .get_undef();
1938 for (idx, value) in results.into_iter().enumerate() {
1939 let value = err!(self.builder.build_bit_cast(
1940 value,
1941 type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1942 "",
1943 ));
1944 struct_value =
1945 err!(
1946 self.builder
1947 .build_insert_value(struct_value, value, idx as u32, "")
1948 )
1949 .into_struct_value();
1950 }
1951 err!(self.builder.build_store(sret, struct_value));
1952 err!(self.builder.build_return(None));
1953 } else {
1954 err!(
1955 self.builder
1956 .build_return(Some(&self.abi.pack_values_for_register_return(
1957 self.intrinsics,
1958 &self.builder,
1959 &results,
1960 &func_type,
1961 )?))
1962 );
1963 }
1964 Ok(())
1965 }
1966
1967 fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1970 if let Some(tag) = self.tags_cache.get(&tag) {
1971 return *tag;
1972 }
1973
1974 let tag_ty = self
1975 .context
1976 .struct_type(&[self.intrinsics.i32_ty.into()], false);
1977 let tag_glbl = self.module.add_global(
1978 tag_ty,
1979 Some(AddressSpace::default()),
1980 &format!("__wasmer_eh_type_info_{tag}"),
1981 );
1982 tag_glbl.set_initializer(
1983 &tag_ty
1984 .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1985 .as_basic_value_enum(),
1986 );
1987
1988 tag_glbl.set_linkage(Linkage::LinkOnceODR);
1989 tag_glbl.set_constant(true);
1990 if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1998 tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1999 }
2000
2001 let tag_glbl = tag_glbl.as_basic_value_enum();
2002
2003 self.tags_cache.insert(tag, tag_glbl);
2004 tag_glbl
2005 }
2006
2007 fn emit_return_call(
2008 &mut self,
2009 call_site: CallSiteValue<'ctx>,
2010 callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
2011 ) -> Result<(), CompileError> {
2012 let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
2019 LLVMTailCallKind::LLVMTailCallKindMustTail
2020 } else {
2021 LLVMTailCallKind::LLVMTailCallKindTail
2022 };
2023 call_site.set_tail_call_kind(tail_call_kind);
2024
2025 if self.function.get_type().get_return_type().is_none() {
2026 err!(self.builder.build_return(None));
2027 } else {
2028 let ret = call_site.try_as_basic_value();
2029 if ret.is_instruction() {
2030 return Err(CompileError::Codegen(
2031 "return_call expected a non-void call result".to_string(),
2032 ));
2033 }
2034 err!(self.builder.build_return(Some(&ret.unwrap_basic())));
2035 }
2036 Ok(())
2037 }
2038
2039 fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
2041 self.abi.is_sret(func_type).ok().map(|_| {
2042 self.function
2043 .get_first_param()
2044 .unwrap()
2045 .into_pointer_value()
2046 })
2047 }
2048
2049 fn build_m0_indirect_call(
2050 &mut self,
2051 table_index: u32,
2052 ctx_ptr: PointerValue<'ctx>,
2053 func_type: &FunctionType,
2054 func_ptr: PointerValue<'ctx>,
2055 func_index: IntValue<'ctx>,
2056 is_return_call: bool,
2057 ) -> Result<(), CompileError> {
2058 let Some(m0) = self.m0_param else {
2059 return Err(CompileError::Codegen(
2060 "Call to build_m0_indirect_call without m0 parameter!".to_string(),
2061 ));
2062 };
2063
2064 let params = self.state.popn_save_extra(func_type.params().len())?;
2065
2066 let mut local_func_indices = vec![];
2067 let mut foreign_func_indices = vec![];
2068
2069 for t in &self.wasm_module.table_initializers {
2070 if t.table_index.as_u32() == table_index {
2071 for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
2072 if self.wasm_module.local_func_index(*func_idx).is_some() {
2073 local_func_indices.push(func_in_table_idx)
2074 } else {
2075 foreign_func_indices.push(func_in_table_idx)
2076 }
2077 }
2078 break;
2079 }
2080 }
2081
2082 let needs_switch = self.m0_param.is_some()
2083 && !local_func_indices.is_empty()
2084 && !foreign_func_indices.is_empty();
2085
2086 if needs_switch {
2087 let foreign_idx_block = self
2088 .context
2089 .append_basic_block(self.function, "foreign_call_block");
2090 let local_idx_block = self
2091 .context
2092 .append_basic_block(self.function, "local_call_block");
2093 let unreachable_indirect_call_branch_block = self
2094 .context
2095 .append_basic_block(self.function, "unreachable_indirect_call_branch");
2096
2097 let cont =
2098 (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
2099
2100 err!(
2101 self.builder.build_switch(
2102 func_index,
2103 unreachable_indirect_call_branch_block,
2104 &local_func_indices
2105 .into_iter()
2106 .map(|v| (
2107 self.intrinsics.i32_ty.const_int(v as _, false),
2108 local_idx_block
2109 ))
2110 .chain(foreign_func_indices.into_iter().map(|v| (
2111 self.intrinsics.i32_ty.const_int(v as _, false),
2112 foreign_idx_block
2113 )))
2114 .collect::<Vec<_>>()
2115 )
2116 );
2117
2118 self.builder
2119 .position_at_end(unreachable_indirect_call_branch_block);
2120 err!(self.builder.build_unreachable());
2121
2122 self.builder.position_at_end(local_idx_block);
2124 let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
2125 ctx_ptr,
2126 func_type,
2127 func_ptr,
2128 Some(m0),
2129 is_return_call,
2130 ¶ms,
2131 )?;
2132
2133 let local_rets = if is_return_call {
2134 self.emit_return_call(local_call_site, local_llvm_func_type)?;
2135 Vec::new()
2136 } else {
2137 let rets = self.abi.rets_from_call(
2138 &self.builder,
2139 self.intrinsics,
2140 local_call_site,
2141 func_type,
2142 )?;
2143 err!(
2144 self.builder
2145 .build_unconditional_branch(cont.expect("non-return call requires cont"))
2146 );
2147 rets
2148 };
2149
2150 self.builder.position_at_end(foreign_idx_block);
2151 let (foreign_call_site, foreign_llvm_func_type) = self
2152 .build_indirect_call_with_params(
2153 ctx_ptr,
2154 func_type,
2155 func_ptr,
2156 None,
2157 is_return_call,
2158 ¶ms,
2159 )?;
2160
2161 let foreign_rets = if is_return_call {
2162 self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
2163 Vec::new()
2164 } else {
2165 let rets = self.abi.rets_from_call(
2166 &self.builder,
2167 self.intrinsics,
2168 foreign_call_site,
2169 func_type,
2170 )?;
2171 err!(
2172 self.builder
2173 .build_unconditional_branch(cont.expect("non-return call requires cont"))
2174 );
2175 rets
2176 };
2177
2178 if is_return_call {
2179 return Ok(());
2180 }
2181
2182 self.builder
2183 .position_at_end(cont.expect("non-return call requires cont"));
2184
2185 for i in 0..foreign_rets.len() {
2186 let f_i = foreign_rets[i];
2187 let l_i = local_rets[i];
2188 let ty = f_i.get_type();
2189 let v = err!(self.builder.build_phi(ty, ""));
2190 v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
2191 self.state.push1(v.as_basic_value());
2192 }
2193 } else if foreign_func_indices.is_empty() {
2194 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2195 ctx_ptr,
2196 func_type,
2197 func_ptr,
2198 Some(m0),
2199 is_return_call,
2200 ¶ms,
2201 )?;
2202
2203 if is_return_call {
2204 self.emit_return_call(call_site, llvm_func_type)?;
2205 } else {
2206 self.abi
2207 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2208 .iter()
2209 .for_each(|ret| self.state.push1(*ret));
2210 }
2211 } else {
2212 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2213 ctx_ptr,
2214 func_type,
2215 func_ptr,
2216 None,
2217 is_return_call,
2218 ¶ms,
2219 )?;
2220 if is_return_call {
2221 self.emit_return_call(call_site, llvm_func_type)?;
2222 } else {
2223 self.abi
2224 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2225 .iter()
2226 .for_each(|ret| self.state.push1(*ret));
2227 }
2228 }
2229
2230 Ok(())
2231 }
2232
2233 fn build_indirect_call(
2234 &mut self,
2235 ctx_ptr: PointerValue<'ctx>,
2236 func_type: &FunctionType,
2237 func_ptr: PointerValue<'ctx>,
2238 m0_param: Option<PointerValue<'ctx>>,
2239 is_return_call: bool,
2240 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2241 let params = self.state.popn_save_extra(func_type.params().len())?;
2242 self.build_indirect_call_with_params(
2243 ctx_ptr,
2244 func_type,
2245 func_ptr,
2246 m0_param,
2247 is_return_call,
2248 ¶ms,
2249 )
2250 }
2251
2252 fn build_indirect_call_with_params(
2253 &mut self,
2254 ctx_ptr: PointerValue<'ctx>,
2255 func_type: &FunctionType,
2256 func_ptr: PointerValue<'ctx>,
2257 m0_param: Option<PointerValue<'ctx>>,
2258 is_return_call: bool,
2259 params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
2260 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2261 let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
2262 self.context,
2263 self.intrinsics,
2264 Some(self.ctx.get_offsets()),
2265 func_type,
2266 m0_param.is_some(),
2267 )?;
2268
2269 let params = params
2271 .iter()
2272 .zip(func_type.params().iter())
2273 .map(|((v, info), wasm_ty)| match wasm_ty {
2274 Type::F32 => err_nt!(self.builder.build_bit_cast(
2275 self.apply_pending_canonicalization(*v, *info)?,
2276 self.intrinsics.f32_ty,
2277 "",
2278 )),
2279 Type::F64 => err_nt!(self.builder.build_bit_cast(
2280 self.apply_pending_canonicalization(*v, *info)?,
2281 self.intrinsics.f64_ty,
2282 "",
2283 )),
2284 Type::V128 => self.apply_pending_canonicalization(*v, *info),
2285 _ => Ok(*v),
2286 })
2287 .collect::<Result<Vec<_>, _>>()?;
2288
2289 let params = self.abi.args_to_call(
2290 &self.alloca_builder,
2291 func_type,
2292 &llvm_func_type,
2293 ctx_ptr,
2294 params.as_slice(),
2295 self.intrinsics,
2296 m0_param,
2297 is_return_call
2298 .then(|| self.current_sret_ptr(func_type))
2299 .flatten(),
2300 )?;
2301
2302 let typed_func_ptr = err!(self.builder.build_pointer_cast(
2303 func_ptr,
2304 self.context.ptr_type(AddressSpace::default()),
2305 "typed_func_ptr",
2306 ));
2307
2308 let call_site_local = self.build_indirect_call_or_invoke(
2309 llvm_func_type,
2310 typed_func_ptr,
2311 params.as_slice(),
2312 "then_block",
2313 is_return_call,
2314 )?;
2315 for (attr, attr_loc) in llvm_func_attrs {
2316 call_site_local.add_attribute(attr_loc, attr);
2317 }
2318
2319 Ok((call_site_local, llvm_func_type))
2320 }
2321
2322 fn build_indirect_call_or_invoke(
2323 &mut self,
2324 llvm_func_type: inkwell::types::FunctionType<'ctx>,
2325 func_ptr: PointerValue<'ctx>,
2326 params: &[BasicValueEnum<'ctx>],
2327 then_block_name: &str,
2328 is_return_call: bool,
2329 ) -> Result<CallSiteValue<'ctx>, CompileError> {
2330 if let Some(lpad) = self.state.get_innermost_landingpad()
2333 && !is_return_call
2334 {
2335 let then_block = self
2336 .context
2337 .append_basic_block(self.function, then_block_name);
2338
2339 let ret = err!(self.builder.build_indirect_invoke(
2340 llvm_func_type,
2341 func_ptr,
2342 params,
2343 then_block,
2344 lpad,
2345 "",
2346 ));
2347
2348 self.builder.position_at_end(then_block);
2349 Ok(ret)
2350 } else {
2351 let call_params = params
2352 .iter()
2353 .copied()
2354 .map(Into::into)
2355 .collect::<Vec<BasicMetadataValueEnum>>();
2356 Ok(err!(self.builder.build_indirect_call(
2357 llvm_func_type,
2358 func_ptr,
2359 call_params.as_slice(),
2360 ""
2361 )))
2362 }
2363 }
2364}
2365
2366pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
2367 m0_param: Option<PointerValue<'ctx>>,
2368 context: &'ctx Context,
2369 builder: Builder<'ctx>,
2370 alloca_builder: Builder<'ctx>,
2371 intrinsics: &'a Intrinsics<'ctx>,
2372 target_data: &'a TargetData,
2373 state: State<'ctx>,
2374 function: FunctionValue<'ctx>,
2375 locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, ctx: CtxType<'ctx, 'a>,
2377 unreachable_depth: usize,
2378 memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
2379 _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
2380 module: &'a Module<'ctx>,
2381 module_translation: &'a ModuleTranslationState,
2382 signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
2383 wasm_module: &'a ModuleInfo,
2384 #[allow(dead_code)]
2385 symbol_registry: &'a dyn SymbolRegistry,
2386 abi: &'a dyn Abi,
2387 config: &'a LLVM,
2388 target_triple: Triple,
2389 tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
2390 binary_fmt: target_lexicon::BinaryFormat,
2391 cpu_features: EnumSet<CpuFeature>,
2392 non_volatile_memory_ops: bool,
2393}
2394
2395impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
2396 fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
2397 let intrinsic = if value
2398 .get_type()
2399 .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2400 {
2401 Some(self.intrinsics.add_f32)
2402 } else if value
2403 .get_type()
2404 .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2405 {
2406 Some(self.intrinsics.add_f64)
2407 } else if value
2408 .get_type()
2409 .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
2410 {
2411 Some(self.intrinsics.add_f32x4)
2412 } else if value
2413 .get_type()
2414 .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
2415 {
2416 Some(self.intrinsics.add_f64x2)
2417 } else {
2418 None
2419 };
2420
2421 match intrinsic {
2422 Some(intrinsic) => err_nt!(
2423 self.builder
2424 .build_call(
2425 intrinsic,
2426 &[
2427 value.into(),
2428 value.get_type().const_zero().into(),
2429 self.intrinsics.fp_rounding_md,
2430 self.intrinsics.fp_exception_md,
2431 ],
2432 "",
2433 )
2434 .map(|v| v.try_as_basic_value().unwrap_basic())
2435 ),
2436 None => Ok(value),
2437 }
2438 }
2439
2440 fn finalize_minmax_result(
2441 &self,
2442 value: BasicValueEnum<'ctx>,
2443 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2444 let ty = value.get_type();
2445 if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2446 || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2447 {
2448 let value = value.into_float_value();
2449 let is_nan = err!(self.builder.build_float_compare(
2450 FloatPredicate::UNO,
2451 value,
2452 value,
2453 "res_is_nan"
2454 ));
2455 let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2456 let result =
2457 err!(
2458 self.builder
2459 .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2460 );
2461 Ok(result.as_basic_value_enum())
2462 } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2463 let value = value.into_vector_value();
2464 let is_nan = self
2465 .build_call_with_param_attributes(
2466 self.intrinsics.cmp_f32x4,
2467 &[
2468 value.into(),
2469 value.into(),
2470 self.intrinsics.fp_uno_md,
2471 self.intrinsics.fp_exception_md,
2472 ],
2473 "",
2474 )?
2475 .try_as_basic_value()
2476 .unwrap_basic()
2477 .into_vector_value();
2478 let quiet = self
2479 .quiet_nan(value.as_basic_value_enum())?
2480 .into_vector_value();
2481 let result = err!(self.builder.build_select(
2482 is_nan,
2483 quiet.as_basic_value_enum(),
2484 value.as_basic_value_enum(),
2485 "",
2486 ));
2487 Ok(result.as_basic_value_enum())
2488 } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2489 let value = value.into_vector_value();
2490 let is_nan = self
2491 .build_call_with_param_attributes(
2492 self.intrinsics.cmp_f64x2,
2493 &[
2494 value.into(),
2495 value.into(),
2496 self.intrinsics.fp_uno_md,
2497 self.intrinsics.fp_exception_md,
2498 ],
2499 "",
2500 )?
2501 .try_as_basic_value()
2502 .unwrap_basic()
2503 .into_vector_value();
2504 let quiet = self
2505 .quiet_nan(value.as_basic_value_enum())?
2506 .into_vector_value();
2507 let result = err!(self.builder.build_select(
2508 is_nan,
2509 quiet.as_basic_value_enum(),
2510 value.as_basic_value_enum(),
2511 "",
2512 ));
2513 Ok(result.as_basic_value_enum())
2514 } else {
2515 Ok(value)
2516 }
2517 }
2518
2519 fn finalize_rounding_result(
2520 &self,
2521 value: BasicValueEnum<'ctx>,
2522 info: ExtraInfo,
2523 ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2524 let ty = value.get_type();
2525 let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2526 let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2527 let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2528 let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2529 debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2530
2531 if matches!(
2532 self.target_triple.architecture,
2533 Architecture::Riscv32(..) | Architecture::Riscv64(..)
2534 ) {
2535 if is_f32 || is_f64 {
2536 let input = value.into_float_value();
2537 let is_nan = err!(self.builder.build_float_compare(
2538 FloatPredicate::UNO,
2539 input,
2540 input,
2541 "res_is_nan",
2542 ));
2543 let canonical_nan_bits = if is_f32 {
2544 self.intrinsics
2545 .i32_ty
2546 .const_int(CANONICAL_NAN_F32 as _, false)
2547 } else {
2548 self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2549 };
2550 let canonical_nan = err!(self.builder.build_bit_cast(
2551 canonical_nan_bits,
2552 ty,
2553 "canonical_nan",
2554 ));
2555 let res =
2556 err!(
2557 self.builder
2558 .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2559 );
2560 Ok((res, info))
2561 } else if is_f32x4 {
2562 let value = value.into_vector_value();
2563 let is_nan = err!(self.builder.build_call(
2564 self.intrinsics.cmp_f32x4,
2565 &[
2566 value.into(),
2567 value.into(),
2568 self.intrinsics.fp_uno_md,
2569 self.intrinsics.fp_exception_md,
2570 ],
2571 "",
2572 ))
2573 .try_as_basic_value()
2574 .unwrap_basic()
2575 .into_vector_value();
2576 let canonical_nan_bits = self
2577 .intrinsics
2578 .i32_ty
2579 .const_int(CANONICAL_NAN_F32 as _, false);
2580 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2581 let canonical_nan = err!(self.builder.build_bit_cast(
2582 canonical_nan_bits,
2583 self.intrinsics.f32x4_ty,
2584 "canonical_nan",
2585 ));
2586 let res = err!(self.builder.build_select(
2587 is_nan,
2588 canonical_nan.as_basic_value_enum(),
2589 value.as_basic_value_enum(),
2590 "canonical_nan",
2591 ));
2592 Ok((res, info))
2593 } else {
2594 let value = value.into_vector_value();
2595 let is_nan = err!(self.builder.build_call(
2596 self.intrinsics.cmp_f64x2,
2597 &[
2598 value.into(),
2599 value.into(),
2600 self.intrinsics.fp_uno_md,
2601 self.intrinsics.fp_exception_md,
2602 ],
2603 "",
2604 ))
2605 .try_as_basic_value()
2606 .unwrap_basic()
2607 .into_vector_value();
2608 let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2609 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2610 let canonical_nan = err!(self.builder.build_bit_cast(
2611 canonical_nan_bits,
2612 self.intrinsics.f64x2_ty,
2613 "canonical_nan",
2614 ));
2615 let res = err!(self.builder.build_select(
2616 is_nan,
2617 canonical_nan.as_basic_value_enum(),
2618 value.as_basic_value_enum(),
2619 "canonical_nan",
2620 ));
2621 Ok((res, info))
2622 }
2623 } else {
2624 Ok((
2625 value,
2626 (info
2627 | if is_f32 || is_f32x4 {
2628 ExtraInfo::pending_f32_nan()
2629 } else {
2630 ExtraInfo::pending_f64_nan()
2631 })?,
2632 ))
2633 }
2634 }
2635
2636 fn translate_control_flow_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2639 match op {
2640 Operator::Block { blockty } => {
2641 let current_block = self
2642 .builder
2643 .get_insert_block()
2644 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2645
2646 let end_block = self.context.append_basic_block(self.function, "end");
2647 self.builder.position_at_end(end_block);
2648
2649 let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2650 .module_translation
2651 .blocktype_params_results(&blockty)?
2652 .1
2653 .iter()
2654 .map(|&wp_ty| {
2655 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2656 type_to_llvm(self.intrinsics, wasm_ty)
2657 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2658 })
2659 })
2660 .collect::<Result<_, _>>()?;
2661
2662 self.state.push_block(
2663 end_block,
2664 phis,
2665 self.module_translation
2666 .blocktype_params_results(&blockty)?
2667 .0
2668 .len(),
2669 );
2670 self.builder.position_at_end(current_block);
2671 }
2672 Operator::Loop { blockty } => {
2673 let loop_body = self.context.append_basic_block(self.function, "loop_body");
2674 let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2675 let pre_loop_block = self.builder.get_insert_block().unwrap();
2676
2677 let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2678
2679 self.builder.position_at_end(loop_next);
2680 let phis = blocktypes
2681 .1
2682 .iter()
2683 .map(|&wp_ty| {
2684 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2685 type_to_llvm(self.intrinsics, wasm_ty)
2686 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2687 })
2688 })
2689 .collect::<Result<_, _>>()?;
2690 self.builder.position_at_end(loop_body);
2691 let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2692 .0
2693 .iter()
2694 .map(|&wp_ty| {
2695 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2696 type_to_llvm(self.intrinsics, wasm_ty)
2697 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2698 })
2699 })
2700 .collect::<Result<_, _>>()?;
2701
2702 self.builder.position_at_end(pre_loop_block);
2706 for phi in loop_phis.iter().rev() {
2707 let (value, info) = self.state.pop1_extra()?;
2708 let value = self.apply_pending_canonicalization(value, info)?;
2709 phi.add_incoming(&[(&value, pre_loop_block)]);
2710 }
2711
2712 err!(self.builder.build_unconditional_branch(loop_body));
2713
2714 self.builder.position_at_end(loop_body);
2715 for phi in &loop_phis {
2716 self.state.push1(phi.as_basic_value());
2717 }
2718
2719 let num_inputs = loop_phis.len();
2720 self.state
2721 .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2722 }
2723 Operator::Br { relative_depth } => {
2724 let frame = self.state.frame_at_depth(relative_depth)?;
2725
2726 let current_block = self
2727 .builder
2728 .get_insert_block()
2729 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2730
2731 let phis = if frame.is_loop() {
2732 frame.loop_body_phis()
2733 } else {
2734 frame.phis()
2735 };
2736
2737 let len = phis.len();
2738 let values = self.state.peekn_extra(len)?;
2739 let values = values
2740 .iter()
2741 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2742 .collect::<Result<Vec<_>, _>>()?;
2743
2744 for (phi, value) in phis.iter().zip(values) {
2748 phi.add_incoming(&[(&value, current_block)]);
2749 }
2750
2751 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2752
2753 self.state.popn(len)?;
2754 self.state.reachable = false;
2755 }
2756 Operator::BrIf { relative_depth } => {
2757 let cond = self.state.pop1()?;
2758 let frame = self.state.frame_at_depth(relative_depth)?;
2759
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
2765 let phis = if frame.is_loop() {
2766 frame.loop_body_phis()
2767 } else {
2768 frame.phis()
2769 };
2770
2771 let param_stack = self.state.peekn_extra(phis.len())?;
2772 let param_stack = param_stack
2773 .iter()
2774 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2775 .collect::<Result<Vec<_>, _>>()?;
2776
2777 for (phi, value) in phis.iter().zip(param_stack) {
2778 phi.add_incoming(&[(&value, current_block)]);
2779 }
2780
2781 let else_block = self.context.append_basic_block(self.function, "else");
2782
2783 let cond_value = err!(self.builder.build_int_compare(
2784 IntPredicate::NE,
2785 cond.into_int_value(),
2786 self.intrinsics.i32_zero,
2787 "",
2788 ));
2789 err!(self.builder.build_conditional_branch(
2790 cond_value,
2791 *frame.br_dest(),
2792 else_block
2793 ));
2794 self.builder.position_at_end(else_block);
2795 }
2796 Operator::BrTable { ref targets } => {
2797 let current_block = self
2798 .builder
2799 .get_insert_block()
2800 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2801
2802 let index = self.state.pop1()?;
2803
2804 let default_frame = self.state.frame_at_depth(targets.default())?;
2805
2806 let phis = if default_frame.is_loop() {
2807 default_frame.loop_body_phis()
2808 } else {
2809 default_frame.phis()
2810 };
2811 let args = self.state.peekn(phis.len())?;
2812
2813 for (phi, value) in phis.iter().zip(args.iter()) {
2814 phi.add_incoming(&[(value, current_block)]);
2815 }
2816
2817 let cases: Vec<_> = targets
2818 .targets()
2819 .enumerate()
2820 .map(|(case_index, depth)| {
2821 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2822 let frame_result: Result<&ControlFrame, CompileError> =
2823 self.state.frame_at_depth(depth);
2824 let frame = match frame_result {
2825 Ok(v) => v,
2826 Err(e) => return Err(e),
2827 };
2828 let case_index_literal =
2829 self.context.i32_type().const_int(case_index as u64, false);
2830 let phis = if frame.is_loop() {
2831 frame.loop_body_phis()
2832 } else {
2833 frame.phis()
2834 };
2835 for (phi, value) in phis.iter().zip(args.iter()) {
2836 phi.add_incoming(&[(value, current_block)]);
2837 }
2838
2839 Ok((case_index_literal, *frame.br_dest()))
2840 })
2841 .collect::<Result<_, _>>()?;
2842
2843 err!(self.builder.build_switch(
2844 index.into_int_value(),
2845 *default_frame.br_dest(),
2846 &cases[..],
2847 ));
2848
2849 let args_len = args.len();
2850 self.state.popn(args_len)?;
2851 self.state.reachable = false;
2852 }
2853 Operator::If { blockty } => {
2854 let current_block = self
2855 .builder
2856 .get_insert_block()
2857 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2858 let if_then_block = self.context.append_basic_block(self.function, "if_then");
2859 let if_else_block = self.context.append_basic_block(self.function, "if_else");
2860 let end_block = self.context.append_basic_block(self.function, "if_end");
2861
2862 let end_phis = {
2863 self.builder.position_at_end(end_block);
2864
2865 let phis = self
2866 .module_translation
2867 .blocktype_params_results(&blockty)?
2868 .1
2869 .iter()
2870 .map(|&wp_ty| {
2871 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2872 type_to_llvm(self.intrinsics, wasm_ty)
2873 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2874 })
2875 })
2876 .collect::<Result<_, _>>()?;
2877
2878 self.builder.position_at_end(current_block);
2879 phis
2880 };
2881
2882 let block_param_types = self
2883 .module_translation
2884 .blocktype_params_results(&blockty)?
2885 .0
2886 .iter()
2887 .map(|&wp_ty| {
2888 err_nt!(wptype_to_type(wp_ty))
2889 .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2890 })
2891 .collect::<Result<Vec<_>, _>>()?;
2892
2893 self.builder.position_at_end(if_else_block);
2895 let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2896 .iter()
2897 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2898 .collect::<Result<SmallVec<_>, _>>()?;
2899 self.builder.position_at_end(if_then_block);
2900 let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2901 .iter()
2902 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2903 .collect::<Result<SmallVec<_>, _>>()?;
2904
2905 let cond = self.state.pop1()?;
2907
2908 self.builder.position_at_end(current_block);
2912 for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2913 let (value, info) = self.state.pop1_extra()?;
2914 let value = self.apply_pending_canonicalization(value, info)?;
2915 else_phi.add_incoming(&[(&value, current_block)]);
2916 then_phi.add_incoming(&[(&value, current_block)]);
2917 }
2918
2919 let cond_value = err!(self.builder.build_int_compare(
2920 IntPredicate::NE,
2921 cond.into_int_value(),
2922 self.intrinsics.i32_zero,
2923 "",
2924 ));
2925
2926 err!(self.builder.build_conditional_branch(
2927 cond_value,
2928 if_then_block,
2929 if_else_block
2930 ));
2931
2932 self.builder.position_at_end(if_then_block);
2933 for phi in then_phis.iter() {
2934 self.state.push1(phi.as_basic_value());
2935 }
2936
2937 self.state.push_if(
2938 if_then_block,
2939 if_else_block,
2940 end_block,
2941 then_phis,
2942 else_phis,
2943 end_phis,
2944 block_param_types.len(),
2945 );
2946 }
2947 Operator::Else => {
2948 if self.state.reachable {
2949 let frame = self.state.frame_at_depth(0)?;
2950 let current_block = self.builder.get_insert_block().ok_or_else(|| {
2951 CompileError::Codegen("not currently in a block".to_string())
2952 })?;
2953
2954 for phi in frame.phis().to_vec().iter().rev() {
2955 let (value, info) = self.state.pop1_extra()?;
2956 let value = self.apply_pending_canonicalization(value, info)?;
2957 phi.add_incoming(&[(&value, current_block)])
2958 }
2959
2960 let frame = self.state.frame_at_depth(0)?;
2961 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2962 }
2963
2964 let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2965 if_else,
2966 if_else_state,
2967 ..
2968 } = self.state.frame_at_depth_mut(0)?
2969 {
2970 (if_else, if_else_state)
2971 } else {
2972 unreachable!()
2973 };
2974
2975 *if_else_state = IfElseState::Else;
2976
2977 self.builder.position_at_end(*if_else_block);
2978 self.state.reachable = true;
2979
2980 if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2981 for phi in else_phis.clone().iter() {
2983 self.state.push1(phi.as_basic_value());
2984 }
2985 };
2986 }
2987
2988 Operator::End => {
2989 let frame = self.state.pop_frame()?;
2990 let current_block = self
2991 .builder
2992 .get_insert_block()
2993 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2994
2995 if self.state.reachable {
2996 for phi in frame.phis().iter().rev() {
2997 let (value, info) = self.state.pop1_extra()?;
2998 let value = self.apply_pending_canonicalization(value, info)?;
2999 phi.add_incoming(&[(&value, current_block)]);
3000 }
3001
3002 err!(self.builder.build_unconditional_branch(*frame.code_after()));
3003 }
3004
3005 if let ControlFrame::IfElse {
3006 if_else,
3007 next,
3008 if_else_state: IfElseState::If,
3009 else_phis,
3010 ..
3011 } = &frame
3012 {
3013 for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
3014 phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
3015 }
3016 self.builder.position_at_end(*if_else);
3017 err!(self.builder.build_unconditional_branch(*next));
3018 } else if let ControlFrame::Landingpad { .. } = &frame {
3019 self.state.pop_landingpad();
3020 };
3021
3022 self.builder.position_at_end(*frame.code_after());
3023 self.state.reset_stack(&frame);
3024
3025 self.state.reachable = true;
3026
3027 for phi in frame.phis() {
3029 if phi.count_incoming() != 0 {
3030 self.state.push1(phi.as_basic_value());
3031 } else {
3032 let basic_ty = phi.as_basic_value().get_type();
3039 let placeholder_value = basic_ty.const_zero();
3040 self.state.push1(placeholder_value);
3041 phi.as_instruction().erase_from_basic_block();
3042 }
3043 }
3044 }
3045 Operator::Return => {
3046 let current_block = self
3047 .builder
3048 .get_insert_block()
3049 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3050
3051 let frame = self.state.outermost_frame()?;
3052 for phi in frame.phis().to_vec().iter().rev() {
3053 let (arg, info) = self.state.pop1_extra()?;
3054 let arg = self.apply_pending_canonicalization(arg, info)?;
3055 phi.add_incoming(&[(&arg, current_block)]);
3056 }
3057 let frame = self.state.outermost_frame()?;
3058 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
3059
3060 self.state.reachable = false;
3061 }
3062
3063 Operator::Unreachable => {
3064 self.build_call_with_param_attributes(
3065 self.intrinsics.throw_trap,
3066 &[self.intrinsics.trap_unreachable.into()],
3067 "throw",
3068 )?;
3069 err!(self.builder.build_unreachable());
3070
3071 self.state.reachable = false;
3072 }
3073 _ => unreachable!(),
3074 }
3075
3076 Ok(())
3077 }
3078
3079 fn translate_basic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3082 let vmctx = &self.ctx.basic().into_pointer_value();
3083
3084 match op {
3085 Operator::Nop => {
3086 }
3088 Operator::Drop => {
3089 self.state.pop1()?;
3090 }
3091
3092 Operator::I32Const { value } => {
3094 let i = self.intrinsics.i32_ty.const_int(value as u64, false);
3095 let info = if is_f32_arithmetic(value as u32) {
3096 ExtraInfo::arithmetic_f32()
3097 } else {
3098 Default::default()
3099 };
3100 self.state.push1_extra(i, info);
3101 }
3102 Operator::I64Const { value } => {
3103 let i = self.intrinsics.i64_ty.const_int(value as u64, false);
3104 let info = if is_f64_arithmetic(value as u64) {
3105 ExtraInfo::arithmetic_f64()
3106 } else {
3107 Default::default()
3108 };
3109 self.state.push1_extra(i, info);
3110 }
3111 Operator::F32Const { value } => {
3112 let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
3113 let info = if is_f32_arithmetic(value.bits()) {
3114 ExtraInfo::arithmetic_f32()
3115 } else {
3116 Default::default()
3117 };
3118 let f = err!(
3119 self.builder
3120 .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
3121 );
3122 self.state.push1_extra(f, info);
3123 }
3124 Operator::F64Const { value } => {
3125 let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
3126 let info = if is_f64_arithmetic(value.bits()) {
3127 ExtraInfo::arithmetic_f64()
3128 } else {
3129 Default::default()
3130 };
3131 let f = err!(
3132 self.builder
3133 .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
3134 );
3135 self.state.push1_extra(f, info);
3136 }
3137 Operator::V128Const { value } => {
3138 let mut hi: [u8; 8] = Default::default();
3139 let mut lo: [u8; 8] = Default::default();
3140 hi.copy_from_slice(&value.bytes()[0..8]);
3141 lo.copy_from_slice(&value.bytes()[8..16]);
3142 let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
3143 let i = self
3144 .intrinsics
3145 .i128_ty
3146 .const_int_arbitrary_precision(&packed);
3147 let mut quad1: [u8; 4] = Default::default();
3148 let mut quad2: [u8; 4] = Default::default();
3149 let mut quad3: [u8; 4] = Default::default();
3150 let mut quad4: [u8; 4] = Default::default();
3151 quad1.copy_from_slice(&value.bytes()[0..4]);
3152 quad2.copy_from_slice(&value.bytes()[4..8]);
3153 quad3.copy_from_slice(&value.bytes()[8..12]);
3154 quad4.copy_from_slice(&value.bytes()[12..16]);
3155 let mut info: ExtraInfo = Default::default();
3156 if is_f32_arithmetic(u32::from_le_bytes(quad1))
3157 && is_f32_arithmetic(u32::from_le_bytes(quad2))
3158 && is_f32_arithmetic(u32::from_le_bytes(quad3))
3159 && is_f32_arithmetic(u32::from_le_bytes(quad4))
3160 {
3161 info |= ExtraInfo::arithmetic_f32();
3162 }
3163 if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
3164 info |= ExtraInfo::arithmetic_f64();
3165 }
3166 self.state.push1_extra(i, info);
3167 }
3168
3169 Operator::I8x16Splat => {
3170 let (v, i) = self.state.pop1_extra()?;
3171 let v = v.into_int_value();
3172 let v = err!(
3173 self.builder
3174 .build_int_truncate(v, self.intrinsics.i8_ty, "")
3175 );
3176 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
3177 let res = err!(
3178 self.builder
3179 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3180 );
3181 self.state.push1_extra(res, i);
3182 }
3183 Operator::I16x8Splat => {
3184 let (v, i) = self.state.pop1_extra()?;
3185 let v = v.into_int_value();
3186 let v = err!(
3187 self.builder
3188 .build_int_truncate(v, self.intrinsics.i16_ty, "")
3189 );
3190 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
3191 let res = err!(
3192 self.builder
3193 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3194 );
3195 self.state.push1_extra(res, i);
3196 }
3197 Operator::I32x4Splat => {
3198 let (v, i) = self.state.pop1_extra()?;
3199 let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
3200 let res = err!(
3201 self.builder
3202 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3203 );
3204 self.state.push1_extra(res, i);
3205 }
3206 Operator::I64x2Splat => {
3207 let (v, i) = self.state.pop1_extra()?;
3208 let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
3209 let res = err!(
3210 self.builder
3211 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3212 );
3213 self.state.push1_extra(res, i);
3214 }
3215 Operator::F32x4Splat => {
3216 let (v, i) = self.state.pop1_extra()?;
3217 let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
3218 let res = err!(
3219 self.builder
3220 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3221 );
3222 self.state.push1_extra(res, i);
3225 }
3226 Operator::F64x2Splat => {
3227 let (v, i) = self.state.pop1_extra()?;
3228 let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
3229 let res = err!(
3230 self.builder
3231 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3232 );
3233 self.state.push1_extra(res, i);
3236 }
3237
3238 Operator::LocalGet { local_index } => {
3240 let (type_value, pointer_value) = self.locals[local_index as usize];
3241 let v = err!(self.builder.build_load(
3242 type_value,
3243 pointer_value,
3244 &format!("local_{local_index}_get")
3245 ));
3246 tbaa_label(
3247 self.module,
3248 self.intrinsics,
3249 format!("local {local_index}"),
3250 v.as_instruction_value().unwrap(),
3251 );
3252 self.state.push1(v);
3253 }
3254 Operator::LocalSet { local_index } => {
3255 let pointer_value = self.locals[local_index as usize].1;
3256 let (v, i) = self.state.pop1_extra()?;
3257 let v = self.apply_pending_canonicalization(v, i)?;
3258 let store = err!(self.builder.build_store(pointer_value, v));
3259 tbaa_label(
3260 self.module,
3261 self.intrinsics,
3262 format!("local {local_index}"),
3263 store,
3264 );
3265 }
3266 Operator::LocalTee { local_index } => {
3267 let pointer_value = self.locals[local_index as usize].1;
3268 let (v, i) = self.state.peek1_extra()?;
3269 let v = self.apply_pending_canonicalization(v, i)?;
3270 let store = err!(self.builder.build_store(pointer_value, v));
3271 tbaa_label(
3272 self.module,
3273 self.intrinsics,
3274 format!("local {local_index}"),
3275 store,
3276 );
3277 }
3278
3279 Operator::GlobalGet { global_index } => {
3280 let global_index = GlobalIndex::from_u32(global_index);
3281 match self
3282 .ctx
3283 .global(global_index, self.intrinsics, self.module)?
3284 {
3285 GlobalCache::Const { value } => {
3286 self.state.push1(*value);
3287 }
3288 GlobalCache::Mut {
3289 ptr_to_value,
3290 value_type,
3291 } => {
3292 let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
3293 tbaa_label(
3294 self.module,
3295 self.intrinsics,
3296 format!("global {}", global_index.as_u32()),
3297 value.as_instruction_value().unwrap(),
3298 );
3299 self.state.push1(value);
3300 }
3301 }
3302 }
3303 Operator::GlobalSet { global_index } => {
3304 let global_index = GlobalIndex::from_u32(global_index);
3305 match self
3306 .ctx
3307 .global(global_index, self.intrinsics, self.module)?
3308 {
3309 GlobalCache::Const { value: _ } => {
3310 return Err(CompileError::Codegen(format!(
3311 "global.set on immutable global index {}",
3312 global_index.as_u32()
3313 )));
3314 }
3315 GlobalCache::Mut { ptr_to_value, .. } => {
3316 let ptr_to_value = *ptr_to_value;
3317 let (value, info) = self.state.pop1_extra()?;
3318 let value = self.apply_pending_canonicalization(value, info)?;
3319 let store = err!(self.builder.build_store(ptr_to_value, value));
3320 tbaa_label(
3321 self.module,
3322 self.intrinsics,
3323 format!("global {}", global_index.as_u32()),
3324 store,
3325 );
3326 }
3327 }
3328 }
3329
3330 Operator::TypedSelect { .. } | Operator::Select => {
3333 let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3334 let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
3342 || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
3343 {
3344 (
3345 self.apply_pending_canonicalization(v1, i1)?,
3346 i1.strip_pending(),
3347 self.apply_pending_canonicalization(v2, i2)?,
3348 i2.strip_pending(),
3349 )
3350 } else {
3351 (v1, i1, v2, i2)
3352 };
3353 let cond_value = err!(self.builder.build_int_compare(
3354 IntPredicate::NE,
3355 cond.into_int_value(),
3356 self.intrinsics.i32_zero,
3357 "",
3358 ));
3359 let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
3360 let info = {
3361 let mut info = (i1.strip_pending() & i2.strip_pending())?;
3362 if i1.has_pending_f32_nan() {
3363 debug_assert!(i2.has_pending_f32_nan());
3364 info = (info | ExtraInfo::pending_f32_nan())?;
3365 }
3366 if i1.has_pending_f64_nan() {
3367 debug_assert!(i2.has_pending_f64_nan());
3368 info = (info | ExtraInfo::pending_f64_nan())?;
3369 }
3370 info
3371 };
3372 self.state.push1_extra(res, info);
3373 }
3374 Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
3375 let is_return_call = matches!(op, Operator::ReturnCall { .. });
3376 let func_index = FunctionIndex::from_u32(function_index);
3377 let sigindex = &self.wasm_module.functions[func_index];
3378 let func_type = &self.wasm_module.signatures[*sigindex];
3379
3380 let FunctionCache {
3381 func,
3382 llvm_func_type,
3383 vmctx: callee_vmctx,
3384 imported_include_m0_param,
3385 attrs,
3386 } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
3387 self.ctx.local_func(
3388 local_func_index,
3389 func_index,
3390 self.intrinsics,
3391 self.module,
3392 self.context,
3393 func_type,
3394 &CompiledKind::Local(local_func_index, String::new()).linkage_name(),
3395 )?
3396 } else {
3397 self.ctx
3398 .imported_func(func_index, self.intrinsics, self.context, func_type)?
3399 };
3400 let llvm_func_type = *llvm_func_type;
3401 let func = *func;
3402 let callee_vmctx = *callee_vmctx;
3403 let imported_include_m0_param = *imported_include_m0_param;
3404 let attrs = attrs.clone();
3405
3406 let params = self.state.popn_save_extra(func_type.params().len())?;
3412
3413 let params = params
3415 .iter()
3416 .zip(func_type.params().iter())
3417 .map(|((v, info), wasm_ty)| match wasm_ty {
3418 Type::F32 => err_nt!(self.builder.build_bit_cast(
3419 self.apply_pending_canonicalization(*v, *info)?,
3420 self.intrinsics.f32_ty,
3421 "",
3422 )),
3423 Type::F64 => err_nt!(self.builder.build_bit_cast(
3424 self.apply_pending_canonicalization(*v, *info)?,
3425 self.intrinsics.f64_ty,
3426 "",
3427 )),
3428 Type::V128 => self.apply_pending_canonicalization(*v, *info),
3429 _ => Ok(*v),
3430 })
3431 .collect::<Result<Vec<_>, _>>()?;
3432
3433 if let (Some(m0_param), Some(include_m0_param)) =
3434 (self.m0_param, imported_include_m0_param)
3435 {
3436 let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3440 self.abi.func_type_to_llvm(
3441 self.context,
3442 self.intrinsics,
3443 Some(self.ctx.get_offsets()),
3444 func_type,
3445 false,
3446 )?;
3447 let params_with_m0 = self.abi.args_to_call(
3448 &self.alloca_builder,
3449 func_type,
3450 &llvm_func_type,
3451 callee_vmctx.into_pointer_value(),
3452 params.as_slice(),
3453 self.intrinsics,
3454 Some(m0_param),
3455 is_return_call
3456 .then(|| self.current_sret_ptr(func_type))
3457 .flatten(),
3458 )?;
3459 let params_no_m0 = self.abi.args_to_call(
3460 &self.alloca_builder,
3461 func_type,
3462 &llvm_func_type_no_m0,
3463 callee_vmctx.into_pointer_value(),
3464 params.as_slice(),
3465 self.intrinsics,
3466 None,
3467 is_return_call
3468 .then(|| self.current_sret_ptr(func_type))
3469 .flatten(),
3470 )?;
3471
3472 let include_m0_call_block = self
3473 .context
3474 .append_basic_block(self.function, "call_block_with_m0");
3475 let skip_m0_call_block =
3476 self.context.append_basic_block(self.function, "call_block");
3477 let call_cont = self.context.append_basic_block(self.function, "call_cont");
3478 err!(self.builder.build_conditional_branch(
3479 include_m0_param,
3480 include_m0_call_block,
3481 skip_m0_call_block,
3482 ));
3483
3484 self.builder.position_at_end(include_m0_call_block);
3485 let call_site_with_m0 = self.build_indirect_call_or_invoke(
3486 llvm_func_type,
3487 func,
3488 params_with_m0.as_slice(),
3489 "then_block_with_m0",
3490 is_return_call,
3491 )?;
3492 for (attr, attr_loc) in &attrs {
3493 call_site_with_m0.add_attribute(*attr_loc, *attr);
3494 }
3495 let rets_with_m0 = self.abi.rets_from_call(
3496 &self.builder,
3497 self.intrinsics,
3498 call_site_with_m0,
3499 func_type,
3500 )?;
3501 let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3502 CompileError::Codegen(
3503 "missing insertion block after call with m0".to_string(),
3504 )
3505 })?;
3506 err!(self.builder.build_unconditional_branch(call_cont));
3507
3508 self.builder.position_at_end(skip_m0_call_block);
3509 let call_site_no_m0 = self.build_indirect_call_or_invoke(
3510 llvm_func_type_no_m0,
3511 func,
3512 params_no_m0.as_slice(),
3513 "then_block",
3514 is_return_call,
3515 )?;
3516 for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3517 call_site_no_m0.add_attribute(*attr_loc, *attr);
3518 }
3519 let rets_no_m0 = self.abi.rets_from_call(
3520 &self.builder,
3521 self.intrinsics,
3522 call_site_no_m0,
3523 func_type,
3524 )?;
3525 let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3526 CompileError::Codegen(
3527 "missing insertion block after call without m0".to_string(),
3528 )
3529 })?;
3530 err!(self.builder.build_unconditional_branch(call_cont));
3531
3532 self.builder.position_at_end(call_cont);
3533 for i in 0..rets_with_m0.len() {
3534 let with_m0 = rets_with_m0[i];
3535 let no_m0 = rets_no_m0[i];
3536 let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3537 phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3538 self.state.push1(phi.as_basic_value());
3539 }
3540 } else {
3541 let params = self.abi.args_to_call(
3542 &self.alloca_builder,
3543 func_type,
3544 &llvm_func_type,
3545 callee_vmctx.into_pointer_value(),
3546 params.as_slice(),
3547 self.intrinsics,
3548 self.m0_param,
3549 if is_return_call {
3550 self.current_sret_ptr(func_type)
3551 } else {
3552 None
3553 },
3554 )?;
3555
3556 let call_site = self.build_indirect_call_or_invoke(
3557 llvm_func_type,
3558 func,
3559 params.as_slice(),
3560 "then_block",
3561 is_return_call,
3562 )?;
3563 for (attr, attr_loc) in attrs {
3564 call_site.add_attribute(attr_loc, attr);
3565 }
3566
3567 if is_return_call {
3568 self.emit_return_call(call_site, llvm_func_type)?;
3569 self.state.reachable = false;
3570 } else {
3571 self.abi
3572 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3573 .iter()
3574 .for_each(|ret| self.state.push1(*ret));
3575 }
3576 }
3577 }
3578 Operator::CallIndirect {
3579 type_index,
3580 table_index,
3581 }
3582 | Operator::ReturnCallIndirect {
3583 type_index,
3584 table_index,
3585 } => {
3586 let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3587 let sigindex = SignatureIndex::from_u32(type_index);
3588 let table_index = TableIndex::from_u32(table_index);
3589 let func_type = &self.wasm_module.signatures[sigindex];
3590 let table = self.wasm_module.tables.get(table_index).unwrap();
3591 let local_fixed_funcref_table = self
3592 .wasm_module
3593 .local_table_index(table_index)
3594 .filter(|_| table.is_fixed_funcref_table());
3595 let expected_signature_hash = self
3596 .intrinsics
3597 .i32_ty
3598 .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3599
3600 let func_index = self.state.pop1()?.into_int_value();
3601 let generic_table = if local_fixed_funcref_table.is_none() {
3602 Some(self.ctx.table(
3603 table_index,
3604 self.intrinsics,
3605 self.module,
3606 &self.builder,
3607 )?)
3608 } else {
3609 None
3610 };
3611
3612 let table_bound = if local_fixed_funcref_table.is_some() {
3613 self.intrinsics
3614 .i32_ty
3615 .const_int(table.minimum.into(), false)
3616 } else {
3617 let (_, table_bound) = *generic_table.as_ref().unwrap();
3618 err!(self.builder.build_int_truncate(
3619 table_bound,
3620 self.intrinsics.i32_ty,
3621 "truncated_table_bounds",
3622 ))
3623 };
3624
3625 let index_in_bounds = err!(self.builder.build_int_compare(
3627 IntPredicate::ULT,
3628 func_index,
3629 table_bound,
3630 "index_in_bounds",
3631 ));
3632
3633 let index_in_bounds = self
3634 .build_call_with_param_attributes(
3635 self.intrinsics.expect_i1,
3636 &[
3637 index_in_bounds.into(),
3638 self.intrinsics.i1_ty.const_int(1, false).into(),
3639 ],
3640 "index_in_bounds_expect",
3641 )?
3642 .try_as_basic_value()
3643 .unwrap_basic()
3644 .into_int_value();
3645
3646 let in_bounds_continue_block = self
3647 .context
3648 .append_basic_block(self.function, "in_bounds_continue_block");
3649 let not_in_bounds_block = self
3650 .context
3651 .append_basic_block(self.function, "not_in_bounds_block");
3652 err!(self.builder.build_conditional_branch(
3653 index_in_bounds,
3654 in_bounds_continue_block,
3655 not_in_bounds_block,
3656 ));
3657 self.builder.position_at_end(not_in_bounds_block);
3658 self.build_call_with_param_attributes(
3659 self.intrinsics.throw_trap,
3660 &[self.intrinsics.trap_table_access_oob.into()],
3661 "throw",
3662 )?;
3663 err!(self.builder.build_unreachable());
3664 self.builder.position_at_end(in_bounds_continue_block);
3665
3666 let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3667 {
3668 let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3669 local_table_index,
3670 self.intrinsics,
3671 &self.builder,
3672 )?;
3673 unsafe {
3674 err!(self.builder.build_in_bounds_gep(
3675 self.intrinsics.anyfunc_ty,
3676 anyfuncs,
3677 &[func_index],
3678 "anyfunc_struct_ptr",
3679 ))
3680 }
3681 } else {
3682 let (table_base, _) = *generic_table.as_ref().unwrap();
3683
3684 let casted_table_base = err!(self.builder.build_pointer_cast(
3687 table_base,
3688 self.context.ptr_type(AddressSpace::default()),
3689 "casted_table_base",
3690 ));
3691
3692 let funcref_ptr = unsafe {
3693 err!(self.builder.build_in_bounds_gep(
3694 self.intrinsics.ptr_ty,
3695 casted_table_base,
3696 &[func_index],
3697 "funcref_ptr",
3698 ))
3699 };
3700
3701 let anyfunc_struct_ptr = err!(self.builder.build_load(
3703 self.intrinsics.ptr_ty,
3704 funcref_ptr,
3705 "anyfunc_struct_ptr",
3706 ))
3707 .into_pointer_value();
3708
3709 if !table.readonly {
3710 let funcref_not_null = err!(
3712 self.builder
3713 .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3714 );
3715
3716 let funcref_continue_deref_block = self
3717 .context
3718 .append_basic_block(self.function, "funcref_continue_deref_block");
3719
3720 let funcref_is_null_block = self
3721 .context
3722 .append_basic_block(self.function, "funcref_is_null_block");
3723 err!(self.builder.build_conditional_branch(
3724 funcref_not_null,
3725 funcref_continue_deref_block,
3726 funcref_is_null_block,
3727 ));
3728 self.builder.position_at_end(funcref_is_null_block);
3729 self.build_call_with_param_attributes(
3730 self.intrinsics.throw_trap,
3731 &[self.intrinsics.trap_call_indirect_null.into()],
3732 "throw",
3733 )?;
3734 err!(self.builder.build_unreachable());
3735 self.builder.position_at_end(funcref_continue_deref_block);
3736 }
3737
3738 anyfunc_struct_ptr
3739 };
3740
3741 let sig_hash_ptr = self
3743 .builder
3744 .build_struct_gep(
3745 self.intrinsics.anyfunc_ty,
3746 anyfunc_struct_ptr,
3747 1,
3748 "sig_hash_ptr",
3749 )
3750 .unwrap();
3751 let func_ptr_ptr = self
3752 .builder
3753 .build_struct_gep(
3754 self.intrinsics.anyfunc_ty,
3755 anyfunc_struct_ptr,
3756 0,
3757 "func_ptr_ptr",
3758 )
3759 .unwrap();
3760 let (func_ptr, found_signature_hash) = (
3761 err!(
3762 self.builder
3763 .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3764 )
3765 .into_pointer_value(),
3766 err!(
3767 self.builder
3768 .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3769 )
3770 .into_int_value(),
3771 );
3772
3773 let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3777
3778 let sig_hashes_equal = err!(self.builder.build_int_compare(
3781 IntPredicate::EQ,
3782 expected_signature_hash,
3783 found_signature_hash,
3784 "sig_hashes_equal",
3785 ));
3786
3787 let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3788 elem_initialized,
3789 sig_hashes_equal,
3790 ""
3791 ));
3792
3793 let initialized_and_sig_hashes_match = self
3795 .build_call_with_param_attributes(
3796 self.intrinsics.expect_i1,
3797 &[
3798 initialized_and_sig_hashes_match.into(),
3799 self.intrinsics.i1_ty.const_int(1, false).into(),
3800 ],
3801 "initialized_and_sig_hashes_match_expect",
3802 )?
3803 .try_as_basic_value()
3804 .unwrap_basic()
3805 .into_int_value();
3806
3807 let continue_block = self
3808 .context
3809 .append_basic_block(self.function, "continue_block");
3810 let sighashes_notequal_block = self
3811 .context
3812 .append_basic_block(self.function, "sighashes_notequal_block");
3813 err!(self.builder.build_conditional_branch(
3814 initialized_and_sig_hashes_match,
3815 continue_block,
3816 sighashes_notequal_block,
3817 ));
3818
3819 self.builder.position_at_end(sighashes_notequal_block);
3820 let trap_code = err!(self.builder.build_select(
3821 elem_initialized,
3822 self.intrinsics.trap_call_indirect_sig,
3823 self.intrinsics.trap_call_indirect_null,
3824 "",
3825 ));
3826 self.build_call_with_param_attributes(
3827 self.intrinsics.throw_trap,
3828 &[trap_code.into()],
3829 "throw",
3830 )?;
3831 err!(self.builder.build_unreachable());
3832 self.builder.position_at_end(continue_block);
3833
3834 let callee_vmctx = if table.readonly {
3835 *vmctx
3836 } else {
3837 let ctx_ptr_ptr = self
3838 .builder
3839 .build_struct_gep(
3840 self.intrinsics.anyfunc_ty,
3841 anyfunc_struct_ptr,
3842 2,
3843 "ctx_ptr_ptr",
3844 )
3845 .unwrap();
3846 err!(
3847 self.builder
3848 .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3849 )
3850 .into_pointer_value()
3851 };
3852
3853 if self.m0_param.is_some() {
3854 self.build_m0_indirect_call(
3855 table_index.as_u32(),
3856 callee_vmctx,
3857 func_type,
3858 func_ptr,
3859 func_index,
3860 is_return_call,
3861 )?;
3862 } else {
3863 let (call_site, llvm_func_type) = self.build_indirect_call(
3864 callee_vmctx,
3865 func_type,
3866 func_ptr,
3867 None,
3868 is_return_call,
3869 )?;
3870
3871 if is_return_call {
3872 self.emit_return_call(call_site, llvm_func_type)?;
3873 } else {
3874 self.abi
3875 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3876 .iter()
3877 .for_each(|ret| self.state.push1(*ret));
3878 }
3879 }
3880
3881 if is_return_call {
3882 self.state.reachable = false;
3883 }
3884 }
3885 _ => unreachable!(),
3886 }
3887 Ok(())
3888 }
3889
3890 fn translate_integer_arithmetic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3893 match op {
3894 Operator::I32Add | Operator::I64Add => {
3895 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3896 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3897 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3898 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3899 let res = err!(self.builder.build_int_add(v1, v2, ""));
3900 self.state.push1(res);
3901 }
3902 Operator::I8x16Add => {
3903 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3904 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3905 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3906 let res = err!(self.builder.build_int_add(v1, v2, ""));
3907 let res = err!(
3908 self.builder
3909 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3910 );
3911 self.state.push1(res);
3912 }
3913 Operator::I16x8Add => {
3914 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3915 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3916 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3917 let res = err!(self.builder.build_int_add(v1, v2, ""));
3918 let res = err!(
3919 self.builder
3920 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3921 );
3922 self.state.push1(res);
3923 }
3924 Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3925 let extend_op = match op {
3926 Operator::I16x8ExtAddPairwiseI8x16S => {
3927 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3928 }
3929 Operator::I16x8ExtAddPairwiseI8x16U => {
3930 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3931 }
3932 _ => unreachable!("Unhandled internal variant"),
3933 };
3934 let (v, i) = self.state.pop1_extra()?;
3935 let (v, _) = self.v128_into_i8x16(v, i)?;
3936
3937 let left = err!(self.builder.build_shuffle_vector(
3938 v,
3939 v.get_type().get_undef(),
3940 VectorType::const_vector(&[
3941 self.intrinsics.i32_consts[0],
3942 self.intrinsics.i32_consts[2],
3943 self.intrinsics.i32_consts[4],
3944 self.intrinsics.i32_consts[6],
3945 self.intrinsics.i32_consts[8],
3946 self.intrinsics.i32_consts[10],
3947 self.intrinsics.i32_consts[12],
3948 self.intrinsics.i32_consts[14],
3949 ]),
3950 "",
3951 ));
3952 let left = err!(extend_op(self, left));
3953 let right = err!(self.builder.build_shuffle_vector(
3954 v,
3955 v.get_type().get_undef(),
3956 VectorType::const_vector(&[
3957 self.intrinsics.i32_consts[1],
3958 self.intrinsics.i32_consts[3],
3959 self.intrinsics.i32_consts[5],
3960 self.intrinsics.i32_consts[7],
3961 self.intrinsics.i32_consts[9],
3962 self.intrinsics.i32_consts[11],
3963 self.intrinsics.i32_consts[13],
3964 self.intrinsics.i32_consts[15],
3965 ]),
3966 "",
3967 ));
3968 let right = err!(extend_op(self, right));
3969
3970 let res = err!(self.builder.build_int_add(left, right, ""));
3971 let res = err!(
3972 self.builder
3973 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3974 );
3975 self.state.push1(res);
3976 }
3977 Operator::I32x4Add => {
3978 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3979 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3980 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3981 let res = err!(self.builder.build_int_add(v1, v2, ""));
3982 let res = err!(
3983 self.builder
3984 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3985 );
3986 self.state.push1(res);
3987 }
3988 Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3989 let extend_op = match op {
3990 Operator::I32x4ExtAddPairwiseI16x8S => {
3991 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3992 }
3993 Operator::I32x4ExtAddPairwiseI16x8U => {
3994 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3995 }
3996 _ => unreachable!("Unhandled internal variant"),
3997 };
3998 let (v, i) = self.state.pop1_extra()?;
3999 let (v, _) = self.v128_into_i16x8(v, i)?;
4000
4001 let left = err!(self.builder.build_shuffle_vector(
4002 v,
4003 v.get_type().get_undef(),
4004 VectorType::const_vector(&[
4005 self.intrinsics.i32_consts[0],
4006 self.intrinsics.i32_consts[2],
4007 self.intrinsics.i32_consts[4],
4008 self.intrinsics.i32_consts[6],
4009 ]),
4010 "",
4011 ));
4012 let left = err!(extend_op(self, left));
4013 let right = err!(self.builder.build_shuffle_vector(
4014 v,
4015 v.get_type().get_undef(),
4016 VectorType::const_vector(&[
4017 self.intrinsics.i32_consts[1],
4018 self.intrinsics.i32_consts[3],
4019 self.intrinsics.i32_consts[5],
4020 self.intrinsics.i32_consts[7],
4021 ]),
4022 "",
4023 ));
4024 let right = err!(extend_op(self, right));
4025
4026 let res = err!(self.builder.build_int_add(left, right, ""));
4027 let res = err!(
4028 self.builder
4029 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4030 );
4031 self.state.push1(res);
4032 }
4033 Operator::I64x2Add => {
4034 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4035 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4036 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4037 let res = err!(self.builder.build_int_add(v1, v2, ""));
4038 let res = err!(
4039 self.builder
4040 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4041 );
4042 self.state.push1(res);
4043 }
4044 Operator::I8x16AddSatS => {
4045 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4046 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4047 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4048 let res = self
4049 .build_call_with_param_attributes(
4050 self.intrinsics.sadd_sat_i8x16,
4051 &[v1.into(), v2.into()],
4052 "",
4053 )?
4054 .try_as_basic_value()
4055 .unwrap_basic();
4056 let res = err!(
4057 self.builder
4058 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4059 );
4060 self.state.push1(res);
4061 }
4062 Operator::I16x8AddSatS => {
4063 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4064 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4065 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4066 let res = self
4067 .build_call_with_param_attributes(
4068 self.intrinsics.sadd_sat_i16x8,
4069 &[v1.into(), v2.into()],
4070 "",
4071 )?
4072 .try_as_basic_value()
4073 .unwrap_basic();
4074 let res = err!(
4075 self.builder
4076 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4077 );
4078 self.state.push1(res);
4079 }
4080 Operator::I8x16AddSatU => {
4081 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4082 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4083 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4084 let res = self
4085 .build_call_with_param_attributes(
4086 self.intrinsics.uadd_sat_i8x16,
4087 &[v1.into(), v2.into()],
4088 "",
4089 )?
4090 .try_as_basic_value()
4091 .unwrap_basic();
4092 let res = err!(
4093 self.builder
4094 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4095 );
4096 self.state.push1(res);
4097 }
4098 Operator::I16x8AddSatU => {
4099 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4100 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4101 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4102 let res = self
4103 .build_call_with_param_attributes(
4104 self.intrinsics.uadd_sat_i16x8,
4105 &[v1.into(), v2.into()],
4106 "",
4107 )?
4108 .try_as_basic_value()
4109 .unwrap_basic();
4110 let res = err!(
4111 self.builder
4112 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4113 );
4114 self.state.push1(res);
4115 }
4116 Operator::I32Sub | Operator::I64Sub => {
4117 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4118 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4119 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4120 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4121 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4122 self.state.push1(res);
4123 }
4124 Operator::I8x16Sub => {
4125 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4126 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4127 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4128 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4129 let res = err!(
4130 self.builder
4131 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4132 );
4133 self.state.push1(res);
4134 }
4135 Operator::I16x8Sub => {
4136 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4137 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4138 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4139 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4140 let res = err!(
4141 self.builder
4142 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4143 );
4144 self.state.push1(res);
4145 }
4146 Operator::I32x4Sub => {
4147 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4148 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4149 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4150 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4151 let res = err!(
4152 self.builder
4153 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4154 );
4155 self.state.push1(res);
4156 }
4157 Operator::I64x2Sub => {
4158 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4159 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4160 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4161 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4162 let res = err!(
4163 self.builder
4164 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4165 );
4166 self.state.push1(res);
4167 }
4168 Operator::I8x16SubSatS => {
4169 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4170 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4171 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4172 let res = self
4173 .build_call_with_param_attributes(
4174 self.intrinsics.ssub_sat_i8x16,
4175 &[v1.into(), v2.into()],
4176 "",
4177 )?
4178 .try_as_basic_value()
4179 .unwrap_basic();
4180 let res = err!(
4181 self.builder
4182 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4183 );
4184 self.state.push1(res);
4185 }
4186 Operator::I16x8SubSatS => {
4187 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4188 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4189 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4190 let res = self
4191 .build_call_with_param_attributes(
4192 self.intrinsics.ssub_sat_i16x8,
4193 &[v1.into(), v2.into()],
4194 "",
4195 )?
4196 .try_as_basic_value()
4197 .unwrap_basic();
4198 let res = err!(
4199 self.builder
4200 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4201 );
4202 self.state.push1(res);
4203 }
4204 Operator::I8x16SubSatU => {
4205 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4206 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4207 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4208 let res = self
4209 .build_call_with_param_attributes(
4210 self.intrinsics.usub_sat_i8x16,
4211 &[v1.into(), v2.into()],
4212 "",
4213 )?
4214 .try_as_basic_value()
4215 .unwrap_basic();
4216 let res = err!(
4217 self.builder
4218 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4219 );
4220 self.state.push1(res);
4221 }
4222 Operator::I16x8SubSatU => {
4223 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4224 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4225 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4226 let res = self
4227 .build_call_with_param_attributes(
4228 self.intrinsics.usub_sat_i16x8,
4229 &[v1.into(), v2.into()],
4230 "",
4231 )?
4232 .try_as_basic_value()
4233 .unwrap_basic();
4234 let res = err!(
4235 self.builder
4236 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4237 );
4238 self.state.push1(res);
4239 }
4240 Operator::I32Mul | Operator::I64Mul => {
4241 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4242 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4243 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4244 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4245 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4246 self.state.push1(res);
4247 }
4248 Operator::I16x8Mul => {
4249 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4250 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4251 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4252 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4253 let res = err!(
4254 self.builder
4255 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4256 );
4257 self.state.push1(res);
4258 }
4259 Operator::I32x4Mul => {
4260 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4261 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4262 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4263 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4264 let res = err!(
4265 self.builder
4266 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4267 );
4268 self.state.push1(res);
4269 }
4270 Operator::I64x2Mul => {
4271 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4272 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4273 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4274 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4275 let res = err!(
4276 self.builder
4277 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4278 );
4279 self.state.push1(res);
4280 }
4281 Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
4282 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4283 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4284 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4285 let res = self
4286 .build_call_with_param_attributes(
4287 self.intrinsics.x86_64.pmulhrsw128,
4288 &[v1.into(), v2.into()],
4289 "",
4290 )?
4291 .try_as_basic_value()
4292 .unwrap_basic();
4293 let res = err!(
4294 self.builder
4295 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4296 );
4297 self.state.push1(res);
4298 }
4299 Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
4300 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4301 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4302 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4303
4304 let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
4305 let max_values = VectorType::const_vector(&[max_value; 8]);
4306
4307 let v1 = err!(
4308 self.builder
4309 .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
4310 );
4311 let v2 = err!(
4312 self.builder
4313 .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
4314 );
4315 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4316
4317 let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
4319 let bits = VectorType::const_vector(&[bit; 8]);
4320
4321 let res = err!(self.builder.build_int_add(res, bits, ""));
4322
4323 let fifteen = self.intrinsics.i32_consts[15];
4324 let fifteens = VectorType::const_vector(&[fifteen; 8]);
4325
4326 let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
4327 let saturate_up = {
4328 let max_values = err!(self.builder.build_int_s_extend(
4329 max_values,
4330 self.intrinsics.i32x8_ty,
4331 ""
4332 ));
4333 err!(
4334 self.builder
4335 .build_int_compare(IntPredicate::SGT, res, max_values, "")
4336 )
4337 };
4338
4339 let res = err!(
4340 self.builder
4341 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
4342 );
4343
4344 let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
4345 .into_vector_value();
4346 let res = err!(
4347 self.builder
4348 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4349 );
4350 self.state.push1(res);
4351 }
4352 Operator::I16x8ExtMulLowI8x16S
4353 | Operator::I16x8ExtMulLowI8x16U
4354 | Operator::I16x8ExtMulHighI8x16S
4355 | Operator::I16x8ExtMulHighI8x16U => {
4356 let extend_op = match op {
4357 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
4358 |s: &Self, v| -> Result<VectorValue, CompileError> {
4359 err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
4360 }
4361 }
4362 Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
4363 |s: &Self, v| -> Result<VectorValue, CompileError> {
4364 err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
4365 }
4366 }
4367 _ => unreachable!("Unhandled internal variant"),
4368 };
4369 let shuffle_array = match op {
4370 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
4371 self.intrinsics.i32_consts[0],
4372 self.intrinsics.i32_consts[1],
4373 self.intrinsics.i32_consts[2],
4374 self.intrinsics.i32_consts[3],
4375 self.intrinsics.i32_consts[4],
4376 self.intrinsics.i32_consts[5],
4377 self.intrinsics.i32_consts[6],
4378 self.intrinsics.i32_consts[7],
4379 ],
4380 Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
4381 self.intrinsics.i32_consts[8],
4382 self.intrinsics.i32_consts[9],
4383 self.intrinsics.i32_consts[10],
4384 self.intrinsics.i32_consts[11],
4385 self.intrinsics.i32_consts[12],
4386 self.intrinsics.i32_consts[13],
4387 self.intrinsics.i32_consts[14],
4388 self.intrinsics.i32_consts[15],
4389 ],
4390 _ => unreachable!("Unhandled internal variant"),
4391 };
4392 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4393 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4394 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4395 let val1 = err!(self.builder.build_shuffle_vector(
4396 v1,
4397 v1.get_type().get_undef(),
4398 VectorType::const_vector(&shuffle_array),
4399 "",
4400 ));
4401 let val1 = err!(extend_op(self, val1));
4402 let val2 = err!(self.builder.build_shuffle_vector(
4403 v2,
4404 v2.get_type().get_undef(),
4405 VectorType::const_vector(&shuffle_array),
4406 "",
4407 ));
4408 let val2 = err!(extend_op(self, val2));
4409 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4410 let res = err!(
4411 self.builder
4412 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4413 );
4414 self.state.push1(res);
4415 }
4416 Operator::I32x4ExtMulLowI16x8S
4417 | Operator::I32x4ExtMulLowI16x8U
4418 | Operator::I32x4ExtMulHighI16x8S
4419 | Operator::I32x4ExtMulHighI16x8U => {
4420 let extend_op = match op {
4421 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4422 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4423 }
4424 Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4425 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4426 }
4427 _ => unreachable!("Unhandled internal variant"),
4428 };
4429 let shuffle_array = match op {
4430 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4431 self.intrinsics.i32_consts[0],
4432 self.intrinsics.i32_consts[1],
4433 self.intrinsics.i32_consts[2],
4434 self.intrinsics.i32_consts[3],
4435 ],
4436 Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4437 self.intrinsics.i32_consts[4],
4438 self.intrinsics.i32_consts[5],
4439 self.intrinsics.i32_consts[6],
4440 self.intrinsics.i32_consts[7],
4441 ],
4442 _ => unreachable!("Unhandled internal variant"),
4443 };
4444 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4445 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4446 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4447 let val1 = err!(self.builder.build_shuffle_vector(
4448 v1,
4449 v1.get_type().get_undef(),
4450 VectorType::const_vector(&shuffle_array),
4451 "",
4452 ));
4453 let val1 = err!(extend_op(self, val1));
4454 let val2 = err!(self.builder.build_shuffle_vector(
4455 v2,
4456 v2.get_type().get_undef(),
4457 VectorType::const_vector(&shuffle_array),
4458 "",
4459 ));
4460 let val2 = err!(extend_op(self, val2));
4461 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4462 let res = err!(
4463 self.builder
4464 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4465 );
4466 self.state.push1(res);
4467 }
4468 Operator::I64x2ExtMulLowI32x4S
4469 | Operator::I64x2ExtMulLowI32x4U
4470 | Operator::I64x2ExtMulHighI32x4S
4471 | Operator::I64x2ExtMulHighI32x4U => {
4472 let extend_op = match op {
4473 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4474 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4475 }
4476 Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4477 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4478 }
4479 _ => unreachable!("Unhandled internal variant"),
4480 };
4481 let shuffle_array = match op {
4482 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4483 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4484 }
4485 Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4486 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4487 }
4488 _ => unreachable!("Unhandled internal variant"),
4489 };
4490 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4491 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4492 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4493 let val1 = err!(self.builder.build_shuffle_vector(
4494 v1,
4495 v1.get_type().get_undef(),
4496 VectorType::const_vector(&shuffle_array),
4497 "",
4498 ));
4499 let val1 = err!(extend_op(self, val1));
4500 let val2 = err!(self.builder.build_shuffle_vector(
4501 v2,
4502 v2.get_type().get_undef(),
4503 VectorType::const_vector(&shuffle_array),
4504 "",
4505 ));
4506 let val2 = err!(extend_op(self, val2));
4507 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4508 let res = err!(
4509 self.builder
4510 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4511 );
4512 self.state.push1(res);
4513 }
4514 Operator::I32x4DotI16x8S => {
4515 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4516 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4517 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4518 let low_i16 = [
4519 self.intrinsics.i32_consts[0],
4520 self.intrinsics.i32_consts[2],
4521 self.intrinsics.i32_consts[4],
4522 self.intrinsics.i32_consts[6],
4523 ];
4524 let high_i16 = [
4525 self.intrinsics.i32_consts[1],
4526 self.intrinsics.i32_consts[3],
4527 self.intrinsics.i32_consts[5],
4528 self.intrinsics.i32_consts[7],
4529 ];
4530 let v1_low = err!(self.builder.build_shuffle_vector(
4531 v1,
4532 v1.get_type().get_undef(),
4533 VectorType::const_vector(&low_i16),
4534 "",
4535 ));
4536 let v1_low = err!(self.builder.build_int_s_extend(
4537 v1_low,
4538 self.intrinsics.i32x4_ty,
4539 ""
4540 ));
4541 let v1_high = err!(self.builder.build_shuffle_vector(
4542 v1,
4543 v1.get_type().get_undef(),
4544 VectorType::const_vector(&high_i16),
4545 "",
4546 ));
4547 let v1_high = err!(self.builder.build_int_s_extend(
4548 v1_high,
4549 self.intrinsics.i32x4_ty,
4550 ""
4551 ));
4552 let v2_low = err!(self.builder.build_shuffle_vector(
4553 v2,
4554 v2.get_type().get_undef(),
4555 VectorType::const_vector(&low_i16),
4556 "",
4557 ));
4558 let v2_low = err!(self.builder.build_int_s_extend(
4559 v2_low,
4560 self.intrinsics.i32x4_ty,
4561 ""
4562 ));
4563 let v2_high = err!(self.builder.build_shuffle_vector(
4564 v2,
4565 v2.get_type().get_undef(),
4566 VectorType::const_vector(&high_i16),
4567 "",
4568 ));
4569 let v2_high = err!(self.builder.build_int_s_extend(
4570 v2_high,
4571 self.intrinsics.i32x4_ty,
4572 ""
4573 ));
4574 let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4575 let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4576
4577 let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4578 let res = err!(
4579 self.builder
4580 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4581 );
4582 self.state.push1(res);
4583 }
4584 Operator::I16x8RelaxedDotI8x16I7x16S
4585 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4586 {
4587 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4588 let (a, _) = self.v128_into_i8x16(v1, i1)?;
4589 let (b, _) = self.v128_into_i8x16(v2, i2)?;
4590
4591 let res = self
4592 .build_call_with_param_attributes(
4593 self.intrinsics.x86_64.pmaddubsw128,
4594 &[b.into(), a.into()],
4595 "",
4596 )?
4597 .try_as_basic_value()
4598 .unwrap_basic()
4599 .into_vector_value();
4600 let res = err!(
4601 self.builder
4602 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4603 );
4604 self.state.push1(res);
4605 }
4606 Operator::I16x8RelaxedDotI8x16I7x16S => {
4607 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4608 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4609 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4610
4611 let left_indices = [
4612 self.intrinsics.i32_consts[0],
4613 self.intrinsics.i32_consts[2],
4614 self.intrinsics.i32_consts[4],
4615 self.intrinsics.i32_consts[6],
4616 self.intrinsics.i32_consts[8],
4617 self.intrinsics.i32_consts[10],
4618 self.intrinsics.i32_consts[12],
4619 self.intrinsics.i32_consts[14],
4620 ];
4621 let right_indices = [
4622 self.intrinsics.i32_consts[1],
4623 self.intrinsics.i32_consts[3],
4624 self.intrinsics.i32_consts[5],
4625 self.intrinsics.i32_consts[7],
4626 self.intrinsics.i32_consts[9],
4627 self.intrinsics.i32_consts[11],
4628 self.intrinsics.i32_consts[13],
4629 self.intrinsics.i32_consts[15],
4630 ];
4631
4632 let v1_left = err!(self.builder.build_shuffle_vector(
4633 v1,
4634 v1.get_type().get_undef(),
4635 VectorType::const_vector(&left_indices),
4636 "",
4637 ));
4638 let v1_left = err!(self.builder.build_int_s_extend(
4639 v1_left,
4640 self.intrinsics.i16x8_ty,
4641 ""
4642 ));
4643 let v1_right = err!(self.builder.build_shuffle_vector(
4644 v1,
4645 v1.get_type().get_undef(),
4646 VectorType::const_vector(&right_indices),
4647 "",
4648 ));
4649 let v1_right = err!(self.builder.build_int_s_extend(
4650 v1_right,
4651 self.intrinsics.i16x8_ty,
4652 ""
4653 ));
4654
4655 let v2_left = err!(self.builder.build_shuffle_vector(
4656 v2,
4657 v2.get_type().get_undef(),
4658 VectorType::const_vector(&left_indices),
4659 "",
4660 ));
4661 let v2_left = err!(self.builder.build_int_s_extend(
4662 v2_left,
4663 self.intrinsics.i16x8_ty,
4664 ""
4665 ));
4666 let v2_right = err!(self.builder.build_shuffle_vector(
4667 v2,
4668 v2.get_type().get_undef(),
4669 VectorType::const_vector(&right_indices),
4670 "",
4671 ));
4672 let v2_right = err!(self.builder.build_int_s_extend(
4673 v2_right,
4674 self.intrinsics.i16x8_ty,
4675 ""
4676 ));
4677
4678 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4679 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4680 let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4681 let res = err!(
4682 self.builder
4683 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4684 );
4685 self.state.push1(res);
4686 }
4687 Operator::I32x4RelaxedDotI8x16I7x16AddS
4688 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4689 {
4690 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4691 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4692 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4693 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4694
4695 let dot16 = self
4698 .build_call_with_param_attributes(
4699 self.intrinsics.x86_64.pmaddubsw128,
4700 &[v2.into(), v1.into()],
4701 "",
4702 )?
4703 .try_as_basic_value()
4704 .unwrap_basic()
4705 .into_vector_value();
4706 let ones =
4707 VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4708 let dot32 = self
4709 .build_call_with_param_attributes(
4710 self.intrinsics.x86_64.pmaddwd128,
4711 &[dot16.into(), ones.into()],
4712 "",
4713 )?
4714 .try_as_basic_value()
4715 .unwrap_basic()
4716 .into_vector_value();
4717 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4718 let res = err!(
4719 self.builder
4720 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4721 );
4722 self.state.push1(res);
4723 }
4724 Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4725 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4726 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4727 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4728 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4729
4730 let left_indices = [
4731 self.intrinsics.i32_consts[0],
4732 self.intrinsics.i32_consts[2],
4733 self.intrinsics.i32_consts[4],
4734 self.intrinsics.i32_consts[6],
4735 self.intrinsics.i32_consts[8],
4736 self.intrinsics.i32_consts[10],
4737 self.intrinsics.i32_consts[12],
4738 self.intrinsics.i32_consts[14],
4739 ];
4740 let right_indices = [
4741 self.intrinsics.i32_consts[1],
4742 self.intrinsics.i32_consts[3],
4743 self.intrinsics.i32_consts[5],
4744 self.intrinsics.i32_consts[7],
4745 self.intrinsics.i32_consts[9],
4746 self.intrinsics.i32_consts[11],
4747 self.intrinsics.i32_consts[13],
4748 self.intrinsics.i32_consts[15],
4749 ];
4750
4751 let v1_left = err!(self.builder.build_shuffle_vector(
4752 v1,
4753 v1.get_type().get_undef(),
4754 VectorType::const_vector(&left_indices),
4755 "",
4756 ));
4757 let v1_left = err!(self.builder.build_int_s_extend(
4758 v1_left,
4759 self.intrinsics.i16x8_ty,
4760 ""
4761 ));
4762 let v1_right = err!(self.builder.build_shuffle_vector(
4763 v1,
4764 v1.get_type().get_undef(),
4765 VectorType::const_vector(&right_indices),
4766 "",
4767 ));
4768 let v1_right = err!(self.builder.build_int_s_extend(
4769 v1_right,
4770 self.intrinsics.i16x8_ty,
4771 ""
4772 ));
4773
4774 let v2_left = err!(self.builder.build_shuffle_vector(
4775 v2,
4776 v2.get_type().get_undef(),
4777 VectorType::const_vector(&left_indices),
4778 "",
4779 ));
4780 let v2_left = err!(self.builder.build_int_s_extend(
4781 v2_left,
4782 self.intrinsics.i16x8_ty,
4783 ""
4784 ));
4785 let v2_right = err!(self.builder.build_shuffle_vector(
4786 v2,
4787 v2.get_type().get_undef(),
4788 VectorType::const_vector(&right_indices),
4789 "",
4790 ));
4791 let v2_right = err!(self.builder.build_int_s_extend(
4792 v2_right,
4793 self.intrinsics.i16x8_ty,
4794 ""
4795 ));
4796
4797 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4798 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4799 let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4800
4801 let pair_left = err!(self.builder.build_shuffle_vector(
4802 dot16,
4803 dot16.get_type().get_undef(),
4804 VectorType::const_vector(&[
4805 self.intrinsics.i32_consts[0],
4806 self.intrinsics.i32_consts[2],
4807 self.intrinsics.i32_consts[4],
4808 self.intrinsics.i32_consts[6],
4809 ]),
4810 "",
4811 ));
4812 let pair_left = err!(self.builder.build_int_s_extend(
4813 pair_left,
4814 self.intrinsics.i32x4_ty,
4815 ""
4816 ));
4817 let pair_right = err!(self.builder.build_shuffle_vector(
4818 dot16,
4819 dot16.get_type().get_undef(),
4820 VectorType::const_vector(&[
4821 self.intrinsics.i32_consts[1],
4822 self.intrinsics.i32_consts[3],
4823 self.intrinsics.i32_consts[5],
4824 self.intrinsics.i32_consts[7],
4825 ]),
4826 "",
4827 ));
4828 let pair_right = err!(self.builder.build_int_s_extend(
4829 pair_right,
4830 self.intrinsics.i32x4_ty,
4831 ""
4832 ));
4833 let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4834 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4835 let res = err!(
4836 self.builder
4837 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4838 );
4839 self.state.push1(res);
4840 }
4841 Operator::I32DivS | Operator::I64DivS => {
4842 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4843 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4844 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4845 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4846
4847 self.trap_if_zero_or_overflow(v1, v2)?;
4848
4849 let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4850 self.state.push1(res);
4851 }
4852 Operator::I32DivU | Operator::I64DivU => {
4853 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4854 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4855 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4856 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4857
4858 self.trap_if_zero(v2)?;
4859
4860 let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4861 self.state.push1(res);
4862 }
4863 Operator::I32RemS | Operator::I64RemS => {
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 int_type = v1.get_type();
4869 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4870 let min_value = int_type.const_int(i32::MIN as u64, false);
4871 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4872 (min_value, neg_one_value)
4873 } else if int_type == self.intrinsics.i64_ty {
4874 let min_value = int_type.const_int(i64::MIN as u64, false);
4875 let neg_one_value = int_type.const_int(-1i64 as u64, false);
4876 (min_value, neg_one_value)
4877 } else {
4878 unreachable!()
4879 };
4880
4881 self.trap_if_zero(v2)?;
4882
4883 let will_overflow = err!(self.builder.build_and(
4895 err!(self.builder.build_int_compare(
4896 IntPredicate::EQ,
4897 v1,
4898 min_value,
4899 "left_is_min"
4900 )),
4901 err!(self.builder.build_int_compare(
4902 IntPredicate::EQ,
4903 v2,
4904 neg_one_value,
4905 "right_is_neg_one",
4906 )),
4907 "srem_will_overflow",
4908 ));
4909 let v1 =
4910 err!(
4911 self.builder
4912 .build_select(will_overflow, int_type.const_zero(), v1, "")
4913 )
4914 .into_int_value();
4915 let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4916 self.state.push1(res);
4917 }
4918 Operator::I32RemU | Operator::I64RemU => {
4919 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4920 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4921 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4922 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4923
4924 self.trap_if_zero(v2)?;
4925
4926 let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4927 self.state.push1(res);
4928 }
4929 Operator::I32And | Operator::I64And | Operator::V128And => {
4930 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4931 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4932 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4933 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4934 let res = err!(self.builder.build_and(v1, v2, ""));
4935 self.state.push1(res);
4936 }
4937 Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4938 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4939 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4940 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4941 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4942 let res = err!(self.builder.build_or(v1, v2, ""));
4943 self.state.push1(res);
4944 }
4945 Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4946 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4947 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4948 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4949 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4950 let res = err!(self.builder.build_xor(v1, v2, ""));
4951 self.state.push1(res);
4952 }
4953 Operator::V128AndNot => {
4954 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4955 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4956 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4957 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4958 let v2 = err!(self.builder.build_not(v2, ""));
4959 let res = err!(self.builder.build_and(v1, v2, ""));
4960 self.state.push1(res);
4961 }
4962 Operator::I8x16RelaxedLaneselect
4963 | Operator::I16x8RelaxedLaneselect
4964 | Operator::I32x4RelaxedLaneselect
4965 | Operator::I64x2RelaxedLaneselect
4966 if self.cpu_features.contains(CpuFeature::SSE41) =>
4967 {
4968 let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4969 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4970 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4971 let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4972
4973 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4974 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4975 let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4976 let res = self
4977 .build_call_with_param_attributes(
4978 self.intrinsics.x86_64.pblendvb,
4979 &[v2.into(), v1.into(), mask.into()],
4980 "",
4981 )?
4982 .try_as_basic_value()
4983 .unwrap_basic();
4984 let res = err!(
4985 self.builder
4986 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4987 );
4988 self.state.push1(res);
4989 }
4990 Operator::I8x16RelaxedLaneselect
4991 | Operator::I16x8RelaxedLaneselect
4992 | Operator::I32x4RelaxedLaneselect
4993 | Operator::I64x2RelaxedLaneselect
4994 | Operator::V128Bitselect => {
4995 let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4996 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4997 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4998 let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4999 let v1 = err!(
5000 self.builder
5001 .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
5002 )
5003 .into_vector_value();
5004 let v2 = err!(
5005 self.builder
5006 .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
5007 )
5008 .into_vector_value();
5009 let cond = err!(
5010 self.builder
5011 .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
5012 )
5013 .into_vector_value();
5014 let res = err!(self.builder.build_select(cond, v1, v2, ""));
5015 let res = err!(
5016 self.builder
5017 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5018 );
5019 self.state.push1(res);
5020 }
5021 Operator::I8x16Bitmask => {
5022 let (v, i) = self.state.pop1_extra()?;
5023 let (v, _) = self.v128_into_i8x16(v, i)?;
5024
5025 let zeros = self.intrinsics.i8x16_ty.const_zero();
5026 let res = err!(
5027 self.builder
5028 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5029 );
5030 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
5031 .into_int_value();
5032 let res = err!(
5033 self.builder
5034 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5035 );
5036 self.state.push1(res);
5037 }
5038 Operator::I16x8Bitmask => {
5039 let (v, i) = self.state.pop1_extra()?;
5040 let (v, _) = self.v128_into_i16x8(v, i)?;
5041
5042 let zeros = self.intrinsics.i16x8_ty.const_zero();
5043 let res = err!(
5044 self.builder
5045 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5046 );
5047 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
5048 .into_int_value();
5049 let res = err!(
5050 self.builder
5051 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5052 );
5053 self.state.push1(res);
5054 }
5055 Operator::I32x4Bitmask => {
5056 let (v, i) = self.state.pop1_extra()?;
5057 let (v, _) = self.v128_into_i32x4(v, i)?;
5058
5059 let zeros = self.intrinsics.i32x4_ty.const_zero();
5060 let res = err!(
5061 self.builder
5062 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5063 );
5064 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
5065 .into_int_value();
5066 let res = err!(
5067 self.builder
5068 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5069 );
5070 self.state.push1(res);
5071 }
5072 Operator::I64x2Bitmask => {
5073 let (v, i) = self.state.pop1_extra()?;
5074 let (v, _) = self.v128_into_i64x2(v, i)?;
5075
5076 let zeros = self.intrinsics.i64x2_ty.const_zero();
5077 let res = err!(
5078 self.builder
5079 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5080 );
5081 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
5082 .into_int_value();
5083 let res = err!(
5084 self.builder
5085 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5086 );
5087 self.state.push1(res);
5088 }
5089 Operator::I32Shl => {
5090 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5091 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5092 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5093 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5094 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5095 let v2 = err!(self.builder.build_and(v2, mask, ""));
5096 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5097 self.state.push1(res);
5098 }
5099 Operator::I64Shl => {
5100 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5101 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5102 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5103 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5104 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5105 let v2 = err!(self.builder.build_and(v2, mask, ""));
5106 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5107 self.state.push1(res);
5108 }
5109 Operator::I8x16Shl => {
5110 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5111 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5112 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5113 let v2 = v2.into_int_value();
5114 let v2 = err!(
5115 self.builder
5116 .build_and(v2, self.intrinsics.i32_consts[7], "")
5117 );
5118 let v2 = err!(
5119 self.builder
5120 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5121 );
5122 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5123 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5124 let res = err!(
5125 self.builder
5126 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5127 );
5128 self.state.push1(res);
5129 }
5130 Operator::I16x8Shl => {
5131 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5132 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5133 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5134 let v2 = v2.into_int_value();
5135 let v2 = err!(
5136 self.builder
5137 .build_and(v2, self.intrinsics.i32_consts[15], "")
5138 );
5139 let v2 = err!(
5140 self.builder
5141 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5142 );
5143 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5144 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5145 let res = err!(
5146 self.builder
5147 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5148 );
5149 self.state.push1(res);
5150 }
5151 Operator::I32x4Shl => {
5152 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5153 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5154 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5155 let v2 = v2.into_int_value();
5156 let v2 = err!(self.builder.build_and(
5157 v2,
5158 self.intrinsics.i32_ty.const_int(31, false),
5159 ""
5160 ));
5161 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5162 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5163 let res = err!(
5164 self.builder
5165 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5166 );
5167 self.state.push1(res);
5168 }
5169 Operator::I64x2Shl => {
5170 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5171 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5172 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5173 let v2 = v2.into_int_value();
5174 let v2 = err!(self.builder.build_and(
5175 v2,
5176 self.intrinsics.i32_ty.const_int(63, false),
5177 ""
5178 ));
5179 let v2 = err!(
5180 self.builder
5181 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5182 );
5183 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5184 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5185 let res = err!(
5186 self.builder
5187 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5188 );
5189 self.state.push1(res);
5190 }
5191 Operator::I32ShrS => {
5192 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5193 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5194 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5195 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5196 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5197 let v2 = err!(self.builder.build_and(v2, mask, ""));
5198 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5199 self.state.push1(res);
5200 }
5201 Operator::I64ShrS => {
5202 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5203 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5204 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5205 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5206 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5207 let v2 = err!(self.builder.build_and(v2, mask, ""));
5208 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5209 self.state.push1(res);
5210 }
5211 Operator::I8x16ShrS => {
5212 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5213 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5214 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5215 let v2 = v2.into_int_value();
5216 let v2 = err!(
5217 self.builder
5218 .build_and(v2, self.intrinsics.i32_consts[7], "")
5219 );
5220 let v2 = err!(
5221 self.builder
5222 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5223 );
5224 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5225 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5226 let res = err!(
5227 self.builder
5228 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5229 );
5230 self.state.push1(res);
5231 }
5232 Operator::I16x8ShrS => {
5233 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5234 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5235 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5236 let v2 = v2.into_int_value();
5237 let v2 = err!(
5238 self.builder
5239 .build_and(v2, self.intrinsics.i32_consts[15], "")
5240 );
5241 let v2 = err!(
5242 self.builder
5243 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5244 );
5245 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5246 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5247 let res = err!(
5248 self.builder
5249 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5250 );
5251 self.state.push1(res);
5252 }
5253 Operator::I32x4ShrS => {
5254 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5255 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5256 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5257 let v2 = v2.into_int_value();
5258 let v2 = err!(self.builder.build_and(
5259 v2,
5260 self.intrinsics.i32_ty.const_int(31, false),
5261 ""
5262 ));
5263 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5264 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5265 let res = err!(
5266 self.builder
5267 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5268 );
5269 self.state.push1(res);
5270 }
5271 Operator::I64x2ShrS => {
5272 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5273 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5274 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5275 let v2 = v2.into_int_value();
5276 let v2 = err!(self.builder.build_and(
5277 v2,
5278 self.intrinsics.i32_ty.const_int(63, false),
5279 ""
5280 ));
5281 let v2 = err!(
5282 self.builder
5283 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5284 );
5285 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5286 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5287 let res = err!(
5288 self.builder
5289 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5290 );
5291 self.state.push1(res);
5292 }
5293 Operator::I32ShrU => {
5294 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5295 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5296 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5297 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5298 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5299 let v2 = err!(self.builder.build_and(v2, mask, ""));
5300 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5301 self.state.push1(res);
5302 }
5303 Operator::I64ShrU => {
5304 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5305 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5306 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5307 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5308 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5309 let v2 = err!(self.builder.build_and(v2, mask, ""));
5310 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5311 self.state.push1(res);
5312 }
5313 Operator::I8x16ShrU => {
5314 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5315 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5316 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5317 let v2 = v2.into_int_value();
5318 let v2 = err!(
5319 self.builder
5320 .build_and(v2, self.intrinsics.i32_consts[7], "")
5321 );
5322 let v2 = err!(
5323 self.builder
5324 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5325 );
5326 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5327 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5328 let res = err!(
5329 self.builder
5330 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5331 );
5332 self.state.push1(res);
5333 }
5334 Operator::I16x8ShrU => {
5335 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5336 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5337 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5338 let v2 = v2.into_int_value();
5339 let v2 = err!(
5340 self.builder
5341 .build_and(v2, self.intrinsics.i32_consts[15], "")
5342 );
5343 let v2 = err!(
5344 self.builder
5345 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5346 );
5347 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5348 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5349 let res = err!(
5350 self.builder
5351 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5352 );
5353 self.state.push1(res);
5354 }
5355 Operator::I32x4ShrU => {
5356 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5357 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5358 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5359 let v2 = v2.into_int_value();
5360 let v2 = err!(self.builder.build_and(
5361 v2,
5362 self.intrinsics.i32_ty.const_int(31, false),
5363 ""
5364 ));
5365 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5366 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5367 let res = err!(
5368 self.builder
5369 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5370 );
5371 self.state.push1(res);
5372 }
5373 Operator::I64x2ShrU => {
5374 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5375 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5376 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5377 let v2 = v2.into_int_value();
5378 let v2 = err!(self.builder.build_and(
5379 v2,
5380 self.intrinsics.i32_ty.const_int(63, false),
5381 ""
5382 ));
5383 let v2 = err!(
5384 self.builder
5385 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5386 );
5387 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5388 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5389 let res = err!(
5390 self.builder
5391 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5392 );
5393 self.state.push1(res);
5394 }
5395 Operator::I32Rotl => {
5396 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5397 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5398 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5399 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5400 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5401 let v2 = err!(self.builder.build_and(v2, mask, ""));
5402 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5403 let rhs = {
5404 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5405 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5406 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5407 };
5408 let res = err!(self.builder.build_or(lhs, rhs, ""));
5409 self.state.push1(res);
5410 }
5411 Operator::I64Rotl => {
5412 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5413 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5414 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5415 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5416 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5417 let v2 = err!(self.builder.build_and(v2, mask, ""));
5418 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5419 let rhs = {
5420 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5421 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5422 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5423 };
5424 let res = err!(self.builder.build_or(lhs, rhs, ""));
5425 self.state.push1(res);
5426 }
5427 Operator::I32Rotr => {
5428 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5429 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5430 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5431 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5432 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5433 let v2 = err!(self.builder.build_and(v2, mask, ""));
5434 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5435 let rhs = {
5436 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5437 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5438 err!(self.builder.build_left_shift(v1, rhs, ""))
5439 };
5440 let res = err!(self.builder.build_or(lhs, rhs, ""));
5441 self.state.push1(res);
5442 }
5443 Operator::I64Rotr => {
5444 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5445 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5446 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5447 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5448 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5449 let v2 = err!(self.builder.build_and(v2, mask, ""));
5450 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5451 let rhs = {
5452 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5453 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5454 err!(self.builder.build_left_shift(v1, rhs, ""))
5455 };
5456 let res = err!(self.builder.build_or(lhs, rhs, ""));
5457 self.state.push1(res);
5458 }
5459 Operator::I32Clz => {
5460 let (input, info) = self.state.pop1_extra()?;
5461 let input = self.apply_pending_canonicalization(input, info)?;
5462 let is_zero_undef = self.intrinsics.i1_zero;
5463 let res = self
5464 .build_call_with_param_attributes(
5465 self.intrinsics.ctlz_i32,
5466 &[input.into(), is_zero_undef.into()],
5467 "",
5468 )?
5469 .try_as_basic_value()
5470 .unwrap_basic();
5471 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5472 }
5473 Operator::I64Clz => {
5474 let (input, info) = self.state.pop1_extra()?;
5475 let input = self.apply_pending_canonicalization(input, info)?;
5476 let is_zero_undef = self.intrinsics.i1_zero;
5477 let res = self
5478 .build_call_with_param_attributes(
5479 self.intrinsics.ctlz_i64,
5480 &[input.into(), is_zero_undef.into()],
5481 "",
5482 )?
5483 .try_as_basic_value()
5484 .unwrap_basic();
5485 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5486 }
5487 Operator::I32Ctz => {
5488 let (input, info) = self.state.pop1_extra()?;
5489 let input = self.apply_pending_canonicalization(input, info)?;
5490 let is_zero_undef = self.intrinsics.i1_zero;
5491 let res = self
5492 .build_call_with_param_attributes(
5493 self.intrinsics.cttz_i32,
5494 &[input.into(), is_zero_undef.into()],
5495 "",
5496 )?
5497 .try_as_basic_value()
5498 .unwrap_basic();
5499 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5500 }
5501 Operator::I64Ctz => {
5502 let (input, info) = self.state.pop1_extra()?;
5503 let input = self.apply_pending_canonicalization(input, info)?;
5504 let is_zero_undef = self.intrinsics.i1_zero;
5505 let res = self
5506 .build_call_with_param_attributes(
5507 self.intrinsics.cttz_i64,
5508 &[input.into(), is_zero_undef.into()],
5509 "",
5510 )?
5511 .try_as_basic_value()
5512 .unwrap_basic();
5513 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5514 }
5515 Operator::I8x16Popcnt => {
5516 let (v, i) = self.state.pop1_extra()?;
5517 let (v, _) = self.v128_into_i8x16(v, i)?;
5518 let res = self
5519 .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5520 .try_as_basic_value()
5521 .unwrap_basic();
5522 let res = err!(
5523 self.builder
5524 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5525 );
5526 self.state.push1(res);
5527 }
5528 Operator::I32Popcnt => {
5529 let (input, info) = self.state.pop1_extra()?;
5530 let input = self.apply_pending_canonicalization(input, info)?;
5531 let res = self
5532 .build_call_with_param_attributes(
5533 self.intrinsics.ctpop_i32,
5534 &[input.into()],
5535 "",
5536 )?
5537 .try_as_basic_value()
5538 .unwrap_basic();
5539 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5540 }
5541 Operator::I64Popcnt => {
5542 let (input, info) = self.state.pop1_extra()?;
5543 let input = self.apply_pending_canonicalization(input, info)?;
5544 let res = self
5545 .build_call_with_param_attributes(
5546 self.intrinsics.ctpop_i64,
5547 &[input.into()],
5548 "",
5549 )?
5550 .try_as_basic_value()
5551 .unwrap_basic();
5552 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5553 }
5554 Operator::I32Eqz => {
5555 let input = self.state.pop1()?.into_int_value();
5556 let cond = err!(self.builder.build_int_compare(
5557 IntPredicate::EQ,
5558 input,
5559 self.intrinsics.i32_zero,
5560 "",
5561 ));
5562 let res = err!(
5563 self.builder
5564 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5565 );
5566 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5567 }
5568 Operator::I64Eqz => {
5569 let input = self.state.pop1()?.into_int_value();
5570 let cond = err!(self.builder.build_int_compare(
5571 IntPredicate::EQ,
5572 input,
5573 self.intrinsics.i64_zero,
5574 "",
5575 ));
5576 let res = err!(
5577 self.builder
5578 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5579 );
5580 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5581 }
5582 Operator::I8x16Abs => {
5583 let (v, i) = self.state.pop1_extra()?;
5584 let (v, _) = self.v128_into_i8x16(v, i)?;
5585
5586 let seven = self.intrinsics.i8_ty.const_int(7, false);
5587 let seven = VectorType::const_vector(&[seven; 16]);
5588 let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5589 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5590 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
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::I16x8Abs => {
5598 let (v, i) = self.state.pop1_extra()?;
5599 let (v, _) = self.v128_into_i16x8(v, i)?;
5600
5601 let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5602 let fifteen = VectorType::const_vector(&[fifteen; 8]);
5603 let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5604 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5605 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
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::I32x4Abs => {
5613 let (v, i) = self.state.pop1_extra()?;
5614 let (v, _) = self.v128_into_i32x4(v, i)?;
5615
5616 let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5617 let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5618 let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5619 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5620 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
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::I64x2Abs => {
5628 let (v, i) = self.state.pop1_extra()?;
5629 let (v, _) = self.v128_into_i64x2(v, i)?;
5630
5631 let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5632 let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5633 let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5634 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5635 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
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::I8x16MinS => {
5643 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5644 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5645 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5646 let cmp = err!(
5647 self.builder
5648 .build_int_compare(IntPredicate::SLT, 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::I8x16MinU => {
5658 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5659 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5660 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5661 let cmp = err!(
5662 self.builder
5663 .build_int_compare(IntPredicate::ULT, 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::I8x16MaxS => {
5673 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5674 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5675 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5676 let cmp = err!(
5677 self.builder
5678 .build_int_compare(IntPredicate::SGT, 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::I8x16MaxU => {
5688 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5689 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5690 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5691 let cmp = err!(
5692 self.builder
5693 .build_int_compare(IntPredicate::UGT, 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::I16x8MinS => {
5703 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5704 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5705 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5706 let cmp = err!(
5707 self.builder
5708 .build_int_compare(IntPredicate::SLT, 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::I16x8MinU => {
5718 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5719 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5720 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5721 let cmp = err!(
5722 self.builder
5723 .build_int_compare(IntPredicate::ULT, 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::I16x8MaxS => {
5733 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5734 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5735 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5736 let cmp = err!(
5737 self.builder
5738 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5739 );
5740 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5741 let res = err!(
5742 self.builder
5743 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5744 );
5745 self.state.push1(res);
5746 }
5747 Operator::I16x8MaxU => {
5748 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5749 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5750 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5751 let cmp = err!(
5752 self.builder
5753 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5754 );
5755 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5756 let res = err!(
5757 self.builder
5758 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5759 );
5760 self.state.push1(res);
5761 }
5762 Operator::I32x4MinS => {
5763 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5764 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5765 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5766 let cmp = err!(
5767 self.builder
5768 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5769 );
5770 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5771 let res = err!(
5772 self.builder
5773 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5774 );
5775 self.state.push1(res);
5776 }
5777 Operator::I32x4MinU => {
5778 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5779 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5780 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5781 let cmp = err!(
5782 self.builder
5783 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5784 );
5785 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5786 let res = err!(
5787 self.builder
5788 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5789 );
5790 self.state.push1(res);
5791 }
5792 Operator::I32x4MaxS => {
5793 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5794 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5795 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5796 let cmp = err!(
5797 self.builder
5798 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5799 );
5800 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5801 let res = err!(
5802 self.builder
5803 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5804 );
5805 self.state.push1(res);
5806 }
5807 Operator::I32x4MaxU => {
5808 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5809 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5810 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5811 let cmp = err!(
5812 self.builder
5813 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5814 );
5815 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5816 let res = err!(
5817 self.builder
5818 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5819 );
5820 self.state.push1(res);
5821 }
5822 Operator::I8x16AvgrU => {
5823 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5824 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5825 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5826
5827 let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5838 let one = self.intrinsics.i16_ty.const_int(1, false);
5839 let one = VectorType::const_vector(&[one; 16]);
5840
5841 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5842 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5843 let res = err!(self.builder.build_int_add(
5844 err!(self.builder.build_int_add(one, v1, "")),
5845 v2,
5846 ""
5847 ));
5848 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5849 let res = err!(
5850 self.builder
5851 .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5852 );
5853 let res = err!(
5854 self.builder
5855 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5856 );
5857 self.state.push1(res);
5858 }
5859 Operator::I16x8AvgrU => {
5860 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5861 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5862 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5863
5864 let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5875 let one = self.intrinsics.i32_consts[1];
5876 let one = VectorType::const_vector(&[one; 8]);
5877
5878 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5879 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5880 let res = err!(self.builder.build_int_add(
5881 err!(self.builder.build_int_add(one, v1, "")),
5882 v2,
5883 ""
5884 ));
5885 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5886 let res = err!(
5887 self.builder
5888 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5889 );
5890 let res = err!(
5891 self.builder
5892 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5893 );
5894 self.state.push1(res);
5895 }
5896 Operator::I64Add128 | Operator::I64Sub128 => {
5897 let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
5898 let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
5899 let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
5900 let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
5901
5902 let lhs_lo = self
5903 .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
5904 .into_int_value();
5905 let lhs_hi = self
5906 .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
5907 .into_int_value();
5908 let rhs_lo = self
5909 .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
5910 .into_int_value();
5911 let rhs_hi = self
5912 .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
5913 .into_int_value();
5914
5915 let idx0 = self.intrinsics.i32_ty.const_zero();
5916 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5917
5918 let lhs = self.intrinsics.i64x2_ty.get_undef();
5919 let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
5920 let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
5921 let lhs = err!(
5922 self.builder
5923 .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
5924 )
5925 .into_int_value();
5926
5927 let rhs = self.intrinsics.i64x2_ty.get_undef();
5928 let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
5929 let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
5930 let rhs = err!(
5931 self.builder
5932 .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
5933 )
5934 .into_int_value();
5935
5936 let result = err!(match op {
5937 Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
5938 Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
5939 _ => unreachable!(),
5940 });
5941 let result = err!(self.builder.build_bit_cast(
5942 result,
5943 self.intrinsics.i64x2_ty,
5944 ""
5945 ))
5946 .into_vector_value();
5947 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5948 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5949
5950 self.state.push1(result_lo);
5951 self.state.push1(result_hi);
5952 }
5953 Operator::I64MulWideS | Operator::I64MulWideU => {
5954 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5955 let lhs = self
5956 .apply_pending_canonicalization(lhs, lhs_info)?
5957 .into_int_value();
5958 let rhs = self
5959 .apply_pending_canonicalization(rhs, rhs_info)?
5960 .into_int_value();
5961
5962 let lhs = err!(match op {
5963 Operator::I64MulWideS => {
5964 self.builder
5965 .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
5966 }
5967 Operator::I64MulWideU => {
5968 self.builder
5969 .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
5970 }
5971 _ => unreachable!(),
5972 });
5973 let rhs = err!(match op {
5974 Operator::I64MulWideS => {
5975 self.builder
5976 .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
5977 }
5978 Operator::I64MulWideU => {
5979 self.builder
5980 .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
5981 }
5982 _ => unreachable!(),
5983 });
5984
5985 let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
5986 let result = err!(self.builder.build_bit_cast(
5987 result,
5988 self.intrinsics.i64x2_ty,
5989 ""
5990 ))
5991 .into_vector_value();
5992 let idx0 = self.intrinsics.i32_ty.const_zero();
5993 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5994 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5995 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5996
5997 self.state.push1(result_lo);
5998 self.state.push1(result_hi);
5999 }
6000 _ => unreachable!(),
6001 }
6002 Ok(())
6003 }
6004
6005 fn translate_floating_point_arithmetic_operator(
6008 &mut self,
6009 op: Operator,
6010 ) -> Result<(), CompileError> {
6011 match op {
6012 Operator::F32Add => {
6013 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6014 let res = self
6015 .build_call_with_param_attributes(
6016 self.intrinsics.add_f32,
6017 &[
6018 v1.into(),
6019 v2.into(),
6020 self.intrinsics.fp_rounding_md,
6021 self.intrinsics.fp_exception_md,
6022 ],
6023 "",
6024 )?
6025 .try_as_basic_value()
6026 .unwrap_basic();
6027 self.state.push1_extra(
6028 res,
6029 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6030 );
6031 }
6032 Operator::F64Add => {
6033 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6034 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6035 let res = self
6036 .build_call_with_param_attributes(
6037 self.intrinsics.add_f64,
6038 &[
6039 v1.into(),
6040 v2.into(),
6041 self.intrinsics.fp_rounding_md,
6042 self.intrinsics.fp_exception_md,
6043 ],
6044 "",
6045 )?
6046 .try_as_basic_value()
6047 .unwrap_basic();
6048 self.state.push1_extra(
6049 res,
6050 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6051 );
6052 }
6053 Operator::F32x4Add => {
6054 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6055 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6056 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6057 let res = self
6058 .build_call_with_param_attributes(
6059 self.intrinsics.add_f32x4,
6060 &[
6061 v1.into(),
6062 v2.into(),
6063 self.intrinsics.fp_rounding_md,
6064 self.intrinsics.fp_exception_md,
6065 ],
6066 "",
6067 )?
6068 .try_as_basic_value()
6069 .unwrap_basic();
6070 let res = err!(
6071 self.builder
6072 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6073 );
6074 self.state.push1_extra(
6075 res,
6076 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6077 );
6078 }
6079 Operator::F64x2Add => {
6080 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6081 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6082 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6083 let res = self
6084 .build_call_with_param_attributes(
6085 self.intrinsics.add_f64x2,
6086 &[
6087 v1.into(),
6088 v2.into(),
6089 self.intrinsics.fp_rounding_md,
6090 self.intrinsics.fp_exception_md,
6091 ],
6092 "",
6093 )?
6094 .try_as_basic_value()
6095 .unwrap_basic();
6096 let res = err!(
6097 self.builder
6098 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6099 );
6100 self.state.push1_extra(
6101 res,
6102 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6103 );
6104 }
6105 Operator::F32Sub => {
6106 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6107 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6108 let res = self
6109 .build_call_with_param_attributes(
6110 self.intrinsics.sub_f32,
6111 &[
6112 v1.into(),
6113 v2.into(),
6114 self.intrinsics.fp_rounding_md,
6115 self.intrinsics.fp_exception_md,
6116 ],
6117 "",
6118 )?
6119 .try_as_basic_value()
6120 .unwrap_basic();
6121 self.state.push1_extra(
6122 res,
6123 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6124 );
6125 }
6126 Operator::F64Sub => {
6127 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6128 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6129 let res = self
6130 .build_call_with_param_attributes(
6131 self.intrinsics.sub_f64,
6132 &[
6133 v1.into(),
6134 v2.into(),
6135 self.intrinsics.fp_rounding_md,
6136 self.intrinsics.fp_exception_md,
6137 ],
6138 "",
6139 )?
6140 .try_as_basic_value()
6141 .unwrap_basic();
6142 self.state.push1_extra(
6143 res,
6144 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6145 );
6146 }
6147 Operator::F32x4Sub => {
6148 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6149 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6150 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6151 let res = self
6152 .build_call_with_param_attributes(
6153 self.intrinsics.sub_f32x4,
6154 &[
6155 v1.into(),
6156 v2.into(),
6157 self.intrinsics.fp_rounding_md,
6158 self.intrinsics.fp_exception_md,
6159 ],
6160 "",
6161 )?
6162 .try_as_basic_value()
6163 .unwrap_basic();
6164 let res = err!(
6165 self.builder
6166 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6167 );
6168 self.state.push1_extra(
6169 res,
6170 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6171 );
6172 }
6173 Operator::F64x2Sub => {
6174 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6175 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6176 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6177 let res = self
6178 .build_call_with_param_attributes(
6179 self.intrinsics.sub_f64x2,
6180 &[
6181 v1.into(),
6182 v2.into(),
6183 self.intrinsics.fp_rounding_md,
6184 self.intrinsics.fp_exception_md,
6185 ],
6186 "",
6187 )?
6188 .try_as_basic_value()
6189 .unwrap_basic();
6190 let res = err!(
6191 self.builder
6192 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6193 );
6194 self.state.push1_extra(
6195 res,
6196 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6197 );
6198 }
6199 Operator::F32Mul => {
6200 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6201 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6202 let res = self
6203 .build_call_with_param_attributes(
6204 self.intrinsics.mul_f32,
6205 &[
6206 v1.into(),
6207 v2.into(),
6208 self.intrinsics.fp_rounding_md,
6209 self.intrinsics.fp_exception_md,
6210 ],
6211 "",
6212 )?
6213 .try_as_basic_value()
6214 .unwrap_basic();
6215 self.state.push1_extra(
6216 res,
6217 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6218 );
6219 }
6220 Operator::F64Mul => {
6221 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6222 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6223 let res = self
6224 .build_call_with_param_attributes(
6225 self.intrinsics.mul_f64,
6226 &[
6227 v1.into(),
6228 v2.into(),
6229 self.intrinsics.fp_rounding_md,
6230 self.intrinsics.fp_exception_md,
6231 ],
6232 "",
6233 )?
6234 .try_as_basic_value()
6235 .unwrap_basic();
6236 self.state.push1_extra(
6237 res,
6238 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6239 );
6240 }
6241 Operator::F32x4Mul => {
6242 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6243 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6244 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6245 let res = self
6246 .build_call_with_param_attributes(
6247 self.intrinsics.mul_f32x4,
6248 &[
6249 v1.into(),
6250 v2.into(),
6251 self.intrinsics.fp_rounding_md,
6252 self.intrinsics.fp_exception_md,
6253 ],
6254 "",
6255 )?
6256 .try_as_basic_value()
6257 .unwrap_basic();
6258 let res = err!(
6259 self.builder
6260 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6261 );
6262 self.state.push1_extra(
6263 res,
6264 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6265 );
6266 }
6267 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
6268 if self.cpu_features.contains(CpuFeature::FMA) =>
6269 {
6270 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6271 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6272 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6273 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6274
6275 let v1 = match op {
6276 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6277 _ => v1,
6278 };
6279 let res = self
6280 .build_call_with_param_attributes(
6281 self.intrinsics.muladd_f32x4,
6282 &[
6283 v1.into(),
6284 v2.into(),
6285 v3.into(),
6286 self.intrinsics.fp_rounding_md,
6287 self.intrinsics.fp_exception_md,
6288 ],
6289 "",
6290 )?
6291 .try_as_basic_value()
6292 .unwrap_basic();
6293 let res = err!(
6294 self.builder
6295 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6296 );
6297 let info = (i1.strip_pending() & i2.strip_pending())?;
6298 let info = (info & i3.strip_pending())?;
6299 let info = (info | ExtraInfo::pending_f32_nan())?;
6300 self.state.push1_extra(res, info);
6301 }
6302 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
6303 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6304 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6305 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6306 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6307
6308 let v1 = match op {
6309 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6310 _ => v1,
6311 };
6312 let mul = self
6313 .build_call_with_param_attributes(
6314 self.intrinsics.mul_f32x4,
6315 &[
6316 v1.into(),
6317 v2.into(),
6318 self.intrinsics.fp_rounding_md,
6319 self.intrinsics.fp_exception_md,
6320 ],
6321 "",
6322 )?
6323 .try_as_basic_value()
6324 .unwrap_basic();
6325 let mul = mul.into_vector_value();
6326 let res = self
6327 .build_call_with_param_attributes(
6328 self.intrinsics.add_f32x4,
6329 &[
6330 mul.into(),
6331 v3.into(),
6332 self.intrinsics.fp_rounding_md,
6333 self.intrinsics.fp_exception_md,
6334 ],
6335 "",
6336 )?
6337 .try_as_basic_value()
6338 .unwrap_basic();
6339 let res = err!(
6340 self.builder
6341 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6342 );
6343 let info = (i1.strip_pending() & i2.strip_pending())?;
6344 let info = (info & i3.strip_pending())?;
6345 let info = (info | ExtraInfo::pending_f32_nan())?;
6346 self.state.push1_extra(res, info);
6347 }
6348 Operator::F64x2Mul => {
6349 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6350 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6351 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6352 let res = self
6353 .build_call_with_param_attributes(
6354 self.intrinsics.mul_f64x2,
6355 &[
6356 v1.into(),
6357 v2.into(),
6358 self.intrinsics.fp_rounding_md,
6359 self.intrinsics.fp_exception_md,
6360 ],
6361 "",
6362 )?
6363 .try_as_basic_value()
6364 .unwrap_basic();
6365 let res = err!(
6366 self.builder
6367 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6368 );
6369 self.state.push1_extra(
6370 res,
6371 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6372 );
6373 }
6374 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
6375 if self.cpu_features.contains(CpuFeature::FMA) =>
6376 {
6377 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6378 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6379 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6380 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6381
6382 let v1 = match op {
6383 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6384 _ => v1,
6385 };
6386 let res = self
6387 .build_call_with_param_attributes(
6388 self.intrinsics.muladd_f64x2,
6389 &[
6390 v1.into(),
6391 v2.into(),
6392 v3.into(),
6393 self.intrinsics.fp_rounding_md,
6394 self.intrinsics.fp_exception_md,
6395 ],
6396 "",
6397 )?
6398 .try_as_basic_value()
6399 .unwrap_basic();
6400 let res = err!(
6401 self.builder
6402 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6403 );
6404 let info = (i1.strip_pending() & i2.strip_pending())?;
6405 let info = (info & i3.strip_pending())?;
6406 let info = (info | ExtraInfo::pending_f64_nan())?;
6407 self.state.push1_extra(res, info);
6408 }
6409 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
6410 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6411 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6412 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6413 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6414
6415 let v1 = match op {
6416 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6417 _ => v1,
6418 };
6419 let mul = self
6420 .build_call_with_param_attributes(
6421 self.intrinsics.mul_f64x2,
6422 &[
6423 v1.into(),
6424 v2.into(),
6425 self.intrinsics.fp_rounding_md,
6426 self.intrinsics.fp_exception_md,
6427 ],
6428 "",
6429 )?
6430 .try_as_basic_value()
6431 .unwrap_basic();
6432 let mul = mul.into_vector_value();
6433 let res = self
6434 .build_call_with_param_attributes(
6435 self.intrinsics.add_f64x2,
6436 &[
6437 mul.into(),
6438 v3.into(),
6439 self.intrinsics.fp_rounding_md,
6440 self.intrinsics.fp_exception_md,
6441 ],
6442 "",
6443 )?
6444 .try_as_basic_value()
6445 .unwrap_basic();
6446 let res = err!(
6447 self.builder
6448 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6449 );
6450 let info = (i1.strip_pending() & i2.strip_pending())?;
6451 let info = (info & i3.strip_pending())?;
6452 let info = (info | ExtraInfo::pending_f64_nan())?;
6453 self.state.push1_extra(res, info);
6454 }
6455 Operator::F32Div => {
6456 let (v1, v2) = self.state.pop2()?;
6457 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6458 let res = self
6459 .build_call_with_param_attributes(
6460 self.intrinsics.div_f32,
6461 &[
6462 v1.into(),
6463 v2.into(),
6464 self.intrinsics.fp_rounding_md,
6465 self.intrinsics.fp_exception_md,
6466 ],
6467 "",
6468 )?
6469 .try_as_basic_value()
6470 .unwrap_basic();
6471 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6472 }
6473 Operator::F64Div => {
6474 let (v1, v2) = self.state.pop2()?;
6475 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6476 let res = self
6477 .build_call_with_param_attributes(
6478 self.intrinsics.div_f64,
6479 &[
6480 v1.into(),
6481 v2.into(),
6482 self.intrinsics.fp_rounding_md,
6483 self.intrinsics.fp_exception_md,
6484 ],
6485 "",
6486 )?
6487 .try_as_basic_value()
6488 .unwrap_basic();
6489 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6490 }
6491 Operator::F32x4Div => {
6492 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6493 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
6494 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
6495 let res = self
6496 .build_call_with_param_attributes(
6497 self.intrinsics.div_f32x4,
6498 &[
6499 v1.into(),
6500 v2.into(),
6501 self.intrinsics.fp_rounding_md,
6502 self.intrinsics.fp_exception_md,
6503 ],
6504 "",
6505 )?
6506 .try_as_basic_value()
6507 .unwrap_basic();
6508 let res = err!(
6509 self.builder
6510 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6511 );
6512 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6513 }
6514 Operator::F64x2Div => {
6515 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6516 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
6517 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
6518 let res = self
6519 .build_call_with_param_attributes(
6520 self.intrinsics.div_f64x2,
6521 &[
6522 v1.into(),
6523 v2.into(),
6524 self.intrinsics.fp_rounding_md,
6525 self.intrinsics.fp_exception_md,
6526 ],
6527 "",
6528 )?
6529 .try_as_basic_value()
6530 .unwrap_basic();
6531 let res = err!(
6532 self.builder
6533 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6534 );
6535 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6536 }
6537 Operator::F32Sqrt => {
6538 let input = self.state.pop1()?;
6539 let res = self
6540 .build_call_with_param_attributes(
6541 self.intrinsics.sqrt_f32,
6542 &[input.into()],
6543 "",
6544 )?
6545 .try_as_basic_value()
6546 .unwrap_basic();
6547 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6548 }
6549 Operator::F64Sqrt => {
6550 let input = self.state.pop1()?;
6551 let res = self
6552 .build_call_with_param_attributes(
6553 self.intrinsics.sqrt_f64,
6554 &[input.into()],
6555 "",
6556 )?
6557 .try_as_basic_value()
6558 .unwrap_basic();
6559 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6560 }
6561 Operator::F32x4Sqrt => {
6562 let (v, i) = self.state.pop1_extra()?;
6563 let (v, _) = self.v128_into_f32x4(v, i)?;
6564 let res = self
6565 .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6566 .try_as_basic_value()
6567 .unwrap_basic();
6568 let bits = err!(
6569 self.builder
6570 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6571 );
6572 self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6573 }
6574 Operator::F64x2Sqrt => {
6575 let (v, i) = self.state.pop1_extra()?;
6576 let (v, _) = self.v128_into_f64x2(v, i)?;
6577 let res = self
6578 .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6579 .try_as_basic_value()
6580 .unwrap_basic();
6581 let bits = err!(
6582 self.builder
6583 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6584 );
6585 self.state.push1(bits);
6586 }
6587 Operator::F32Min => {
6588 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6589 let lhs = self
6590 .apply_pending_canonicalization(lhs, lhs_info)?
6591 .into_float_value();
6592 let rhs = self
6593 .apply_pending_canonicalization(rhs, rhs_info)?
6594 .into_float_value();
6595
6596 let res = self
6597 .build_call_with_param_attributes(
6598 self.intrinsics.minimum_f32,
6599 &[lhs.into(), rhs.into()],
6600 "",
6601 )?
6602 .try_as_basic_value()
6603 .unwrap_basic();
6604
6605 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6606 let res = res.into_float_value();
6607
6608 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6609 }
6610 Operator::F64Min => {
6611 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6612 let lhs = self
6613 .apply_pending_canonicalization(lhs, lhs_info)?
6614 .into_float_value();
6615 let rhs = self
6616 .apply_pending_canonicalization(rhs, rhs_info)?
6617 .into_float_value();
6618
6619 let res = self
6620 .build_call_with_param_attributes(
6621 self.intrinsics.minimum_f64,
6622 &[lhs.into(), rhs.into()],
6623 "",
6624 )?
6625 .try_as_basic_value()
6626 .unwrap_basic();
6627
6628 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6629 let res = res.into_float_value();
6630
6631 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6632 }
6633 Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6634 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6635 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6636 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6637 let res = self
6638 .build_call_with_param_attributes(
6639 self.intrinsics.x86_64.min_ps,
6640 &[v1.into(), v2.into()],
6641 "",
6642 )?
6643 .try_as_basic_value()
6644 .unwrap_basic();
6645 let res = err!(
6646 self.builder
6647 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6648 );
6649 self.state.push1_extra(
6650 res,
6651 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6652 );
6653 }
6654 Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6655 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6656 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6657 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6658 let res = self
6659 .build_call_with_param_attributes(
6660 self.intrinsics.minimum_f32x4,
6661 &[v1.into(), v2.into()],
6662 "",
6663 )?
6664 .try_as_basic_value()
6665 .unwrap_basic();
6666
6667 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6668 let res = res.into_vector_value();
6669
6670 let res = err!(
6671 self.builder
6672 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6673 );
6674 self.state.push1_extra(
6675 res,
6676 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6677 );
6678 }
6679 Operator::F32x4PMin => {
6680 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6682 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6683 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6684 let cmp = err!(
6685 self.builder
6686 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6687 );
6688 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6689 let res = err!(
6690 self.builder
6691 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6692 );
6693 self.state.push1(res);
6694 }
6695 Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6696 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6697 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6698 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6699 let res = self
6700 .build_call_with_param_attributes(
6701 self.intrinsics.x86_64.min_pd,
6702 &[v1.into(), v2.into()],
6703 "",
6704 )?
6705 .try_as_basic_value()
6706 .unwrap_basic();
6707 let res = err!(
6708 self.builder
6709 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6710 );
6711 self.state.push1_extra(
6712 res,
6713 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6714 );
6715 }
6716 Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6717 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6718 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6719 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6720 let res = self
6721 .build_call_with_param_attributes(
6722 self.intrinsics.minimum_f64x2,
6723 &[v1.into(), v2.into()],
6724 "",
6725 )?
6726 .try_as_basic_value()
6727 .unwrap_basic();
6728
6729 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6730 let res = res.into_vector_value();
6731
6732 let res = err!(
6733 self.builder
6734 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6735 );
6736 self.state.push1_extra(
6737 res,
6738 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6739 );
6740 }
6741 Operator::F64x2PMin => {
6742 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6744 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6745 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6746 let cmp = err!(
6747 self.builder
6748 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6749 );
6750 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6751 let res = err!(
6752 self.builder
6753 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6754 );
6755 self.state.push1(res);
6756 }
6757 Operator::F32Max => {
6758 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6759 let lhs = self
6760 .apply_pending_canonicalization(lhs, lhs_info)?
6761 .into_float_value();
6762 let rhs = self
6763 .apply_pending_canonicalization(rhs, rhs_info)?
6764 .into_float_value();
6765
6766 let res = self
6767 .build_call_with_param_attributes(
6768 self.intrinsics.maximum_f32,
6769 &[lhs.into(), rhs.into()],
6770 "",
6771 )?
6772 .try_as_basic_value()
6773 .unwrap_basic();
6774
6775 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6776 let res = res.into_float_value();
6777
6778 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6779 }
6780 Operator::F64Max => {
6781 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6782 let lhs = self
6783 .apply_pending_canonicalization(lhs, lhs_info)?
6784 .into_float_value();
6785 let rhs = self
6786 .apply_pending_canonicalization(rhs, rhs_info)?
6787 .into_float_value();
6788
6789 let res = self
6790 .build_call_with_param_attributes(
6791 self.intrinsics.maximum_f64,
6792 &[lhs.into(), rhs.into()],
6793 "",
6794 )?
6795 .try_as_basic_value()
6796 .unwrap_basic();
6797
6798 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6799 let res = res.into_float_value();
6800
6801 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6802 }
6803 Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6804 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6805 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6806 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6807 let res = self
6808 .build_call_with_param_attributes(
6809 self.intrinsics.x86_64.max_ps,
6810 &[v1.into(), v2.into()],
6811 "",
6812 )?
6813 .try_as_basic_value()
6814 .unwrap_basic();
6815 let res = err!(
6816 self.builder
6817 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6818 );
6819 self.state.push1_extra(
6820 res,
6821 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6822 );
6823 }
6824 Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6825 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6826 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6827 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6828 let res = self
6829 .build_call_with_param_attributes(
6830 self.intrinsics.maximum_f32x4,
6831 &[v1.into(), v2.into()],
6832 "",
6833 )?
6834 .try_as_basic_value()
6835 .unwrap_basic();
6836
6837 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6838 let res = res.into_vector_value();
6839
6840 let res = err!(
6841 self.builder
6842 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6843 );
6844 self.state.push1_extra(
6845 res,
6846 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6847 );
6848 }
6849 Operator::F32x4PMax => {
6850 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6852 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6853 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6854 let cmp = err!(
6855 self.builder
6856 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6857 );
6858 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6859
6860 let res = err!(
6861 self.builder
6862 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6863 );
6864 self.state.push1(res);
6865 }
6866 Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6867 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6868 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6869 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6870 let res = self
6871 .build_call_with_param_attributes(
6872 self.intrinsics.x86_64.max_pd,
6873 &[v1.into(), v2.into()],
6874 "",
6875 )?
6876 .try_as_basic_value()
6877 .unwrap_basic();
6878 let res = err!(
6879 self.builder
6880 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6881 );
6882 self.state.push1_extra(
6883 res,
6884 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6885 );
6886 }
6887 Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6888 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6889 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6890 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6891 let res = self
6892 .build_call_with_param_attributes(
6893 self.intrinsics.maximum_f64x2,
6894 &[v1.into(), v2.into()],
6895 "",
6896 )?
6897 .try_as_basic_value()
6898 .unwrap_basic();
6899
6900 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6901 let res = res.into_vector_value();
6902
6903 let res = err!(
6904 self.builder
6905 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6906 );
6907 self.state.push1_extra(
6908 res,
6909 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6910 );
6911 }
6912 Operator::F64x2PMax => {
6913 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6915 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6916 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6917 let cmp = err!(
6918 self.builder
6919 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6920 );
6921 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6922 let res = err!(
6923 self.builder
6924 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6925 );
6926 self.state.push1(res);
6927 }
6928 Operator::F32Ceil => {
6929 let (input, info) = self.state.pop1_extra()?;
6930 let res = err!(self.build_call_with_param_attributes(
6931 self.intrinsics.ceil_f32,
6932 &[input.into()],
6933 ""
6934 ))
6935 .try_as_basic_value()
6936 .unwrap_basic();
6937 let (res, info) = self.finalize_rounding_result(res, info)?;
6938 self.state.push1_extra(res, info);
6939 }
6940 Operator::F32x4Ceil => {
6941 let (v, i) = self.state.pop1_extra()?;
6942 let (v, _) = self.v128_into_f32x4(v, i)?;
6943 let res = err!(self.build_call_with_param_attributes(
6944 self.intrinsics.ceil_f32x4,
6945 &[v.into()],
6946 ""
6947 ))
6948 .try_as_basic_value()
6949 .unwrap_basic();
6950 let (res, info) = self.finalize_rounding_result(res, i)?;
6951 let res = err!(
6952 self.builder
6953 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6954 );
6955 self.state.push1_extra(res, info);
6956 }
6957 Operator::F64Ceil => {
6958 let (input, info) = self.state.pop1_extra()?;
6959 let res = err!(self.build_call_with_param_attributes(
6960 self.intrinsics.ceil_f64,
6961 &[input.into()],
6962 ""
6963 ))
6964 .try_as_basic_value()
6965 .unwrap_basic();
6966 let (res, info) = self.finalize_rounding_result(res, info)?;
6967 self.state.push1_extra(res, info);
6968 }
6969 Operator::F64x2Ceil => {
6970 let (v, i) = self.state.pop1_extra()?;
6971 let (v, _) = self.v128_into_f64x2(v, i)?;
6972 let res = err!(self.build_call_with_param_attributes(
6973 self.intrinsics.ceil_f64x2,
6974 &[v.into()],
6975 ""
6976 ))
6977 .try_as_basic_value()
6978 .unwrap_basic();
6979 let (res, info) = self.finalize_rounding_result(res, i)?;
6980 let res = err!(
6981 self.builder
6982 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6983 );
6984 self.state.push1_extra(res, info);
6985 }
6986 Operator::F32Floor => {
6987 let (input, info) = self.state.pop1_extra()?;
6988 let res = err!(self.build_call_with_param_attributes(
6989 self.intrinsics.floor_f32,
6990 &[input.into()],
6991 ""
6992 ))
6993 .try_as_basic_value()
6994 .unwrap_basic();
6995 let (res, info) = self.finalize_rounding_result(res, info)?;
6996 self.state.push1_extra(res, info);
6997 }
6998 Operator::F32x4Floor => {
6999 let (v, i) = self.state.pop1_extra()?;
7000 let (v, _) = self.v128_into_f32x4(v, i)?;
7001 let res = err!(self.build_call_with_param_attributes(
7002 self.intrinsics.floor_f32x4,
7003 &[v.into()],
7004 ""
7005 ))
7006 .try_as_basic_value()
7007 .unwrap_basic();
7008 let (res, info) = self.finalize_rounding_result(res, i)?;
7009 let res = err!(
7010 self.builder
7011 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7012 );
7013 self.state.push1_extra(res, info);
7014 }
7015 Operator::F64Floor => {
7016 let (input, info) = self.state.pop1_extra()?;
7017 let res = err!(self.build_call_with_param_attributes(
7018 self.intrinsics.floor_f64,
7019 &[input.into()],
7020 ""
7021 ))
7022 .try_as_basic_value()
7023 .unwrap_basic();
7024 let (res, info) = self.finalize_rounding_result(res, info)?;
7025 self.state.push1_extra(res, info);
7026 }
7027 Operator::F64x2Floor => {
7028 let (v, i) = self.state.pop1_extra()?;
7029 let (v, _) = self.v128_into_f64x2(v, i)?;
7030 let res = err!(self.build_call_with_param_attributes(
7031 self.intrinsics.floor_f64x2,
7032 &[v.into()],
7033 ""
7034 ))
7035 .try_as_basic_value()
7036 .unwrap_basic();
7037 let (res, info) = self.finalize_rounding_result(res, i)?;
7038 let res = err!(
7039 self.builder
7040 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7041 );
7042 self.state.push1_extra(res, info);
7043 }
7044 Operator::F32Trunc => {
7045 let (v, info) = self.state.pop1_extra()?;
7046 let res = err!(
7047 self.builder
7048 .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
7049 )
7050 .try_as_basic_value()
7051 .unwrap_basic();
7052 let (res, info) = self.finalize_rounding_result(res, info)?;
7053 self.state.push1_extra(res, info);
7054 }
7055 Operator::F32x4Trunc => {
7056 let (v, i) = self.state.pop1_extra()?;
7057 let (v, _) = self.v128_into_f32x4(v, i)?;
7058 let res = err!(self.build_call_with_param_attributes(
7059 self.intrinsics.trunc_f32x4,
7060 &[v.into()],
7061 ""
7062 ))
7063 .try_as_basic_value()
7064 .unwrap_basic();
7065 let (res, info) = self.finalize_rounding_result(res, i)?;
7066 let res = err!(
7067 self.builder
7068 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7069 );
7070 self.state.push1_extra(res, info);
7071 }
7072 Operator::F64Trunc => {
7073 let (v, info) = self.state.pop1_extra()?;
7074 let res = err!(
7075 self.builder
7076 .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
7077 )
7078 .try_as_basic_value()
7079 .unwrap_basic();
7080 let (res, info) = self.finalize_rounding_result(res, info)?;
7081 self.state.push1_extra(res, info);
7082 }
7083 Operator::F64x2Trunc => {
7084 let (v, i) = self.state.pop1_extra()?;
7085 let (v, _) = self.v128_into_f64x2(v, i)?;
7086 let res = err!(self.build_call_with_param_attributes(
7087 self.intrinsics.trunc_f64x2,
7088 &[v.into()],
7089 ""
7090 ))
7091 .try_as_basic_value()
7092 .unwrap_basic();
7093 let (res, info) = self.finalize_rounding_result(res, i)?;
7094 let res = err!(
7095 self.builder
7096 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7097 );
7098 self.state.push1_extra(res, info);
7099 }
7100 Operator::F32Nearest => {
7101 let (v, info) = self.state.pop1_extra()?;
7102 let res = err!(self.build_call_with_param_attributes(
7103 self.intrinsics.nearbyint_f32,
7104 &[v.into()],
7105 ""
7106 ))
7107 .try_as_basic_value()
7108 .unwrap_basic();
7109 let (res, info) = self.finalize_rounding_result(res, info)?;
7110 self.state.push1_extra(res, info);
7111 }
7112 Operator::F32x4Nearest => {
7113 let (v, i) = self.state.pop1_extra()?;
7114 let (v, _) = self.v128_into_f32x4(v, i)?;
7115 let res = err!(self.build_call_with_param_attributes(
7116 self.intrinsics.nearbyint_f32x4,
7117 &[v.into()],
7118 ""
7119 ))
7120 .try_as_basic_value()
7121 .unwrap_basic();
7122 let (res, info) = self.finalize_rounding_result(res, i)?;
7123 let res = err!(
7124 self.builder
7125 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7126 );
7127 self.state.push1_extra(res, info);
7128 }
7129 Operator::F64Nearest => {
7130 let (v, info) = self.state.pop1_extra()?;
7131 let res = err!(self.build_call_with_param_attributes(
7132 self.intrinsics.nearbyint_f64,
7133 &[v.into()],
7134 ""
7135 ))
7136 .try_as_basic_value()
7137 .unwrap_basic();
7138 let (res, info) = self.finalize_rounding_result(res, info)?;
7139 self.state.push1_extra(res, info);
7140 }
7141 Operator::F64x2Nearest => {
7142 let (v, i) = self.state.pop1_extra()?;
7143 let (v, _) = self.v128_into_f64x2(v, i)?;
7144 let res = err!(self.build_call_with_param_attributes(
7145 self.intrinsics.nearbyint_f64x2,
7146 &[v.into()],
7147 ""
7148 ))
7149 .try_as_basic_value()
7150 .unwrap_basic();
7151 let (res, info) = self.finalize_rounding_result(res, i)?;
7152 let res = err!(
7153 self.builder
7154 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7155 );
7156 self.state.push1_extra(res, info);
7157 }
7158 Operator::F32Abs => {
7159 let (v, i) = self.state.pop1_extra()?;
7160 let v = self.apply_pending_canonicalization(v, i)?;
7161 let res = err!(
7162 self.builder
7163 .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
7164 )
7165 .try_as_basic_value()
7166 .unwrap_basic();
7167 self.state.push1_extra(res, i.strip_pending());
7170 }
7171 Operator::F64Abs => {
7172 let (v, i) = self.state.pop1_extra()?;
7173 let v = self.apply_pending_canonicalization(v, i)?;
7174 let res = err!(
7175 self.builder
7176 .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
7177 )
7178 .try_as_basic_value()
7179 .unwrap_basic();
7180 self.state.push1_extra(res, i.strip_pending());
7183 }
7184 Operator::F32x4Abs => {
7185 let (v, i) = self.state.pop1_extra()?;
7186 let v = err!(self.builder.build_bit_cast(
7187 v.into_int_value(),
7188 self.intrinsics.f32x4_ty,
7189 ""
7190 ));
7191 let v = self.apply_pending_canonicalization(v, i)?;
7192 let res = self
7193 .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
7194 .try_as_basic_value()
7195 .unwrap_basic();
7196 let res = err!(
7197 self.builder
7198 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7199 );
7200 self.state.push1_extra(res, i.strip_pending());
7203 }
7204 Operator::F64x2Abs => {
7205 let (v, i) = self.state.pop1_extra()?;
7206 let v = err!(self.builder.build_bit_cast(
7207 v.into_int_value(),
7208 self.intrinsics.f64x2_ty,
7209 ""
7210 ));
7211 let v = self.apply_pending_canonicalization(v, i)?;
7212 let res = self
7213 .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
7214 .try_as_basic_value()
7215 .unwrap_basic();
7216 let res = err!(
7217 self.builder
7218 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7219 );
7220 self.state.push1_extra(res, i.strip_pending());
7223 }
7224 Operator::F32x4Neg => {
7225 let (v, i) = self.state.pop1_extra()?;
7226 let v = err!(self.builder.build_bit_cast(
7227 v.into_int_value(),
7228 self.intrinsics.f32x4_ty,
7229 ""
7230 ));
7231 let v = self
7232 .apply_pending_canonicalization(v, i)?
7233 .into_vector_value();
7234 let res = err!(self.builder.build_float_neg(v, ""));
7235 let res = err!(
7236 self.builder
7237 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7238 );
7239 self.state.push1_extra(res, i.strip_pending());
7242 }
7243 Operator::F64x2Neg => {
7244 let (v, i) = self.state.pop1_extra()?;
7245 let v = err!(self.builder.build_bit_cast(
7246 v.into_int_value(),
7247 self.intrinsics.f64x2_ty,
7248 ""
7249 ));
7250 let v = self
7251 .apply_pending_canonicalization(v, i)?
7252 .into_vector_value();
7253 let res = err!(self.builder.build_float_neg(v, ""));
7254 let res = err!(
7255 self.builder
7256 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7257 );
7258 self.state.push1_extra(res, i.strip_pending());
7261 }
7262 Operator::F32Neg | Operator::F64Neg => {
7263 let (v, i) = self.state.pop1_extra()?;
7264 let v = self
7265 .apply_pending_canonicalization(v, i)?
7266 .into_float_value();
7267 let res = err!(self.builder.build_float_neg(v, ""));
7268 self.state.push1_extra(res, i.strip_pending());
7271 }
7272 Operator::F32Copysign => {
7273 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7274 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7275 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7276 let res = self
7277 .build_call_with_param_attributes(
7278 self.intrinsics.copysign_f32,
7279 &[mag.into(), sgn.into()],
7280 "",
7281 )?
7282 .try_as_basic_value()
7283 .unwrap_basic();
7284 self.state.push1_extra(res, mag_info.strip_pending());
7287 }
7288 Operator::F64Copysign => {
7289 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7290 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7291 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7292 let res = self
7293 .build_call_with_param_attributes(
7294 self.intrinsics.copysign_f64,
7295 &[mag.into(), sgn.into()],
7296 "",
7297 )?
7298 .try_as_basic_value()
7299 .unwrap_basic();
7300 self.state.push1_extra(res, mag_info.strip_pending());
7303 }
7304 _ => unreachable!(),
7305 }
7306 Ok(())
7307 }
7308
7309 fn translate_integer_comparison_operator(&mut self, op: Operator) -> Result<(), CompileError> {
7312 match op {
7313 Operator::I32Eq | Operator::I64Eq => {
7314 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7315 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7316 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7317 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7318 let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7319 let res = err!(
7320 self.builder
7321 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7322 );
7323 self.state.push1_extra(
7324 res,
7325 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7326 );
7327 }
7328 Operator::I8x16Eq => {
7329 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7330 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7331 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7332 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7333 let res = err!(
7334 self.builder
7335 .build_int_s_extend(res, self.intrinsics.i8x16_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::I16x8Eq => {
7344 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7345 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7346 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7347 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7348 let res = err!(
7349 self.builder
7350 .build_int_s_extend(res, self.intrinsics.i16x8_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::I32x4Eq => {
7359 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7360 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7361 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7362 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7363 let res = err!(
7364 self.builder
7365 .build_int_s_extend(res, self.intrinsics.i32x4_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::I64x2Eq => {
7374 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7375 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7376 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7377 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7378 let res = err!(
7379 self.builder
7380 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7381 );
7382 let res = err!(
7383 self.builder
7384 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7385 );
7386 self.state.push1(res);
7387 }
7388 Operator::I32Ne | Operator::I64Ne => {
7389 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7390 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7391 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7392 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7393 let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7394 let res = err!(
7395 self.builder
7396 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7397 );
7398 self.state.push1_extra(
7399 res,
7400 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7401 );
7402 }
7403 Operator::I8x16Ne => {
7404 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7405 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7406 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7407 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7408 let res = err!(
7409 self.builder
7410 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7411 );
7412 let res = err!(
7413 self.builder
7414 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7415 );
7416 self.state.push1(res);
7417 }
7418 Operator::I16x8Ne => {
7419 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7420 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7421 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7422 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7423 let res = err!(
7424 self.builder
7425 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7426 );
7427 let res = err!(
7428 self.builder
7429 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7430 );
7431 self.state.push1(res);
7432 }
7433 Operator::I32x4Ne => {
7434 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7435 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7436 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7437 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7438 let res = err!(
7439 self.builder
7440 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7441 );
7442 let res = err!(
7443 self.builder
7444 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7445 );
7446 self.state.push1(res);
7447 }
7448 Operator::I64x2Ne => {
7449 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7450 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7451 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7452 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
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::I32LtS | Operator::I64LtS => {
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::SLT, 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_extra(
7477 res,
7478 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7479 );
7480 }
7481 Operator::I8x16LtS => {
7482 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7483 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7484 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7485 let res = err!(
7486 self.builder
7487 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7488 );
7489 let res = err!(
7490 self.builder
7491 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7492 );
7493 let res = err!(
7494 self.builder
7495 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7496 );
7497 self.state.push1(res);
7498 }
7499 Operator::I16x8LtS => {
7500 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7501 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7502 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7503 let res = err!(
7504 self.builder
7505 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7506 );
7507 let res = err!(
7508 self.builder
7509 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7510 );
7511 let res = err!(
7512 self.builder
7513 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7514 );
7515 self.state.push1(res);
7516 }
7517 Operator::I32x4LtS => {
7518 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7519 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7520 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7521 let res = err!(
7522 self.builder
7523 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7524 );
7525 let res = err!(
7526 self.builder
7527 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7528 );
7529 let res = err!(
7530 self.builder
7531 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7532 );
7533 self.state.push1(res);
7534 }
7535 Operator::I64x2LtS => {
7536 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7537 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7538 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7539 let res = err!(
7540 self.builder
7541 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7542 );
7543 let res = err!(
7544 self.builder
7545 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7546 );
7547 let res = err!(
7548 self.builder
7549 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7550 );
7551 self.state.push1(res);
7552 }
7553 Operator::I32LtU | Operator::I64LtU => {
7554 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7555 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7556 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7557 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7558 let cond = err!(
7559 self.builder
7560 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7561 );
7562 let res = err!(
7563 self.builder
7564 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7565 );
7566 self.state.push1(res);
7567 }
7568 Operator::I8x16LtU => {
7569 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7570 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7571 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7572 let res = err!(
7573 self.builder
7574 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7575 );
7576 let res = err!(
7577 self.builder
7578 .build_int_s_extend(res, self.intrinsics.i8x16_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::I16x8LtU => {
7587 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7588 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7589 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7590 let res = err!(
7591 self.builder
7592 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7593 );
7594 let res = err!(
7595 self.builder
7596 .build_int_s_extend(res, self.intrinsics.i16x8_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::I32x4LtU => {
7605 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7606 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7607 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7608 let res = err!(
7609 self.builder
7610 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7611 );
7612 let res = err!(
7613 self.builder
7614 .build_int_s_extend(res, self.intrinsics.i32x4_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::I32LeS | Operator::I64LeS => {
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::SLE, 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::I8x16LeS => {
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::SLE, 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::I16x8LeS => {
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::SLE, 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::I32x4LeS => {
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::SLE, 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::I64x2LeS => {
7695 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7696 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7697 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7698 let res = err!(
7699 self.builder
7700 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7701 );
7702 let res = err!(
7703 self.builder
7704 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7705 );
7706 let res = err!(
7707 self.builder
7708 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7709 );
7710 self.state.push1(res);
7711 }
7712 Operator::I32LeU | Operator::I64LeU => {
7713 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7714 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7715 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7716 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7717 let cond = err!(
7718 self.builder
7719 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7720 );
7721 let res = err!(
7722 self.builder
7723 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7724 );
7725 self.state.push1_extra(
7726 res,
7727 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7728 );
7729 }
7730 Operator::I8x16LeU => {
7731 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7732 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7733 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7734 let res = err!(
7735 self.builder
7736 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7737 );
7738 let res = err!(
7739 self.builder
7740 .build_int_s_extend(res, self.intrinsics.i8x16_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::I16x8LeU => {
7749 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7750 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7751 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7752 let res = err!(
7753 self.builder
7754 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7755 );
7756 let res = err!(
7757 self.builder
7758 .build_int_s_extend(res, self.intrinsics.i16x8_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::I32x4LeU => {
7767 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7768 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7769 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7770 let res = err!(
7771 self.builder
7772 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7773 );
7774 let res = err!(
7775 self.builder
7776 .build_int_s_extend(res, self.intrinsics.i32x4_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::I32GtS | Operator::I64GtS => {
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::SGT, 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::I8x16GtS => {
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::SGT, 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::I16x8GtS => {
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::SGT, 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::I32x4GtS => {
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::SGT, 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::I64x2GtS => {
7857 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7858 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7859 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7860 let res = err!(
7861 self.builder
7862 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7863 );
7864 let res = err!(
7865 self.builder
7866 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7867 );
7868 let res = err!(
7869 self.builder
7870 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7871 );
7872 self.state.push1(res);
7873 }
7874 Operator::I32GtU | Operator::I64GtU => {
7875 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7876 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7877 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7878 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7879 let cond = err!(
7880 self.builder
7881 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7882 );
7883 let res = err!(
7884 self.builder
7885 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7886 );
7887 self.state.push1_extra(
7888 res,
7889 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7890 );
7891 }
7892 Operator::I8x16GtU => {
7893 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7894 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7895 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7896 let res = err!(
7897 self.builder
7898 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7899 );
7900 let res = err!(
7901 self.builder
7902 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7903 );
7904 let res = err!(
7905 self.builder
7906 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7907 );
7908 self.state.push1(res);
7909 }
7910 Operator::I16x8GtU => {
7911 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7912 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7913 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7914 let res = err!(
7915 self.builder
7916 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7917 );
7918 let res = err!(
7919 self.builder
7920 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7921 );
7922 let res = err!(
7923 self.builder
7924 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7925 );
7926 self.state.push1(res);
7927 }
7928 Operator::I32x4GtU => {
7929 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7930 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7931 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7932 let res = err!(
7933 self.builder
7934 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7935 );
7936 let res = err!(
7937 self.builder
7938 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7939 );
7940 let res = err!(
7941 self.builder
7942 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7943 );
7944 self.state.push1(res);
7945 }
7946 Operator::I32GeS | Operator::I64GeS => {
7947 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7948 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7949 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7950 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7951 let cond = err!(
7952 self.builder
7953 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7954 );
7955 let res = err!(
7956 self.builder
7957 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7958 );
7959 self.state.push1(res);
7960 }
7961 Operator::I8x16GeS => {
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::SGE, 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::I16x8GeS => {
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::SGE, 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::I32x4GeS => {
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::SGE, 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 Operator::I64x2GeS => {
8016 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8017 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
8018 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
8019 let res = err!(
8020 self.builder
8021 .build_int_compare(IntPredicate::SGE, v1, v2, "")
8022 );
8023 let res = err!(
8024 self.builder
8025 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8026 );
8027 let res = err!(
8028 self.builder
8029 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8030 );
8031 self.state.push1(res);
8032 }
8033 Operator::I32GeU | Operator::I64GeU => {
8034 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8035 let v1 = self.apply_pending_canonicalization(v1, i1)?;
8036 let v2 = self.apply_pending_canonicalization(v2, i2)?;
8037 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8038 let cond = err!(
8039 self.builder
8040 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8041 );
8042 let res = err!(
8043 self.builder
8044 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8045 );
8046 self.state.push1_extra(
8047 res,
8048 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8049 );
8050 }
8051 Operator::I8x16GeU => {
8052 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8053 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8054 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8055 let res = err!(
8056 self.builder
8057 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8058 );
8059 let res = err!(
8060 self.builder
8061 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8062 );
8063 let res = err!(
8064 self.builder
8065 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8066 );
8067 self.state.push1(res);
8068 }
8069 Operator::I16x8GeU => {
8070 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8071 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8072 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8073 let res = err!(
8074 self.builder
8075 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8076 );
8077 let res = err!(
8078 self.builder
8079 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8080 );
8081 let res = err!(
8082 self.builder
8083 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8084 );
8085 self.state.push1(res);
8086 }
8087 Operator::I32x4GeU => {
8088 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8089 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8090 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8091 let res = err!(
8092 self.builder
8093 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8094 );
8095 let res = err!(
8096 self.builder
8097 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8098 );
8099 let res = err!(
8100 self.builder
8101 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8102 );
8103 self.state.push1(res);
8104 }
8105 _ => unreachable!(),
8106 }
8107 Ok(())
8108 }
8109
8110 fn translate_floating_point_comparison_operator(
8113 &mut self,
8114 op: Operator,
8115 ) -> Result<(), CompileError> {
8116 match op {
8117 Operator::F32Eq | Operator::F64Eq => {
8118 let (v1, v2) = self.state.pop2()?;
8119 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8120 let cond = err!(
8121 self.builder
8122 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8123 );
8124 let res = err!(
8125 self.builder
8126 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8127 );
8128 self.state.push1_extra(
8129 res,
8130 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8131 );
8132 }
8133 Operator::F32x4Eq => {
8134 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8135 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8136 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8137 let res = err!(
8138 self.builder
8139 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8140 );
8141 let res = err!(
8142 self.builder
8143 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8144 );
8145 let res = err!(
8146 self.builder
8147 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8148 );
8149 self.state.push1(res);
8150 }
8151 Operator::F64x2Eq => {
8152 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8153 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8154 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8155 let res = err!(
8156 self.builder
8157 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8158 );
8159 let res = err!(
8160 self.builder
8161 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8162 );
8163 let res = err!(
8164 self.builder
8165 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8166 );
8167 self.state.push1(res);
8168 }
8169 Operator::F32Ne | Operator::F64Ne => {
8170 let (v1, v2) = self.state.pop2()?;
8171 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8172 let cond = err!(
8173 self.builder
8174 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8175 );
8176 let res = err!(
8177 self.builder
8178 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8179 );
8180 self.state.push1_extra(
8181 res,
8182 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8183 );
8184 }
8185 Operator::F32x4Ne => {
8186 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8187 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8188 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8189 let res = err!(
8190 self.builder
8191 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8192 );
8193 let res = err!(
8194 self.builder
8195 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8196 );
8197 let res = err!(
8198 self.builder
8199 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8200 );
8201 self.state.push1(res);
8202 }
8203 Operator::F64x2Ne => {
8204 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8205 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8206 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8207 let res = err!(
8208 self.builder
8209 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8210 );
8211 let res = err!(
8212 self.builder
8213 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8214 );
8215 let res = err!(
8216 self.builder
8217 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8218 );
8219 self.state.push1(res);
8220 }
8221 Operator::F32Lt | Operator::F64Lt => {
8222 let (v1, v2) = self.state.pop2()?;
8223 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8224 let cond = err!(
8225 self.builder
8226 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8227 );
8228 let res = err!(
8229 self.builder
8230 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8231 );
8232 self.state.push1_extra(
8233 res,
8234 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8235 );
8236 }
8237 Operator::F32x4Lt => {
8238 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8239 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8240 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8241 let res = err!(
8242 self.builder
8243 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8244 );
8245 let res = err!(
8246 self.builder
8247 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8248 );
8249 let res = err!(
8250 self.builder
8251 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8252 );
8253 self.state.push1(res);
8254 }
8255 Operator::F64x2Lt => {
8256 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8257 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8258 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8259 let res = err!(
8260 self.builder
8261 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8262 );
8263 let res = err!(
8264 self.builder
8265 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8266 );
8267 let res = err!(
8268 self.builder
8269 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8270 );
8271 self.state.push1(res);
8272 }
8273 Operator::F32Le | Operator::F64Le => {
8274 let (v1, v2) = self.state.pop2()?;
8275 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8276 let cond = err!(
8277 self.builder
8278 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8279 );
8280 let res = err!(
8281 self.builder
8282 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8283 );
8284 self.state.push1_extra(
8285 res,
8286 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8287 );
8288 }
8289 Operator::F32x4Le => {
8290 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8291 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8292 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8293 let res = err!(
8294 self.builder
8295 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8296 );
8297 let res = err!(
8298 self.builder
8299 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8300 );
8301 let res = err!(
8302 self.builder
8303 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8304 );
8305 self.state.push1(res);
8306 }
8307 Operator::F64x2Le => {
8308 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8309 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8310 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8311 let res = err!(
8312 self.builder
8313 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8314 );
8315 let res = err!(
8316 self.builder
8317 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8318 );
8319 let res = err!(
8320 self.builder
8321 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8322 );
8323 self.state.push1(res);
8324 }
8325 Operator::F32Gt | Operator::F64Gt => {
8326 let (v1, v2) = self.state.pop2()?;
8327 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8328 let cond = err!(
8329 self.builder
8330 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8331 );
8332 let res = err!(
8333 self.builder
8334 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8335 );
8336 self.state.push1_extra(
8337 res,
8338 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8339 );
8340 }
8341 Operator::F32x4Gt => {
8342 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8343 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8344 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8345 let res = err!(
8346 self.builder
8347 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8348 );
8349 let res = err!(
8350 self.builder
8351 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8352 );
8353 let res = err!(
8354 self.builder
8355 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8356 );
8357 self.state.push1(res);
8358 }
8359 Operator::F64x2Gt => {
8360 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8361 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8362 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8363 let res = err!(
8364 self.builder
8365 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8366 );
8367 let res = err!(
8368 self.builder
8369 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8370 );
8371 let res = err!(
8372 self.builder
8373 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8374 );
8375 self.state.push1(res);
8376 }
8377 Operator::F32Ge | Operator::F64Ge => {
8378 let (v1, v2) = self.state.pop2()?;
8379 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8380 let cond = err!(
8381 self.builder
8382 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8383 );
8384 let res = err!(
8385 self.builder
8386 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8387 );
8388 self.state.push1_extra(
8389 res,
8390 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8391 );
8392 }
8393 Operator::F32x4Ge => {
8394 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8395 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8396 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8397 let res = err!(
8398 self.builder
8399 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8400 );
8401 let res = err!(
8402 self.builder
8403 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8404 );
8405 let res = err!(
8406 self.builder
8407 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8408 );
8409 self.state.push1(res);
8410 }
8411 Operator::F64x2Ge => {
8412 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8413 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8414 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8415 let res = err!(
8416 self.builder
8417 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8418 );
8419 let res = err!(
8420 self.builder
8421 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8422 );
8423 let res = err!(
8424 self.builder
8425 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8426 );
8427 self.state.push1(res);
8428 }
8429 _ => unreachable!(),
8430 }
8431 Ok(())
8432 }
8433
8434 fn translate_conversion_operator(&mut self, op: Operator) -> Result<(), CompileError> {
8437 match op {
8438 Operator::I32WrapI64 => {
8439 let (v, i) = self.state.pop1_extra()?;
8440 let v = self.apply_pending_canonicalization(v, i)?;
8441 let v = v.into_int_value();
8442 let res = err!(
8443 self.builder
8444 .build_int_truncate(v, self.intrinsics.i32_ty, "")
8445 );
8446 self.state.push1(res);
8447 }
8448 Operator::I64ExtendI32S => {
8449 let (v, i) = self.state.pop1_extra()?;
8450 let v = self.apply_pending_canonicalization(v, i)?;
8451 let v = v.into_int_value();
8452 let res = err!(
8453 self.builder
8454 .build_int_s_extend(v, self.intrinsics.i64_ty, "")
8455 );
8456 self.state.push1(res);
8457 }
8458 Operator::I64ExtendI32U => {
8459 let (v, i) = self.state.pop1_extra()?;
8460 let v = self.apply_pending_canonicalization(v, i)?;
8461 let v = v.into_int_value();
8462 let res = err!(
8463 self.builder
8464 .build_int_z_extend(v, self.intrinsics.i64_ty, "")
8465 );
8466 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
8467 }
8468 Operator::I16x8ExtendLowI8x16S => {
8469 let (v, i) = self.state.pop1_extra()?;
8470 let (v, _) = self.v128_into_i8x16(v, i)?;
8471 let low = err!(self.builder.build_shuffle_vector(
8472 v,
8473 v.get_type().get_undef(),
8474 VectorType::const_vector(&[
8475 self.intrinsics.i32_consts[0],
8476 self.intrinsics.i32_consts[1],
8477 self.intrinsics.i32_consts[2],
8478 self.intrinsics.i32_consts[3],
8479 self.intrinsics.i32_consts[4],
8480 self.intrinsics.i32_consts[5],
8481 self.intrinsics.i32_consts[6],
8482 self.intrinsics.i32_consts[7],
8483 ]),
8484 "",
8485 ));
8486 let res = err!(
8487 self.builder
8488 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8489 );
8490 let res = err!(
8491 self.builder
8492 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8493 );
8494 self.state.push1(res);
8495 }
8496 Operator::I16x8ExtendHighI8x16S => {
8497 let (v, i) = self.state.pop1_extra()?;
8498 let (v, _) = self.v128_into_i8x16(v, i)?;
8499 let low = err!(self.builder.build_shuffle_vector(
8500 v,
8501 v.get_type().get_undef(),
8502 VectorType::const_vector(&[
8503 self.intrinsics.i32_consts[8],
8504 self.intrinsics.i32_consts[9],
8505 self.intrinsics.i32_consts[10],
8506 self.intrinsics.i32_consts[11],
8507 self.intrinsics.i32_consts[12],
8508 self.intrinsics.i32_consts[13],
8509 self.intrinsics.i32_consts[14],
8510 self.intrinsics.i32_consts[15],
8511 ]),
8512 "",
8513 ));
8514 let res = err!(
8515 self.builder
8516 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8517 );
8518 let res = err!(
8519 self.builder
8520 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8521 );
8522 self.state.push1(res);
8523 }
8524 Operator::I16x8ExtendLowI8x16U => {
8525 let (v, i) = self.state.pop1_extra()?;
8526 let (v, _) = self.v128_into_i8x16(v, i)?;
8527 let low = err!(self.builder.build_shuffle_vector(
8528 v,
8529 v.get_type().get_undef(),
8530 VectorType::const_vector(&[
8531 self.intrinsics.i32_consts[0],
8532 self.intrinsics.i32_consts[1],
8533 self.intrinsics.i32_consts[2],
8534 self.intrinsics.i32_consts[3],
8535 self.intrinsics.i32_consts[4],
8536 self.intrinsics.i32_consts[5],
8537 self.intrinsics.i32_consts[6],
8538 self.intrinsics.i32_consts[7],
8539 ]),
8540 "",
8541 ));
8542 let res = err!(
8543 self.builder
8544 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8545 );
8546 let res = err!(
8547 self.builder
8548 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8549 );
8550 self.state.push1(res);
8551 }
8552 Operator::I16x8ExtendHighI8x16U => {
8553 let (v, i) = self.state.pop1_extra()?;
8554 let (v, _) = self.v128_into_i8x16(v, i)?;
8555 let low = err!(self.builder.build_shuffle_vector(
8556 v,
8557 v.get_type().get_undef(),
8558 VectorType::const_vector(&[
8559 self.intrinsics.i32_consts[8],
8560 self.intrinsics.i32_consts[9],
8561 self.intrinsics.i32_consts[10],
8562 self.intrinsics.i32_consts[11],
8563 self.intrinsics.i32_consts[12],
8564 self.intrinsics.i32_consts[13],
8565 self.intrinsics.i32_consts[14],
8566 self.intrinsics.i32_consts[15],
8567 ]),
8568 "",
8569 ));
8570 let res = err!(
8571 self.builder
8572 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8573 );
8574 let res = err!(
8575 self.builder
8576 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8577 );
8578 self.state.push1(res);
8579 }
8580 Operator::I32x4ExtendLowI16x8S => {
8581 let (v, i) = self.state.pop1_extra()?;
8582 let (v, _) = self.v128_into_i16x8(v, i)?;
8583 let low = err!(self.builder.build_shuffle_vector(
8584 v,
8585 v.get_type().get_undef(),
8586 VectorType::const_vector(&[
8587 self.intrinsics.i32_consts[0],
8588 self.intrinsics.i32_consts[1],
8589 self.intrinsics.i32_consts[2],
8590 self.intrinsics.i32_consts[3],
8591 ]),
8592 "",
8593 ));
8594 let res = err!(
8595 self.builder
8596 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8597 );
8598 let res = err!(
8599 self.builder
8600 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8601 );
8602 self.state.push1(res);
8603 }
8604 Operator::I32x4ExtendHighI16x8S => {
8605 let (v, i) = self.state.pop1_extra()?;
8606 let (v, _) = self.v128_into_i16x8(v, i)?;
8607 let low = err!(self.builder.build_shuffle_vector(
8608 v,
8609 v.get_type().get_undef(),
8610 VectorType::const_vector(&[
8611 self.intrinsics.i32_consts[4],
8612 self.intrinsics.i32_consts[5],
8613 self.intrinsics.i32_consts[6],
8614 self.intrinsics.i32_consts[7],
8615 ]),
8616 "",
8617 ));
8618 let res = err!(
8619 self.builder
8620 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8621 );
8622 let res = err!(
8623 self.builder
8624 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8625 );
8626 self.state.push1(res);
8627 }
8628 Operator::I32x4ExtendLowI16x8U => {
8629 let (v, i) = self.state.pop1_extra()?;
8630 let (v, _) = self.v128_into_i16x8(v, i)?;
8631 let low = err!(self.builder.build_shuffle_vector(
8632 v,
8633 v.get_type().get_undef(),
8634 VectorType::const_vector(&[
8635 self.intrinsics.i32_consts[0],
8636 self.intrinsics.i32_consts[1],
8637 self.intrinsics.i32_consts[2],
8638 self.intrinsics.i32_consts[3],
8639 ]),
8640 "",
8641 ));
8642 let res = err!(
8643 self.builder
8644 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8645 );
8646 let res = err!(
8647 self.builder
8648 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8649 );
8650 self.state.push1(res);
8651 }
8652 Operator::I32x4ExtendHighI16x8U => {
8653 let (v, i) = self.state.pop1_extra()?;
8654 let (v, _) = self.v128_into_i16x8(v, i)?;
8655 let low = err!(self.builder.build_shuffle_vector(
8656 v,
8657 v.get_type().get_undef(),
8658 VectorType::const_vector(&[
8659 self.intrinsics.i32_consts[4],
8660 self.intrinsics.i32_consts[5],
8661 self.intrinsics.i32_consts[6],
8662 self.intrinsics.i32_consts[7],
8663 ]),
8664 "",
8665 ));
8666 let res = err!(
8667 self.builder
8668 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8669 );
8670 let res = err!(
8671 self.builder
8672 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8673 );
8674 self.state.push1(res);
8675 }
8676 Operator::I64x2ExtendLowI32x4U
8677 | Operator::I64x2ExtendLowI32x4S
8678 | Operator::I64x2ExtendHighI32x4U
8679 | Operator::I64x2ExtendHighI32x4S => {
8680 let extend = match op {
8681 Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8682 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8683 }
8684 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8685 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8686 }
8687 _ => unreachable!("Unhandled inner case"),
8688 };
8689 let indices = match op {
8690 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8691 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8692 }
8693 Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8694 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8695 }
8696 _ => unreachable!("Unhandled inner case"),
8697 };
8698 let (v, i) = self.state.pop1_extra()?;
8699 let (v, _) = self.v128_into_i32x4(v, i)?;
8700 let low = err!(self.builder.build_shuffle_vector(
8701 v,
8702 v.get_type().get_undef(),
8703 VectorType::const_vector(&indices),
8704 "",
8705 ));
8706 let res = err!(extend(self, low));
8707 let res = err!(
8708 self.builder
8709 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8710 );
8711 self.state.push1(res);
8712 }
8713 Operator::I8x16NarrowI16x8S => {
8714 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8715 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8716 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8717 let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8718 let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8719 let min = VectorType::const_vector(&[min; 8]);
8720 let max = VectorType::const_vector(&[max; 8]);
8721 let apply_min_clamp_v1 =
8722 err!(
8723 self.builder
8724 .build_int_compare(IntPredicate::SLT, v1, min, "")
8725 );
8726 let apply_max_clamp_v1 =
8727 err!(
8728 self.builder
8729 .build_int_compare(IntPredicate::SGT, v1, max, "")
8730 );
8731 let apply_min_clamp_v2 =
8732 err!(
8733 self.builder
8734 .build_int_compare(IntPredicate::SLT, v2, min, "")
8735 );
8736 let apply_max_clamp_v2 =
8737 err!(
8738 self.builder
8739 .build_int_compare(IntPredicate::SGT, v2, max, "")
8740 );
8741 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8742 .into_vector_value();
8743 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8744 .into_vector_value();
8745 let v1 = err!(self.builder.build_int_truncate(
8746 v1,
8747 self.intrinsics.i8_ty.vec_type(8),
8748 ""
8749 ));
8750 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8751 .into_vector_value();
8752 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8753 .into_vector_value();
8754 let v2 = err!(self.builder.build_int_truncate(
8755 v2,
8756 self.intrinsics.i8_ty.vec_type(8),
8757 ""
8758 ));
8759 let res = err!(self.builder.build_shuffle_vector(
8760 v1,
8761 v2,
8762 VectorType::const_vector(&[
8763 self.intrinsics.i32_consts[0],
8764 self.intrinsics.i32_consts[1],
8765 self.intrinsics.i32_consts[2],
8766 self.intrinsics.i32_consts[3],
8767 self.intrinsics.i32_consts[4],
8768 self.intrinsics.i32_consts[5],
8769 self.intrinsics.i32_consts[6],
8770 self.intrinsics.i32_consts[7],
8771 self.intrinsics.i32_consts[8],
8772 self.intrinsics.i32_consts[9],
8773 self.intrinsics.i32_consts[10],
8774 self.intrinsics.i32_consts[11],
8775 self.intrinsics.i32_consts[12],
8776 self.intrinsics.i32_consts[13],
8777 self.intrinsics.i32_consts[14],
8778 self.intrinsics.i32_consts[15],
8779 ]),
8780 "",
8781 ));
8782 let res = err!(
8783 self.builder
8784 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8785 );
8786 self.state.push1(res);
8787 }
8788 Operator::I8x16NarrowI16x8U => {
8789 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8790 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8791 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8792 let min = self.intrinsics.i16x8_ty.const_zero();
8793 let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8794 let max = VectorType::const_vector(&[max; 8]);
8795 let apply_min_clamp_v1 =
8796 err!(
8797 self.builder
8798 .build_int_compare(IntPredicate::SLT, v1, min, "")
8799 );
8800 let apply_max_clamp_v1 =
8801 err!(
8802 self.builder
8803 .build_int_compare(IntPredicate::SGT, v1, max, "")
8804 );
8805 let apply_min_clamp_v2 =
8806 err!(
8807 self.builder
8808 .build_int_compare(IntPredicate::SLT, v2, min, "")
8809 );
8810 let apply_max_clamp_v2 =
8811 err!(
8812 self.builder
8813 .build_int_compare(IntPredicate::SGT, v2, max, "")
8814 );
8815 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8816 .into_vector_value();
8817 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8818 .into_vector_value();
8819 let v1 = err!(self.builder.build_int_truncate(
8820 v1,
8821 self.intrinsics.i8_ty.vec_type(8),
8822 ""
8823 ));
8824 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8825 .into_vector_value();
8826 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8827 .into_vector_value();
8828 let v2 = err!(self.builder.build_int_truncate(
8829 v2,
8830 self.intrinsics.i8_ty.vec_type(8),
8831 ""
8832 ));
8833 let res = err!(self.builder.build_shuffle_vector(
8834 v1,
8835 v2,
8836 VectorType::const_vector(&[
8837 self.intrinsics.i32_consts[0],
8838 self.intrinsics.i32_consts[1],
8839 self.intrinsics.i32_consts[2],
8840 self.intrinsics.i32_consts[3],
8841 self.intrinsics.i32_consts[4],
8842 self.intrinsics.i32_consts[5],
8843 self.intrinsics.i32_consts[6],
8844 self.intrinsics.i32_consts[7],
8845 self.intrinsics.i32_consts[8],
8846 self.intrinsics.i32_consts[9],
8847 self.intrinsics.i32_consts[10],
8848 self.intrinsics.i32_consts[11],
8849 self.intrinsics.i32_consts[12],
8850 self.intrinsics.i32_consts[13],
8851 self.intrinsics.i32_consts[14],
8852 self.intrinsics.i32_consts[15],
8853 ]),
8854 "",
8855 ));
8856 let res = err!(
8857 self.builder
8858 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8859 );
8860 self.state.push1(res);
8861 }
8862 Operator::I16x8NarrowI32x4S => {
8863 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8864 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8865 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8866 let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8867 let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8868 let min = VectorType::const_vector(&[min; 4]);
8869 let max = VectorType::const_vector(&[max; 4]);
8870 let apply_min_clamp_v1 =
8871 err!(
8872 self.builder
8873 .build_int_compare(IntPredicate::SLT, v1, min, "")
8874 );
8875 let apply_max_clamp_v1 =
8876 err!(
8877 self.builder
8878 .build_int_compare(IntPredicate::SGT, v1, max, "")
8879 );
8880 let apply_min_clamp_v2 =
8881 err!(
8882 self.builder
8883 .build_int_compare(IntPredicate::SLT, v2, min, "")
8884 );
8885 let apply_max_clamp_v2 =
8886 err!(
8887 self.builder
8888 .build_int_compare(IntPredicate::SGT, v2, max, "")
8889 );
8890 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8891 .into_vector_value();
8892 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8893 .into_vector_value();
8894 let v1 = err!(self.builder.build_int_truncate(
8895 v1,
8896 self.intrinsics.i16_ty.vec_type(4),
8897 ""
8898 ));
8899 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8900 .into_vector_value();
8901 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8902 .into_vector_value();
8903 let v2 = err!(self.builder.build_int_truncate(
8904 v2,
8905 self.intrinsics.i16_ty.vec_type(4),
8906 ""
8907 ));
8908 let res = err!(self.builder.build_shuffle_vector(
8909 v1,
8910 v2,
8911 VectorType::const_vector(&[
8912 self.intrinsics.i32_consts[0],
8913 self.intrinsics.i32_consts[1],
8914 self.intrinsics.i32_consts[2],
8915 self.intrinsics.i32_consts[3],
8916 self.intrinsics.i32_consts[4],
8917 self.intrinsics.i32_consts[5],
8918 self.intrinsics.i32_consts[6],
8919 self.intrinsics.i32_consts[7],
8920 ]),
8921 "",
8922 ));
8923 let res = err!(
8924 self.builder
8925 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8926 );
8927 self.state.push1(res);
8928 }
8929 Operator::I16x8NarrowI32x4U => {
8930 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8931 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8932 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8933 let min = self.intrinsics.i32x4_ty.const_zero();
8934 let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8935 let max = VectorType::const_vector(&[max; 4]);
8936 let apply_min_clamp_v1 =
8937 err!(
8938 self.builder
8939 .build_int_compare(IntPredicate::SLT, v1, min, "")
8940 );
8941 let apply_max_clamp_v1 =
8942 err!(
8943 self.builder
8944 .build_int_compare(IntPredicate::SGT, v1, max, "")
8945 );
8946 let apply_min_clamp_v2 =
8947 err!(
8948 self.builder
8949 .build_int_compare(IntPredicate::SLT, v2, min, "")
8950 );
8951 let apply_max_clamp_v2 =
8952 err!(
8953 self.builder
8954 .build_int_compare(IntPredicate::SGT, v2, max, "")
8955 );
8956 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8957 .into_vector_value();
8958 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8959 .into_vector_value();
8960 let v1 = err!(self.builder.build_int_truncate(
8961 v1,
8962 self.intrinsics.i16_ty.vec_type(4),
8963 ""
8964 ));
8965 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8966 .into_vector_value();
8967 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8968 .into_vector_value();
8969 let v2 = err!(self.builder.build_int_truncate(
8970 v2,
8971 self.intrinsics.i16_ty.vec_type(4),
8972 ""
8973 ));
8974 let res = err!(self.builder.build_shuffle_vector(
8975 v1,
8976 v2,
8977 VectorType::const_vector(&[
8978 self.intrinsics.i32_consts[0],
8979 self.intrinsics.i32_consts[1],
8980 self.intrinsics.i32_consts[2],
8981 self.intrinsics.i32_consts[3],
8982 self.intrinsics.i32_consts[4],
8983 self.intrinsics.i32_consts[5],
8984 self.intrinsics.i32_consts[6],
8985 self.intrinsics.i32_consts[7],
8986 ]),
8987 "",
8988 ));
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::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8996 let (v, i) = self.state.pop1_extra()?;
8997 let (v, _) = self.v128_into_f32x4(v, i)?;
8998 let res = self
8999 .build_call_with_param_attributes(
9000 self.intrinsics.x86_64.cvttps2dq,
9001 &[v.into()],
9002 "",
9003 )?
9004 .try_as_basic_value()
9005 .unwrap_basic();
9006 let res = err!(
9007 self.builder
9008 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9009 );
9010 self.state.push1(res);
9011 }
9012 Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
9013 let (v, i) = self.state.pop1_extra()?;
9014 let v = self.apply_pending_canonicalization(v, i)?;
9015 let v = v.into_int_value();
9016 let res = self.trunc_sat_into_int(
9017 self.intrinsics.f32x4_ty,
9018 self.intrinsics.i32x4_ty,
9019 LEF32_GEQ_I32_MIN,
9020 GEF32_LEQ_I32_MAX,
9021 i32::MIN as u64,
9022 i32::MAX as u64,
9023 v,
9024 )?;
9025 self.state.push1(res);
9026 }
9027 Operator::I32x4RelaxedTruncF32x4U
9028 if self.cpu_features.contains(CpuFeature::AVX512F)
9029 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9030 {
9031 let (v, i) = self.state.pop1_extra()?;
9032 let (v, _) = self.v128_into_f32x4(v, i)?;
9033 let res = self
9034 .build_call_with_param_attributes(
9035 self.intrinsics.x86_64.cvtps2udq128,
9036 &[
9037 v.into(),
9038 self.intrinsics.i32x4_ty.const_zero().into(),
9039 self.intrinsics.i8_ty.const_int(0xff, false).into(),
9040 ],
9041 "",
9042 )?
9043 .try_as_basic_value()
9044 .unwrap_basic();
9045 let res = err!(
9046 self.builder
9047 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9048 );
9049 self.state.push1(res);
9050 }
9051 Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
9052 let (v, i) = self.state.pop1_extra()?;
9053 let v = self.apply_pending_canonicalization(v, i)?;
9054 let v = v.into_int_value();
9055 let res = self.trunc_sat_into_int(
9056 self.intrinsics.f32x4_ty,
9057 self.intrinsics.i32x4_ty,
9058 LEF32_GEQ_U32_MIN,
9059 GEF32_LEQ_U32_MAX,
9060 u32::MIN as u64,
9061 u32::MAX as u64,
9062 v,
9063 )?;
9064 self.state.push1(res);
9065 }
9066 Operator::I32x4RelaxedTruncF64x2SZero
9067 if self.cpu_features.contains(CpuFeature::SSE2) =>
9068 {
9069 let (v, i) = self.state.pop1_extra()?;
9070 let (v, _) = self.v128_into_f64x2(v, i)?;
9071 let res = self
9072 .build_call_with_param_attributes(
9073 self.intrinsics.x86_64.cvtpd2dq,
9074 &[v.into()],
9075 "",
9076 )?
9077 .try_as_basic_value()
9078 .unwrap_basic();
9079 let res = err!(
9080 self.builder
9081 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9082 );
9083 self.state.push1(res);
9084 }
9085 Operator::I32x4RelaxedTruncF64x2UZero
9086 if self.cpu_features.contains(CpuFeature::AVX512F)
9087 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9088 {
9089 let (v, i) = self.state.pop1_extra()?;
9090 let (v, _) = self.v128_into_f64x2(v, i)?;
9091 let res = self
9092 .build_call_with_param_attributes(
9093 self.intrinsics.x86_64.cvtpd2udq128,
9094 &[
9095 v.into(),
9096 self.intrinsics.i32x4_ty.const_zero().into(),
9097 self.intrinsics.i8_ty.const_int(0xff, false).into(),
9098 ],
9099 "",
9100 )?
9101 .try_as_basic_value()
9102 .unwrap_basic();
9103 let res = err!(
9104 self.builder
9105 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9106 );
9107 self.state.push1(res);
9108 }
9109 Operator::I32x4TruncSatF64x2SZero
9110 | Operator::I32x4TruncSatF64x2UZero
9111 | Operator::I32x4RelaxedTruncF64x2SZero
9112 | Operator::I32x4RelaxedTruncF64x2UZero => {
9113 let ((min, max), (cmp_min, cmp_max)) = match op {
9114 Operator::I32x4TruncSatF64x2SZero => (
9115 (i32::MIN as u64, i32::MAX as u64),
9116 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9117 ),
9118 Operator::I32x4TruncSatF64x2UZero => (
9119 (u32::MIN as u64, u32::MAX as u64),
9120 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9121 ),
9122 Operator::I32x4RelaxedTruncF64x2SZero => (
9123 (i32::MIN as u64, i32::MAX as u64),
9124 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9125 ),
9126 Operator::I32x4RelaxedTruncF64x2UZero => (
9127 (u32::MIN as u64, u32::MAX as u64),
9128 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9129 ),
9130 _ => unreachable!("Unhandled internal variant"),
9131 };
9132 let (v, i) = self.state.pop1_extra()?;
9133 let v = self.apply_pending_canonicalization(v, i)?;
9134 let v = v.into_int_value();
9135 let res = self.trunc_sat(
9136 self.intrinsics.f64x2_ty,
9137 self.intrinsics.i32_ty.vec_type(2),
9138 cmp_min,
9139 cmp_max,
9140 min,
9141 max,
9142 v,
9143 )?;
9144
9145 let zero = self.intrinsics.i32_consts[0];
9146 let zeros = VectorType::const_vector(&[zero; 2]);
9147 let res = err!(self.builder.build_shuffle_vector(
9148 res,
9149 zeros,
9150 VectorType::const_vector(&[
9151 self.intrinsics.i32_consts[0],
9152 self.intrinsics.i32_consts[1],
9153 self.intrinsics.i32_consts[2],
9154 self.intrinsics.i32_consts[3],
9155 ]),
9156 "",
9157 ));
9158 let res = err!(
9159 self.builder
9160 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9161 );
9162 self.state.push1(res);
9163 }
9164 Operator::I32TruncF32S => {
9195 let v1 = self.state.pop1()?.into_float_value();
9196 self.trap_if_not_representable_as_int(
9197 0xcf000000, 0x4effffff, v1,
9200 )?;
9201 let res = err!(self.builder.build_float_to_signed_int(
9202 v1,
9203 self.intrinsics.i32_ty,
9204 ""
9205 ));
9206 self.state.push1(res);
9207 }
9208 Operator::I32TruncF64S => {
9209 let v1 = self.state.pop1()?.into_float_value();
9210 self.trap_if_not_representable_as_int(
9211 0xc1e00000001fffff, 0x41dfffffffffffff, v1,
9214 )?;
9215 let res = err!(self.builder.build_float_to_signed_int(
9216 v1,
9217 self.intrinsics.i32_ty,
9218 ""
9219 ));
9220 self.state.push1(res);
9221 }
9222 Operator::I32TruncSatF32S => {
9223 let (v, i) = self.state.pop1_extra()?;
9224 let v = self.apply_pending_canonicalization(v, i)?;
9225 let v = v.into_float_value();
9226 let res = self.trunc_sat_scalar(
9227 self.intrinsics.i32_ty,
9228 LEF32_GEQ_I32_MIN,
9229 GEF32_LEQ_I32_MAX,
9230 i32::MIN as u32 as u64,
9231 i32::MAX as u32 as u64,
9232 v,
9233 )?;
9234 self.state.push1(res);
9235 }
9236 Operator::I32TruncSatF64S => {
9237 let (v, i) = self.state.pop1_extra()?;
9238 let v = self.apply_pending_canonicalization(v, i)?;
9239 let v = v.into_float_value();
9240 let res = self.trunc_sat_scalar(
9241 self.intrinsics.i32_ty,
9242 LEF64_GEQ_I32_MIN,
9243 GEF64_LEQ_I32_MAX,
9244 i32::MIN as u64,
9245 i32::MAX as u64,
9246 v,
9247 )?;
9248 self.state.push1(res);
9249 }
9250 Operator::I64TruncF32S => {
9251 let v1 = self.state.pop1()?.into_float_value();
9252 self.trap_if_not_representable_as_int(
9253 0xdf000000, 0x5effffff, v1,
9256 )?;
9257 let res = err!(self.builder.build_float_to_signed_int(
9258 v1,
9259 self.intrinsics.i64_ty,
9260 ""
9261 ));
9262 self.state.push1(res);
9263 }
9264 Operator::I64TruncF64S => {
9265 let v1 = self.state.pop1()?.into_float_value();
9266 self.trap_if_not_representable_as_int(
9267 0xc3e0000000000000, 0x43dfffffffffffff, v1,
9270 )?;
9271 let res = err!(self.builder.build_float_to_signed_int(
9272 v1,
9273 self.intrinsics.i64_ty,
9274 ""
9275 ));
9276 self.state.push1(res);
9277 }
9278 Operator::I64TruncSatF32S => {
9279 let (v, i) = self.state.pop1_extra()?;
9280 let v = self.apply_pending_canonicalization(v, i)?;
9281 let v = v.into_float_value();
9282 let res = self.trunc_sat_scalar(
9283 self.intrinsics.i64_ty,
9284 LEF32_GEQ_I64_MIN,
9285 GEF32_LEQ_I64_MAX,
9286 i64::MIN as u64,
9287 i64::MAX as u64,
9288 v,
9289 )?;
9290 self.state.push1(res);
9291 }
9292 Operator::I64TruncSatF64S => {
9293 let (v, i) = self.state.pop1_extra()?;
9294 let v = self.apply_pending_canonicalization(v, i)?;
9295 let v = v.into_float_value();
9296 let res = self.trunc_sat_scalar(
9297 self.intrinsics.i64_ty,
9298 LEF64_GEQ_I64_MIN,
9299 GEF64_LEQ_I64_MAX,
9300 i64::MIN as u64,
9301 i64::MAX as u64,
9302 v,
9303 )?;
9304 self.state.push1(res);
9305 }
9306 Operator::I32TruncF32U => {
9307 let v1 = self.state.pop1()?.into_float_value();
9308 self.trap_if_not_representable_as_int(
9309 0xbf7fffff, 0x4f7fffff, v1,
9312 )?;
9313 let res = err!(self.builder.build_float_to_unsigned_int(
9314 v1,
9315 self.intrinsics.i32_ty,
9316 ""
9317 ));
9318 self.state.push1(res);
9319 }
9320 Operator::I32TruncF64U => {
9321 let v1 = self.state.pop1()?.into_float_value();
9322 self.trap_if_not_representable_as_int(
9323 0xbfefffffffffffff, 0x41efffffffffffff, v1,
9326 )?;
9327 let res = err!(self.builder.build_float_to_unsigned_int(
9328 v1,
9329 self.intrinsics.i32_ty,
9330 ""
9331 ));
9332 self.state.push1(res);
9333 }
9334 Operator::I32TruncSatF32U => {
9335 let (v, i) = self.state.pop1_extra()?;
9336 let v = self.apply_pending_canonicalization(v, i)?;
9337 let v = v.into_float_value();
9338 let res = self.trunc_sat_scalar(
9339 self.intrinsics.i32_ty,
9340 LEF32_GEQ_U32_MIN,
9341 GEF32_LEQ_U32_MAX,
9342 u32::MIN as u64,
9343 u32::MAX as u64,
9344 v,
9345 )?;
9346 self.state.push1(res);
9347 }
9348 Operator::I32TruncSatF64U => {
9349 let (v, i) = self.state.pop1_extra()?;
9350 let v = self.apply_pending_canonicalization(v, i)?;
9351 let v = v.into_float_value();
9352 let res = self.trunc_sat_scalar(
9353 self.intrinsics.i32_ty,
9354 LEF64_GEQ_U32_MIN,
9355 GEF64_LEQ_U32_MAX,
9356 u32::MIN as u64,
9357 u32::MAX as u64,
9358 v,
9359 )?;
9360 self.state.push1(res);
9361 }
9362 Operator::I64TruncF32U => {
9363 let v1 = self.state.pop1()?.into_float_value();
9364 self.trap_if_not_representable_as_int(
9365 0xbf7fffff, 0x5f7fffff, v1,
9368 )?;
9369 let res = err!(self.builder.build_float_to_unsigned_int(
9370 v1,
9371 self.intrinsics.i64_ty,
9372 ""
9373 ));
9374 self.state.push1(res);
9375 }
9376 Operator::I64TruncF64U => {
9377 let v1 = self.state.pop1()?.into_float_value();
9378 self.trap_if_not_representable_as_int(
9379 0xbfefffffffffffff, 0x43efffffffffffff, v1,
9382 )?;
9383 let res = err!(self.builder.build_float_to_unsigned_int(
9384 v1,
9385 self.intrinsics.i64_ty,
9386 ""
9387 ));
9388 self.state.push1(res);
9389 }
9390 Operator::I64TruncSatF32U => {
9391 let (v, i) = self.state.pop1_extra()?;
9392 let v = self.apply_pending_canonicalization(v, i)?;
9393 let v = v.into_float_value();
9394 let res = self.trunc_sat_scalar(
9395 self.intrinsics.i64_ty,
9396 LEF32_GEQ_U64_MIN,
9397 GEF32_LEQ_U64_MAX,
9398 u64::MIN,
9399 u64::MAX,
9400 v,
9401 )?;
9402 self.state.push1(res);
9403 }
9404 Operator::I64TruncSatF64U => {
9405 let (v, i) = self.state.pop1_extra()?;
9406 let v = self.apply_pending_canonicalization(v, i)?;
9407 let v = v.into_float_value();
9408 let res = self.trunc_sat_scalar(
9409 self.intrinsics.i64_ty,
9410 LEF64_GEQ_U64_MIN,
9411 GEF64_LEQ_U64_MAX,
9412 u64::MIN,
9413 u64::MAX,
9414 v,
9415 )?;
9416 self.state.push1(res);
9417 }
9418 Operator::F32DemoteF64 => {
9419 let v = self.state.pop1()?;
9420 let v = v.into_float_value();
9421 let res = self
9422 .build_call_with_param_attributes(
9423 self.intrinsics.fptrunc_f64,
9424 &[
9425 v.into(),
9426 self.intrinsics.fp_rounding_md,
9427 self.intrinsics.fp_exception_md,
9428 ],
9429 "",
9430 )?
9431 .try_as_basic_value()
9432 .unwrap_basic();
9433 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9434 }
9435 Operator::F64PromoteF32 => {
9436 let v = self.state.pop1()?;
9437 let v = v.into_float_value();
9438 let res = self
9439 .build_call_with_param_attributes(
9440 self.intrinsics.fpext_f32,
9441 &[v.into(), self.intrinsics.fp_exception_md],
9442 "",
9443 )?
9444 .try_as_basic_value()
9445 .unwrap_basic();
9446 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9447 }
9448 Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
9449 let (v, i) = self.state.pop1_extra()?;
9450 let v = self.apply_pending_canonicalization(v, i)?;
9451 let v = v.into_int_value();
9452 let res = err!(self.builder.build_signed_int_to_float(
9453 v,
9454 self.intrinsics.f32_ty,
9455 ""
9456 ));
9457 self.state.push1(res);
9458 }
9459 Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
9460 let (v, i) = self.state.pop1_extra()?;
9461 let v = self.apply_pending_canonicalization(v, i)?;
9462 let v = v.into_int_value();
9463 let res = err!(self.builder.build_signed_int_to_float(
9464 v,
9465 self.intrinsics.f64_ty,
9466 ""
9467 ));
9468 self.state.push1(res);
9469 }
9470 Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
9471 let (v, i) = self.state.pop1_extra()?;
9472 let v = self.apply_pending_canonicalization(v, i)?;
9473 let v = v.into_int_value();
9474 let res = err!(self.builder.build_unsigned_int_to_float(
9475 v,
9476 self.intrinsics.f32_ty,
9477 ""
9478 ));
9479 self.state.push1(res);
9480 }
9481 Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
9482 let (v, i) = self.state.pop1_extra()?;
9483 let v = self.apply_pending_canonicalization(v, i)?;
9484 let v = v.into_int_value();
9485 let res = err!(self.builder.build_unsigned_int_to_float(
9486 v,
9487 self.intrinsics.f64_ty,
9488 ""
9489 ));
9490 self.state.push1(res);
9491 }
9492 Operator::F32x4ConvertI32x4S => {
9493 let v = self.state.pop1()?;
9494 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9495 .into_vector_value();
9496 let res = err!(self.builder.build_signed_int_to_float(
9497 v,
9498 self.intrinsics.f32x4_ty,
9499 ""
9500 ));
9501 let res = err!(
9502 self.builder
9503 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9504 );
9505 self.state.push1(res);
9506 }
9507 Operator::F32x4ConvertI32x4U => {
9508 let v = self.state.pop1()?;
9509 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9510 .into_vector_value();
9511 let res = err!(self.builder.build_unsigned_int_to_float(
9512 v,
9513 self.intrinsics.f32x4_ty,
9514 ""
9515 ));
9516 let res = err!(
9517 self.builder
9518 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9519 );
9520 self.state.push1(res);
9521 }
9522 Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
9523 let extend = match op {
9524 Operator::F64x2ConvertLowI32x4U => {
9525 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
9526 }
9527 Operator::F64x2ConvertLowI32x4S => {
9528 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
9529 }
9530 _ => unreachable!("Unhandled inner case"),
9531 };
9532 let (v, i) = self.state.pop1_extra()?;
9533 let (v, _) = self.v128_into_i32x4(v, i)?;
9534 let low = err!(self.builder.build_shuffle_vector(
9535 v,
9536 v.get_type().get_undef(),
9537 VectorType::const_vector(&[
9538 self.intrinsics.i32_consts[0],
9539 self.intrinsics.i32_consts[1],
9540 ]),
9541 "",
9542 ));
9543 let res = err!(extend(self, low));
9544 let res = err!(self.builder.build_signed_int_to_float(
9545 res,
9546 self.intrinsics.f64x2_ty,
9547 ""
9548 ));
9549 let res = err!(
9550 self.builder
9551 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9552 );
9553 self.state.push1(res);
9554 }
9555 Operator::F64x2PromoteLowF32x4 => {
9556 let (v, i) = self.state.pop1_extra()?;
9557 let (v, _) = self.v128_into_f32x4(v, i)?;
9558 let low = err!(self.builder.build_shuffle_vector(
9559 v,
9560 v.get_type().get_undef(),
9561 VectorType::const_vector(&[
9562 self.intrinsics.i32_consts[0],
9563 self.intrinsics.i32_consts[1],
9564 ]),
9565 "",
9566 ));
9567 let res = err!(
9568 self.builder
9569 .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9570 );
9571 let res = err!(
9572 self.builder
9573 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9574 );
9575 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9576 }
9577 Operator::F32x4DemoteF64x2Zero => {
9578 let (v, i) = self.state.pop1_extra()?;
9579 let (v, _) = self.v128_into_f64x2(v, i)?;
9580 let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9581 let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9582 let zeros = f32x2_ty.const_zero();
9583 let res = err!(self.builder.build_shuffle_vector(
9584 res,
9585 zeros,
9586 VectorType::const_vector(&[
9587 self.intrinsics.i32_consts[0],
9588 self.intrinsics.i32_consts[1],
9589 self.intrinsics.i32_consts[2],
9590 self.intrinsics.i32_consts[3],
9591 ]),
9592 "",
9593 ));
9594 let res = err!(
9595 self.builder
9596 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9597 );
9598 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9599 }
9600 Operator::I32ReinterpretF32 => {
9625 let (v, i) = self.state.pop1_extra()?;
9626 let v = self.apply_pending_canonicalization(v, i)?;
9627 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9628 self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9629 }
9630 Operator::I64ReinterpretF64 => {
9631 let (v, i) = self.state.pop1_extra()?;
9632 let v = self.apply_pending_canonicalization(v, i)?;
9633 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9634 self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9635 }
9636 Operator::F32ReinterpretI32 => {
9637 let (v, i) = self.state.pop1_extra()?;
9638 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9639 self.state.push1_extra(ret, i);
9640 }
9641 Operator::F64ReinterpretI64 => {
9642 let (v, i) = self.state.pop1_extra()?;
9643 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9644 self.state.push1_extra(ret, i);
9645 }
9646 _ => unreachable!(),
9647 }
9648 Ok(())
9649 }
9650
9651 fn translate_sign_extension_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9654 match op {
9655 Operator::I32Extend8S => {
9656 let value = self.state.pop1()?.into_int_value();
9657 let narrow_value = err!(self.builder.build_int_truncate(
9658 value,
9659 self.intrinsics.i8_ty,
9660 ""
9661 ));
9662 let extended_value = err!(self.builder.build_int_s_extend(
9663 narrow_value,
9664 self.intrinsics.i32_ty,
9665 ""
9666 ));
9667 self.state.push1(extended_value);
9668 }
9669 Operator::I32Extend16S => {
9670 let value = self.state.pop1()?.into_int_value();
9671 let narrow_value = err!(self.builder.build_int_truncate(
9672 value,
9673 self.intrinsics.i16_ty,
9674 ""
9675 ));
9676 let extended_value = err!(self.builder.build_int_s_extend(
9677 narrow_value,
9678 self.intrinsics.i32_ty,
9679 ""
9680 ));
9681 self.state.push1(extended_value);
9682 }
9683 Operator::I64Extend8S => {
9684 let value = self.state.pop1()?.into_int_value();
9685 let narrow_value = err!(self.builder.build_int_truncate(
9686 value,
9687 self.intrinsics.i8_ty,
9688 ""
9689 ));
9690 let extended_value = err!(self.builder.build_int_s_extend(
9691 narrow_value,
9692 self.intrinsics.i64_ty,
9693 ""
9694 ));
9695 self.state.push1(extended_value);
9696 }
9697 Operator::I64Extend16S => {
9698 let value = self.state.pop1()?.into_int_value();
9699 let narrow_value = err!(self.builder.build_int_truncate(
9700 value,
9701 self.intrinsics.i16_ty,
9702 ""
9703 ));
9704 let extended_value = err!(self.builder.build_int_s_extend(
9705 narrow_value,
9706 self.intrinsics.i64_ty,
9707 ""
9708 ));
9709 self.state.push1(extended_value);
9710 }
9711 Operator::I64Extend32S => {
9712 let value = self.state.pop1()?.into_int_value();
9713 let narrow_value = err!(self.builder.build_int_truncate(
9714 value,
9715 self.intrinsics.i32_ty,
9716 ""
9717 ));
9718 let extended_value = err!(self.builder.build_int_s_extend(
9719 narrow_value,
9720 self.intrinsics.i64_ty,
9721 ""
9722 ));
9723 self.state.push1(extended_value);
9724 }
9725 _ => unreachable!(),
9726 }
9727 Ok(())
9728 }
9729
9730 fn translate_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9733 let vmctx = &self.ctx.basic().into_pointer_value();
9734
9735 match op {
9736 Operator::I32Load { ref memarg } => {
9737 let offset = self.state.pop1()?.into_int_value();
9738 let result =
9739 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9740 self.state.push1(result);
9741 }
9742 Operator::I64Load { ref memarg } => {
9743 let offset = self.state.pop1()?.into_int_value();
9744 let result =
9745 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9746 self.state.push1(result);
9747 }
9748 Operator::F32Load { ref memarg } => {
9749 let offset = self.state.pop1()?.into_int_value();
9750 let result =
9751 self.build_annotated_load(self.intrinsics.f32_ty, offset, memarg, 1)?;
9752 self.state.push1(result);
9753 }
9754 Operator::F64Load { ref memarg } => {
9755 let offset = self.state.pop1()?.into_int_value();
9756 let result =
9757 self.build_annotated_load(self.intrinsics.f64_ty, offset, memarg, 1)?;
9758 self.state.push1(result);
9759 }
9760 Operator::V128Load { ref memarg } => {
9761 let offset = self.state.pop1()?.into_int_value();
9762 let result =
9763 self.build_annotated_load(self.intrinsics.i128_ty, offset, memarg, 1)?;
9764 self.state.push1(result);
9765 }
9766 Operator::V128Load8Lane { ref memarg, lane } => {
9767 let (v, i) = self.state.pop1_extra()?;
9768 let (v, _i) = self.v128_into_i8x16(v, i)?;
9769 let offset = self.state.pop1()?.into_int_value();
9770 let element =
9771 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9772 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9773 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9774 let res = err!(
9775 self.builder
9776 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9777 );
9778 self.state.push1(res);
9779 }
9780 Operator::V128Load16Lane { ref memarg, lane } => {
9781 let (v, i) = self.state.pop1_extra()?;
9782 let (v, i) = self.v128_into_i16x8(v, i)?;
9783 let offset = self.state.pop1()?.into_int_value();
9784 let element =
9785 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9786 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9787 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9788 let res = err!(
9789 self.builder
9790 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9791 );
9792 self.state.push1_extra(res, i);
9793 }
9794 Operator::V128Load32Lane { ref memarg, lane } => {
9795 let (v, i) = self.state.pop1_extra()?;
9796 let (v, i) = self.v128_into_i32x4(v, i)?;
9797 let offset = self.state.pop1()?.into_int_value();
9798 let element =
9799 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9800 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9801 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9802 let res = err!(
9803 self.builder
9804 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9805 );
9806 self.state.push1_extra(res, i);
9807 }
9808 Operator::V128Load64Lane { ref memarg, lane } => {
9809 let (v, i) = self.state.pop1_extra()?;
9810 let (v, i) = self.v128_into_i64x2(v, i)?;
9811 let offset = self.state.pop1()?.into_int_value();
9812 let element =
9813 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9814 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9815 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9816 let res = err!(
9817 self.builder
9818 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9819 );
9820 self.state.push1_extra(res, i);
9821 }
9822
9823 Operator::I32Store { ref memarg } => {
9824 let value = self.state.pop1()?;
9825 let offset = self.state.pop1()?.into_int_value();
9826 self.build_annotated_store(self.intrinsics.i32_ty, offset, value, memarg, 1)?;
9827 }
9828 Operator::I64Store { ref memarg } => {
9829 let value = self.state.pop1()?;
9830 let offset = self.state.pop1()?.into_int_value();
9831 self.build_annotated_store(self.intrinsics.i64_ty, offset, value, memarg, 1)?;
9832 }
9833 Operator::F32Store { ref memarg } => {
9834 let (v, i) = self.state.pop1_extra()?;
9835 let v = self.apply_pending_canonicalization(v, i)?;
9836 let offset = self.state.pop1()?.into_int_value();
9837 self.build_annotated_store(self.intrinsics.f32_ty, offset, v, memarg, 1)?;
9838 }
9839 Operator::F64Store { ref memarg } => {
9840 let (v, i) = self.state.pop1_extra()?;
9841 let v = self.apply_pending_canonicalization(v, i)?;
9842 let offset = self.state.pop1()?.into_int_value();
9843 self.build_annotated_store(self.intrinsics.f64_ty, offset, v, memarg, 1)?;
9844 }
9845 Operator::V128Store { ref memarg } => {
9846 let (v, i) = self.state.pop1_extra()?;
9847 let v = self.apply_pending_canonicalization(v, i)?;
9848 let offset = self.state.pop1()?.into_int_value();
9849 self.build_annotated_store(self.intrinsics.i128_ty, offset, v, memarg, 1)?;
9850 }
9851 Operator::V128Store8Lane { ref memarg, lane } => {
9852 let (v, i) = self.state.pop1_extra()?;
9853 let (v, _i) = self.v128_into_i8x16(v, i)?;
9854 let offset = self.state.pop1()?.into_int_value();
9855 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9856 let val = err!(self.builder.build_extract_element(v, idx, ""));
9857 self.build_annotated_store(self.intrinsics.i8_ty, offset, val, memarg, 1)?;
9858 }
9859 Operator::V128Store16Lane { ref memarg, lane } => {
9860 let (v, i) = self.state.pop1_extra()?;
9861 let (v, _i) = self.v128_into_i16x8(v, i)?;
9862 let offset = self.state.pop1()?.into_int_value();
9863 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9864 let val = err!(self.builder.build_extract_element(v, idx, ""));
9865 self.build_annotated_store(self.intrinsics.i16_ty, offset, val, memarg, 1)?;
9866 }
9867 Operator::V128Store32Lane { ref memarg, lane } => {
9868 let (v, i) = self.state.pop1_extra()?;
9869 let (v, _i) = self.v128_into_i32x4(v, i)?;
9870 let offset = self.state.pop1()?.into_int_value();
9871 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9872 let val = err!(self.builder.build_extract_element(v, idx, ""));
9873 self.build_annotated_store(self.intrinsics.i32_ty, offset, val, memarg, 1)?;
9874 }
9875 Operator::V128Store64Lane { ref memarg, lane } => {
9876 let (v, i) = self.state.pop1_extra()?;
9877 let (v, _i) = self.v128_into_i64x2(v, i)?;
9878 let offset = self.state.pop1()?.into_int_value();
9879 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9880 let val = err!(self.builder.build_extract_element(v, idx, ""));
9881 self.build_annotated_store(self.intrinsics.i64_ty, offset, val, memarg, 1)?;
9882 }
9883 Operator::I32Load8S { ref memarg } => {
9884 let offset = self.state.pop1()?.into_int_value();
9885 let narrow_result =
9886 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9887 let result = err!(self.builder.build_int_s_extend(
9888 narrow_result.into_int_value(),
9889 self.intrinsics.i32_ty,
9890 "",
9891 ));
9892 self.state.push1(result);
9893 }
9894 Operator::I32Load16S { ref memarg } => {
9895 let offset = self.state.pop1()?.into_int_value();
9896 let narrow_result =
9897 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9898 let result = err!(self.builder.build_int_s_extend(
9899 narrow_result.into_int_value(),
9900 self.intrinsics.i32_ty,
9901 "",
9902 ));
9903 self.state.push1(result);
9904 }
9905 Operator::I64Load8S { ref memarg } => {
9906 let offset = self.state.pop1()?.into_int_value();
9907 let narrow_result =
9908 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9909 let result = err!(self.builder.build_int_s_extend(
9910 narrow_result.into_int_value(),
9911 self.intrinsics.i64_ty,
9912 ""
9913 ));
9914 self.state.push1(result);
9915 }
9916 Operator::I64Load16S { ref memarg } => {
9917 let offset = self.state.pop1()?.into_int_value();
9918 let narrow_result =
9919 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9920 let result = err!(self.builder.build_int_s_extend(
9921 narrow_result.into_int_value(),
9922 self.intrinsics.i64_ty,
9923 ""
9924 ));
9925 self.state.push1(result);
9926 }
9927 Operator::I64Load32S { ref memarg } => {
9928 let offset = self.state.pop1()?.into_int_value();
9929 let narrow_result =
9930 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9931 let result = err!(self.builder.build_int_s_extend(
9932 narrow_result.into_int_value(),
9933 self.intrinsics.i64_ty,
9934 "",
9935 ));
9936 self.state.push1(result);
9937 }
9938
9939 Operator::I32Load8U { ref memarg } => {
9940 let offset = self.state.pop1()?.into_int_value();
9941 let narrow_result =
9942 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9943 let result = err!(self.builder.build_int_z_extend(
9944 narrow_result.into_int_value(),
9945 self.intrinsics.i32_ty,
9946 "",
9947 ));
9948 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9949 }
9950 Operator::I32Load16U { ref memarg } => {
9951 let offset = self.state.pop1()?.into_int_value();
9952 let narrow_result =
9953 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9954 let result = err!(self.builder.build_int_z_extend(
9955 narrow_result.into_int_value(),
9956 self.intrinsics.i32_ty,
9957 "",
9958 ));
9959 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9960 }
9961 Operator::I64Load8U { ref memarg } => {
9962 let offset = self.state.pop1()?.into_int_value();
9963 let narrow_result =
9964 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9965 let result = err!(self.builder.build_int_z_extend(
9966 narrow_result.into_int_value(),
9967 self.intrinsics.i64_ty,
9968 "",
9969 ));
9970 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9971 }
9972 Operator::I64Load16U { ref memarg } => {
9973 let offset = self.state.pop1()?.into_int_value();
9974 let narrow_result =
9975 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9976 let result = err!(self.builder.build_int_z_extend(
9977 narrow_result.into_int_value(),
9978 self.intrinsics.i64_ty,
9979 "",
9980 ));
9981 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9982 }
9983 Operator::I64Load32U { ref memarg } => {
9984 let offset = self.state.pop1()?.into_int_value();
9985 let narrow_result =
9986 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9987 let result = err!(self.builder.build_int_z_extend(
9988 narrow_result.into_int_value(),
9989 self.intrinsics.i64_ty,
9990 "",
9991 ));
9992 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9993 }
9994
9995 Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9996 let value = self.state.pop1()?.into_int_value();
9997 let offset = self.state.pop1()?.into_int_value();
9998 let narrow_value = err!(self.builder.build_int_truncate(
9999 value,
10000 self.intrinsics.i8_ty,
10001 ""
10002 ));
10003 self.build_annotated_store(
10004 self.intrinsics.i8_ty,
10005 offset,
10006 narrow_value.into(),
10007 memarg,
10008 1,
10009 )?;
10010 }
10011 Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
10012 let value = self.state.pop1()?.into_int_value();
10013 let offset = self.state.pop1()?.into_int_value();
10014 let narrow_value = err!(self.builder.build_int_truncate(
10015 value,
10016 self.intrinsics.i16_ty,
10017 ""
10018 ));
10019 self.build_annotated_store(
10020 self.intrinsics.i16_ty,
10021 offset,
10022 narrow_value.into(),
10023 memarg,
10024 1,
10025 )?;
10026 }
10027 Operator::I64Store32 { ref memarg } => {
10028 let value = self.state.pop1()?.into_int_value();
10029 let offset = self.state.pop1()?.into_int_value();
10030 let narrow_value = err!(self.builder.build_int_truncate(
10031 value,
10032 self.intrinsics.i32_ty,
10033 ""
10034 ));
10035 self.build_annotated_store(
10036 self.intrinsics.i32_ty,
10037 offset,
10038 narrow_value.into(),
10039 memarg,
10040 1,
10041 )?;
10042 }
10043 Operator::I8x16Neg => {
10044 let (v, i) = self.state.pop1_extra()?;
10045 let (v, _) = self.v128_into_i8x16(v, i)?;
10046 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10047 let res = err!(
10048 self.builder
10049 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10050 );
10051 self.state.push1(res);
10052 }
10053 Operator::I16x8Neg => {
10054 let (v, i) = self.state.pop1_extra()?;
10055 let (v, _) = self.v128_into_i16x8(v, i)?;
10056 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10057 let res = err!(
10058 self.builder
10059 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10060 );
10061 self.state.push1(res);
10062 }
10063 Operator::I32x4Neg => {
10064 let (v, i) = self.state.pop1_extra()?;
10065 let (v, _) = self.v128_into_i32x4(v, i)?;
10066 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10067 let res = err!(
10068 self.builder
10069 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10070 );
10071 self.state.push1(res);
10072 }
10073 Operator::I64x2Neg => {
10074 let (v, i) = self.state.pop1_extra()?;
10075 let (v, _) = self.v128_into_i64x2(v, i)?;
10076 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10077 let res = err!(
10078 self.builder
10079 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10080 );
10081 self.state.push1(res);
10082 }
10083 Operator::V128Not => {
10084 let (v, i) = self.state.pop1_extra()?;
10085 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10086 let res = err!(self.builder.build_not(v, ""));
10087 self.state.push1(res);
10088 }
10089 Operator::V128AnyTrue => {
10090 let v = self.state.pop1()?.into_int_value();
10093 let res = err!(self.builder.build_int_compare(
10094 IntPredicate::NE,
10095 v,
10096 v.get_type().const_zero(),
10097 "",
10098 ));
10099 let res = err!(
10100 self.builder
10101 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10102 );
10103 self.state.push1_extra(
10104 res,
10105 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10106 );
10107 }
10108 Operator::I8x16AllTrue
10109 | Operator::I16x8AllTrue
10110 | Operator::I32x4AllTrue
10111 | Operator::I64x2AllTrue => {
10112 let vec_ty = match op {
10113 Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10114 Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10115 Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10116 Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10117 _ => unreachable!(),
10118 };
10119 let (v, i) = self.state.pop1_extra()?;
10120 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10121 let lane_int_ty = self
10122 .context
10123 .custom_width_int_type(NonZero::new(vec_ty.get_size()).unwrap())
10124 .unwrap();
10125 let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10126 let mask = err!(self.builder.build_int_compare(
10127 IntPredicate::NE,
10128 vec,
10129 vec_ty.const_zero(),
10130 "mask",
10131 ));
10132 let cmask =
10133 err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10134 let res = err!(self.builder.build_int_compare(
10135 IntPredicate::EQ,
10136 cmask,
10137 lane_int_ty.const_int(u64::MAX, true),
10138 "",
10139 ));
10140 let res = err!(
10141 self.builder
10142 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10143 );
10144 self.state.push1_extra(
10145 res,
10146 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10147 );
10148 }
10149 Operator::I8x16ExtractLaneS { lane } => {
10150 let (v, i) = self.state.pop1_extra()?;
10151 let (v, _) = self.v128_into_i8x16(v, i)?;
10152 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10153 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10154 let res = err!(
10155 self.builder
10156 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10157 );
10158 self.state.push1(res);
10159 }
10160 Operator::I8x16ExtractLaneU { lane } => {
10161 let (v, i) = self.state.pop1_extra()?;
10162 let (v, _) = self.v128_into_i8x16(v, i)?;
10163 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10164 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10165 let res = err!(
10166 self.builder
10167 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10168 );
10169 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10170 }
10171 Operator::I16x8ExtractLaneS { lane } => {
10172 let (v, i) = self.state.pop1_extra()?;
10173 let (v, _) = self.v128_into_i16x8(v, i)?;
10174 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10175 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10176 let res = err!(
10177 self.builder
10178 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10179 );
10180 self.state.push1(res);
10181 }
10182 Operator::I16x8ExtractLaneU { lane } => {
10183 let (v, i) = self.state.pop1_extra()?;
10184 let (v, _) = self.v128_into_i16x8(v, i)?;
10185 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10186 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10187 let res = err!(
10188 self.builder
10189 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10190 );
10191 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10192 }
10193 Operator::I32x4ExtractLane { lane } => {
10194 let (v, i) = self.state.pop1_extra()?;
10195 let (v, i) = self.v128_into_i32x4(v, i)?;
10196 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10197 let res = err!(self.builder.build_extract_element(v, idx, ""));
10198 self.state.push1_extra(res, i);
10199 }
10200 Operator::I64x2ExtractLane { lane } => {
10201 let (v, i) = self.state.pop1_extra()?;
10202 let (v, i) = self.v128_into_i64x2(v, i)?;
10203 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10204 let res = err!(self.builder.build_extract_element(v, idx, ""));
10205 self.state.push1_extra(res, i);
10206 }
10207 Operator::F32x4ExtractLane { lane } => {
10208 let (v, i) = self.state.pop1_extra()?;
10209 let (v, i) = self.v128_into_f32x4(v, i)?;
10210 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10211 let res = err!(self.builder.build_extract_element(v, idx, ""));
10212 self.state.push1_extra(res, i);
10213 }
10214 Operator::F64x2ExtractLane { lane } => {
10215 let (v, i) = self.state.pop1_extra()?;
10216 let (v, i) = self.v128_into_f64x2(v, i)?;
10217 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10218 let res = err!(self.builder.build_extract_element(v, idx, ""));
10219 self.state.push1_extra(res, i);
10220 }
10221 Operator::I8x16ReplaceLane { lane } => {
10222 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10223 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10224 let v2 = v2.into_int_value();
10225 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10226 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10227 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10228 let res = err!(
10229 self.builder
10230 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10231 );
10232 self.state.push1(res);
10233 }
10234 Operator::I16x8ReplaceLane { lane } => {
10235 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10236 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10237 let v2 = v2.into_int_value();
10238 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10239 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10240 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10241 let res = err!(
10242 self.builder
10243 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10244 );
10245 self.state.push1(res);
10246 }
10247 Operator::I32x4ReplaceLane { lane } => {
10248 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10249 let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10250 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10251 let v2 = v2.into_int_value();
10252 let i2 = i2.strip_pending();
10253 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10254 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10255 let res = err!(
10256 self.builder
10257 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10258 );
10259 self.state
10260 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10261 }
10262 Operator::I64x2ReplaceLane { lane } => {
10263 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10264 let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10265 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10266 let v2 = v2.into_int_value();
10267 let i2 = i2.strip_pending();
10268 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10269 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10270 let res = err!(
10271 self.builder
10272 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10273 );
10274 self.state
10275 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10276 }
10277 Operator::F32x4ReplaceLane { lane } => {
10278 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10279 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10280 let push_pending_f32_nan_to_result =
10281 i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10282 let (v1, v2) = if !push_pending_f32_nan_to_result {
10283 (
10284 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10285 .into_vector_value(),
10286 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10287 .into_float_value(),
10288 )
10289 } else {
10290 (v1, v2.into_float_value())
10291 };
10292 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10293 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10294 let res = err!(
10295 self.builder
10296 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10297 );
10298 let info = if push_pending_f32_nan_to_result {
10299 ExtraInfo::pending_f32_nan()
10300 } else {
10301 (i1.strip_pending() & i2.strip_pending())?
10302 };
10303 self.state.push1_extra(res, info);
10304 }
10305 Operator::F64x2ReplaceLane { lane } => {
10306 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10307 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10308 let push_pending_f64_nan_to_result =
10309 i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10310 let (v1, v2) = if !push_pending_f64_nan_to_result {
10311 (
10312 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10313 .into_vector_value(),
10314 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10315 .into_float_value(),
10316 )
10317 } else {
10318 (v1, v2.into_float_value())
10319 };
10320 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10321 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10322 let res = err!(
10323 self.builder
10324 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10325 );
10326 let info = if push_pending_f64_nan_to_result {
10327 ExtraInfo::pending_f64_nan()
10328 } else {
10329 (i1.strip_pending() & i2.strip_pending())?
10330 };
10331 self.state.push1_extra(res, info);
10332 }
10333 Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10334 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10335 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10336 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10337
10338 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10339 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10340 let res = self
10341 .build_call_with_param_attributes(
10342 self.intrinsics.x86_64.pshufb128,
10343 &[v1.into(), v2.into()],
10344 "",
10345 )?
10346 .try_as_basic_value()
10347 .unwrap_basic();
10348 let res = err!(
10349 self.builder
10350 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10351 );
10352 self.state.push1(res);
10353 }
10354 Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10355 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10356 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10357 let v1 = err!(
10358 self.builder
10359 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10360 )
10361 .into_vector_value();
10362 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10363 let v2 = err!(
10364 self.builder
10365 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10366 )
10367 .into_vector_value();
10368 let lanes = self.intrinsics.i8_ty.const_int(16, false);
10369 let lanes =
10370 self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10371 let mut res = self.intrinsics.i8x16_ty.get_undef();
10372 let idx_out_of_range = err!(self.builder.build_int_compare(
10373 IntPredicate::UGE,
10374 v2,
10375 lanes,
10376 "idx_out_of_range",
10377 ));
10378 let idx_clamped = err!(self.builder.build_select(
10379 idx_out_of_range,
10380 self.intrinsics.i8x16_ty.const_zero(),
10381 v2,
10382 "idx_clamped",
10383 ))
10384 .into_vector_value();
10385 for i in 0..16 {
10386 let idx = err!(self.builder.build_extract_element(
10387 idx_clamped,
10388 self.intrinsics.i32_ty.const_int(i, false),
10389 "idx",
10390 ))
10391 .into_int_value();
10392 let replace_with_zero = err!(self.builder.build_extract_element(
10393 idx_out_of_range,
10394 self.intrinsics.i32_ty.const_int(i, false),
10395 "replace_with_zero",
10396 ))
10397 .into_int_value();
10398 let elem =
10399 err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10400 let elem_or_zero = err!(self.builder.build_select(
10401 replace_with_zero,
10402 self.intrinsics.i8_zero,
10403 elem,
10404 "elem_or_zero",
10405 ));
10406 res = err!(self.builder.build_insert_element(
10407 res,
10408 elem_or_zero,
10409 self.intrinsics.i32_ty.const_int(i, false),
10410 "",
10411 ));
10412 }
10413 let res = err!(
10414 self.builder
10415 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10416 );
10417 self.state.push1(res);
10418 }
10419 Operator::I8x16Shuffle { lanes } => {
10420 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10421 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10422 let v1 = err!(
10423 self.builder
10424 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10425 )
10426 .into_vector_value();
10427 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10428 let v2 = err!(
10429 self.builder
10430 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10431 )
10432 .into_vector_value();
10433 let mask = VectorType::const_vector(
10434 lanes
10435 .iter()
10436 .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10437 .collect::<Vec<IntValue>>()
10438 .as_slice(),
10439 );
10440 let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10441 let res = err!(
10442 self.builder
10443 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10444 );
10445 self.state.push1(res);
10446 }
10447 Operator::V128Load8x8S { ref memarg } => {
10448 let offset = self.state.pop1()?.into_int_value();
10449 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10450 let v = err!(
10451 self.builder
10452 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10453 )
10454 .into_vector_value();
10455 let res = err!(
10456 self.builder
10457 .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10458 );
10459 let res = err!(
10460 self.builder
10461 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10462 );
10463 self.state.push1(res);
10464 }
10465 Operator::V128Load8x8U { ref memarg } => {
10466 let offset = self.state.pop1()?.into_int_value();
10467 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10468 let v = err!(
10469 self.builder
10470 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10471 )
10472 .into_vector_value();
10473 let res = err!(
10474 self.builder
10475 .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10476 );
10477 let res = err!(
10478 self.builder
10479 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10480 );
10481 self.state.push1(res);
10482 }
10483 Operator::V128Load16x4S { ref memarg } => {
10484 let offset = self.state.pop1()?.into_int_value();
10485 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10486 let v = err!(self.builder.build_bit_cast(
10487 v,
10488 self.intrinsics.i16_ty.vec_type(4),
10489 ""
10490 ))
10491 .into_vector_value();
10492 let res = err!(
10493 self.builder
10494 .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10495 );
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::V128Load16x4U { ref memarg } => {
10503 let offset = self.state.pop1()?.into_int_value();
10504 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10505 let v = err!(self.builder.build_bit_cast(
10506 v,
10507 self.intrinsics.i16_ty.vec_type(4),
10508 ""
10509 ))
10510 .into_vector_value();
10511 let res = err!(
10512 self.builder
10513 .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10514 );
10515 let res = err!(
10516 self.builder
10517 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10518 );
10519 self.state.push1(res);
10520 }
10521 Operator::V128Load32x2S { ref memarg } => {
10522 let offset = self.state.pop1()?.into_int_value();
10523 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10524 let v = err!(self.builder.build_bit_cast(
10525 v,
10526 self.intrinsics.i32_ty.vec_type(2),
10527 ""
10528 ))
10529 .into_vector_value();
10530 let res = err!(
10531 self.builder
10532 .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10533 );
10534 let res = err!(
10535 self.builder
10536 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10537 );
10538 self.state.push1(res);
10539 }
10540 Operator::V128Load32x2U { ref memarg } => {
10541 let offset = self.state.pop1()?.into_int_value();
10542 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10543 let v = err!(self.builder.build_bit_cast(
10544 v,
10545 self.intrinsics.i32_ty.vec_type(2),
10546 ""
10547 ))
10548 .into_vector_value();
10549 let res = err!(
10550 self.builder
10551 .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10552 );
10553 let res = err!(
10554 self.builder
10555 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10556 );
10557 self.state.push1(res);
10558 }
10559 Operator::V128Load32Zero { ref memarg } => {
10560 let offset = self.state.pop1()?.into_int_value();
10561 let element =
10562 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10563 let res = err!(self.builder.build_int_z_extend(
10564 element.into_int_value(),
10565 self.intrinsics.i128_ty,
10566 "",
10567 ));
10568 self.state.push1(res);
10569 }
10570 Operator::V128Load64Zero { ref memarg } => {
10571 let offset = self.state.pop1()?.into_int_value();
10572 let element =
10573 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10574 let res = err!(self.builder.build_int_z_extend(
10575 element.into_int_value(),
10576 self.intrinsics.i128_ty,
10577 "",
10578 ));
10579 self.state.push1(res);
10580 }
10581 Operator::V128Load8Splat { ref memarg } => {
10582 let offset = self.state.pop1()?.into_int_value();
10583 let element =
10584 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10585 let res = self.splat_vector(element, self.intrinsics.i8x16_ty)?;
10586 let res = err!(
10587 self.builder
10588 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10589 );
10590 self.state.push1(res);
10591 }
10592 Operator::V128Load16Splat { ref memarg } => {
10593 let offset = self.state.pop1()?.into_int_value();
10594 let element =
10595 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10596 let res = self.splat_vector(element, self.intrinsics.i16x8_ty)?;
10597 let res = err!(
10598 self.builder
10599 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10600 );
10601 self.state.push1(res);
10602 }
10603 Operator::V128Load32Splat { ref memarg } => {
10604 let offset = self.state.pop1()?.into_int_value();
10605 let element =
10606 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10607 let res = self.splat_vector(element, self.intrinsics.i32x4_ty)?;
10608 let res = err!(
10609 self.builder
10610 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10611 );
10612 self.state.push1(res);
10613 }
10614 Operator::V128Load64Splat { ref memarg } => {
10615 let offset = self.state.pop1()?.into_int_value();
10616 let element =
10617 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10618 let res = self.splat_vector(element, self.intrinsics.i64x2_ty)?;
10619 let res = err!(
10620 self.builder
10621 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10622 );
10623 self.state.push1(res);
10624 }
10625
10626 Operator::MemoryGrow { mem } => {
10627 let memory_index = MemoryIndex::from_u32(mem);
10628 let delta = self.state.pop1()?;
10629 let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
10630 let grow = err!(self.builder.build_indirect_call(
10631 self.intrinsics.memory_grow_ty,
10632 grow_fn_ptr,
10633 &[
10634 vmctx.as_basic_value_enum().into(),
10635 delta.into(),
10636 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10637 ],
10638 "",
10639 ));
10640 self.state.push1(grow.try_as_basic_value().unwrap_basic());
10641 }
10642 Operator::MemorySize { mem } => {
10643 let memory_index = MemoryIndex::from_u32(mem);
10644 let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
10645 let size = err!(self.builder.build_indirect_call(
10646 self.intrinsics.memory_size_ty,
10647 size_fn_ptr,
10648 &[
10649 vmctx.as_basic_value_enum().into(),
10650 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10651 ],
10652 "",
10653 ));
10654 self.state.push1(size.try_as_basic_value().unwrap_basic());
10656 }
10657 Operator::MemoryInit { data_index, mem } => {
10658 let (dest, src, len) = self.state.pop3()?;
10659 let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
10660 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10661 self.build_call_with_param_attributes(
10662 self.intrinsics.memory_init,
10663 &[
10664 vmctx.as_basic_value_enum().into(),
10665 mem.into(),
10666 segment.into(),
10667 dest.into(),
10668 src.into(),
10669 len.into(),
10670 ],
10671 "",
10672 )?;
10673 }
10674 Operator::DataDrop { data_index } => {
10675 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10676 self.build_call_with_param_attributes(
10677 self.intrinsics.data_drop,
10678 &[vmctx.as_basic_value_enum().into(), segment.into()],
10679 "",
10680 )?;
10681 }
10682 Operator::MemoryCopy { dst_mem, src_mem } => {
10683 let _dst = dst_mem;
10685 let (memory_copy, src) = if let Some(local_memory_index) = self
10686 .wasm_module
10687 .local_memory_index(MemoryIndex::from_u32(src_mem))
10688 {
10689 (self.intrinsics.memory_copy, local_memory_index.as_u32())
10690 } else {
10691 (self.intrinsics.imported_memory_copy, src_mem)
10692 };
10693
10694 let (dest_pos, src_pos, len) = self.state.pop3()?;
10695 let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
10696 self.build_call_with_param_attributes(
10697 memory_copy,
10698 &[
10699 vmctx.as_basic_value_enum().into(),
10700 src_index.into(),
10701 dest_pos.into(),
10702 src_pos.into(),
10703 len.into(),
10704 ],
10705 "",
10706 )?;
10707 }
10708 Operator::MemoryFill { mem } => {
10709 let (memory_fill, mem) = if let Some(local_memory_index) = self
10710 .wasm_module
10711 .local_memory_index(MemoryIndex::from_u32(mem))
10712 {
10713 (self.intrinsics.memory_fill, local_memory_index.as_u32())
10714 } else {
10715 (self.intrinsics.imported_memory_fill, mem)
10716 };
10717
10718 let (dst, val, len) = self.state.pop3()?;
10719 let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
10720 self.build_call_with_param_attributes(
10721 memory_fill,
10722 &[
10723 vmctx.as_basic_value_enum().into(),
10724 mem_index.into(),
10725 dst.into(),
10726 val.into(),
10727 len.into(),
10728 ],
10729 "",
10730 )?;
10731 }
10732 _ => unreachable!(),
10733 }
10734 Ok(())
10735 }
10736
10737 fn translate_atomic_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
10739 let vmctx = &self.ctx.basic().into_pointer_value();
10740
10741 match op {
10742 Operator::AtomicFence => {
10743 }
10751 Operator::I32AtomicLoad { ref memarg } => {
10752 let offset = self.state.pop1()?.into_int_value();
10753 let result = self.build_annotated_atomic_load(
10754 self.intrinsics.i32_ty,
10755 self.intrinsics.i32_ty,
10756 offset,
10757 memarg,
10758 )?;
10759 self.state.push1(result);
10760 }
10761 Operator::I64AtomicLoad { ref memarg } => {
10762 let offset = self.state.pop1()?.into_int_value();
10763 let result = self.build_annotated_atomic_load(
10764 self.intrinsics.i64_ty,
10765 self.intrinsics.i64_ty,
10766 offset,
10767 memarg,
10768 )?;
10769 self.state.push1(result);
10770 }
10771 Operator::I32AtomicLoad8U { ref memarg } => {
10772 let offset = self.state.pop1()?.into_int_value();
10773 let result = self.build_annotated_atomic_load(
10774 self.intrinsics.i32_ty,
10775 self.intrinsics.i8_ty,
10776 offset,
10777 memarg,
10778 )?;
10779 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10780 }
10781 Operator::I32AtomicLoad16U { ref memarg } => {
10782 let offset = self.state.pop1()?.into_int_value();
10783 let result = self.build_annotated_atomic_load(
10784 self.intrinsics.i32_ty,
10785 self.intrinsics.i16_ty,
10786 offset,
10787 memarg,
10788 )?;
10789 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10790 }
10791 Operator::I64AtomicLoad8U { ref memarg } => {
10792 let offset = self.state.pop1()?.into_int_value();
10793 let result = self.build_annotated_atomic_load(
10794 self.intrinsics.i64_ty,
10795 self.intrinsics.i8_ty,
10796 offset,
10797 memarg,
10798 )?;
10799 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10800 }
10801 Operator::I64AtomicLoad16U { ref memarg } => {
10802 let offset = self.state.pop1()?.into_int_value();
10803 let result = self.build_annotated_atomic_load(
10804 self.intrinsics.i64_ty,
10805 self.intrinsics.i16_ty,
10806 offset,
10807 memarg,
10808 )?;
10809 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10810 }
10811 Operator::I64AtomicLoad32U { ref memarg } => {
10812 let offset = self.state.pop1()?.into_int_value();
10813 let result = self.build_annotated_atomic_load(
10814 self.intrinsics.i64_ty,
10815 self.intrinsics.i32_ty,
10816 offset,
10817 memarg,
10818 )?;
10819 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10820 }
10821 Operator::I32AtomicStore { ref memarg } => {
10822 let value = self.state.pop1()?.into_int_value();
10823 let offset = self.state.pop1()?.into_int_value();
10824 self.build_annotated_atomic_store(
10825 self.intrinsics.i32_ty,
10826 self.intrinsics.i32_ty,
10827 offset,
10828 value,
10829 memarg,
10830 )?;
10831 }
10832 Operator::I64AtomicStore { ref memarg } => {
10833 let value = self.state.pop1()?.into_int_value();
10834 let offset = self.state.pop1()?.into_int_value();
10835 self.build_annotated_atomic_store(
10836 self.intrinsics.i64_ty,
10837 self.intrinsics.i64_ty,
10838 offset,
10839 value,
10840 memarg,
10841 )?;
10842 }
10843 Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10844 let value = self.state.pop1()?.into_int_value();
10845 let offset = self.state.pop1()?.into_int_value();
10846 self.build_annotated_atomic_store(
10847 value.get_type(),
10848 self.intrinsics.i8_ty,
10849 offset,
10850 value,
10851 memarg,
10852 )?;
10853 }
10854 Operator::I32AtomicStore16 { ref memarg }
10855 | Operator::I64AtomicStore16 { ref memarg } => {
10856 let value = self.state.pop1()?.into_int_value();
10857 let offset = self.state.pop1()?.into_int_value();
10858 self.build_annotated_atomic_store(
10859 value.get_type(),
10860 self.intrinsics.i16_ty,
10861 offset,
10862 value,
10863 memarg,
10864 )?;
10865 }
10866 Operator::I64AtomicStore32 { ref memarg } => {
10867 let value = self.state.pop1()?.into_int_value();
10868 let offset = self.state.pop1()?.into_int_value();
10869 self.build_annotated_atomic_store(
10870 self.intrinsics.i64_ty,
10871 self.intrinsics.i32_ty,
10872 offset,
10873 value,
10874 memarg,
10875 )?;
10876 }
10877 Operator::I32AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10878 self.intrinsics.i32_ty,
10879 self.intrinsics.i8_ty,
10880 memarg,
10881 AtomicRMWBinOp::Add,
10882 Some(ExtraInfo::arithmetic_f32()),
10883 )?,
10884 Operator::I32AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10885 self.intrinsics.i32_ty,
10886 self.intrinsics.i16_ty,
10887 memarg,
10888 AtomicRMWBinOp::Add,
10889 Some(ExtraInfo::arithmetic_f32()),
10890 )?,
10891 Operator::I32AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10892 self.intrinsics.i32_ty,
10893 self.intrinsics.i32_ty,
10894 memarg,
10895 AtomicRMWBinOp::Add,
10896 None,
10897 )?,
10898 Operator::I64AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10899 self.intrinsics.i64_ty,
10900 self.intrinsics.i8_ty,
10901 memarg,
10902 AtomicRMWBinOp::Add,
10903 Some(ExtraInfo::arithmetic_f64()),
10904 )?,
10905 Operator::I64AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10906 self.intrinsics.i64_ty,
10907 self.intrinsics.i16_ty,
10908 memarg,
10909 AtomicRMWBinOp::Add,
10910 Some(ExtraInfo::arithmetic_f64()),
10911 )?,
10912 Operator::I64AtomicRmw32AddU { ref memarg } => self.translate_atomic_rmw(
10913 self.intrinsics.i64_ty,
10914 self.intrinsics.i32_ty,
10915 memarg,
10916 AtomicRMWBinOp::Add,
10917 Some(ExtraInfo::arithmetic_f64()),
10918 )?,
10919 Operator::I64AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10920 self.intrinsics.i64_ty,
10921 self.intrinsics.i64_ty,
10922 memarg,
10923 AtomicRMWBinOp::Add,
10924 None,
10925 )?,
10926 Operator::I32AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10927 self.intrinsics.i32_ty,
10928 self.intrinsics.i8_ty,
10929 memarg,
10930 AtomicRMWBinOp::Sub,
10931 Some(ExtraInfo::arithmetic_f32()),
10932 )?,
10933 Operator::I32AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10934 self.intrinsics.i32_ty,
10935 self.intrinsics.i16_ty,
10936 memarg,
10937 AtomicRMWBinOp::Sub,
10938 Some(ExtraInfo::arithmetic_f32()),
10939 )?,
10940 Operator::I32AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10941 self.intrinsics.i32_ty,
10942 self.intrinsics.i32_ty,
10943 memarg,
10944 AtomicRMWBinOp::Sub,
10945 None,
10946 )?,
10947 Operator::I64AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10948 self.intrinsics.i64_ty,
10949 self.intrinsics.i8_ty,
10950 memarg,
10951 AtomicRMWBinOp::Sub,
10952 Some(ExtraInfo::arithmetic_f32()),
10953 )?,
10954 Operator::I64AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10955 self.intrinsics.i64_ty,
10956 self.intrinsics.i16_ty,
10957 memarg,
10958 AtomicRMWBinOp::Sub,
10959 Some(ExtraInfo::arithmetic_f64()),
10960 )?,
10961 Operator::I64AtomicRmw32SubU { ref memarg } => self.translate_atomic_rmw(
10962 self.intrinsics.i64_ty,
10963 self.intrinsics.i32_ty,
10964 memarg,
10965 AtomicRMWBinOp::Sub,
10966 Some(ExtraInfo::arithmetic_f64()),
10967 )?,
10968 Operator::I64AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10969 self.intrinsics.i64_ty,
10970 self.intrinsics.i64_ty,
10971 memarg,
10972 AtomicRMWBinOp::Sub,
10973 None,
10974 )?,
10975 Operator::I32AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10976 self.intrinsics.i32_ty,
10977 self.intrinsics.i8_ty,
10978 memarg,
10979 AtomicRMWBinOp::And,
10980 Some(ExtraInfo::arithmetic_f32()),
10981 )?,
10982 Operator::I32AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
10983 self.intrinsics.i32_ty,
10984 self.intrinsics.i16_ty,
10985 memarg,
10986 AtomicRMWBinOp::And,
10987 Some(ExtraInfo::arithmetic_f32()),
10988 )?,
10989 Operator::I32AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
10990 self.intrinsics.i32_ty,
10991 self.intrinsics.i32_ty,
10992 memarg,
10993 AtomicRMWBinOp::And,
10994 None,
10995 )?,
10996 Operator::I64AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10997 self.intrinsics.i64_ty,
10998 self.intrinsics.i8_ty,
10999 memarg,
11000 AtomicRMWBinOp::And,
11001 Some(ExtraInfo::arithmetic_f64()),
11002 )?,
11003 Operator::I64AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
11004 self.intrinsics.i64_ty,
11005 self.intrinsics.i16_ty,
11006 memarg,
11007 AtomicRMWBinOp::And,
11008 Some(ExtraInfo::arithmetic_f64()),
11009 )?,
11010 Operator::I64AtomicRmw32AndU { ref memarg } => self.translate_atomic_rmw(
11011 self.intrinsics.i64_ty,
11012 self.intrinsics.i32_ty,
11013 memarg,
11014 AtomicRMWBinOp::And,
11015 Some(ExtraInfo::arithmetic_f64()),
11016 )?,
11017 Operator::I64AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
11018 self.intrinsics.i64_ty,
11019 self.intrinsics.i64_ty,
11020 memarg,
11021 AtomicRMWBinOp::And,
11022 None,
11023 )?,
11024 Operator::I32AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11025 self.intrinsics.i32_ty,
11026 self.intrinsics.i8_ty,
11027 memarg,
11028 AtomicRMWBinOp::Or,
11029 Some(ExtraInfo::arithmetic_f32()),
11030 )?,
11031 Operator::I32AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11032 self.intrinsics.i32_ty,
11033 self.intrinsics.i16_ty,
11034 memarg,
11035 AtomicRMWBinOp::Or,
11036 Some(ExtraInfo::arithmetic_f32()),
11037 )?,
11038 Operator::I32AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11039 self.intrinsics.i32_ty,
11040 self.intrinsics.i32_ty,
11041 memarg,
11042 AtomicRMWBinOp::Or,
11043 Some(ExtraInfo::arithmetic_f32()),
11044 )?,
11045 Operator::I64AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11046 self.intrinsics.i64_ty,
11047 self.intrinsics.i8_ty,
11048 memarg,
11049 AtomicRMWBinOp::Or,
11050 Some(ExtraInfo::arithmetic_f64()),
11051 )?,
11052 Operator::I64AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11053 self.intrinsics.i64_ty,
11054 self.intrinsics.i16_ty,
11055 memarg,
11056 AtomicRMWBinOp::Or,
11057 Some(ExtraInfo::arithmetic_f64()),
11058 )?,
11059 Operator::I64AtomicRmw32OrU { ref memarg } => self.translate_atomic_rmw(
11060 self.intrinsics.i64_ty,
11061 self.intrinsics.i32_ty,
11062 memarg,
11063 AtomicRMWBinOp::Or,
11064 Some(ExtraInfo::arithmetic_f64()),
11065 )?,
11066 Operator::I64AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11067 self.intrinsics.i64_ty,
11068 self.intrinsics.i64_ty,
11069 memarg,
11070 AtomicRMWBinOp::Or,
11071 None,
11072 )?,
11073 Operator::I32AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11074 self.intrinsics.i32_ty,
11075 self.intrinsics.i8_ty,
11076 memarg,
11077 AtomicRMWBinOp::Xor,
11078 Some(ExtraInfo::arithmetic_f32()),
11079 )?,
11080 Operator::I32AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11081 self.intrinsics.i32_ty,
11082 self.intrinsics.i16_ty,
11083 memarg,
11084 AtomicRMWBinOp::Xor,
11085 Some(ExtraInfo::arithmetic_f32()),
11086 )?,
11087 Operator::I32AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11088 self.intrinsics.i32_ty,
11089 self.intrinsics.i32_ty,
11090 memarg,
11091 AtomicRMWBinOp::Xor,
11092 None,
11093 )?,
11094 Operator::I64AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11095 self.intrinsics.i64_ty,
11096 self.intrinsics.i8_ty,
11097 memarg,
11098 AtomicRMWBinOp::Xor,
11099 Some(ExtraInfo::arithmetic_f64()),
11100 )?,
11101 Operator::I64AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11102 self.intrinsics.i64_ty,
11103 self.intrinsics.i16_ty,
11104 memarg,
11105 AtomicRMWBinOp::Xor,
11106 Some(ExtraInfo::arithmetic_f64()),
11107 )?,
11108 Operator::I64AtomicRmw32XorU { ref memarg } => self.translate_atomic_rmw(
11109 self.intrinsics.i64_ty,
11110 self.intrinsics.i32_ty,
11111 memarg,
11112 AtomicRMWBinOp::Xor,
11113 Some(ExtraInfo::arithmetic_f64()),
11114 )?,
11115 Operator::I64AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11116 self.intrinsics.i64_ty,
11117 self.intrinsics.i64_ty,
11118 memarg,
11119 AtomicRMWBinOp::Xor,
11120 None,
11121 )?,
11122 Operator::I32AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11123 self.intrinsics.i32_ty,
11124 self.intrinsics.i8_ty,
11125 memarg,
11126 AtomicRMWBinOp::Xchg,
11127 Some(ExtraInfo::arithmetic_f32()),
11128 )?,
11129 Operator::I32AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11130 self.intrinsics.i32_ty,
11131 self.intrinsics.i16_ty,
11132 memarg,
11133 AtomicRMWBinOp::Xchg,
11134 Some(ExtraInfo::arithmetic_f32()),
11135 )?,
11136 Operator::I32AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11137 self.intrinsics.i32_ty,
11138 self.intrinsics.i32_ty,
11139 memarg,
11140 AtomicRMWBinOp::Xchg,
11141 None,
11142 )?,
11143 Operator::I64AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11144 self.intrinsics.i64_ty,
11145 self.intrinsics.i8_ty,
11146 memarg,
11147 AtomicRMWBinOp::Xchg,
11148 Some(ExtraInfo::arithmetic_f64()),
11149 )?,
11150 Operator::I64AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11151 self.intrinsics.i64_ty,
11152 self.intrinsics.i16_ty,
11153 memarg,
11154 AtomicRMWBinOp::Xchg,
11155 Some(ExtraInfo::arithmetic_f64()),
11156 )?,
11157 Operator::I64AtomicRmw32XchgU { ref memarg } => self.translate_atomic_rmw(
11158 self.intrinsics.i64_ty,
11159 self.intrinsics.i32_ty,
11160 memarg,
11161 AtomicRMWBinOp::Xchg,
11162 Some(ExtraInfo::arithmetic_f64()),
11163 )?,
11164 Operator::I64AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11165 self.intrinsics.i64_ty,
11166 self.intrinsics.i64_ty,
11167 memarg,
11168 AtomicRMWBinOp::Xchg,
11169 None,
11170 )?,
11171 Operator::I32AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11172 self.intrinsics.i32_ty,
11173 self.intrinsics.i8_ty,
11174 memarg,
11175 Some(ExtraInfo::arithmetic_f32()),
11176 )?,
11177 Operator::I32AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11178 self.intrinsics.i32_ty,
11179 self.intrinsics.i16_ty,
11180 memarg,
11181 Some(ExtraInfo::arithmetic_f32()),
11182 )?,
11183 Operator::I32AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11184 self.intrinsics.i32_ty,
11185 self.intrinsics.i32_ty,
11186 memarg,
11187 None,
11188 )?,
11189 Operator::I64AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11190 self.intrinsics.i64_ty,
11191 self.intrinsics.i8_ty,
11192 memarg,
11193 Some(ExtraInfo::arithmetic_f64()),
11194 )?,
11195 Operator::I64AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11196 self.intrinsics.i64_ty,
11197 self.intrinsics.i16_ty,
11198 memarg,
11199 Some(ExtraInfo::arithmetic_f64()),
11200 )?,
11201 Operator::I64AtomicRmw32CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11202 self.intrinsics.i64_ty,
11203 self.intrinsics.i32_ty,
11204 memarg,
11205 Some(ExtraInfo::arithmetic_f64()),
11206 )?,
11207 Operator::I64AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11208 self.intrinsics.i64_ty,
11209 self.intrinsics.i64_ty,
11210 memarg,
11211 None,
11212 )?,
11213 Operator::MemoryAtomicWait32 { memarg } => {
11214 let memory_index = MemoryIndex::from_u32(memarg.memory);
11215 let (dst, val, timeout) = self.state.pop3()?;
11216 let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
11217 let ret = err!(
11218 self.builder.build_indirect_call(
11219 self.intrinsics.memory_wait32_ty,
11220 wait32_fn_ptr,
11221 &[
11222 vmctx.as_basic_value_enum().into(),
11223 self.intrinsics
11224 .i32_ty
11225 .const_int(memarg.memory as u64, false)
11226 .into(),
11227 dst.into(),
11228 val.into(),
11229 timeout.into(),
11230 ],
11231 "",
11232 )
11233 );
11234 self.state.push1(ret.try_as_basic_value().unwrap_basic());
11235 }
11236 Operator::MemoryAtomicWait64 { memarg } => {
11237 let memory_index = MemoryIndex::from_u32(memarg.memory);
11238 let (dst, val, timeout) = self.state.pop3()?;
11239 let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
11240 let ret = err!(
11241 self.builder.build_indirect_call(
11242 self.intrinsics.memory_wait64_ty,
11243 wait64_fn_ptr,
11244 &[
11245 vmctx.as_basic_value_enum().into(),
11246 self.intrinsics
11247 .i32_ty
11248 .const_int(memarg.memory as u64, false)
11249 .into(),
11250 dst.into(),
11251 val.into(),
11252 timeout.into(),
11253 ],
11254 "",
11255 )
11256 );
11257 self.state.push1(ret.try_as_basic_value().unwrap_basic());
11258 }
11259 Operator::MemoryAtomicNotify { memarg } => {
11260 let memory_index = MemoryIndex::from_u32(memarg.memory);
11261 let (dst, count) = self.state.pop2()?;
11262 let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
11263 let cnt = err!(
11264 self.builder.build_indirect_call(
11265 self.intrinsics.memory_notify_ty,
11266 notify_fn_ptr,
11267 &[
11268 vmctx.as_basic_value_enum().into(),
11269 self.intrinsics
11270 .i32_ty
11271 .const_int(memarg.memory as u64, false)
11272 .into(),
11273 dst.into(),
11274 count.into(),
11275 ],
11276 "",
11277 )
11278 );
11279 self.state.push1(cnt.try_as_basic_value().unwrap_basic());
11280 }
11281 _ => unreachable!(),
11282 }
11283 Ok(())
11284 }
11285
11286 fn translate_reference_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11289 match op {
11290 Operator::RefNull { hty } => {
11291 let ty = err!(wpheaptype_to_type(hty));
11292 let ty = type_to_llvm(self.intrinsics, ty)?;
11293 self.state.push1(ty.const_zero());
11294 }
11295 Operator::RefIsNull => {
11296 let value = self.state.pop1()?;
11297 let is_null = match value {
11298 BasicValueEnum::IntValue(value) => err!(self.builder.build_int_compare(
11299 IntPredicate::EQ,
11300 value,
11301 value.get_type().const_zero(),
11302 "",
11303 )),
11304 BasicValueEnum::PointerValue(value) => {
11305 err!(self.builder.build_is_null(value, ""))
11306 }
11307 _ => unreachable!("ref.is_null only accepts reference types"),
11308 };
11309 let is_null = err!(self.builder.build_int_z_extend(
11310 is_null,
11311 self.intrinsics.i32_ty,
11312 ""
11313 ));
11314 self.state.push1(is_null);
11315 }
11316 Operator::RefFunc { function_index } => {
11317 let index = self
11318 .intrinsics
11319 .i32_ty
11320 .const_int(function_index.into(), false);
11321 let value = self
11322 .build_call_with_param_attributes(
11323 self.intrinsics.func_ref,
11324 &[self.ctx.basic().into(), index.into()],
11325 "",
11326 )?
11327 .try_as_basic_value()
11328 .unwrap_basic();
11329 self.state.push1(value);
11330 }
11331 _ => unreachable!(),
11332 }
11333 Ok(())
11334 }
11335
11336 fn translate_table_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11338 match op {
11339 Operator::TableGet { table } => {
11340 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11341 let elem = self.state.pop1()?;
11342 let table_get = if self
11343 .wasm_module
11344 .local_table_index(TableIndex::from_u32(table))
11345 .is_some()
11346 {
11347 self.intrinsics.table_get
11348 } else {
11349 self.intrinsics.imported_table_get
11350 };
11351 let value = self
11352 .build_call_with_param_attributes(
11353 table_get,
11354 &[self.ctx.basic().into(), table_index.into(), elem.into()],
11355 "",
11356 )?
11357 .try_as_basic_value()
11358 .unwrap_basic();
11359 let value = err!(
11360 self.builder.build_bit_cast(
11361 value,
11362 type_to_llvm(
11363 self.intrinsics,
11364 self.wasm_module
11365 .tables
11366 .get(TableIndex::from_u32(table))
11367 .unwrap()
11368 .ty,
11369 )?,
11370 "",
11371 )
11372 );
11373 self.state.push1(value);
11374 }
11375 Operator::TableSet { table } => {
11376 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11377 let (elem, value) = self.state.pop2()?;
11378 let value = err!(
11379 self.builder
11380 .build_bit_cast(value, self.intrinsics.ptr_ty, "")
11381 );
11382 let table_set = if self
11383 .wasm_module
11384 .local_table_index(TableIndex::from_u32(table))
11385 .is_some()
11386 {
11387 self.intrinsics.table_set
11388 } else {
11389 self.intrinsics.imported_table_set
11390 };
11391 self.build_call_with_param_attributes(
11392 table_set,
11393 &[
11394 self.ctx.basic().into(),
11395 table_index.into(),
11396 elem.into(),
11397 value.into(),
11398 ],
11399 "",
11400 )?;
11401 }
11402 Operator::TableCopy {
11403 dst_table,
11404 src_table,
11405 } => {
11406 let (dst, src, len) = self.state.pop3()?;
11407 let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
11408 let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
11409 self.build_call_with_param_attributes(
11410 self.intrinsics.table_copy,
11411 &[
11412 self.ctx.basic().into(),
11413 dst_table.into(),
11414 src_table.into(),
11415 dst.into(),
11416 src.into(),
11417 len.into(),
11418 ],
11419 "",
11420 )?;
11421 }
11422 Operator::TableInit { elem_index, table } => {
11423 let (dst, src, len) = self.state.pop3()?;
11424 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11425 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11426 self.build_call_with_param_attributes(
11427 self.intrinsics.table_init,
11428 &[
11429 self.ctx.basic().into(),
11430 table.into(),
11431 segment.into(),
11432 dst.into(),
11433 src.into(),
11434 len.into(),
11435 ],
11436 "",
11437 )?;
11438 }
11439 Operator::ElemDrop { elem_index } => {
11440 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11441 self.build_call_with_param_attributes(
11442 self.intrinsics.elem_drop,
11443 &[self.ctx.basic().into(), segment.into()],
11444 "",
11445 )?;
11446 }
11447 Operator::TableFill { table } => {
11448 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11449 let (start, elem, len) = self.state.pop3()?;
11450 let elem = err!(
11451 self.builder
11452 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11453 );
11454 self.build_call_with_param_attributes(
11455 self.intrinsics.table_fill,
11456 &[
11457 self.ctx.basic().into(),
11458 table.into(),
11459 start.into(),
11460 elem.into(),
11461 len.into(),
11462 ],
11463 "",
11464 )?;
11465 }
11466 Operator::TableGrow { table } => {
11467 let (elem, delta) = self.state.pop2()?;
11468 let elem = err!(
11469 self.builder
11470 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11471 );
11472 let (table_grow, table_index) = if let Some(local_table_index) = self
11473 .wasm_module
11474 .local_table_index(TableIndex::from_u32(table))
11475 {
11476 (self.intrinsics.table_grow, local_table_index.as_u32())
11477 } else {
11478 (self.intrinsics.imported_table_grow, table)
11479 };
11480 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11481 let size = self
11482 .build_call_with_param_attributes(
11483 table_grow,
11484 &[
11485 self.ctx.basic().into(),
11486 elem.into(),
11487 delta.into(),
11488 table_index.into(),
11489 ],
11490 "",
11491 )?
11492 .try_as_basic_value()
11493 .unwrap_basic();
11494 self.state.push1(size);
11495 }
11496 Operator::TableSize { table } => {
11497 let (table_size, table_index) = if let Some(local_table_index) = self
11498 .wasm_module
11499 .local_table_index(TableIndex::from_u32(table))
11500 {
11501 (self.intrinsics.table_size, local_table_index.as_u32())
11502 } else {
11503 (self.intrinsics.imported_table_size, table)
11504 };
11505 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11506 let size = self
11507 .build_call_with_param_attributes(
11508 table_size,
11509 &[self.ctx.basic().into(), table_index.into()],
11510 "",
11511 )?
11512 .try_as_basic_value()
11513 .unwrap_basic();
11514 self.state.push1(size);
11515 }
11516 _ => unreachable!(),
11517 }
11518 Ok(())
11519 }
11520
11521 fn translate_eh_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11524 match op {
11525 Operator::TryTable { try_table } => {
11526 let current_block = self
11527 .builder
11528 .get_insert_block()
11529 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11530
11531 self.builder.position_at_end(current_block);
11532
11533 let end_block = self.context.append_basic_block(self.function, "try_end");
11534
11535 let end_phis = {
11536 self.builder.position_at_end(end_block);
11537
11538 let phis = self
11539 .module_translation
11540 .blocktype_params_results(&try_table.ty)?
11541 .1
11542 .iter()
11543 .map(|&wp_ty| {
11544 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
11545 type_to_llvm(self.intrinsics, wasm_ty)
11546 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
11547 })
11548 })
11549 .collect::<Result<_, _>>()?;
11550
11551 self.builder.position_at_end(current_block);
11552 phis
11553 };
11554
11555 let catches: Vec<_> = try_table
11559 .catches
11560 .into_iter()
11561 .unique_by(|v| match v {
11562 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
11563 Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
11564 })
11565 .collect();
11566
11567 let null = self.intrinsics.ptr_ty.const_zero();
11569
11570 let mut catch_tag_values = vec![];
11571 let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
11572 .iter()
11573 .map(|catch| match catch {
11574 Catch::All { .. } | Catch::AllRef { .. } => {
11575 catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
11576 Ok(null.into())
11577 }
11578 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
11579 catch_tag_values.push(*tag);
11580 Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
11581 }
11582 })
11583 .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
11584
11585 let mut outer_catch_blocks = vec![];
11589 for outer_landingpad in self.state.landingpads.iter().rev() {
11590 for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
11591 if !catch_tag_values.contains(tag) {
11592 catch_tag_values.push(*tag);
11593 lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
11594 null.into()
11595 } else {
11596 *self.tags_cache.get(&(*tag as i32)).expect(
11597 "If a previous try_table encountered a tag, \
11598 it should be in the cache",
11599 )
11600 });
11601 outer_catch_blocks.push(*catch_info);
11602 }
11603 }
11604 }
11605
11606 let mut maybe_lpad_block = None;
11610 let mut catch_blocks = vec![];
11611 if !lpad_clauses.is_empty() {
11612 let lpad_block = self.context.append_basic_block(self.function, "catch");
11613 let catch_all_block =
11614 self.context.append_basic_block(self.function, "catch_all");
11615 let catch_specific_block = self
11616 .context
11617 .append_basic_block(self.function, "catch_specific");
11618 let catch_end_block =
11619 self.context.append_basic_block(self.function, "catch_end");
11620 let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
11621
11622 self.builder.position_at_end(lpad_block);
11623
11624 let res = err!(self.builder.build_landing_pad(
11625 self.intrinsics.lpad_exception_ty,
11626 self.intrinsics.personality,
11627 &lpad_clauses,
11628 false,
11629 "exc_struct",
11630 ));
11631
11632 let res = res.into_struct_value();
11633
11634 let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
11635 let pre_selector =
11636 err!(self.builder.build_extract_value(res, 1, "pre_selector"));
11637
11638 let pre_selector_is_zero = err!(self.builder.build_int_compare(
11641 IntPredicate::EQ,
11642 pre_selector.into_int_value(),
11643 self.intrinsics.i32_zero,
11644 "pre_selector_is_zero"
11645 ));
11646 err!(self.builder.build_conditional_branch(
11647 pre_selector_is_zero,
11648 catch_all_block,
11649 catch_specific_block
11650 ));
11651
11652 self.builder.position_at_end(catch_all_block);
11653 err!(self.builder.build_unconditional_branch(catch_end_block));
11654
11655 self.builder.position_at_end(catch_specific_block);
11656 let selector_value = self.build_call_with_param_attributes(
11657 self.intrinsics.personality2,
11658 &[self.ctx.basic().into(), uw_exc.into()],
11659 "selector",
11660 )?;
11661 err!(self.builder.build_unconditional_branch(catch_end_block));
11662
11663 self.builder.position_at_end(catch_end_block);
11664 let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
11665 selector.add_incoming(&[
11666 (
11667 &self
11668 .intrinsics
11669 .i32_ty
11670 .const_int(CATCH_ALL_TAG_VALUE as u64, false),
11671 catch_all_block,
11672 ),
11673 (
11674 &selector_value
11675 .try_as_basic_value()
11676 .unwrap_basic()
11677 .into_int_value(),
11678 catch_specific_block,
11679 ),
11680 ]);
11681
11682 let uw_exc = uw_exc.into_pointer_value();
11727 let exnref = self.build_call_with_param_attributes(
11728 self.intrinsics.exception_into_exnref,
11729 &[uw_exc.into()],
11730 "exnref",
11731 )?;
11732
11733 let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
11734 let selector = selector.as_basic_value().into_int_value();
11735
11736 for catch in catches.iter() {
11737 match catch {
11738 Catch::All { label } => {
11739 let b = self
11740 .context
11741 .append_basic_block(self.function, "catch_all_clause");
11742 self.builder.position_at_end(b);
11743 let frame = self.state.frame_at_depth(*label)?;
11744
11745 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11746
11747 self.builder.position_at_end(catch_end_block);
11748 catch_blocks.push((b, None));
11749 }
11750 Catch::One { tag, label } => {
11751 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11752 let signature = &self.wasm_module.signatures[tag_idx];
11753 let params = signature.params();
11754
11755 let b = self.context.append_basic_block(
11756 self.function,
11757 format!("catch_one_clause_{tag}").as_str(),
11758 );
11759 self.builder.position_at_end(b);
11760
11761 let exnref_phi = err!(
11762 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11763 );
11764 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11765
11766 let exn_payload_ptr = err!(self.builder.build_direct_call(
11768 self.intrinsics.read_exnref,
11769 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11770 "exn_ptr",
11771 ));
11772 let exn_payload_ptr = exn_payload_ptr
11773 .try_as_basic_value()
11774 .unwrap_basic()
11775 .into_pointer_value();
11776
11777 let values = params
11779 .iter()
11780 .enumerate()
11781 .map(|(i, v)| {
11782 let name = format!("value_{i}");
11783 let ptr = err!(unsafe {
11784 self.builder.build_gep(
11785 self.intrinsics.i128_ty,
11786 exn_payload_ptr,
11787 &[self
11788 .intrinsics
11789 .i32_ty
11790 .const_int(i as u64, false)],
11791 format!("{name}_ptr").as_str(),
11792 )
11793 });
11794 err_nt!(self.builder.build_load(
11795 type_to_llvm(self.intrinsics, *v)?,
11796 ptr,
11797 &name,
11798 ))
11799 })
11800 .collect::<Result<Vec<_>, CompileError>>()?;
11801
11802 let frame = self.state.frame_at_depth(*label)?;
11803
11804 for (phi, value) in frame.phis().iter().zip(values.iter()) {
11805 phi.add_incoming(&[(value, b)])
11806 }
11807
11808 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11809
11810 self.builder.position_at_end(catch_end_block);
11811 catch_blocks.push((b, Some(exnref_phi)));
11812 }
11813 Catch::OneRef { label, tag } => {
11814 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11815 let signature = &self.wasm_module.signatures[tag_idx];
11816 let params = signature.params();
11817
11818 let b = self.context.append_basic_block(
11819 self.function,
11820 format!("catch_one_ref_clause_{tag}").as_str(),
11821 );
11822 self.builder.position_at_end(b);
11823
11824 let exnref_phi = err!(
11825 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11826 );
11827 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11828
11829 let exn_payload_ptr = err!(self.builder.build_direct_call(
11831 self.intrinsics.read_exnref,
11832 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11833 "exn_ptr",
11834 ));
11835 let exn_payload_ptr = exn_payload_ptr
11836 .try_as_basic_value()
11837 .unwrap_basic()
11838 .into_pointer_value();
11839
11840 let mut values = params
11842 .iter()
11843 .enumerate()
11844 .map(|(i, v)| {
11845 let name = format!("value_{i}");
11846 let ptr = err!(unsafe {
11847 self.builder.build_gep(
11848 self.intrinsics.i128_ty,
11849 exn_payload_ptr,
11850 &[self
11851 .intrinsics
11852 .i32_ty
11853 .const_int(i as u64, false)],
11854 format!("{name}_ptr").as_str(),
11855 )
11856 });
11857 err_nt!(self.builder.build_load(
11858 type_to_llvm(self.intrinsics, *v)?,
11859 ptr,
11860 &name,
11861 ))
11862 })
11863 .collect::<Result<Vec<_>, CompileError>>()?;
11864
11865 values.push(exnref_phi.as_basic_value());
11866
11867 let frame = self.state.frame_at_depth(*label)?;
11868
11869 for (phi, value) in frame.phis().iter().zip(values.iter()) {
11870 phi.add_incoming(&[(value, b)])
11871 }
11872
11873 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11874
11875 self.builder.position_at_end(catch_end_block);
11876 catch_blocks.push((b, Some(exnref_phi)));
11877 }
11878 Catch::AllRef { label } => {
11879 let b = self
11880 .context
11881 .append_basic_block(self.function, "catch_all_ref_clause");
11882 self.builder.position_at_end(b);
11883
11884 let exnref_phi = err!(
11885 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11886 );
11887 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11888
11889 let frame = self.state.frame_at_depth(*label)?;
11890
11891 let phis = frame.phis();
11892
11893 assert_eq!(phis.len(), 1);
11894 phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
11895
11896 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11897
11898 self.builder.position_at_end(catch_end_block);
11899 catch_blocks.push((b, Some(exnref_phi)));
11900 }
11901 }
11902 }
11903
11904 for catch_info in &outer_catch_blocks {
11905 if let Some(phi) = catch_info.exnref_phi {
11906 phi.add_incoming(&[(&exnref, catch_end_block)]);
11907 }
11908 }
11909
11910 err!(
11911 self.builder.build_switch(
11912 selector,
11913 rethrow_block,
11914 catch_blocks
11915 .iter()
11916 .enumerate()
11917 .map(|(i, v)| (
11918 self.intrinsics
11919 .i32_ty
11920 .const_int(catch_tag_values[i] as _, false),
11921 v.0
11922 ))
11923 .chain(outer_catch_blocks.iter().map(|catch_info| (
11924 self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
11925 catch_info.catch_block
11926 )))
11927 .collect::<Vec<_>>()
11928 .as_slice()
11929 )
11930 );
11931
11932 self.builder.position_at_end(rethrow_block);
11936
11937 self.build_call_with_param_attributes(
11938 self.intrinsics.throw,
11939 &[self.ctx.basic().into(), exnref.into()],
11940 "rethrow",
11941 )?;
11942 err!(self.builder.build_unreachable());
11944
11945 maybe_lpad_block = Some(lpad_block);
11946 }
11947
11948 self.builder.position_at_end(current_block);
11950
11951 let catch_tags_and_blocks = catch_tag_values
11954 .into_iter()
11955 .zip(catch_blocks)
11956 .map(|(tag, (block, exnref_phi))| TagCatchInfo {
11957 tag,
11958 catch_block: block,
11959 exnref_phi,
11960 })
11961 .collect::<Vec<_>>();
11962 self.state.push_landingpad(
11963 maybe_lpad_block,
11964 end_block,
11965 end_phis,
11966 &catch_tags_and_blocks,
11967 self.module_translation
11968 .blocktype_params_results(&try_table.ty)?
11969 .0
11970 .len(),
11971 );
11972 }
11973 Operator::Throw { tag_index } => {
11974 let current_block = self
11975 .builder
11976 .get_insert_block()
11977 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11978
11979 let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
11980 let signature = &self.wasm_module.signatures[sig_index];
11981 let params = signature.params();
11982 let values = self.state.popn_save_extra(params.len())?;
11983
11984 values.iter().enumerate().try_for_each(|(i, (v, _))| {
11985 let t = type_to_llvm(self.intrinsics, params[i])?;
11986 if t != v.get_type() {
11987 return Err(CompileError::Codegen(format!(
11988 "Incompatible types: {:?} != {:?}",
11989 t,
11990 v.get_type()
11991 )));
11992 }
11993
11994 Ok(())
11995 })?;
11996
11997 let exnref = err!(
11999 self.builder.build_direct_call(
12000 self.intrinsics.alloc_exception,
12001 &[
12002 self.ctx.basic().into(),
12003 self.intrinsics
12004 .i32_ty
12005 .const_int(tag_index as _, false)
12006 .into()
12007 ],
12008 "exnref",
12009 )
12010 );
12011 let exnref = exnref.try_as_basic_value().unwrap_basic();
12012
12013 let exn_payload_ptr = err!(self.builder.build_direct_call(
12014 self.intrinsics.read_exnref,
12015 &[self.ctx.basic().into(), exnref.into()],
12016 "exn_ptr",
12017 ));
12018 let exn_payload_ptr = exn_payload_ptr
12019 .try_as_basic_value()
12020 .unwrap_basic()
12021 .into_pointer_value();
12022
12023 for (i, value) in values.into_iter().enumerate() {
12024 let ptr = err!(unsafe {
12025 self.builder.build_gep(
12026 self.intrinsics.i128_ty,
12027 exn_payload_ptr,
12028 &[self.intrinsics.i32_ty.const_int(i as u64, false)],
12029 format!("value_{i}_ptr").as_str(),
12030 )
12031 });
12032 err!(self.builder.build_store(ptr, value.0));
12033 }
12034
12035 if let Some(pad) = self.state.get_innermost_landingpad() {
12036 let unreachable_block = self
12037 .context
12038 .append_basic_block(self.function, "_throw_unreachable");
12039
12040 err!(self.builder.build_invoke(
12041 self.intrinsics.throw,
12042 &[self.ctx.basic(), exnref],
12043 unreachable_block,
12044 pad,
12045 "throw",
12046 ));
12047
12048 self.builder.position_at_end(unreachable_block);
12049 err!(self.builder.build_unreachable());
12051
12052 self.builder.position_at_end(current_block);
12053 } else {
12054 self.build_call_with_param_attributes(
12055 self.intrinsics.throw,
12056 &[self.ctx.basic().into(), exnref.into()],
12057 "throw",
12058 )?;
12059 err!(self.builder.build_unreachable());
12061 }
12062
12063 self.state.reachable = false;
12064 }
12065 Operator::ThrowRef => {
12066 let current_block = self
12067 .builder
12068 .get_insert_block()
12069 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
12070
12071 let exnref = self.state.pop1()?;
12072
12073 if let Some(pad) = self.state.get_innermost_landingpad() {
12074 let unreachable_block = self
12075 .context
12076 .append_basic_block(self.function, "_rethrow_unreachable");
12077
12078 err!(self.builder.build_invoke(
12079 self.intrinsics.throw,
12080 &[self.ctx.basic(), exnref],
12081 unreachable_block,
12082 pad,
12083 "throw",
12084 ));
12085
12086 self.builder.position_at_end(unreachable_block);
12087 err!(self.builder.build_unreachable());
12089
12090 self.builder.position_at_end(current_block);
12091 } else {
12092 self.build_call_with_param_attributes(
12093 self.intrinsics.throw,
12094 &[self.ctx.basic().into(), exnref.into()],
12095 "throw",
12096 )?;
12097 err!(self.builder.build_unreachable());
12099 }
12100
12101 self.state.reachable = false;
12102 }
12103 _ => unreachable!(),
12104 }
12105 Ok(())
12106 }
12107
12108 fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
12109 if !self.state.reachable {
12112 match op {
12113 Operator::Block { blockty: _ }
12114 | Operator::Loop { blockty: _ }
12115 | Operator::If { blockty: _ }
12116 | Operator::TryTable { .. } => {
12117 self.unreachable_depth += 1;
12118 return Ok(());
12119 }
12120 Operator::Else => {
12121 if self.unreachable_depth != 0 {
12122 return Ok(());
12123 }
12124 }
12125 Operator::End => {
12126 if self.unreachable_depth != 0 {
12127 self.unreachable_depth -= 1;
12128 return Ok(());
12129 }
12130 }
12131 _ => {
12132 return Ok(());
12133 }
12134 }
12135 }
12136
12137 match op {
12138 Operator::Block { .. }
12139 | Operator::Loop { .. }
12140 | Operator::Br { .. }
12141 | Operator::BrIf { .. }
12142 | Operator::BrTable { .. }
12143 | Operator::If { .. }
12144 | Operator::Else
12145 | Operator::End
12146 | Operator::Return
12147 | Operator::Unreachable => {
12148 self.translate_control_flow_operator(op)?;
12149 }
12150 Operator::Nop
12151 | Operator::Drop
12152 | Operator::I32Const { .. }
12153 | Operator::I64Const { .. }
12154 | Operator::F32Const { .. }
12155 | Operator::F64Const { .. }
12156 | Operator::V128Const { .. }
12157 | Operator::I8x16Splat
12158 | Operator::I16x8Splat
12159 | Operator::I32x4Splat
12160 | Operator::I64x2Splat
12161 | Operator::F32x4Splat
12162 | Operator::F64x2Splat
12163 | Operator::LocalGet { .. }
12164 | Operator::LocalSet { .. }
12165 | Operator::LocalTee { .. }
12166 | Operator::GlobalGet { .. }
12167 | Operator::GlobalSet { .. }
12168 | Operator::Call { .. }
12169 | Operator::ReturnCall { .. }
12170 | Operator::CallIndirect { .. }
12171 | Operator::ReturnCallIndirect { .. }
12172 | Operator::TypedSelect { .. }
12173 | Operator::Select => {
12174 self.translate_basic_operator(op)?;
12175 }
12176 Operator::I32Add
12177 | Operator::I64Add
12178 | Operator::I8x16Add
12179 | Operator::I16x8Add
12180 | Operator::I16x8ExtAddPairwiseI8x16S
12181 | Operator::I16x8ExtAddPairwiseI8x16U
12182 | Operator::I32x4Add
12183 | Operator::I32x4ExtAddPairwiseI16x8S
12184 | Operator::I32x4ExtAddPairwiseI16x8U
12185 | Operator::I64x2Add
12186 | Operator::I8x16AddSatS
12187 | Operator::I16x8AddSatS
12188 | Operator::I8x16AddSatU
12189 | Operator::I16x8AddSatU
12190 | Operator::I32Sub
12191 | Operator::I64Sub
12192 | Operator::I8x16Sub
12193 | Operator::I16x8Sub
12194 | Operator::I32x4Sub
12195 | Operator::I64x2Sub
12196 | Operator::I8x16SubSatS
12197 | Operator::I16x8SubSatS
12198 | Operator::I8x16SubSatU
12199 | Operator::I16x8SubSatU
12200 | Operator::I32Mul
12201 | Operator::I64Mul
12202 | Operator::I16x8Mul
12203 | Operator::I32x4Mul
12204 | Operator::I64x2Mul
12205 | Operator::I16x8RelaxedQ15mulrS
12206 | Operator::I16x8Q15MulrSatS
12207 | Operator::I16x8ExtMulLowI8x16S
12208 | Operator::I16x8ExtMulLowI8x16U
12209 | Operator::I16x8ExtMulHighI8x16S
12210 | Operator::I16x8ExtMulHighI8x16U
12211 | Operator::I32x4ExtMulLowI16x8S
12212 | Operator::I32x4ExtMulLowI16x8U
12213 | Operator::I32x4ExtMulHighI16x8S
12214 | Operator::I32x4ExtMulHighI16x8U
12215 | Operator::I64x2ExtMulLowI32x4S
12216 | Operator::I64x2ExtMulLowI32x4U
12217 | Operator::I64x2ExtMulHighI32x4S
12218 | Operator::I64x2ExtMulHighI32x4U
12219 | Operator::I32x4DotI16x8S
12220 | Operator::I16x8RelaxedDotI8x16I7x16S
12221 | Operator::I32x4RelaxedDotI8x16I7x16AddS
12222 | Operator::I32DivS
12223 | Operator::I64DivS
12224 | Operator::I32DivU
12225 | Operator::I64DivU
12226 | Operator::I32RemS
12227 | Operator::I64RemS
12228 | Operator::I32RemU
12229 | Operator::I64RemU
12230 | Operator::I32And
12231 | Operator::I64And
12232 | Operator::V128And
12233 | Operator::I32Or
12234 | Operator::I64Or
12235 | Operator::V128Or
12236 | Operator::I32Xor
12237 | Operator::I64Xor
12238 | Operator::V128Xor
12239 | Operator::V128AndNot
12240 | Operator::I8x16RelaxedLaneselect
12241 | Operator::I16x8RelaxedLaneselect
12242 | Operator::I32x4RelaxedLaneselect
12243 | Operator::I64x2RelaxedLaneselect
12244 | Operator::V128Bitselect
12245 | Operator::I8x16Bitmask
12246 | Operator::I16x8Bitmask
12247 | Operator::I32x4Bitmask
12248 | Operator::I64x2Bitmask
12249 | Operator::I32Shl
12250 | Operator::I64Shl
12251 | Operator::I8x16Shl
12252 | Operator::I16x8Shl
12253 | Operator::I32x4Shl
12254 | Operator::I64x2Shl
12255 | Operator::I32ShrS
12256 | Operator::I64ShrS
12257 | Operator::I8x16ShrS
12258 | Operator::I16x8ShrS
12259 | Operator::I32x4ShrS
12260 | Operator::I64x2ShrS
12261 | Operator::I32ShrU
12262 | Operator::I64ShrU
12263 | Operator::I8x16ShrU
12264 | Operator::I16x8ShrU
12265 | Operator::I32x4ShrU
12266 | Operator::I64x2ShrU
12267 | Operator::I32Rotl
12268 | Operator::I64Rotl
12269 | Operator::I32Rotr
12270 | Operator::I64Rotr
12271 | Operator::I32Clz
12272 | Operator::I64Clz
12273 | Operator::I32Ctz
12274 | Operator::I64Ctz
12275 | Operator::I8x16Popcnt
12276 | Operator::I32Popcnt
12277 | Operator::I64Popcnt
12278 | Operator::I32Eqz
12279 | Operator::I64Eqz
12280 | Operator::I8x16Abs
12281 | Operator::I16x8Abs
12282 | Operator::I32x4Abs
12283 | Operator::I64x2Abs
12284 | Operator::I8x16MinS
12285 | Operator::I8x16MinU
12286 | Operator::I8x16MaxS
12287 | Operator::I8x16MaxU
12288 | Operator::I16x8MinS
12289 | Operator::I16x8MinU
12290 | Operator::I16x8MaxS
12291 | Operator::I16x8MaxU
12292 | Operator::I32x4MinS
12293 | Operator::I32x4MinU
12294 | Operator::I32x4MaxS
12295 | Operator::I32x4MaxU
12296 | Operator::I8x16AvgrU
12297 | Operator::I16x8AvgrU
12298 | Operator::I64Add128
12299 | Operator::I64Sub128
12300 | Operator::I64MulWideS
12301 | Operator::I64MulWideU => self.translate_integer_arithmetic_operator(op)?,
12302 Operator::F32Add
12303 | Operator::F64Add
12304 | Operator::F32x4Add
12305 | Operator::F64x2Add
12306 | Operator::F32Sub
12307 | Operator::F64Sub
12308 | Operator::F32x4Sub
12309 | Operator::F64x2Sub
12310 | Operator::F32Mul
12311 | Operator::F64Mul
12312 | Operator::F32x4Mul
12313 | Operator::F32x4RelaxedMadd
12314 | Operator::F32x4RelaxedNmadd
12315 | Operator::F64x2Mul
12316 | Operator::F64x2RelaxedMadd
12317 | Operator::F64x2RelaxedNmadd
12318 | Operator::F32Div
12319 | Operator::F64Div
12320 | Operator::F32x4Div
12321 | Operator::F64x2Div
12322 | Operator::F32Sqrt
12323 | Operator::F64Sqrt
12324 | Operator::F32x4Sqrt
12325 | Operator::F64x2Sqrt
12326 | Operator::F32Min
12327 | Operator::F64Min
12328 | Operator::F32x4RelaxedMin
12329 | Operator::F32x4Min
12330 | Operator::F32x4PMin
12331 | Operator::F64x2RelaxedMin
12332 | Operator::F64x2Min
12333 | Operator::F64x2PMin
12334 | Operator::F32Max
12335 | Operator::F64Max
12336 | Operator::F32x4RelaxedMax
12337 | Operator::F32x4Max
12338 | Operator::F32x4PMax
12339 | Operator::F64x2RelaxedMax
12340 | Operator::F64x2Max
12341 | Operator::F64x2PMax
12342 | Operator::F32Ceil
12343 | Operator::F32x4Ceil
12344 | Operator::F64Ceil
12345 | Operator::F64x2Ceil
12346 | Operator::F32Floor
12347 | Operator::F32x4Floor
12348 | Operator::F64Floor
12349 | Operator::F64x2Floor
12350 | Operator::F32Trunc
12351 | Operator::F32x4Trunc
12352 | Operator::F64Trunc
12353 | Operator::F64x2Trunc
12354 | Operator::F32Nearest
12355 | Operator::F32x4Nearest
12356 | Operator::F64Nearest
12357 | Operator::F64x2Nearest
12358 | Operator::F32Abs
12359 | Operator::F64Abs
12360 | Operator::F32x4Abs
12361 | Operator::F64x2Abs
12362 | Operator::F32x4Neg
12363 | Operator::F64x2Neg
12364 | Operator::F32Neg
12365 | Operator::F64Neg
12366 | Operator::F32Copysign
12367 | Operator::F64Copysign => self.translate_floating_point_arithmetic_operator(op)?,
12368 Operator::I32Eq
12369 | Operator::I64Eq
12370 | Operator::I8x16Eq
12371 | Operator::I16x8Eq
12372 | Operator::I32x4Eq
12373 | Operator::I64x2Eq
12374 | Operator::I32Ne
12375 | Operator::I64Ne
12376 | Operator::I8x16Ne
12377 | Operator::I16x8Ne
12378 | Operator::I32x4Ne
12379 | Operator::I64x2Ne
12380 | Operator::I32LtS
12381 | Operator::I64LtS
12382 | Operator::I8x16LtS
12383 | Operator::I16x8LtS
12384 | Operator::I32x4LtS
12385 | Operator::I64x2LtS
12386 | Operator::I32LtU
12387 | Operator::I64LtU
12388 | Operator::I8x16LtU
12389 | Operator::I16x8LtU
12390 | Operator::I32x4LtU
12391 | Operator::I32LeS
12392 | Operator::I64LeS
12393 | Operator::I8x16LeS
12394 | Operator::I16x8LeS
12395 | Operator::I32x4LeS
12396 | Operator::I64x2LeS
12397 | Operator::I32LeU
12398 | Operator::I64LeU
12399 | Operator::I8x16LeU
12400 | Operator::I16x8LeU
12401 | Operator::I32x4LeU
12402 | Operator::I32GtS
12403 | Operator::I64GtS
12404 | Operator::I8x16GtS
12405 | Operator::I16x8GtS
12406 | Operator::I32x4GtS
12407 | Operator::I64x2GtS
12408 | Operator::I32GtU
12409 | Operator::I64GtU
12410 | Operator::I8x16GtU
12411 | Operator::I16x8GtU
12412 | Operator::I32x4GtU
12413 | Operator::I32GeS
12414 | Operator::I64GeS
12415 | Operator::I8x16GeS
12416 | Operator::I16x8GeS
12417 | Operator::I32x4GeS
12418 | Operator::I64x2GeS
12419 | Operator::I32GeU
12420 | Operator::I64GeU
12421 | Operator::I8x16GeU
12422 | Operator::I16x8GeU
12423 | Operator::I32x4GeU => self.translate_integer_comparison_operator(op)?,
12424 Operator::F32Eq
12425 | Operator::F64Eq
12426 | Operator::F32x4Eq
12427 | Operator::F64x2Eq
12428 | Operator::F32Ne
12429 | Operator::F64Ne
12430 | Operator::F32x4Ne
12431 | Operator::F64x2Ne
12432 | Operator::F32Lt
12433 | Operator::F64Lt
12434 | Operator::F32x4Lt
12435 | Operator::F64x2Lt
12436 | Operator::F32Le
12437 | Operator::F64Le
12438 | Operator::F32x4Le
12439 | Operator::F64x2Le
12440 | Operator::F32Gt
12441 | Operator::F64Gt
12442 | Operator::F32x4Gt
12443 | Operator::F64x2Gt
12444 | Operator::F32Ge
12445 | Operator::F64Ge
12446 | Operator::F32x4Ge
12447 | Operator::F64x2Ge => self.translate_floating_point_comparison_operator(op)?,
12448 Operator::I32WrapI64
12449 | Operator::I64ExtendI32S
12450 | Operator::I64ExtendI32U
12451 | Operator::I16x8ExtendLowI8x16S
12452 | Operator::I16x8ExtendHighI8x16S
12453 | Operator::I16x8ExtendLowI8x16U
12454 | Operator::I16x8ExtendHighI8x16U
12455 | Operator::I32x4ExtendLowI16x8S
12456 | Operator::I32x4ExtendHighI16x8S
12457 | Operator::I32x4ExtendLowI16x8U
12458 | Operator::I32x4ExtendHighI16x8U
12459 | Operator::I64x2ExtendLowI32x4U
12460 | Operator::I64x2ExtendLowI32x4S
12461 | Operator::I64x2ExtendHighI32x4U
12462 | Operator::I64x2ExtendHighI32x4S
12463 | Operator::I8x16NarrowI16x8S
12464 | Operator::I8x16NarrowI16x8U
12465 | Operator::I16x8NarrowI32x4S
12466 | Operator::I16x8NarrowI32x4U
12467 | Operator::I32x4RelaxedTruncF32x4S
12468 | Operator::I32x4TruncSatF32x4S
12469 | Operator::I32x4RelaxedTruncF32x4U
12470 | Operator::I32x4TruncSatF32x4U
12471 | Operator::I32x4RelaxedTruncF64x2SZero
12472 | Operator::I32x4RelaxedTruncF64x2UZero
12473 | Operator::I32x4TruncSatF64x2SZero
12474 | Operator::I32x4TruncSatF64x2UZero
12475 | Operator::I32TruncF32S
12476 | Operator::I32TruncF64S
12477 | Operator::I32TruncSatF32S
12478 | Operator::I32TruncSatF64S
12479 | Operator::I64TruncF32S
12480 | Operator::I64TruncF64S
12481 | Operator::I64TruncSatF32S
12482 | Operator::I64TruncSatF64S
12483 | Operator::I32TruncF32U
12484 | Operator::I32TruncF64U
12485 | Operator::I32TruncSatF32U
12486 | Operator::I32TruncSatF64U
12487 | Operator::I64TruncF32U
12488 | Operator::I64TruncF64U
12489 | Operator::I64TruncSatF32U
12490 | Operator::I64TruncSatF64U
12491 | Operator::F32DemoteF64
12492 | Operator::F64PromoteF32
12493 | Operator::F32ConvertI32S
12494 | Operator::F32ConvertI64S
12495 | Operator::F64ConvertI32S
12496 | Operator::F64ConvertI64S
12497 | Operator::F32ConvertI32U
12498 | Operator::F32ConvertI64U
12499 | Operator::F64ConvertI32U
12500 | Operator::F64ConvertI64U
12501 | Operator::F32x4ConvertI32x4S
12502 | Operator::F32x4ConvertI32x4U
12503 | Operator::F64x2ConvertLowI32x4S
12504 | Operator::F64x2ConvertLowI32x4U
12505 | Operator::F64x2PromoteLowF32x4
12506 | Operator::F32x4DemoteF64x2Zero
12507 | Operator::I32ReinterpretF32
12508 | Operator::I64ReinterpretF64
12509 | Operator::F32ReinterpretI32
12510 | Operator::F64ReinterpretI64 => self.translate_conversion_operator(op)?,
12511 Operator::I32Extend8S
12512 | Operator::I32Extend16S
12513 | Operator::I64Extend8S
12514 | Operator::I64Extend16S
12515 | Operator::I64Extend32S => self.translate_sign_extension_operator(op)?,
12516 Operator::I32Load { .. }
12517 | Operator::I64Load { .. }
12518 | Operator::F32Load { .. }
12519 | Operator::F64Load { .. }
12520 | Operator::V128Load { .. }
12521 | Operator::V128Load8Lane { .. }
12522 | Operator::V128Load16Lane { .. }
12523 | Operator::V128Load32Lane { .. }
12524 | Operator::V128Load64Lane { .. }
12525 | Operator::I32Store { .. }
12526 | Operator::I64Store { .. }
12527 | Operator::F32Store { .. }
12528 | Operator::F64Store { .. }
12529 | Operator::V128Store { .. }
12530 | Operator::V128Store8Lane { .. }
12531 | Operator::V128Store16Lane { .. }
12532 | Operator::V128Store32Lane { .. }
12533 | Operator::V128Store64Lane { .. }
12534 | Operator::I32Load8S { .. }
12535 | Operator::I32Load16S { .. }
12536 | Operator::I64Load8S { .. }
12537 | Operator::I64Load16S { .. }
12538 | Operator::I64Load32S { .. }
12539 | Operator::I32Load8U { .. }
12540 | Operator::I32Load16U { .. }
12541 | Operator::I64Load8U { .. }
12542 | Operator::I64Load16U { .. }
12543 | Operator::I64Load32U { .. }
12544 | Operator::I32Store8 { .. }
12545 | Operator::I64Store8 { .. }
12546 | Operator::I32Store16 { .. }
12547 | Operator::I64Store16 { .. }
12548 | Operator::I64Store32 { .. }
12549 | Operator::I8x16Neg
12550 | Operator::I16x8Neg
12551 | Operator::I32x4Neg
12552 | Operator::I64x2Neg
12553 | Operator::V128Not
12554 | Operator::V128AnyTrue
12555 | Operator::I8x16AllTrue
12556 | Operator::I16x8AllTrue
12557 | Operator::I32x4AllTrue
12558 | Operator::I64x2AllTrue
12559 | Operator::I8x16ExtractLaneS { .. }
12560 | Operator::I8x16ExtractLaneU { .. }
12561 | Operator::I16x8ExtractLaneS { .. }
12562 | Operator::I16x8ExtractLaneU { .. }
12563 | Operator::I32x4ExtractLane { .. }
12564 | Operator::I64x2ExtractLane { .. }
12565 | Operator::F32x4ExtractLane { .. }
12566 | Operator::F64x2ExtractLane { .. }
12567 | Operator::I8x16ReplaceLane { .. }
12568 | Operator::I16x8ReplaceLane { .. }
12569 | Operator::I32x4ReplaceLane { .. }
12570 | Operator::I64x2ReplaceLane { .. }
12571 | Operator::F32x4ReplaceLane { .. }
12572 | Operator::F64x2ReplaceLane { .. }
12573 | Operator::I8x16RelaxedSwizzle
12574 | Operator::I8x16Swizzle
12575 | Operator::I8x16Shuffle { .. }
12576 | Operator::V128Load8x8S { .. }
12577 | Operator::V128Load8x8U { .. }
12578 | Operator::V128Load16x4S { .. }
12579 | Operator::V128Load16x4U { .. }
12580 | Operator::V128Load32x2S { .. }
12581 | Operator::V128Load32x2U { .. }
12582 | Operator::V128Load32Zero { .. }
12583 | Operator::V128Load64Zero { .. }
12584 | Operator::V128Load8Splat { .. }
12585 | Operator::V128Load16Splat { .. }
12586 | Operator::V128Load32Splat { .. }
12587 | Operator::V128Load64Splat { .. }
12588 | Operator::MemoryGrow { .. }
12589 | Operator::MemorySize { .. }
12590 | Operator::MemoryInit { .. }
12591 | Operator::DataDrop { .. }
12592 | Operator::MemoryCopy { .. }
12593 | Operator::MemoryFill { .. } => self.translate_memory_operator(op)?,
12594 Operator::AtomicFence { .. }
12595 | Operator::I32AtomicLoad { .. }
12596 | Operator::I64AtomicLoad { .. }
12597 | Operator::I32AtomicLoad8U { .. }
12598 | Operator::I32AtomicLoad16U { .. }
12599 | Operator::I64AtomicLoad8U { .. }
12600 | Operator::I64AtomicLoad16U { .. }
12601 | Operator::I64AtomicLoad32U { .. }
12602 | Operator::I32AtomicStore { .. }
12603 | Operator::I64AtomicStore { .. }
12604 | Operator::I32AtomicStore8 { .. }
12605 | Operator::I64AtomicStore8 { .. }
12606 | Operator::I32AtomicStore16 { .. }
12607 | Operator::I64AtomicStore16 { .. }
12608 | Operator::I64AtomicStore32 { .. }
12609 | Operator::I32AtomicRmw8AddU { .. }
12610 | Operator::I32AtomicRmw16AddU { .. }
12611 | Operator::I32AtomicRmwAdd { .. }
12612 | Operator::I64AtomicRmw8AddU { .. }
12613 | Operator::I64AtomicRmw16AddU { .. }
12614 | Operator::I64AtomicRmw32AddU { .. }
12615 | Operator::I64AtomicRmwAdd { .. }
12616 | Operator::I32AtomicRmw8SubU { .. }
12617 | Operator::I32AtomicRmw16SubU { .. }
12618 | Operator::I32AtomicRmwSub { .. }
12619 | Operator::I64AtomicRmw8SubU { .. }
12620 | Operator::I64AtomicRmw16SubU { .. }
12621 | Operator::I64AtomicRmw32SubU { .. }
12622 | Operator::I64AtomicRmwSub { .. }
12623 | Operator::I32AtomicRmw8AndU { .. }
12624 | Operator::I32AtomicRmw16AndU { .. }
12625 | Operator::I32AtomicRmwAnd { .. }
12626 | Operator::I64AtomicRmw8AndU { .. }
12627 | Operator::I64AtomicRmw16AndU { .. }
12628 | Operator::I64AtomicRmw32AndU { .. }
12629 | Operator::I64AtomicRmwAnd { .. }
12630 | Operator::I32AtomicRmw8OrU { .. }
12631 | Operator::I32AtomicRmw16OrU { .. }
12632 | Operator::I32AtomicRmwOr { .. }
12633 | Operator::I64AtomicRmw8OrU { .. }
12634 | Operator::I64AtomicRmw16OrU { .. }
12635 | Operator::I64AtomicRmw32OrU { .. }
12636 | Operator::I64AtomicRmwOr { .. }
12637 | Operator::I32AtomicRmw8XorU { .. }
12638 | Operator::I32AtomicRmw16XorU { .. }
12639 | Operator::I32AtomicRmwXor { .. }
12640 | Operator::I64AtomicRmw8XorU { .. }
12641 | Operator::I64AtomicRmw16XorU { .. }
12642 | Operator::I64AtomicRmw32XorU { .. }
12643 | Operator::I64AtomicRmwXor { .. }
12644 | Operator::I32AtomicRmw8XchgU { .. }
12645 | Operator::I32AtomicRmw16XchgU { .. }
12646 | Operator::I32AtomicRmwXchg { .. }
12647 | Operator::I64AtomicRmw8XchgU { .. }
12648 | Operator::I64AtomicRmw16XchgU { .. }
12649 | Operator::I64AtomicRmw32XchgU { .. }
12650 | Operator::I64AtomicRmwXchg { .. }
12651 | Operator::I32AtomicRmw8CmpxchgU { .. }
12652 | Operator::I32AtomicRmw16CmpxchgU { .. }
12653 | Operator::I32AtomicRmwCmpxchg { .. }
12654 | Operator::I64AtomicRmw8CmpxchgU { .. }
12655 | Operator::I64AtomicRmw16CmpxchgU { .. }
12656 | Operator::I64AtomicRmw32CmpxchgU { .. }
12657 | Operator::I64AtomicRmwCmpxchg { .. }
12658 | Operator::MemoryAtomicWait32 { .. }
12659 | Operator::MemoryAtomicWait64 { .. }
12660 | Operator::MemoryAtomicNotify { .. } => self.translate_atomic_memory_operator(op)?,
12661 Operator::RefNull { .. } | Operator::RefIsNull | Operator::RefFunc { .. } => {
12662 self.translate_reference_operator(op)?;
12663 }
12664 Operator::TableGet { .. }
12665 | Operator::TableSet { .. }
12666 | Operator::TableCopy { .. }
12667 | Operator::TableInit { .. }
12668 | Operator::ElemDrop { .. }
12669 | Operator::TableFill { .. }
12670 | Operator::TableGrow { .. }
12671 | Operator::TableSize { .. } => self.translate_table_operator(op)?,
12672 Operator::TryTable { .. } | Operator::Throw { .. } | Operator::ThrowRef => {
12673 self.translate_eh_operator(op)?;
12674 }
12675 _ => {
12676 return Err(CompileError::Codegen(format!(
12677 "Operator {op:?} unimplemented",
12678 )));
12679 }
12680 }
12681
12682 Ok(())
12683 }
12684
12685 fn build_call_with_param_attributes(
12686 &self,
12687 function: FunctionValue<'ctx>,
12688 args: &[BasicMetadataValueEnum<'ctx>],
12689 name: &str,
12690 ) -> Result<CallSiteValue<'ctx>, CompileError> {
12691 let call = self
12692 .builder
12693 .build_call(function, args, name)
12694 .map_err(|e| CompileError::Codegen(e.to_string()))?;
12695
12696 if matches!(
12701 self.target_triple.architecture,
12702 Architecture::Riscv32(..) | Architecture::Riscv64(..)
12703 ) {
12704 let param_types = function.get_type().get_param_types();
12705 for (i, ty) in param_types.into_iter().enumerate() {
12706 if ty == self.context.i32_type().into() {
12707 call.add_attribute(
12708 AttributeLoc::Param(i as u32),
12709 self.context
12710 .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
12711 );
12712 call.add_attribute(
12713 AttributeLoc::Param(i as u32),
12714 self.context
12715 .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
12716 );
12717 }
12718 }
12719 }
12720
12721 Ok(call)
12722 }
12723}
12724
12725fn is_f32_arithmetic(bits: u32) -> bool {
12726 let bits = bits & 0x7FFF_FFFF;
12728 bits < 0x7FC0_0000
12729}
12730
12731fn is_f64_arithmetic(bits: u64) -> bool {
12732 let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12734 bits < 0x7FF8_0000_0000_0000
12735}